33. Proyecto integrador: laboratorio de colisiones en una y dos dimensiones

El proyecto reúne modelo de datos, conservación del momento, restitución, impulso normal, energía, tolerancias y visualización en una herramienta que calcula, explica y verifica cada ensayo.

33.1 Objetivo del proyecto

Construiremos un laboratorio que permita configurar dos cuerpos, resolver un choque frontal u oblicuo y presentar evidencias de que el resultado satisface las hipótesis elegidas.

El producto final no es solo una calculadora: conserva las entradas, distingue ausencia de impacto, muestra magnitudes derivadas y registra ensayos reproducibles.

33.2 Requisitos funcionales

ConfigurarMasas, velocidades, dirección normal, restitución y modo dimensional.
ResolverImpulso y velocidades finales sin modificar las entradas.
ComprobarMomento, restitución, tangencial y energía.
VisualizarVectores antes y después y barras energéticas.
RegistrarGuardar ensayos dentro de la sesión.
ComunicarGenerar un informe estructurado en JSON.

33.3 Arquitectura en cuatro capas

Configuración y validación
Motor físico
Auditoría
Interfaz y registro

Cada capa recibe datos y devuelve resultados. El lienzo nunca decide las velocidades; solo representa la salida del motor.

33.4 Modelo de cuerpo y vector

const cuerpoA = {
  id: "A",
  masa: 2,
  velocidad: { x: 5, y: 0 }
};

const cuerpoB = {
  id: "B",
  masa: 3,
  velocidad: { x: 0, y: 0 }
};

function momentoLineal(cuerpo) {
  return {
    x: cuerpo.masa * cuerpo.velocidad.x,
    y: cuerpo.masa * cuerpo.velocidad.y
  };
}

console.log("Cuerpo A:", cuerpoA);
console.log("Momento de A:", momentoLineal(cuerpoA), "kg·m/s");
console.log("Cuerpo B:", cuerpoB);
console.log("Momento de B:", momentoLineal(cuerpoB), "kg·m/s");

El laboratorio trabaja en unidades SI y usa vectores cartesianos internamente, aunque la interfaz reciba rapidez y ángulo.

33.5 Dos modos con un solo motor

En modo 1D fijamos todas las direcciones sobre x y n̂ = (1, 0). En modo 2D permitimos direcciones arbitrarias y proyectamos sobre la normal.

modo 1D ⊂ modelo 2D con vy = 0 y n̂ = (1, 0)

Reutilizar el mismo motor reduce duplicación y permite aplicar las mismas auditorías.

33.6 Validación de entradas

  • las masas deben ser finitas y positivas;
  • las componentes de velocidad deben ser finitas;
  • la normal debe poder normalizarse;
  • para un choque pasivo, 0 ≤ e ≤ 1;
  • las unidades y la orientación de n̂ deben estar documentadas.

33.7 Detectar si corresponde resolver

gn,i = (v⃗Bi − v⃗Ai) · n̂

Con n̂ de A hacia B, existe aproximación cuando gn,i < −εv. Si no, el resultado debe indicar sin-impacto y conservar las velocidades.

33.8 Motor impulsivo

j = −(1 + e)gn,i/(1/mA + 1/mB)
v⃗Af = v⃗Ai − (j/mA)n̂    v⃗Bf = v⃗Bi + (j/mB)n̂

Estas ecuaciones cubren el choque frontal y el contacto oblicuo entre superficies lisas.

33.9 Informe de salida

// Informe autocontenido del ensayo oblicuo de la sección 33.14.
const resultado = {
  estado: "resuelto",
  entradas: {
    cuerpoA: { id: "A", masa: 2, velocidad: { x: 5, y: 0 } },
    cuerpoB: { id: "B", masa: 3, velocidad: { x: 0, y: 0 } },
    normal: { x: 0.866025, y: 0.5 },
    restitucion: 0.8
  },
  impulso: {
    escalar: 9.353074,
    sobreA: { x: -8.1, y: -4.676537 },
    sobreB: { x: 8.1, y: 4.676537 }
  },
  velocidadesFinales: {
    A: { x: 0.95, y: -2.338269 },
    B: { x: 2.7, y: 1.558846 }
  },
  energia: { inicial: 25, final: 20.95, cambio: -4.05 },
  auditoria: {
    momento: { residuo: 0, cumple: true },
    restitucion: { residuo: 0, cumple: true },
    tangencial: { residuo: 0, cumple: true },
    energia: { cambio: -4.05, cumple: true }
  }
};

console.log(JSON.stringify(resultado, null, 2));

33.10 Auditorías independientes

MomentorP = |P⃗f − P⃗i|
Restituciónre = |gn,f + egn,i|
TangencialVariación máxima de las proyecciones sobre t̂.
EnergíaComparación de ΔK con el valor previsto.
FinitudNinguna salida puede ser NaN o infinita.
EstadoNo aplicar impulso si los cuerpos se separan.

33.11 Escalas y tolerancias

El proyecto usa una tolerancia combinada para no depender de una única escala:

umbral = εabs + εrel·escala

El informe conserva tanto el residuo como el umbral. Una etiqueta “cumple” sin esos valores sería difícil de auditar.

33.12 Escenarios predefinidos

EscenarioQué permite comprobar
Elástico con masas igualesIntercambio de velocidades normales y conservación de K.
Perfectamente inelásticoVelocidad normal común y máxima reducción compatible.
OblicuoConservación de componentes tangenciales.
SeparándoseRechazo correcto de un impulso innecesario.

33.13 Ensayo unidimensional

Para mA = mB, vAi = +5 m/s, vBi = 0 y e = 1:

vAf = 0    vBf = +5 m/s

