El catalogo actual (sim-catalog.ts) tiene los valores del A320 CFM56-5B hardcoded. Pero los instrumentos son reutilizables — un velocimetro funciona igual en un A320 que en un B737 o un C172, solo cambian los rangos, limites y umbrales. Necesitamos separar que se mide (sensores universales) de con que limites (perfil del avion).
Ademas, el velocimetro actual conecta las 3 agujas (speed, vmo, bug) al mismo sensor IAS. En la realidad, cada una tiene una fuente distinta: IAS viene del ADC, VMO es un limite operacional que varia con altitud, y el bug es el valor seleccionado por el piloto en el FCU.
| ID | Label | Unit | Min | Max | Cruise | Estado |
|---|---|---|---|---|---|---|
IAS | Indicated Airspeed | kt | 0 | 400 | 250 | EXISTE |
Mach | Mach Number | — | 0 | 1 | 0.78 | EXISTE |
ALT | Barometric Altitude | ft | 0 | 45000 | 35000 | EXISTE |
VS | Vertical Speed | ft/m | -6000 | 6000 | 0 | EXISTE |
QNH | QNH Setting | hPa | 950 | 1060 | 1013 | EXISTE |
SelSpd | Selected Speed (FCU) | kt | 0 | 400 | 250 | EXISTE (en fdr_auto) |
| ID | Label | Unit | Min | Max | Cruise A320 | Notas |
|---|---|---|---|---|---|---|
TAS | True Airspeed | kt | 0 | 600 | 480 | NUEVO Derivado de IAS + ALT + SAT. Esencial para ND y conversiones. |
SAT | Static Air Temp | °C | -80 | 50 | -56 | NUEVO ISA a FL350 = -56.5°C. Necesario para Mach↔IAS. |
TAT | Total Air Temp | °C | -80 | 60 | -28 | NUEVO SAT + calentamiento por ram. TAT = SAT × (1 + 0.2·M²). |
VMO | Max Operating Speed | kt | 0 | 400 | 350 | NUEVO A320: VMO=350kt, MMO=0.82. Varia con altitud (cross-over). |
VFE | Max Flap Extended | kt | 0 | 300 | 0 | FUTURO Depende de configuracion de flaps. Arco ambar en PFD. |
VS1G | Stall Speed 1G | kt | 0 | 250 | 0 | FUTURO Franja roja inferior. Depende de peso y config. |
GSpd | Ground Speed | kt | 0 | 600 | 480 | EXISTE (en nd_route) |
Los sensores VMO, TAS, SAT, TAT son los prioritarios. VMO porque alimenta directamente la aguja vmo del velocimetro. TAS y SAT porque son la base para las conversiones de unidades y para el calculo de Mach. TAT porque es lo que muestra el piloto en la pantalla.
Un AircraftProfile es un objeto que contiene todos los valores que varian entre modelos de avion. El catalogo de sensores sigue siendo universal (IAS es IAS en cualquier avion), pero el perfil define los rangos operativos, umbrales, y limites para un modelo concreto.
interface AircraftProfile {
id: string; // 'a320', 'b737ng', 'c172', 'a350'
name: string; // 'Airbus A320-214'
family: string; // 'A320' | 'B737' | 'Cessna' | 'A350'
engines: string; // 'CFM56-5B' | 'CFM LEAP-1A' | 'Lycoming IO-360'
category: 'transport' | 'ga' | 'military';
// ── Limites de velocidad ──
vmo: number; // kt — Max Operating Speed
mmo: number; // Mach — Max Operating Mach
crossoverAlt: number; // ft — altitud donde VMO=MMO (A320: ~FL310)
vfe: Record<string, number>; // flap config → max speed: { 'CONF1': 230, 'CONF2': 215, ... }
vle: number; // kt — max speed landing gear extended
// ── Rangos de instrumentos ──
iasRange: [number, number]; // [0, 400] A320, [0, 300] C172
altRange: [number, number]; // [0, 45000] A320, [0, 14000] C172
vsRange: [number, number]; // [-6000, 6000] A320, [-2000, 2000] C172
// ── Umbrales ECAM/PFD ──
thresholds: Record<string, SensorThresholds>;
// 'IAS': { c: [340,350], w: [350,400], cLow: [180,210], wLow: [0,180] } // A320
// 'IAS': { w: [163,200], wLow: [0,40] } // C172
// ── Motores ──
n1Range: [number, number]; // [0, 110] jet, [0, 2800] piston (RPM)
egtRange: [number, number]; // [0, 1000] jet, [0, 900] piston (°C)
// ── Otros ──
mtow: number; // kg — para calculo de VS1G
weights: { oew: number; mzfw: number; mtow: number; mlw: number };
}
Hay dos niveles de datos:
Define que sensores existen y sus propiedades base. No cambia entre aviones. IAS siempre es velocidad indicada en knots, ALT siempre es altitud en feet.
Fichero: sim-catalog.ts
Define los limites operacionales de un modelo concreto. VMO, rangos de instrumentos, umbrales de alerta, configs de flaps. Overridea los defaults del catalogo.
Fichero nuevo: aircraft-profiles.ts
El flujo es: al seleccionar un modelo de avion, el perfil sobreescribe los min/max/th del catalogo para los sensores que define. Los sensores que el perfil no menciona mantienen los defaults del catalogo. Esto permite que un C172 redefina IAS.max = 200 sin tocar los sensores de hidraulica que no tiene.
| Unidad | ID | Uso | Conversion desde kt |
|---|---|---|---|
| Knots | kt | Unidad base internacional | × 1 |
| km/h | kmh | Rusia, China, algunos GA | × 1.852 |
| mph | mph | Aviacion GA en USA (raro) | × 1.15078 |
| m/s | ms | Meteorologia, planeadores | × 0.51444 |
| Mach | mach | Crucero jets. Depende de SAT | IAS / (a₀ × √(T/T₀)) — no lineal |
| ft/min | fpm | Velocidad vertical (VS) | N/A (unidad propia) |
Las conversiones simples (kt↔km/h↔mph) son multiplicaciones lineales y pueden vivir en cualquier capa. Pero la conversion IAS↔Mach↔TAS depende de altitud y temperatura — es un calculo aerodinamico que necesita multiples sensores.
Propuesta: crear un modulo units.ts en src/simulation/ con funciones puras de conversion. IB_04 no convierte — el clip recibe rawValue en la unidad base del sensor (kt para IAS) y tiene todo lo que necesita. Si el clip quiere mostrar km/h, llama a la funcion de conversion en su change1:
// En units.ts (nuevo)
export const ktToKmh = (kt: number) => kt * 1.852;
export const ktToMph = (kt: number) => kt * 1.15078;
export const ktToMs = (kt: number) => kt * 0.51444;
// Conversion IAS → Mach (simplificada, valida hasta FL350)
// Necesita SAT (Static Air Temperature en °C)
export function iasMach(ias: number, sat: number): number {
const T = sat + 273.15; // Kelvin
const a = 340.3 * Math.sqrt(T / 288.15); // velocidad del sonido local
return ias / a; // aproximacion subsonica
}
// Conversion IAS → TAS
// Necesita altitud presion (ft) y SAT (°C)
export function iasTas(ias: number, altFt: number, sat: number): number {
const rho0 = 1.225; // densidad nivel del mar kg/m³
const T = sat + 273.15;
const T0 = 288.15;
const lapseRate = 0.0065; // °C/m en troposfera
const altM = altFt * 0.3048;
const rho = rho0 * Math.pow(1 - lapseRate * altM / T0, 4.256);
return ias * Math.sqrt(rho0 / rho);
}
Un clip futuro con display multi-unidad podria hacer:
// frame_0 del contenedor
// import no funciona en clips Animate, pero units.ts expone en window
var units = window.LRU_UNITS || {};
// En la aguja speed
this.change1 = function(pct, rawKt) {
_this.rotation = angMin + pct * rango;
// Display en la unidad seleccionada por el usuario
var displayUnit = window.LRU_SPEED_UNIT || 'kt';
var val = displayUnit === 'kmh' ? units.ktToKmh(rawKt)
: displayUnit === 'mph' ? units.ktToMph(rawKt)
: rawKt;
if (_this.parent && _this.parent.txtSpeed) {
_this.parent.txtSpeed.text = Math.round(val) + '';
}
};
Con sensores reales diferenciados por aguja:
// frame_0 del contenedor AirSpeed2Det
var _this = this;
_this.ib04 = {
swObj: "AirSpeed1",
needles: {
speed: { sensorId: "IAS" }, // velocidad indicada — ADC
vmo: { sensorId: "VMO" }, // limite operacional — perfil avion
bug: { sensorId: "SelSpd" }, // bug velocidad — FCU piloto
},
meta: {
type: "gauge",
label: "Airspeed Indicator",
ata: "34",
unit: "kt",
arcRange: [15, 345],
}
};
Cada aguja apunta a su verdadero sensor. Cuando el perfil del avion cambie de A320 a B737, el sensor VMO automaticamente tendra un valor diferente (350→340kt), y la aguja vmo se movera al nuevo limite sin tocar el clip.
| # | Item | Esfuerzo |
|---|---|---|
| 1 | Anadir VMO, TAS, SAT, TAT al sistema airdata en sim-catalog.ts | ~20 lineas |
| 2 | SimService: calcular VMO segun altitud (crossover VMO/MMO) | ~15 lineas |
| 3 | SimService: calcular TAS y TAT derivados de IAS+ALT+SAT | ~20 lineas |
| 4 | Migrar clip airSpeed_01 en Adobe Animate a manifiesto .ib04 | Manual en Animate |
| 5 | Crear units.ts con conversiones basicas | ~40 lineas |
| 6 | Actualizar sim-bridges.ts: AirSpeed1 con sensorIds reales | ~5 lineas |
| # | Item | Esfuerzo |
|---|---|---|
| 7 | Crear aircraft-profiles.ts con tipo AircraftProfile | ~100 lineas |
| 8 | Perfil A320-214 (extraer valores hardcoded del catalogo) | ~60 lineas |
| 9 | Mecanismo de override: perfil sobreescribe th/min/max del catalogo | ~40 lineas |
| 10 | UI selector de modelo de avion (Sim1Header o Settings) | Componente React |
| 11 | Segundo perfil (B737-800 o C172) para validar el modelo | ~60 lineas |
| # | Item | Esfuerzo |
|---|---|---|
| 12 | Preferencia de unidad de velocidad en settings (kt/kmh/mph) | Zustand store |
| 13 | Exponer window.LRU_UNITS y window.LRU_SPEED_UNIT | ~10 lineas en init |
| 14 | Clips con display numerico multi-unidad | En cada clip migrado |
D1. VMO: sensor fisico o calculado? En un avion real, VMO no viene de un sensor — es un valor computado por el FMC segun altitud. Propuesta: SimService lo calcula cada tick y lo escribe al DataPlane como un sensor mas. El clip no sabe ni le importa si viene de un ADC o de un calculo.
D2. Perfil de avion: donde se selecciona? Opciones: (a) en Sim1Header junto al selector de escenario, (b) en Settings global (aplica a toda la sesion), (c) en EscenariosContext (cada escenario puede definir su modelo). La opcion (c) es la mas flexible — un escenario de "takeoff A320" define su modelo, y otro de "VFR C172" define el suyo.
D3. Conversiones IAS↔Mach: precision vs simplicidad? La formula exacta usa la ecuacion de Saint-Venant y requiere calibracion. Para entrenamiento una aproximacion subsonica es suficiente y mucho mas simple. Si en el futuro se necesita precision (SimBridge con MSFS), se puede mejorar sin cambiar la interfaz.