Claude: Umbau Robot
This commit is contained in:
102
test/Speed.coordination.test.js
Normal file
102
test/Speed.coordination.test.js
Normal file
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* Integrationstest der Speed-Koordination (ToDo_6a).
|
||||
*
|
||||
* Kernaussage des Korrekt-Modus: Alle Controller müssen den Bewegungsschritt in
|
||||
* DERSELBEN Zeit beenden. Dieser Test prüft genau das — komplett unabhängig von der
|
||||
* internen Berechnung: er liest die tatsächlich gesendeten G-Code-Zeilen, rechnet aus
|
||||
* den absoluten Achswerten die Strecke jedes Senders aus und teilt durch die gesendete
|
||||
* Feedrate. Das Ergebnis (= Zeit) muss für jeden Sender gleich der robot-moveTime sein.
|
||||
*
|
||||
* Damit werden gleichzeitig abgesichert: moveTime-Propagation Robot→Sender, portValue
|
||||
* gegen den echten Sende-Pfad, und die Feedrate-Auswahl im Korrekt-Modus.
|
||||
*/
|
||||
const Robot = require('../robot/Robot');
|
||||
const GCode = require('../robot/GCode');
|
||||
const TelnetSender = require('../robot/TelnetSenderGRBL');
|
||||
|
||||
function parseLine(line) {
|
||||
const out = {};
|
||||
const re = /([a-z])(-?\d+(?:\.\d+)?)/g;
|
||||
let m;
|
||||
while ((m = re.exec(line)) !== null) out[m[1]] = parseFloat(m[2]);
|
||||
return out;
|
||||
}
|
||||
|
||||
function makeSender(...args) {
|
||||
const s = new TelnetSender(...args); // "test.test" → isTestMode
|
||||
s.writes = [];
|
||||
s.tSocket = { write(t) { s.writes.push(t); } };
|
||||
return s;
|
||||
}
|
||||
|
||||
// Produktiv-Verkabelung wie in startRobot.js
|
||||
function buildRobot(speedMode) {
|
||||
const robot = new Robot(250, 264, 100);
|
||||
robot.speedMode = speedMode;
|
||||
robot.useSpeedCalc = (speedMode === 'correct');
|
||||
robot.moveRelative = false; // M1 absolut
|
||||
|
||||
const base = makeSender('test.test', 2300, 'x', 'y', 'z');
|
||||
const elbow = makeSender('test.test', 5000, 'a', null, null);
|
||||
const hand = makeSender('test.test', 5000, 'c', 'e', 'b');
|
||||
robot.cmdReceivers.push(base, elbow, hand);
|
||||
|
||||
return { robot, base, elbow, hand };
|
||||
}
|
||||
|
||||
// drei absolute Motor-Stellungen; Schritt 0 = Warmup (erster Aufruf → Fallback)
|
||||
function runMoves(robot) {
|
||||
GCode.receiveGCode(robot, 'M1 X5 Y0.10 Z0.20 A0.30 B0.40 C0.50'); // 0 warmup
|
||||
GCode.receiveGCode(robot, 'M1 X10 Y0.20 Z0.30 A0.40 B0.50 C0.60'); // 1 baseline
|
||||
GCode.receiveGCode(robot, 'M1 X22 Y0.45 Z0.50 A0.65 B0.85 C0.90'); // 2 gemessen
|
||||
}
|
||||
|
||||
describe('Speed-Koordination (ToDo_6a)', () => {
|
||||
beforeAll(() => { jest.spyOn(console, 'log').mockImplementation(() => {}); });
|
||||
afterAll(() => { jest.restoreAllMocks(); });
|
||||
|
||||
test('correct: alle Sender beenden den Schritt in gleicher Zeit (= moveTime)', () => {
|
||||
const { robot, base, elbow, hand } = buildRobot('correct');
|
||||
runMoves(robot);
|
||||
|
||||
const moveTime = robot.motorPosition.moveTime;
|
||||
expect(moveTime).toBeGreaterThan(0);
|
||||
|
||||
for (const s of [base, elbow, hand]) {
|
||||
const v1 = parseLine(s.writes[1]); // baseline
|
||||
const v2 = parseLine(s.writes[2]); // gemessen
|
||||
const axes = Object.keys(v2).filter(k => k !== 'f');
|
||||
|
||||
let sumSq = 0;
|
||||
for (const ax of axes) sumSq += (v2[ax] - v1[ax]) ** 2;
|
||||
const dist = Math.sqrt(sumSq);
|
||||
|
||||
const time = dist / v2.f; // unabhängig aus Output berechnet
|
||||
// jeder Controller braucht dieselbe Zeit (Rundung auf 2 Dezimalen → 2% Toleranz)
|
||||
expect(Math.abs(time - moveTime) / moveTime).toBeLessThan(0.02);
|
||||
}
|
||||
});
|
||||
|
||||
test('correct: die Sender bekommen UNTERSCHIEDLICHE Feedrates', () => {
|
||||
const { robot, base, elbow, hand } = buildRobot('correct');
|
||||
runMoves(robot);
|
||||
|
||||
const fBase = parseLine(base.writes[2]).f;
|
||||
const fElbow = parseLine(elbow.writes[2]).f;
|
||||
const fHand = parseLine(hand.writes[2]).f;
|
||||
|
||||
// Genau das ist der Unterschied zu legacy: nicht alle gleich.
|
||||
expect(fBase).not.toBeCloseTo(fElbow, 2);
|
||||
expect(fBase).not.toBeCloseTo(fHand, 2);
|
||||
});
|
||||
|
||||
test('legacy (Kontrast): alle Sender bekommen dieselbe kartesische Feedrate', () => {
|
||||
const { robot, base, elbow, hand } = buildRobot('legacy');
|
||||
runMoves(robot);
|
||||
|
||||
// robot.feedrate ist 1000 (kein F in M1) → alle Sender f1000.00
|
||||
expect(parseLine(base.writes[2]).f).toBeCloseTo(1000, 2);
|
||||
expect(parseLine(elbow.writes[2]).f).toBeCloseTo(1000, 2);
|
||||
expect(parseLine(hand.writes[2]).f).toBeCloseTo(1000, 2);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user