El momento y la energía cinética permanecen constantes. Este caso debe formar parte de las pruebas mínimas.

33.14 Ensayo bidimensional

Con mA = 2 kg, mB = 3 kg, v⃗Ai = (5, 0), B en reposo, θn = 30° y e = 0,8:

v⃗Af ≈ (0,95; −2,338) m/s    v⃗Bf ≈ (2,70; 1,559) m/s

El resultado conserva P⃗ = (10, 0) kg·m/s y reduce K en 4,05 J.

33.15 Flujo de uso experimental

  1. Elegir el modo y un escenario o configurar los controles.
  2. Confirmar la orientación de la normal y la aproximación.
  3. Leer las velocidades e impulso calculados.
  4. Examinar cada residuo y su tolerancia.
  5. Comparar las barras de energía.
  6. Guardar el ensayo y modificar una sola variable.
  7. Explicar físicamente el cambio observado.

33.16 Separar cálculo y presentación

El motor trabaja con números y objetos. La presentación convierte esos valores en texto localizado, colores, barras y flechas.

Nunca uses el texto ya formateado —por ejemplo “3,20 m/s”— como entrada de una nueva ecuación. Conservá el número 3.2 en el modelo.

33.17 Accesibilidad y comunicación

Los colores se acompañan con etiquetas, los controles tienen label, los resultados dinámicos usan regiones accesibles y el lienzo posee una descripción. El informe textual conserva la información aunque no se interprete el gráfico.

33.18 Actividad interactiva: laboratorio integrador

Elegí un modo o escenario, modificá los parámetros y guardá ensayos para compararlos.

Laboratorio final de colisiones

Modelo impulsivo de dos cuerpos con superficies lisas.

Tu navegador no admite el gráfico de vectores. Consulta las velocidades finales y el informe numérico que aparecen junto a esta visualización.
Inicial
25,00 J
Final
20,95 J
Velocidad final A(+0,95; −2,34) m/s
Velocidad final B(+2,70; +1,56) m/s
Impulso escalar9,35 N·s
Variación de energía−4,05 J
Momento: cumple
Restitución: cumple
Tangencial: cumple
Energía: cumple
#Modoev⃗Afv⃗BfΔK
Todavía no se guardaron ensayos.

Choque resuelto y verificado.

33.19 Núcleo reutilizable

function resolverChoque(a, b, normal, e, tolerancia = 1e-9) {
  const longitud = Math.hypot(normal.x, normal.y);
  if (a.masa <= 0 || b.masa <= 0 || longitud <= tolerancia) {
    throw new Error("Entrada inválida");
  }
  const n = { x: normal.x / longitud, y: normal.y / longitud };
  const gn = (b.velocidad.x - a.velocidad.x) * n.x
           + (b.velocidad.y - a.velocidad.y) * n.y;
  if (gn >= -tolerancia) return { estado: "sin-impacto", impulso: 0 };

  const j = -(1 + e) * gn / (1 / a.masa + 1 / b.masa);
  return {
    estado: "resuelto",
    impulso: j,
    vAf: { x: a.velocidad.x - j * n.x / a.masa,
           y: a.velocidad.y - j * n.y / a.masa },
    vBf: { x: b.velocidad.x + j * n.x / b.masa,
           y: b.velocidad.y + j * n.y / b.masa }
  };
}

const cuerpoA = { masa: 2, velocidad: { x: 5, y: 0 } };
const cuerpoB = { masa: 3, velocidad: { x: 0, y: 0 } };
const normal = { x: Math.cos(Math.PI / 6), y: Math.sin(Math.PI / 6) };

const choqueOblicuo = resolverChoque(cuerpoA, cuerpoB, normal, 0.8);
console.log("Choque oblicuo:");
console.log(JSON.stringify(choqueOblicuo, null, 2));

const separandoseA = { masa: 2, velocidad: { x: -2, y: 0 } };
const separandoseB = { masa: 3, velocidad: { x: 2, y: 0 } };
const sinImpacto = resolverChoque(separandoseA, separandoseB, { x: 1, y: 0 }, 0.8);
console.log("Caso separándose:");
console.log(JSON.stringify(sinImpacto, null, 2));

33.20 Plan de pruebas

NivelPruebas
VectoresSuma, escala, producto escalar, módulo y normalización.
MotorCasos analíticos para e = 0, e = 1 y masas iguales.
AuditoríaErrores introducidos deliberadamente deben ser detectados.
InterfazModo 1D desactiva ángulos; escenarios cargan valores coherentes.
Casos límiteSeparación, velocidad relativa cero y razones de masa grandes.

33.21 Desafíos de ampliación

  1. Agregar paredes con masa inversa cero.
  2. Permitir ingreso directo de componentes cartesianas.
  3. Animar la aproximación y separación sin mezclar dibujo y motor.
  4. Incorporar una secuencia de tres cuerpos.
  5. Exportar e importar ensayos como JSON.
  6. Agregar incertidumbres de medición y barras de error.
  7. Construir pruebas automatizadas para todos los escenarios.

33.22 Cierre del curso

  • El impulso conecta fuerzas breves con cambios de momento.
  • El momento total se conserva cuando el impulso externo es despreciable.
  • Las colisiones requieren condiciones adicionales como restitución o conservación de energía cinética.
  • En dos dimensiones, elegir ejes normal–tangencial simplifica el contacto.
  • Una simulación debe actualizar estados en orden temporal.
  • Las estructuras de datos y las funciones puras hacen visible el modelo.
  • Los residuos y tolerancias convierten una respuesta en un resultado verificable.

El laboratorio reúne estas ideas en un programa que puede crecer sin perder de vista las leyes físicas que representa.