31.1 Calcular y auditar son partes del mismo algoritmo
Una fórmula puede producir números aunque los datos no describan un choque, la normal sea inválida o exista un error de signos. Por eso conviene diseñar juntas la solución física y sus comprobaciones.
31.2 Contrato de entrada y salida
Definir este contrato evita que la función dependa del dibujo, de controles HTML o de variables globales.
31.3 Conservar una fotografía del estado anterior
Las auditorías requieren comparar antes y después. Copiamos las velocidades antes de cualquier actualización:
const cuerpoA = { id: "A", velocidad: { x: 5, y: 1 } };
const cuerpoB = { id: "B", velocidad: { x: -2, y: 0 } };
const vAi = { ...cuerpoA.velocidad };
const vBi = { ...cuerpoB.velocidad };
console.log("Fotografía inicial de A:", vAi);
console.log("Fotografía inicial de B:", vBi);
cuerpoA.velocidad.x = 0;
console.log("Velocidad actual de A:", cuerpoA.velocidad);
console.log("La fotografía de A se conserva:", vAi);Asignar const vAi = cuerpoA.velocidad solo crea otra referencia; si el vector cambia, se pierde el estado anterior.
31.4 Preparar la normal
La respuesta usa una normal unitaria n̂ orientada de A hacia B:
Si |n⃗| es cero o demasiado pequeño, no existe una dirección fiable y el cálculo debe detenerse con un error descriptivo.
31.5 Comprobar la aproximación
La velocidad relativa normal inicial es:
Con nuestra orientación, solo se resuelve un choque si gn,i < 0. Si gn,i ≥ 0, se devuelven las velocidades sin cambios y un estado "separando".
31.6 Calcular el impulso normal
Para masas traslacionales y superficies lisas:
El impulso sobre A es −j n̂ y sobre B es +j n̂.
31.7 Obtener las velocidades posteriores
Calcular ambos vectores desde las mismas velocidades iniciales elimina dependencias accidentales del orden de escritura.
31.8 Devolver resultados sin mutar entradas
Una función pura devuelve cuerpos actualizados como objetos nuevos:
const cuerpoA = {
id: "A", masa: 2, velocidad: { x: 5, y: 0 }
};
const cuerpoB = {
id: "B", masa: 3, velocidad: { x: 0, y: 0 }
};
const vAf = { x: 0.95, y: -2.338 };
const vBf = { x: 2.7, y: 1.559 };
const cuerpoAf = {
...cuerpoA,
velocidad: { ...vAf }
};
const cuerpoBf = {
...cuerpoB,
velocidad: { ...vBf }
};
console.log("Resultado A:", cuerpoAf);
console.log("Resultado B:", cuerpoBf);
console.log("Entrada A sin cambios:", cuerpoA);
console.log("Entrada B sin cambios:", cuerpoB);
console.log("¿Son objetos nuevos?", cuerpoAf !== cuerpoA && cuerpoBf !== cuerpoB);La simulación decide luego cuándo reemplazar el estado actual. Esto simplifica pruebas y permite comparar fácilmente ambos estados.
31.9 Residuo de cantidad de movimiento
Calculamos el momento total antes y después:
En dos dimensiones:
El residuo conserva más información que comparar solo los módulos de P⃗.
31.10 Residuo de restitución
Después del choque calculamos gn,f con las velocidades obtenidas. El residuo es:
Un valor próximo a cero confirma que la rapidez relativa normal final coincide con la exigida por e.
31.11 Comprobar la componente tangencial
Para superficies lisas, t̂ = (−ny, nx) y:
Este control detecta impulsos tangenciales introducidos por un error de implementación.
31.12 Comprobar la energía cinética
Calculamos ΔK = Kf − Ki. Para un choque pasivo con 0 ≤ e ≤ 1 debe cumplirse ΔK ≤ 0 dentro de la tolerancia.
La igualdad permite auditar no solo el signo, sino también el valor de la variación energética del modelo.
31.13 Escala y tolerancia
Un residuo absoluto de 10−8 puede ser excelente para momentos del orden de 1000 y grande para datos del orden de 10−10. Una comparación práctica combina tolerancias:
El próximo tema profundizará en la elección de estas tolerancias y los casos límite.
31.14 Construir un informe de diagnóstico
// Valores obtenidos para el choque oblicuo de la sección 31.15.
const tolerancia = 1e-9;
const residuoMomento = 0;
const residuoRestitucion = 1.78e-15;
const residuoTangencial = 4.44e-16;
const ki = 25;
const kf = 20.95;
const momentoOk = residuoMomento <= tolerancia;
const restitucionOk = residuoRestitucion <= tolerancia;
const tangencialOk = residuoTangencial <= tolerancia;
const energiaOk = kf <= ki + tolerancia;
const diagnostico = {
estado: "resuelto",
momento: { residuo: residuoMomento, cumple: momentoOk },
restitucion: { residuo: residuoRestitucion, cumple: restitucionOk },
tangencial: { residuo: residuoTangencial, cumple: tangencialOk },
energia: { inicial: ki, final: kf, cambio: kf - ki, cumple: energiaOk }
};
console.log(JSON.stringify(diagnostico, null, 2));Guardar valores y decisiones permite investigar un fallo sin repetir el cálculo manualmente.
31.15 Ejemplo numérico
mA = 2 kg, mB = 3 kg, v⃗Ai = (5, 0) m/s, v⃗Bi = (0, 0), n̂ = (cos 30°, sen 30°) y e = 0,8.
El momento final es (10, 0) kg·m/s, gn,f ≈ 3,464 m/s y ΔK = −4,05 J.
31.16 Resultados que no representan un choque nuevo
Si los cuerpos ya se separan, devolver velocidades iguales a las entradas no es un fallo. Es una respuesta válida con estado distinto:
function copiarCuerpo(cuerpo) {
return { ...cuerpo, velocidad: { ...cuerpo.velocidad } };
}
function evaluarImpacto(cuerpoA, cuerpoB, normal, tolerancia = 1e-9) {
const gnInicial =
(cuerpoB.velocidad.x - cuerpoA.velocidad.x) * normal.x +
(cuerpoB.velocidad.y - cuerpoA.velocidad.y) * normal.y;
if (gnInicial >= -tolerancia) {
return {
estado: "sin-impacto",
razon: "Los cuerpos no se aproximan",
impulso: 0,
cuerpoA: copiarCuerpo(cuerpoA),
cuerpoB: copiarCuerpo(cuerpoB)
};
}
return { estado: "requiere-resolucion", gnInicial };
}
const cuerpoA = { id: "A", velocidad: { x: -2, y: 0 } };
const cuerpoB = { id: "B", velocidad: { x: 2, y: 0 } };
const resultado = evaluarImpacto(cuerpoA, cuerpoB, { x: 1, y: 0 });
console.log(JSON.stringify(resultado, null, 2));31.17 Flujo recomendado
La interfaz puede presentar este informe, guardarlo o convertir un incumplimiento en una aserción durante las pruebas.
31.18 Actividad interactiva: solucionador con auditoría
Modificá los datos del choque. El laboratorio calcula las velocidades finales y evalúa momento, restitución, componente tangencial y energía.
Solucionador y auditor físico
n̂ apunta de A hacia B; los ángulos se miden desde +x.
Choque resuelto: todas las comprobaciones satisfacen la tolerancia.
31.19 Implementación completa
La siguiente función reúne resolución y residuos principales:
function resolverYComprobar(a, b, normal, e, tolerancia = 1e-9) {
if (a.masa <= 0 || b.masa <= 0 || e < 0) {
throw new Error("Datos fuera de rango");
}
const longitud = Math.hypot(normal.x, normal.y);
if (longitud <= tolerancia) throw new Error("Normal no válida");
const n = { x: normal.x / longitud, y: normal.y / longitud };
const dot = (u, v) => u.x * v.x + u.y * v.y;
const gn = dot({ x: b.velocidad.x - a.velocidad.x,
y: b.velocidad.y - a.velocidad.y }, n);
if (gn >= -tolerancia) {
return { estado: "sin-impacto", impulso: 0 };
}
const j = -(1 + e) * gn / (1 / a.masa + 1 / b.masa);
const vAf = { x: a.velocidad.x - j * n.x / a.masa,
y: a.velocidad.y - j * n.y / a.masa };
const vBf = { x: b.velocidad.x + j * n.x / b.masa,
y: b.velocidad.y + j * n.y / b.masa };
const gnFinal = dot({ x: vBf.x - vAf.x, y: vBf.y - vAf.y }, n);
const momentoAntes = {
x: a.masa * a.velocidad.x + b.masa * b.velocidad.x,
y: a.masa * a.velocidad.y + b.masa * b.velocidad.y
};
const momentoDespues = {
x: a.masa * vAf.x + b.masa * vBf.x,
y: a.masa * vAf.y + b.masa * vBf.y
};
return {
estado: "resuelto", impulso: j, vAf, vBf,
residuos: {
momento: Math.hypot(momentoDespues.x - momentoAntes.x,
momentoDespues.y - momentoAntes.y),
restitucion: Math.abs(gnFinal + e * gn)
}
};
}
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 resultado = resolverYComprobar(cuerpoA, cuerpoB, normal, 0.8);
console.log(JSON.stringify(resultado, null, 2));31.20 Pruebas automatizadas útiles
| Caso | Resultado esperado |
|---|---|
| Masas iguales, e = 1, choque frontal | Intercambio de componentes normales. |
| e = 0 | Velocidad relativa normal final nula. |
| Contacto oblicuo liso | Componentes tangenciales sin cambio. |
| Cuerpos separándose | Impulso cero y estado sin-impacto. |
| Normal escalada | Mismo resultado después de normalizar. |
| Masa inválida | Error explícito antes de calcular. |
31.21 Errores frecuentes y ejercicios
Errores frecuentes
- Modificar las entradas antes de guardar las velocidades iniciales.
- Calcular v⃗Bf usando v⃗Af en lugar de v⃗Ai.
- Comparar solo los módulos del momento.
- Aplicar restitución a la rapidez total y no a la componente relativa normal.
- Declarar que un resultado cumple sin informar tolerancia ni residuo.
- Convertir “sin impacto” en una excepción aunque sea un estado físico normal.
Ejercicios propuestos
- Calculá j para mA = 1 kg, mB = 2 kg, gn,i = −6 m/s y e = 0,5.
- Con n̂ = (1, 0), v⃗Ai = (6, 2) y v⃗Bi = (0, −1), obtené las velocidades finales del ejercicio anterior.
- Comprobá por componentes el momento del ejercicio 2.
- Calculá gn,f y el residuo de restitución.
- Verificá que las componentes tangenciales no cambiaron.
- Diseñá una prueba para confirmar que las entradas no fueron mutadas.
- Usá el laboratorio con A moviéndose en sentido opuesto a n̂ y explicá el estado informado.
Ver soluciones y orientaciones
- j = −1,5(−6)/(1 + 1/2) = 6 N·s.
- v⃗Af = (0, 2) m/s y v⃗Bf = (3, −1) m/s.
- P⃗i = (6, 0) kg·m/s y P⃗f = 1(0, 2) + 2(3, −1) = (6, 0) kg·m/s.
- gn,f = 3 m/s y re = |3 + 0,5(−6)| = 0.
- Para A permanece +2 m/s; para B permanece −1 m/s.
- Guardá copias profundas, ejecutá la función y compará cada propiedad de entrada con la copia.
- Si gn,i ≥ 0, el laboratorio informa que no existe un impacto nuevo y devuelve las velocidades originales.
31.22 Ideas para recordar
- Validar, calcular y auditar forman un único flujo.
- Las velocidades finales deben calcularse desde el mismo estado inicial.
- Una normal casi nula invalida el cálculo.
- Los cuerpos que se separan no reciben un nuevo impulso.
- Los residuos cuantifican cuánto se aparta el resultado de cada ecuación.
- Momento, restitución, tangencial y energía comprueban aspectos diferentes.
- Una función pura simplifica las pruebas y conserva los datos de entrada.
- El informe de diagnóstico debe incluir valores, tolerancias y decisiones.
En el próximo tema profundizaremos en tolerancias numéricas, conservación y casos límite.