Files
appRobotDriver/robot/KinematicsFactory.js
2026-06-11 07:57:51 +02:00

85 lines
3.5 KiB
JavaScript

// robot/KinematicsFactory.js — Phase 2 der Roadmap 12.
//
// Wählt anhand der Umgebungsvariable ROBOT_KINEMATICS eine Kinematik-Klasse aus
// `robot/kinematics/` und instantiiert sie mit den Parametern aus
// ROBOT_KINEMATICS_PARAMS (JSON). Eine unbekannte Kinematik führt zu einem
// klaren Fehler beim Start — kein silent fail.
//
// Liest process.env vorerst direkt (gleicher Stil wie ROBOT_DEFAULT_FEEDRATE in
// RobotBase). Ein späteres zentrales Config-Modul (ToDo_3_Config) kann diese
// Variablen übernehmen.
/** Default-Bezeichner der Kinematik, wenn ROBOT_KINEMATICS nicht gesetzt ist. */
const DEFAULT_KINEMATICS = 'arm3segmentlinearx';
// Registry: Bezeichner (lowercase) → Modulpfad relativ zu dieser Datei.
// Neue Kinematiken hier eintragen (siehe Phase 3). Mehrere Bezeichner dürfen auf
// dasselbe Modul zeigen (Alias, z. B. Produktname).
const KINEMATICS_REGISTRY = {
arm3segmentlinearx: './kinematics/Arm3SegmentLinearX',
arm3segmentrotarybase: './kinematics/Arm3SegmentRotaryBase',
grabit: './kinematics/Arm3SegmentRotaryBase', // Alias: Joy-IT „Grab-It" (Robot02)
robot02: './kinematics/Arm3SegmentRotaryBase', // Alias: Joy-IT-Modellbezeichnung
};
/**
* Lädt die Kinematik-Klasse zu einem Bezeichner.
* @param {string} [identifier] z. B. 'arm3segmentlinearx' (case-insensitive)
* @returns {Function} die Konstruktor-Klasse
* @throws {Error} bei unbekanntem Bezeichner
*/
function loadKinematicsClass(identifier = DEFAULT_KINEMATICS) {
const key = String(identifier).toLowerCase();
const modulePath = KINEMATICS_REGISTRY[key];
if (!modulePath) {
const known = Object.keys(KINEMATICS_REGISTRY).join(', ');
throw new Error(
`Unbekannte Kinematik "${identifier}" (ROBOT_KINEMATICS). Verfügbar: ${known}.`
);
}
return require(modulePath);
}
/**
* Parst ROBOT_KINEMATICS_PARAMS (JSON) zu einem Parameter-Objekt.
* @param {string} [raw] JSON-String, z. B. '{"l1":250,"l2":264,"l3":100}'
* @returns {Object} geparste Parameter (leeres Objekt, wenn nicht gesetzt)
* @throws {Error} bei ungültigem JSON
*/
function parseParams(raw) {
if (!raw) return {};
try {
return JSON.parse(raw);
} catch (err) {
throw new Error(`ROBOT_KINEMATICS_PARAMS ist kein gültiges JSON: ${err.message}`);
}
}
/**
* Erzeugt eine Roboter-Instanz anhand der Umgebungsvariablen.
*
* @param {Object} [env] Umgebungs-Objekt (Default: process.env)
* @param {Object} [defaultParams] Fallback-Parameter für die Default-Kinematik
* (z. B. die Armlängen der produktiven Standard-Hardware). Werte aus
* ROBOT_KINEMATICS_PARAMS überschreiben diese.
* @returns {import('./RobotBase')} die instantiierte Kinematik
*/
function createRobotFromEnv(env = process.env, defaultParams = {}) {
const identifier = env.ROBOT_KINEMATICS || DEFAULT_KINEMATICS;
const params = { ...defaultParams, ...parseParams(env.ROBOT_KINEMATICS_PARAMS) };
const KinematicsClass = loadKinematicsClass(identifier);
// l1/l2/l3 positional (Kompatibilität mit Arm3SegmentLinearX); das vollständige
// params-Objekt als 4. Argument für Kinematiken mit weiteren Parametern
// (z. B. baseHeight bei Arm3SegmentRotaryBase). Klassen, die es nicht brauchen,
// ignorieren das Argument.
return new KinematicsClass(params.l1, params.l2, params.l3, params);
}
module.exports = {
createRobotFromEnv,
loadKinematicsClass,
parseParams,
DEFAULT_KINEMATICS,
KINEMATICS_REGISTRY,
};