Remove old Code.
The functionality is moved to calculateAngles.js
This commit is contained in:
@@ -1,723 +0,0 @@
|
||||
// calculateActions.js
|
||||
// Berechnung + nachvollziehbare Result-Struktur + Live-Logs in analysis-log
|
||||
|
||||
function getAnalysisLogEl() {
|
||||
if (typeof document === "undefined") return null;
|
||||
return document.getElementById("analysis-log");
|
||||
}
|
||||
|
||||
function appendToAnalysis(line) {
|
||||
const el = getAnalysisLogEl();
|
||||
if (!el) return;
|
||||
|
||||
const now = new Date().toISOString();
|
||||
el.value += `[${now}] ${line}\n`;
|
||||
el.scrollTop = el.scrollHeight;
|
||||
}
|
||||
|
||||
function createAnalysisResult(meta = {}) {
|
||||
return {
|
||||
meta: {
|
||||
timestamp: new Date().toISOString(),
|
||||
...meta
|
||||
},
|
||||
inputs: {
|
||||
source: null,
|
||||
headers: [],
|
||||
rowCount: 0
|
||||
},
|
||||
observations: [],
|
||||
calculations: [],
|
||||
features: {},
|
||||
commands: [],
|
||||
logs: [],
|
||||
errors: [],
|
||||
summary: {
|
||||
observationCount: 0,
|
||||
calculationCount: 0,
|
||||
featureCount: 0,
|
||||
commandCount: 0
|
||||
},
|
||||
status: "ok"
|
||||
};
|
||||
}
|
||||
|
||||
function rowSnapshot(row) {
|
||||
return {
|
||||
id: row?.id,
|
||||
seen_by: row?.seen_by,
|
||||
x_mm: row?.x_mm,
|
||||
y_mm: row?.y_mm,
|
||||
z_mm: row?.z_mm,
|
||||
roll_deg: row?.roll_deg,
|
||||
pitch_deg: row?.pitch_deg
|
||||
};
|
||||
}
|
||||
|
||||
function addLog(result, message, level = "info") {
|
||||
const entry = {
|
||||
timestamp: new Date().toISOString(),
|
||||
level,
|
||||
message
|
||||
};
|
||||
result.logs.push(entry);
|
||||
appendToAnalysis(message);
|
||||
}
|
||||
|
||||
function addError(result, message, error = null) {
|
||||
result.status = "error";
|
||||
result.errors.push({
|
||||
timestamp: new Date().toISOString(),
|
||||
message,
|
||||
details: error ? String(error) : null
|
||||
});
|
||||
addLog(result, `Fehler: ${message}`, "error");
|
||||
}
|
||||
|
||||
function addObservation(result, key, row, confidence = 1.0, notes = []) {
|
||||
result.observations.push({
|
||||
key,
|
||||
source: {
|
||||
rowId: row?.id,
|
||||
seenBy: row?.seen_by
|
||||
},
|
||||
values: rowSnapshot(row),
|
||||
confidence,
|
||||
notes
|
||||
});
|
||||
}
|
||||
|
||||
function addCalculation(result, calc) {
|
||||
result.calculations.push({
|
||||
timestamp: new Date().toISOString(),
|
||||
...calc
|
||||
});
|
||||
}
|
||||
|
||||
function addFeature(result, key, feature) {
|
||||
result.features[key] = feature;
|
||||
}
|
||||
|
||||
function addCommand(result, id, command, basedOn = [], confidence = 1.0, format = "gcode") {
|
||||
result.commands.push({
|
||||
id,
|
||||
command,
|
||||
basedOn,
|
||||
confidence,
|
||||
format
|
||||
});
|
||||
}
|
||||
|
||||
function weightedAverage(candidates) {
|
||||
const weightSum = candidates.reduce((sum, c) => sum + c.weight, 0);
|
||||
if (!weightSum) return null;
|
||||
|
||||
const valueRad = candidates.reduce((sum, c) => sum + (c.valueRad * c.weight), 0) / weightSum;
|
||||
const spreadRad = candidates.length > 1
|
||||
? Math.sqrt(
|
||||
candidates.reduce(
|
||||
(sum, c) => sum + c.weight * Math.pow(c.valueRad - valueRad, 2),
|
||||
0
|
||||
) / weightSum
|
||||
)
|
||||
: 0;
|
||||
|
||||
const confidence = Math.max(
|
||||
0.2,
|
||||
Math.min(
|
||||
0.98,
|
||||
0.55 +
|
||||
Math.min(candidates.length * 0.1, 0.25) -
|
||||
Math.min(spreadRad / 1.0, 0.2)
|
||||
)
|
||||
);
|
||||
|
||||
return { valueRad, weightSum, spreadRad, confidence };
|
||||
}
|
||||
|
||||
async function fetchCSV() {
|
||||
const res = await fetch("/api/latest-snapshot");
|
||||
if (!res.ok) throw new Error("Fehler beim Laden des Snapshots");
|
||||
|
||||
let data;
|
||||
if (res.headers.get("content-type")?.includes("application/json")) {
|
||||
data = await res.json();
|
||||
} else {
|
||||
const csvData = await res.text();
|
||||
data = {
|
||||
filename: "latest.csv",
|
||||
mtime: new Date().toISOString(),
|
||||
content: csvData
|
||||
};
|
||||
}
|
||||
|
||||
const lines = data.content.trim().split(/\r?\n/).filter(Boolean);
|
||||
if (lines.length < 2) {
|
||||
throw new Error("Keine oder unvollständige Daten");
|
||||
}
|
||||
|
||||
const headers = lines[0].split(",").map(h => h.trim());
|
||||
|
||||
const rows = lines.slice(1).map(line => {
|
||||
const cells = line.split(",");
|
||||
const obj = {};
|
||||
headers.forEach((h, i) => {
|
||||
const raw = (cells[i] ?? "").trim();
|
||||
const numeric = Number(raw);
|
||||
obj[h] = raw !== "" && Number.isFinite(numeric) ? numeric : raw;
|
||||
});
|
||||
return obj;
|
||||
});
|
||||
|
||||
return { data, headers, rows };
|
||||
}
|
||||
|
||||
function calculateAngleFromPosition(result, row, axisY, axisZ, deltaYangle0, deltaZangle0 = 0, label = "angle") {
|
||||
const y = parseFloat(row.y_mm);
|
||||
const z = parseFloat(row.z_mm);
|
||||
|
||||
const dy = -(y - axisY);
|
||||
const dz = z - axisZ;
|
||||
|
||||
let angle0Rad = 0;
|
||||
if (deltaZangle0 !== 0 && deltaYangle0 !== 0) {
|
||||
angle0Rad = Math.atan(deltaZangle0 / deltaYangle0);
|
||||
}
|
||||
|
||||
const angleRad = Math.atan2(dz, dy) - angle0Rad;
|
||||
const angleDeg = angleRad * 180 / Math.PI;
|
||||
|
||||
const message = `(${label} = ${angleDeg.toFixed(2)}° = ${angleRad.toFixed(4)} rad) aus Position von ID = ${row.id}`;
|
||||
addLog(result, message);
|
||||
|
||||
addCalculation(result, {
|
||||
type: "angleFromPosition",
|
||||
label,
|
||||
source: {
|
||||
rowId: row.id,
|
||||
seenBy: row.seen_by
|
||||
},
|
||||
input: {
|
||||
axisY,
|
||||
axisZ,
|
||||
deltaYangle0,
|
||||
deltaZangle0,
|
||||
y_mm: y,
|
||||
z_mm: z,
|
||||
dy,
|
||||
dz,
|
||||
angle0Rad
|
||||
},
|
||||
output: {
|
||||
angleRad,
|
||||
angleDeg
|
||||
}
|
||||
});
|
||||
|
||||
return angleRad;
|
||||
}
|
||||
|
||||
function calculateAngleFromRollColumn(result, row, roll0 = 0, pitch0 = 0, yaw0 = 0, strMotor = "motor") {
|
||||
const rollDeg = -parseFloat(row.roll_deg) + roll0;
|
||||
const rollRad = rollDeg * Math.PI / 180;
|
||||
|
||||
const message = `(${strMotor} = ${rollDeg.toFixed(2)}° = ${rollRad.toFixed(4)} rad) aus roll_deg von ID = ${row.id}`;
|
||||
addLog(result, message);
|
||||
|
||||
addCalculation(result, {
|
||||
type: "angleFromRollColumn",
|
||||
label: strMotor,
|
||||
source: {
|
||||
rowId: row.id,
|
||||
seenBy: row.seen_by
|
||||
},
|
||||
input: {
|
||||
roll0,
|
||||
pitch0,
|
||||
yaw0,
|
||||
roll_deg: row.roll_deg
|
||||
},
|
||||
output: {
|
||||
angleRad: rollRad,
|
||||
angleDeg: rollDeg
|
||||
}
|
||||
});
|
||||
|
||||
return rollRad;
|
||||
}
|
||||
|
||||
function calculateAngleFromRelativePosition(result, row1, row2, strMotor = "motor") {
|
||||
const y1 = parseFloat(row1.y_mm);
|
||||
const z1 = parseFloat(row1.z_mm);
|
||||
const y2 = parseFloat(row2.y_mm);
|
||||
const z2 = parseFloat(row2.z_mm);
|
||||
|
||||
const dy = y1 - y2;
|
||||
const dz = z1 - z2;
|
||||
|
||||
const angleRad = -Math.atan2(dz, dy);
|
||||
const angleDeg = angleRad * 180 / Math.PI;
|
||||
|
||||
const message = `(${strMotor} = ${angleDeg.toFixed(2)}° = ${angleRad.toFixed(4)} rad) aus relativer Position von ID = ${row1.id} und ID = ${row2.id}`;
|
||||
addLog(result, message);
|
||||
|
||||
addCalculation(result, {
|
||||
type: "angleFromRelativePosition",
|
||||
label: strMotor,
|
||||
source: {
|
||||
rowIds: [row1.id, row2.id],
|
||||
seenBy: [row1.seen_by, row2.seen_by]
|
||||
},
|
||||
input: {
|
||||
y1_mm: y1,
|
||||
z1_mm: z1,
|
||||
y2_mm: y2,
|
||||
z2_mm: z2,
|
||||
dy,
|
||||
dz
|
||||
},
|
||||
output: {
|
||||
angleRad,
|
||||
angleDeg
|
||||
}
|
||||
});
|
||||
|
||||
return angleRad;
|
||||
}
|
||||
|
||||
function buildFeatureFromCandidates(result, key, title, method, candidates) {
|
||||
const summary = weightedAverage(candidates);
|
||||
if (!summary) return null;
|
||||
|
||||
const feature = {
|
||||
title,
|
||||
method,
|
||||
valueRad: summary.valueRad,
|
||||
valueDeg: summary.valueRad * 180 / Math.PI,
|
||||
confidence: summary.confidence,
|
||||
spreadRad: summary.spreadRad,
|
||||
weightSum: summary.weightSum,
|
||||
evidence: candidates.map(c => c.source),
|
||||
parts: candidates
|
||||
};
|
||||
|
||||
addFeature(result, key, feature);
|
||||
addCalculation(result, {
|
||||
type: "featureSummary",
|
||||
key,
|
||||
title,
|
||||
method,
|
||||
input: candidates,
|
||||
output: {
|
||||
valueRad: feature.valueRad,
|
||||
valueDeg: feature.valueDeg,
|
||||
confidence: feature.confidence,
|
||||
spreadRad: feature.spreadRad,
|
||||
weightSum: feature.weightSum
|
||||
}
|
||||
});
|
||||
|
||||
return feature;
|
||||
}
|
||||
|
||||
function calculate_angleY(row243, row229, row198, row197, shoulderAxisY, shoulderAxisZ, result) {
|
||||
const angleYCandidates = [];
|
||||
|
||||
if (row243) {
|
||||
const a1 = calculateAngleFromPosition(result, row243, shoulderAxisY, shoulderAxisZ, 285, 0, "yMotor");
|
||||
const a2 = calculateAngleFromRollColumn(result, row243, 90, 0, 0, "yMotor");
|
||||
|
||||
angleYCandidates.push({
|
||||
source: "row243.position",
|
||||
valueRad: a1,
|
||||
weight: 1
|
||||
});
|
||||
/*
|
||||
angleYCandidates.push({
|
||||
source: "row243.roll_deg",
|
||||
valueRad: a2,
|
||||
weight: 1
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
if (row229) {
|
||||
const a = calculateAngleFromPosition(result, row229, shoulderAxisY, shoulderAxisZ, 250, 35, "yMotor");
|
||||
angleYCandidates.push({
|
||||
source: "row229.position",
|
||||
valueRad: a,
|
||||
weight: 1
|
||||
});
|
||||
}
|
||||
|
||||
if (row198) {
|
||||
const a = calculateAngleFromPosition(result, row198, shoulderAxisY, shoulderAxisZ, 165, 35, "yMotor");
|
||||
angleYCandidates.push({
|
||||
source: "row198.position",
|
||||
valueRad: a,
|
||||
weight: 1
|
||||
});
|
||||
}
|
||||
|
||||
if (row198 && row229) {
|
||||
const a = calculateAngleFromRelativePosition(result, row198, row229, "yMotor");
|
||||
angleYCandidates.push({
|
||||
source: "row198-row229.relative",
|
||||
valueRad: a,
|
||||
weight: 3
|
||||
});
|
||||
}
|
||||
|
||||
if (row197) {
|
||||
const angleDeg = 90 - parseFloat(row197.pitch_deg);
|
||||
const angleRad = angleDeg * Math.PI / 180;
|
||||
|
||||
addLog(result, `(yMotor = ${angleDeg.toFixed(2)}° = ${angleRad.toFixed(4)} rad ) aus Pitch von ${row197.id}`);
|
||||
|
||||
addCalculation(result, {
|
||||
type: "angleFromPitch",
|
||||
label: "yMotor",
|
||||
source: {
|
||||
rowId: row197.id,
|
||||
seenBy: row197.seen_by
|
||||
},
|
||||
input: {
|
||||
pitch_deg: row197.pitch_deg
|
||||
},
|
||||
output: {
|
||||
angleRad,
|
||||
angleDeg
|
||||
}
|
||||
});
|
||||
|
||||
angleYCandidates.push({
|
||||
source: "row197.pitch_deg",
|
||||
valueRad: angleRad,
|
||||
weight: 1
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (angleYCandidates.length > 0) {
|
||||
buildFeatureFromCandidates(
|
||||
result,
|
||||
"shoulder.angleY",
|
||||
"Schulter Y",
|
||||
"weighted-average",
|
||||
angleYCandidates
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async function calculate() {
|
||||
const result = createAnalysisResult({
|
||||
sourceScript: "calculateActions.js"
|
||||
});
|
||||
|
||||
try {
|
||||
addLog(result, "Starte Berechnung...");
|
||||
|
||||
const { data, headers, rows } = await fetchCSV();
|
||||
|
||||
result.inputs = {
|
||||
source: {
|
||||
filename: data.filename,
|
||||
mtime: data.mtime
|
||||
},
|
||||
headers,
|
||||
rowCount: rows.length
|
||||
};
|
||||
|
||||
addLog(result, `CSV-Daten geladen: ${rows.length} Zeilen, ${headers.length} Spalten.`);
|
||||
|
||||
const getRow = (id, seenBy = null) => {
|
||||
const row = rows.find(r => r.id == id && (seenBy === null || r.seen_by == seenBy));
|
||||
if (row) {
|
||||
addObservation(
|
||||
result,
|
||||
`row-${id}${seenBy !== null ? `-seenBy-${seenBy}` : ""}`,
|
||||
row,
|
||||
seenBy === 3 ? 0.95 : 0.75,
|
||||
[
|
||||
`id=${id}`,
|
||||
seenBy !== null ? `seen_by=${seenBy}` : "seen_by=any"
|
||||
]
|
||||
);
|
||||
} else {
|
||||
addLog(result, `Zeile nicht gefunden: id=${id}${seenBy !== null ? `, seen_by=${seenBy}` : ""}`, "warn");
|
||||
}
|
||||
return row;
|
||||
};
|
||||
|
||||
const shoulderAxisY = 115;
|
||||
const shoulderAxisZ = 61;
|
||||
|
||||
|
||||
const row200 = getRow(200, 3); // Base
|
||||
const row204 = getRow(204, 3); // Base
|
||||
const row201 = getRow(201, 3); // Base
|
||||
|
||||
|
||||
const row198 = getRow(198, 3); // Bizeps oben-hinten
|
||||
const row242 = getRow(242, 3); // Bizeps unten
|
||||
const row243 = getRow(243, 3); // Bizeps vorne
|
||||
const row229 = getRow(229, 3); // Bizeps oben
|
||||
const row197 = getRow(197); // Bizeps Seiten-Abdeckung
|
||||
|
||||
const row222 = getRow(222, 3); // Ellbow
|
||||
const row226 = getRow(226, 3); // Ellbow
|
||||
|
||||
const row223 = getRow(223, 3); // Forearm
|
||||
const row228 = getRow(228, 3); // Forearm
|
||||
const row218 = getRow(218, 3); // Forearm 90°
|
||||
const row219 = getRow(219, 3); // Forearm 90°
|
||||
|
||||
const row212 = getRow(212, 3); // Hand
|
||||
|
||||
|
||||
|
||||
// Bizeps > Y-Achse der Schulter: angleYCandidates
|
||||
calculate_angleY(row243, row229, row198, row197, shoulderAxisY, shoulderAxisZ, result);
|
||||
|
||||
// Forearm rotation: a axis:
|
||||
|
||||
listForearmID = [row223, row228, row218, row219];
|
||||
listForearmAngle = [60, 145, -90, -90];
|
||||
addLog(result, "Berechnung der Unterarm-Rotation (a axis) aus x Positionen von Forearm und Ellbogen...");
|
||||
for(let r = 0; r < listForearmID.length; r++){
|
||||
if (listForearmID[r] && (row222 || row226)) {
|
||||
dx = listForearmID[r].x_mm - (row222 ? row222.x_mm : row226.x_mm);
|
||||
if(dx > 35 || dx < -35){
|
||||
addLog(result, `dx=${dx.toFixed(2)} mm ist zu groß für eine realistische Unterarm-Rotation. Überspringe...`, "warn");
|
||||
continue;
|
||||
}
|
||||
addLog(result, `dx between ${listForearmID[r].id} and Ellbow: ${dx.toFixed(2)} mm results in angle: ${Math.asin(dx / 35)*180/Math.PI}°`);
|
||||
|
||||
var angleRad = Math.asin(dx / 35) + listForearmAngle[r] * Math.PI / 180
|
||||
if(row222){angleRad = -angleRad }
|
||||
const angleDeg = angleRad * 180 / Math.PI;
|
||||
addLog(result, `(a axis from ${listForearmID[r].id} with dx ${dx.toFixed(2)} mm: ${angleDeg.toFixed(2)}° = ${angleRad.toFixed(4)} rad ) aus x von ${listForearmID[r].id} und Ellbogen`);
|
||||
|
||||
|
||||
addCalculation(result, {
|
||||
type: "forearmrotationAFromX",
|
||||
input: {
|
||||
dx,
|
||||
r
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Unterarm / z
|
||||
const angleZCandidates = [];
|
||||
|
||||
if (row218 && row219) {
|
||||
const lowerArmAngle = calculateAngleFromRelativePosition(result, row218, row219, "zMotor");
|
||||
angleZCandidates.push({
|
||||
source: "row218-row219.relative",
|
||||
valueRad: lowerArmAngle,
|
||||
weight: 200 // Hohes gewicht, da ich sicher bin, dass es korrekt ist
|
||||
});
|
||||
}
|
||||
|
||||
if (row226) {
|
||||
const a = calculateAngleFromRollColumn(result, row226, 0, 0, 0, "zMotor");
|
||||
angleZCandidates.push({
|
||||
source: "row226.roll_deg",
|
||||
valueRad: a,
|
||||
weight: 1
|
||||
});
|
||||
}
|
||||
|
||||
if (angleZCandidates.length > 0) {
|
||||
buildFeatureFromCandidates(
|
||||
result,
|
||||
"forearm.angleZ",
|
||||
"Unterarm Z",
|
||||
"combined",
|
||||
angleZCandidates
|
||||
);
|
||||
}
|
||||
|
||||
// Commands
|
||||
const angleY = result.features["shoulder.angleY"];
|
||||
const angleZ = result.features["forearm.angleZ"];
|
||||
|
||||
if (angleY && angleZ) {
|
||||
const cmdConfidence = Math.min(angleY.confidence, angleZ.confidence);
|
||||
|
||||
addCommand(
|
||||
result,
|
||||
"set-coord-angles-deg",
|
||||
`G92 y${angleY.valueDeg.toFixed(1)} z${angleZ.valueDeg.toFixed(1)} (Set Coord. Angles in deg)`,
|
||||
["shoulder.angleY", "forearm.angleZ"],
|
||||
cmdConfidence
|
||||
);
|
||||
|
||||
addCommand(
|
||||
result,
|
||||
"set-coord-angles-rad",
|
||||
`M92 y${angleY.valueRad.toFixed(3)} z${angleZ.valueRad.toFixed(3)} (Set Coord. Angles in rad)`,
|
||||
["shoulder.angleY", "forearm.angleZ"],
|
||||
cmdConfidence
|
||||
);
|
||||
}
|
||||
|
||||
// Ellbow / Zusatzschätzung
|
||||
if (row222 || row226 || row229 || row198 || row243 || row242 || row200 || row204) {
|
||||
let x226 = 0;
|
||||
let xCount = 0;
|
||||
|
||||
if (row226) {
|
||||
x226 += row226.x_mm * 5;
|
||||
xCount += 5;
|
||||
}
|
||||
if(row222){
|
||||
/// 222 should have the same as x226
|
||||
x226 += row222.x_mm * 5;
|
||||
xCount += 5;
|
||||
}
|
||||
if (row229) {
|
||||
x226 += row229.x_mm + 90;
|
||||
xCount += 1;
|
||||
}
|
||||
if (row198) {
|
||||
x226 += row198.x_mm + 90;
|
||||
xCount += 1;
|
||||
}
|
||||
if (row243) {
|
||||
x226 += row243.x_mm + 90;
|
||||
xCount += 1;
|
||||
}
|
||||
if (row242) {
|
||||
x226 += row242.x_mm + 90;
|
||||
xCount += 1;
|
||||
}
|
||||
if (row200) {
|
||||
x226 += row200.x_mm + 154;
|
||||
xCount += 1;
|
||||
}
|
||||
if (row204) {
|
||||
x226 += row204.x_mm + 160;
|
||||
xCount += 1;
|
||||
}
|
||||
|
||||
if (xCount > 0) {
|
||||
x226 = x226 / xCount;
|
||||
addLog(result, `Ellbogen x226=${x226}`);
|
||||
|
||||
addCalculation(result, {
|
||||
type: "elbowXEstimate",
|
||||
source: {
|
||||
rowIds: [row226, row229, row198, row243, row242, row200, row204].filter(Boolean).map(r => r.id)
|
||||
},
|
||||
output: {
|
||||
x226
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (row218 || row219) {
|
||||
let x219 = 0;
|
||||
let x219Count = 0;
|
||||
|
||||
if (row218) {
|
||||
x219 += row218.x_mm;
|
||||
x219Count += 1;
|
||||
}
|
||||
if (row219) {
|
||||
x219 += row219.x_mm;
|
||||
x219Count += 1;
|
||||
}
|
||||
|
||||
if (x219Count > 0) {
|
||||
x219 = x219 / x219Count;
|
||||
addLog(result, `Ellbogen x219=${x219}`);
|
||||
|
||||
const xDelta = x219 - x226;
|
||||
|
||||
addCalculation(result, {
|
||||
type: "elbowXComparison",
|
||||
input: {
|
||||
x226,
|
||||
x219,
|
||||
xDelta
|
||||
}
|
||||
});
|
||||
|
||||
if (Math.abs(xDelta) < 35) {
|
||||
addLog(result, `Ellbogen xDelta / 35=${xDelta / 35}`);
|
||||
const angleRad = Math.asin(xDelta / 35);
|
||||
const angleDeg = 90 - angleRad * 180 / Math.PI;
|
||||
addLog(result, `(xEllbow = ${angleDeg.toFixed(2)}° = ${angleRad.toFixed(4)} rad ) aus x von 218 bzw. 219`);
|
||||
|
||||
addCalculation(result, {
|
||||
type: "elbowAngleFromX",
|
||||
input: {
|
||||
x226,
|
||||
x219,
|
||||
xDelta
|
||||
},
|
||||
output: {
|
||||
angleRad,
|
||||
angleDeg
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ellbow-Rotation wenn X Position OK und 223 oder so bekannt ist.
|
||||
if(row223 && xCount > 2){
|
||||
// unterarm-roll => a aus der position von 223
|
||||
dx = row223.x_mm - x226;
|
||||
// aus der X Position kann der Unterarm-Winkel (a) berechnet werden
|
||||
|
||||
const angleRad = Math.asin(dx / 35);
|
||||
const angleDeg = 90 - angleRad * 180 / Math.PI;
|
||||
addLog(result, `(xEllbowRotation = ${angleDeg.toFixed(2)}° = ${angleRad.toFixed(4)} rad ) aus x von 223 und Ellbogen x226`);
|
||||
addCalculation(result, {
|
||||
type: "elbowRotationAFromX223",
|
||||
input: {
|
||||
x223: row223.x_mm,
|
||||
x226
|
||||
},
|
||||
output: {
|
||||
angleRad, angleDeg
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
result.summary = {
|
||||
observationCount: result.observations.length,
|
||||
calculationCount: result.calculations.length,
|
||||
featureCount: Object.keys(result.features).length,
|
||||
commandCount: result.commands.length
|
||||
};
|
||||
|
||||
addLog(
|
||||
result,
|
||||
`Berechnung fertig: ${result.summary.featureCount} Features, ${result.summary.commandCount} Commands.`
|
||||
);
|
||||
|
||||
return result;
|
||||
} catch (err) {
|
||||
addError(result, err.message, err);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof window !== "undefined") {
|
||||
window.calculate = calculate;
|
||||
window.createAnalysisResult = createAnalysisResult;
|
||||
}
|
||||
|
||||
if (typeof module !== "undefined") {
|
||||
module.exports = {
|
||||
calculate,
|
||||
createAnalysisResult
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user