262 lines
8.7 KiB
JavaScript
Executable File
262 lines
8.7 KiB
JavaScript
Executable File
// calculateActions.js
|
|
// Funktionen zum Berechnen von Vorschlägen basierend auf den neuesten CSV-Daten
|
|
|
|
const analysisLogEl = document.getElementById('analysis-log');
|
|
|
|
function appendToAnalysis(line) {
|
|
const now = new Date().toISOString();
|
|
analysisLogEl.value += `[${now}] ${line}\n`;
|
|
analysisLogEl.scrollTop = analysisLogEl.scrollHeight;
|
|
}
|
|
|
|
async function fetchCSV() {
|
|
console.log('Lade und verarbeite CSV-Daten...');
|
|
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 };
|
|
}
|
|
|
|
// CSV parsen
|
|
const lines = data.content.trim().split('\n');
|
|
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(',');
|
|
let obj = {};
|
|
headers.forEach((h, i) => {
|
|
const val = cells[i]?.trim();
|
|
obj[h] = isNaN(val) ? val : parseFloat(val);
|
|
});
|
|
return obj;
|
|
});
|
|
appendToAnalysis(`CSV-Daten geladen: ${rows.length} Zeilen, ${headers.length} Spalten.`);
|
|
return { data, headers, rows };
|
|
}
|
|
|
|
async function readValues( data, headers, rows ){
|
|
console.log('Geladene Daten:', data);
|
|
console.log('Headers:', headers);
|
|
console.log('Parsed rows:', rows);
|
|
|
|
|
|
}
|
|
|
|
function calculateAngleFromPosition(row, axisY, axisZ, deltaYangle0, deltaZangle0 = 0) {
|
|
let y = parseFloat(row.y_mm);
|
|
let z = parseFloat(row.z_mm);
|
|
|
|
let dy = -(y - axisY);
|
|
let dz = z - axisZ;
|
|
|
|
let angle0Rad = 0;
|
|
if(deltaZangle0 !== 0){
|
|
angle0Rad = Math.atan(deltaZangle0/deltaYangle0);
|
|
}
|
|
|
|
angleRad = Math.atan(dz/dy) - angle0Rad;
|
|
angleDeg = angleRad * (180 / Math.PI);
|
|
|
|
appendToAnalysis(`(yMotor = ${angleDeg.toFixed(2)}° = ${angleRad.toFixed(4)} rad ) aus Position von ID = ${row.id}`);
|
|
return angleRad;
|
|
}
|
|
|
|
function calculateAngleFromRollColumn(row, roll0 = 0, pitch0 = 0, yaw0 = 0, strMotor = "yMotor") {
|
|
let roll = -parseFloat(row.roll_deg) + roll0;
|
|
appendToAnalysis(`(${strMotor} = ${roll.toFixed(2)}° = ${(roll * Math.PI / 180).toFixed(4)} rad) aus roll_deg von ID = ${row.id}`);
|
|
return roll*Math.PI / 180;
|
|
}
|
|
|
|
function calculateAngleFromRelativePosition(row1, row2, strMotor = "zMotor") {
|
|
let y1 = parseFloat(row1.y_mm);
|
|
let z1 = parseFloat(row1.z_mm);
|
|
let y2 = parseFloat(row2.y_mm);
|
|
let z2 = parseFloat(row2.z_mm);
|
|
let dy = y1 - y2;
|
|
let dz = z1 - z2;
|
|
let angleRad = -Math.atan(dz/dy);
|
|
let angleDeg = angleRad * (180 / Math.PI);
|
|
appendToAnalysis(`(${strMotor} = ${angleDeg.toFixed(2)}° = ${angleRad.toFixed(4)} rad) aus relativer Position von ID = ${row1.id} und ID = ${row2.id}`);
|
|
return angleRad;
|
|
}
|
|
|
|
async function calculate() {
|
|
|
|
let shoulderAxisY = 115;
|
|
let shoulderAxisZ = 61;
|
|
|
|
let rows = null;
|
|
let headers = null;
|
|
|
|
try {
|
|
appendToAnalysis('Starte Berechnung...');
|
|
const result = await fetchCSV();
|
|
rows = result.rows;
|
|
headers = result.headers;
|
|
const data = result.data;
|
|
await readValues( data, headers, rows );
|
|
} catch (err) {
|
|
appendToAnalysis('Fehler in calculate: ' + err.message);
|
|
}
|
|
|
|
|
|
// Oberarm:
|
|
var angleY = 0;
|
|
var angleZ = 0;
|
|
var angleYcount = 0;
|
|
var angleZcount = 0;
|
|
|
|
// 243 damit 35mm weiter außen (250+35) und 0mm höher als Schulterachse
|
|
const row243 = rows.find(r => r.id == 243 && r.seen_by == 3)
|
|
if(row243){
|
|
angleY += await calculateAngleFromPosition(row243, shoulderAxisY, shoulderAxisZ, 250+35, 0);
|
|
angleY += await calculateAngleFromRollColumn(row243, 90, 0, 0);
|
|
angleYcount+=2;
|
|
}
|
|
const row229 = rows.find(r => r.id == 229 && r.seen_by == 3)
|
|
if(row229){
|
|
angleY += await calculateAngleFromPosition(row229, shoulderAxisY, shoulderAxisZ, 250, 35);
|
|
//angleY +=calculateAngleFromRollColumn(row229, 0, 0, 0); // Roll ist extrem unzuverlässig
|
|
angleYcount+=1;
|
|
}
|
|
console.log(angleY, angleYcount);
|
|
const row198 = rows.find(r => r.id == 198 && r.seen_by == 3)
|
|
if(row198){
|
|
angleY += await calculateAngleFromPosition(row198, shoulderAxisY, shoulderAxisZ, 165, 35);
|
|
//angleY +=calculateAngleFromRollColumn(row198, 180, 0, 0); // ist ungenau
|
|
angleYcount++;
|
|
}
|
|
|
|
if(row198 && row229){
|
|
angleY += 3*(calculateAngleFromRelativePosition(row198, row229, "yMotor"));
|
|
angleYcount += 3;
|
|
}
|
|
|
|
const row197 = rows.find(r => r.id == 197)
|
|
if(row197){
|
|
var angleDeg = 90 - row197.pitch_deg;
|
|
var angleRad = angleDeg * Math.PI / 180;
|
|
appendToAnalysis(`(yMotor = ${angleDeg.toFixed(2)}° = ${angleRad.toFixed(4)} rad ) aus Pitch von ${row197.id}`);
|
|
}
|
|
|
|
// Unterarm:
|
|
|
|
// 218 und 219, wenn die sichtbar sind, ist auch die Schulter eindeutig definiert
|
|
const row218 = rows.find(r => r.id == 218 && r.seen_by == 3)
|
|
const row219 = rows.find(r => r.id == 219 && r.seen_by == 3)
|
|
if(row218 && row219){
|
|
const lowerArmAngle = calculateAngleFromRelativePosition(row218, row219, "zMotor");
|
|
angleZ += lowerArmAngle;
|
|
angleZcount++;
|
|
}
|
|
console.log("z", angleZ);
|
|
|
|
const row226 = rows.find(r => r.id == 226 && r.seen_by == 3)
|
|
if(row226){
|
|
angleZ += calculateAngleFromRollColumn(row226, 0, 0, 0, "zMotor");
|
|
angleZcount++;
|
|
}
|
|
|
|
console.log("z", angleZ);
|
|
|
|
if(angleYcount > 0 && angleYcount > 0){
|
|
strActionOptionA = `G92 y${(angleY*180/(angleYcount*Math.PI)).toFixed(1)} z${(angleZ*180/(Math.PI*angleZcount)).toFixed(1)} (Set Coord. Angles in deg)`;
|
|
strActionOptionB = `M92 y${(angleY/(angleYcount)).toFixed(3)} z${(angleZ/(angleZcount)).toFixed(3)} (Set Coord. Angles in rad)`;
|
|
|
|
appendToAnalysis(`Suggestion: ${strActionOptionA}`);
|
|
appendToAnalysis(`Suggestion: ${strActionOptionB}`);
|
|
|
|
// ToDo: Change
|
|
}
|
|
|
|
// Ellbow
|
|
const row242 = rows.find(r => r.id == 242 && r.seen_by == 3)
|
|
const row200 = rows.find(r => r.id == 200 && r.seen_by == 3)
|
|
const row204 = rows.find(r => r.id == 204 && r.seen_by == 3)
|
|
// Ellenbogen-Rotation aus x-Position 218 219
|
|
// dazu brauche ich genaue x-Position von 226
|
|
if(row226 || row229 || row198 || row243 || row242 || row200 || row200){
|
|
var x226 = 0;
|
|
var xCount = 0;
|
|
if(row226){
|
|
x226 += row226.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;
|
|
}
|
|
x226 = x226 / xCount;
|
|
appendToAnalysis(`Ellebogen x226=${x226}`)
|
|
|
|
// Wenn 218 und/oder 219 sicher gesehen wird, kann ich daraus x-pos bestimmen
|
|
if(row218 || row219){
|
|
var x219 = 0;
|
|
xCount = 0;
|
|
if(row218){
|
|
x219 += row218.x_mm;
|
|
xCount += 1;
|
|
}
|
|
if(row219){
|
|
x219 += row219.x_mm;
|
|
xCount += 1;
|
|
}
|
|
x219 = x219 / xCount;
|
|
appendToAnalysis(`Ellebogen x219=${x219}`)
|
|
var xDelta = x219 - x226;
|
|
if(Math.abs(xDelta) < 35){
|
|
|
|
appendToAnalysis(`Ellebogen xDelta / 35=${xDelta / 35}`)
|
|
var angleRad = Math.asin(xDelta / 35)
|
|
var angleDeg = 90 -angleRad*180/Math.PI;
|
|
appendToAnalysis(`(xEllbow = ${angleDeg.toFixed(2)}° = ${angleRad.toFixed(4)} rad ) aus x von 218 bzw. 219`);
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (typeof module !== 'undefined') {
|
|
module.exports = {
|
|
calculateAngleFromPosition,
|
|
calculateAngleFromRollColumn,
|
|
calculateAngleFromRelativePosition,
|
|
calculate
|
|
};
|
|
}
|
|
|
|
|
|
// Export für Module, falls benötigt
|
|
// export { fetchCSV, calculate };
|