Tierra y Alma
Nota técnica · El Laboratorio

Un laboratorio de urbanismo: simulando el tráfico de Puebla para encontrar lo que estorba

Resumen

Se describe el simulador de tráfico que corre de forma continua en tierrayalmapr.com/trafico. La red vial de Puebla se representa como un grafo dirigido de 67,216 nodos y 160,332 aristas obtenido de OpenStreetMap. Sobre él vive una flota de 900,000 vehículos, de la que circula entre el 1 % y el 20 % según la hora y el día de la semana; el resto está estacionado. Cada vehículo en movimiento es una partícula con una regla de velocidad segura: acelera hasta el límite de su calle y frena lo justo para no alcanzar al de enfrente ni rebasar una línea de alto en rojo. En cada esquina, el vehículo elige su siguiente calle con una probabilidad proporcional al cuadrado de su velocidad límite, modulada por zonas de atracción que cambian con la hora. Los semáforos se definen por calle y sentido, y se agrupan en cruces que se turnan el verde con tiempos que dependen de la prioridad. Al final se explica cómo se transmite el estado al navegador con un error menor a un metro. Las cuatro figuras son interactivas y usan las mismas reglas y constantes que el simulador.

1 La ciudad como grafo

Para la computadora, Puebla es un grafo dirigido \(G = (V, E)\). Los nodos \(V\) son los puntos donde la geometría de una calle cambia: esquinas, curvas, entronques. Las aristas \(E\) son los tramos de calle entre dos nodos, en un solo sentido. Una calle de doble sentido aporta dos aristas, \(u \to v\) y \(v \to u\); un bulevar con camellón se dibuja como dos calles paralelas de un solo sentido, una por cada arroyo.

ElementoCantidadAtributos
Nodos \(V\)67,216latitud, longitud
Aristas \(E\)160,332longitud \(\ell_e\) (m), velocidad límite \(v^{\max}_e\) (m/s), carriles \(n_e\), nombre, geometría
Vehículos900,000arista \(e_i\), posición \(x_i \in [0, \ell_{e_i}]\), velocidad \(v_i\), estacionado o circulando

El estado completo de un vehículo son tres números: en qué arista está, cuántos metros lleva recorridos sobre ella y a qué velocidad va. Su posición geográfica se obtiene interpolando sobre la geometría de la calle. Los tres números se guardan en arreglos tipados paralelos (Int32Array, Float64Array, Float32Array), uno por atributo, en lugar de un objeto por vehículo: memoria contigua que el motor de JavaScript recorre rápido, porque la simulación completa corre en un solo hilo de Node.js.

El tiempo avanza en pasos fijos de

(1)\[ \Delta t = 0.25\ \text{s}, \qquad t_{k+1} = t_k + \Delta t \]

y en cada paso se actualizan todos los vehículos que circulan. Los estacionados, que son la mayoría, no ocupan lugar en la calle ni cuestan cálculo hasta que vuelven a salir (sección 6).

2 Seguimiento vehicular

Cada vehículo mira hacia adelante y encuentra su obstáculo: la posición máxima a la que puede llegar sin problema. Si el vehículo es el primero de su calle y el semáforo al final está en rojo, el obstáculo es la línea de alto, en \(x = \ell_e\). Si tiene un vehículo enfrente, el obstáculo es la defensa trasera de ese vehículo menos una separación mínima. Si no hay nada, el obstáculo está en el infinito. La distancia libre hasta el obstáculo es el hueco:

(2)\[ g_i = O_i - x_i, \qquad O_i = \begin{cases} x_{i+1} - s_e & \text{si hay un vehículo } i{+}1 \text{ enfrente} \\[4pt] \ell_e & \text{si es el primero y el semáforo está en rojo} \\[4pt] \infty & \text{si no} \end{cases} \]\[ \begin{gathered} g_i = O_i - x_i \\[6pt] O_i = \begin{cases} x_{i+1} - s_e & \text{auto enfrente} \\ \ell_e & \text{primero, en rojo} \\ \infty & \text{si no} \end{cases} \end{gathered} \]

Con desaceleración máxima \(b\), la distancia que necesita un vehículo para detenerse es la de la cinemática elemental, más un metro de margen:

(3)\[ d_i = \frac{v_i^{2}}{2b} + 1\ \text{m} \]

La regla de velocidad compara ambas cantidades. Si el hueco es menor que la distancia de frenado, el vehículo baja a la velocidad segura \(\sqrt{2 b g_i}\), la máxima con la que todavía puede detenerse en \(g_i\) metros. Si no, acelera hacia el límite de la calle:

(4)\[ v_i' = \begin{cases} \min\!\left(v_i,\ \sqrt{2\,b\,\max(0, g_i)}\right) & g_i < d_i \\[6pt] \min\!\left(v^{\max}_e,\ v_i + a\,\Delta t\right) & g_i \ge d_i \end{cases} \qquad v_i' \leftarrow 0 \ \text{ si } g_i \le 0.3\ \text{m} \]\[ \begin{gathered} v_i' = \begin{cases} \min\!\big(v_i,\,\sqrt{2b\max(0,g_i)}\big) & g_i < d_i \\ \min\!\big(v^{\max}_e,\, v_i + a\Delta t\big) & g_i \ge d_i \end{cases} \\[6pt] v_i' \leftarrow 0 \ \text{ si } g_i \le 0.3\ \text{m} \end{gathered} \]
(5)\[ x_i' = x_i + v_i'\,\Delta t \]
ConstanteSímboloValor
Aceleración\(a\)2.0 m/s²
Desaceleración máxima\(b\)4.0 m/s²
Longitud del vehículo\(L\)4.5 m
Hueco mínimo\(s_0\)2.0 m
Paso de tiempo\(\Delta t\)0.25 s

Los vehículos de cada arista se mantienen ordenados por posición y se procesan del primero al último. Así, cuando un vehículo calcula su hueco, el de enfrente ya tiene su posición nueva: la información de un frenazo se propaga hacia atrás de la fila dentro del mismo paso. Como los vehículos casi nunca cambian de orden, el reordenamiento se hace con inserción, que es lineal en listas casi ordenadas.

Relación con modelos clásicos. La regla (4) pertenece a la familia de modelos de velocidad segura, cuyo representante más conocido es el de Gipps (1981). A diferencia de Gipps, aquí no se modela el tiempo de reacción del conductor ni la desaceleración estimada del vehículo de enfrente: el frenado es ideal. Es una simplificación deliberada; a esta escala importa más la capacidad de las calles que la fineza del comportamiento individual.

Carriles sin carriles

El simulador no representa carriles por separado: todos los vehículos de una arista forman una sola fila. Para que una avenida de varios carriles tenga más capacidad que una calle de colonia, la separación mínima se reparte entre los carriles reales de la calle:

(6)\[ s_e = \frac{L + s_0}{n_e} = \frac{6.5\ \text{m}}{n_e} \]

La densidad máxima de la fila es entonces \(n_e / 6.5\) vehículos por metro: una avenida de tres carriles aguanta tres veces más vehículos antes de formar cola. Es una aproximación de capacidad, no una simulación de carriles: no hay rebases ni cambios de carril. La Fig. 1 aplica exactamente las ecuaciones (2)–(6) a una calle con un semáforo.

Carriles \(n_e\)
Velocidad
fluido (≥ 60 % del límite) lento atorado (< 15 %)
—
Reloj
—
En cola
—
Cruzan / hora
—
Fracción en verde

Fig. 1 Una calle de 400 m a 50 km/h con un semáforo a 260 m, simulada con las ecuaciones (2)–(6) y las constantes de la tabla. Si las llegadas superan lo que el verde alcanza a despachar, la cola crece de un ciclo a otro hasta llegar al inicio de la calle. Más carriles reducen la separación (6) y despachan más vehículos por segundo de verde.

3 Paso de una calle a otra

Cuando un vehículo rebasa el final de su arista con el semáforo en verde, se registra como movimiento pendiente junto con los metros que le sobraron. Los movimientos se resuelven después de actualizar todas las aristas, en tres pasos.

// para cada vehículo i que llegó al final de su arista e
elegir la siguiente arista e'                     // sección 4
agrupar las llegadas por arista destino e'

// para cada arista destino, de la llegada más adelantada a la menos
x_deseada  = min(sobrante, ℓ_e' / 2)
x_permitida = (vehículo más cercano adelante en e') − s_e'
si x_permitida < 0:
    rechazar: i se queda en e, detenido en la línea de alto
si no:
    i pasa a e' en x = max(0, min(x_deseada, x_permitida))
    v_i ← v_i · φ(θ)                                // ec. (7)

// los rechazados se apilan detrás de la línea de alto con separación s_e

El rechazo es lo que en ingeniería de tránsito se llama bloqueo por saturación (spillback): con el semáforo en verde, un vehículo no entra a un cruce si la cuadra de enfrente no tiene espacio. Sin esta regla los vehículos se encimarían en los tramos cortos; con ella, las colas se propagan hacia atrás de una calle a otra, como en la ciudad real.

Al cambiar de calle, el vehículo pierde velocidad según el ángulo \(\theta\) entre la dirección con la que llega y la dirección con la que sale:

(7)\[ \varphi(\theta) = \begin{cases} 1 & \theta < 10^\circ \quad \text{sigue derecho} \\ 0.8 & 10^\circ \le \theta < 30^\circ \quad \text{se incorpora} \\ 0.5 & \theta \ge 30^\circ \quad \text{vuelta cerrada} \end{cases} \]\[ \varphi(\theta) = \begin{cases} 1 & \theta < 10^\circ \ \text{derecho} \\ 0.8 & 10^\circ \le \theta < 30^\circ \\ 0.5 & \theta \ge 30^\circ \ \text{vuelta} \end{cases} \]

4 Elección de ruta

Los vehículos no tienen origen ni destino: deciden esquina por esquina. Al llegar al nodo final de su arista, el vehículo elige una de las aristas de salida \(\mathcal{O}\), descartando la vuelta en U salvo que sea la única opción, con probabilidad

(8)\[ P(e) = \frac{w_e}{\displaystyle\sum_{j \in \mathcal{O}} w_j}, \qquad w_e = \left(v^{\max}_e\right)^{2} \cdot p_e \cdot z_e \]\[ \begin{gathered} P(e) = \frac{w_e}{\sum_{j \in \mathcal{O}} w_j} \\[6pt] w_e = \left(v^{\max}_e\right)^{2} p_e\, z_e \end{gathered} \]

El factor cuadrático hace que las avenidas atraigan mucho más que las calles locales: una salida a 60 km/h pesa cuatro veces lo que una a 30 km/h. Con un peso lineal, los vehículos se dispersarían por las calles de colonia, que son la mayoría de la red, y las avenidas se verían vacías. El mismo peso \((v^{\max}_e)^2\) se usa para decidir dónde aparece cada vehículo nuevo.

El factor \(p_e \in \{0,\ 0.25,\ 1,\ 2,\ 4\}\) es una prioridad que se ajusta a mano por calle desde el editor; \(p_e = 0\) cierra la calle a la circulación. El factor \(z_e\) modela la hora pico. La ciudad tiene zonas dibujadas a mano, comerciales o residenciales, cada una con un nivel \(\lambda \in \{1, \dots, 5\}\) de importancia. Según la hora de Puebla, una de las dos clases se vuelve destino:

(9)\[ z_e = \begin{cases} 5\,(6 - \lambda) & \text{si la arista entra a una zona destino de nivel } \lambda \\ 1 & \text{si no} \end{cases} \qquad \text{destino} = \begin{cases} \text{comercial} & 7{:}00\text{–}10{:}00 \\ \text{residencial} & 17{:}00\text{–}20{:}00 \\ \text{ninguno} & \text{resto del día} \end{cases} \]\[ \begin{gathered} z_e = \begin{cases} 5\,(6 - \lambda) & \text{entra a zona destino} \\ 1 & \text{si no} \end{cases} \\[10pt] \text{destino} = \begin{cases} \text{comercial} & 7\text{–}10\ \text{h} \\ \text{residencial} & 17\text{–}20\ \text{h} \\ \text{ninguno} & \text{resto del día} \end{cases} \end{gathered} \]

Una zona de nivel 1 multiplica el peso de sus calles por 25; una de nivel 5, por 5. Durante la hora pico, además, los vehículos nuevos aparecen en la clase de zona contraria al destino, para que tengan el viaje completo por delante. En fin de semana no hay ida y vuelta al trabajo: el horario de (9) se sustituye por una sola atracción a las zonas comerciales de 12:00 a 18:00, con un factor más suave (3 en lugar de 5).

Hora

Fig. 2 Una esquina con tres salidas. La probabilidad de cada una sale de la ecuación (8). En hora pico, la salida marcada como «entra a zona destino» recibe el factor \(z_e\) de la ecuación (9): una calle lenta de colonia puede ganarle a una avenida si lleva hacia donde va la gente a esa hora.

5 Semáforos

Un semáforo controla una arista: una calle, en un sentido. Los vehículos de esa arista se detienen al final de ella cuando está en rojo; el resto de la red no se entera. Los semáforos de una misma esquina se agrupan en un cruce y reciben un turno \(k \in \{1, \dots, K\}\). Los semáforos con el mismo turno están en verde al mismo tiempo, y dos turnos distintos nunca lo están.

Cada semáforo tiene una prioridad con multiplicador \(m \in \{0.6,\ 1,\ 1.5\}\) (baja, media, alta). El verde del turno \(k\) lo fija el semáforo más prioritario del turno:

(10)\[ G_k = G_0 \cdot \max_{s \,\in\, \text{turno } k} m_s, \qquad G_0 = 20\ \text{s} \]

Entre un turno y el siguiente hay un intervalo de despeje de \(C = 3\) s con todo en rojo. El ciclo completo y el inicio de cada turno son

(11)\[ T = \sum_{k=1}^{K} \left(G_k + C\right), \qquad S_k = \sum_{j=1}^{k-1} \left(G_j + C\right) \]\[ \begin{gathered} T = \sum_{k=1}^{K} \left(G_k + C\right) \\[6pt] S_k = \sum_{j=1}^{k-1} \left(G_j + C\right) \end{gathered} \]

y un semáforo del turno \(k\) está en verde en el instante \(t\) si y solo si

(12)\[ \big( (t + \phi) \bmod T \big) \in \left[\, S_k,\ S_k + G_k \,\right) \]

donde \(\phi\) es el desfase del cruce, es decir, en qué punto de su ciclo se encontraba en \(t = 0\). Un semáforo suelto se trata como un cruce de un solo semáforo al que se agrega una fase vacía de \(G_0\) segundos, para que también tenga rojo. Cuando un turno se queda sin semáforos, los turnos superiores se recorren para que la numeración siga siendo \(1, 2, \dots, K\).

Al crear un cruce, los turnos se asignan por eje: se toma el rumbo \(\beta\) con el que cada calle llega a la esquina, se pliega a \([0^\circ, 180^\circ)\) para que ambos sentidos de una calle coincidan, y se compara con el del primer semáforo seleccionado:

(13)\[ k_s = \begin{cases} 1 & \left| (\beta_s \bmod 180^\circ) - (\beta_1 \bmod 180^\circ) \right| < 45^\circ \ \text{ o } \ > 135^\circ \\ 2 & \text{si no} \end{cases} \]\[ \begin{gathered} \Delta\beta_s = \left| (\beta_s \bmod 180^\circ) - (\beta_1 \bmod 180^\circ) \right| \\[8pt] k_s = \begin{cases} 1 & \Delta\beta_s < 45^\circ \text{ o } \Delta\beta_s > 135^\circ \\ 2 & \text{si no} \end{cases} \end{gathered} \]

Las calles paralelas a la primera quedan en el turno 1 y las perpendiculares en el 2. Desde el editor se puede cambiar cualquier turno y crear turnos adicionales.

De dónde salen los semáforos

Cualquier persona con cuenta puede proponer un semáforo desde el mapa: toca 🚦 Proponer semáforo y luego la calle donde hace falta. El punto se convierte en una arista con la misma regla que usa el editor: si el toque cae a menos de 40 m de una esquina, el semáforo va en la calle que llega a esa esquina y está más cerca del toque; si no, en la calle más cercana, y los vehículos se detienen en su siguiente esquina. No se aceptan puntos a más de 40 m de una calle de la red ni a menos de 25 m de otro semáforo o de otra propuesta.

Cada propuesta pasa por revisión antes de contar. Primero la meto a la simulación en vivo, a prueba, para ver cómo reaccionan los vehículos; si la cola que forma tiene sentido, se queda; si no, se quita. Una propuesta aprobada entra como semáforo suelto, con prioridad media y un desfase \(\phi\) al azar entre 0 y 45 s. Como un semáforo controla un solo sentido de una sola calle, una esquina completa se arma con varias propuestas que después agrupo en un cruce.

Turnos \(K\)
Fig. 3 Ciclo de un cruce según las ecuaciones (10)–(12). Cada bloque de color es el verde de un turno; los bloques grises son los 3 s de despeje. La línea vertical recorre el ciclo en tiempo real. Con un solo turno aparece la fase vacía que le da rojo a un semáforo suelto.

Ejemplo: Valsequillo y Municipio Libre

Si Bulevar Valsequillo (turno 1) tiene prioridad alta y Bulevar Municipio Libre (turno 2) media:

\[ T = (30 + 3) + (20 + 3) = 56\ \text{s}, \qquad \frac{G_1}{T} = \frac{30}{56} \approx 54\,\%, \qquad \frac{G_2}{T} = \frac{20}{56} \approx 36\,\% \]\[ \begin{gathered} T = (30 + 3) + (20 + 3) = 56\ \text{s} \\[6pt] \frac{G_1}{T} = \frac{30}{56} \approx 54\,\% \qquad \frac{G_2}{T} = \frac{20}{56} \approx 36\,\% \end{gathered} \]

Con ambas en prioridad media, cada una tendría \(20/46 \approx 43\,\%\). Son diez segundos más de verde en cada ciclo para el bulevar que mueve más vehículos.

Coordinación entre cruces

Dos cruces consecutivos sobre la misma avenida forman una ola verde si su diferencia de fase se mantiene constante. Con ciclos \(T_1\) y \(T_2\), la diferencia de fase avanza \(|T_1 - T_2|\) segundos en cada ciclo:

(14)\[ \Delta\phi(n) = \Delta\phi(0) + n\,(T_1 - T_2) \pmod{T_2} \]\[ \begin{gathered} \Delta\phi(n) = \Delta\phi(0) + n\,(T_1 - T_2) \\ \pmod{T_2} \end{gathered} \]

Solo si \(T_1 = T_2\) la coordinación se conserva. Un cruce con prioridad alta en uno de sus turnos (\(T = 56\) s) junto a uno con todo en media (\(T = 46\) s) se desfasa diez segundos por ciclo: la ola verde se rompe en menos de cinco ciclos.

6 Cuántos circulan: estacionamiento y hora del día

En la ciudad real casi todos los autos están estacionados casi todo el tiempo. El simulador parte de una flota fija de \(N = 900{,}000\) vehículos. El registro da unos 750 mil para el área del mapa (Puebla, las Cholulas, Cuautlancingo, Amozoc…): alrededor de 2.4 millones de habitantes con una motorización de 318 vehículos por cada mil (Conapo, 2023). A eso se suma lo que el registro no ve: autos con placas de Tlaxcala u otros estados y los que entran a diario desde fuera del mapa.

De esa flota, la fracción que circula en el instante \(t\) mezcla dos poblaciones. Los autos particulares (\(1-\sigma\) de la flota) pasan el día estacionados y salen con los horarios de trabajo y escuela, con una curva \(p_d(h)\) que depende de la hora \(h\) y del tipo de día \(d\) (entre semana, sábado o domingo). El transporte de servicio (\(\sigma = 10\,\%\): combis, camiones, taxis, plataformas, reparto) casi no se estaciona de día y sigue una curva propia \(s(h)\):

(15)\[ M^{*}(t) = N\,\big[\,(1-\sigma)\,p_d(h) + \sigma\,s(h)\,\big], \qquad \max_h p_{\text{semana}}(h) = 0.15, \quad \max_h s(h) = 0.65 \]\[ \begin{gathered} M^{*}(t) = N\,\big[(1-\sigma)\,p_d(h) + \sigma\,s(h)\big] \\[8pt] \max_h p_{\text{semana}}(h) = 0.15, \ \ \max_h s(h) = 0.65 \end{gathered} \]

Entre semana, a las 8:00 y a las 19:00, eso da \(M^{*} \approx 0.9 \cdot 0.15 + 0.1 \cdot 0.65 = 0.20\): una de cada cinco unidades de la flota está en la calle, unos 180 mil vehículos. De madrugada circula alrededor del 1 %. Las curvas se interpolan minuto a minuto, y a medianoche se enlazan con las del día siguiente, para que la madrugada del sábado refleje la salida del viernes.

Un regulador corre cada segundo. Cuenta los vehículos que circulan, \(M\), y corrige la diferencia con un tope, para que la ciudad se llene y se vacíe de forma gradual:

(16)\[ \Delta M = \operatorname{clip}\!\big(M^{*}(t) - M,\ -400,\ 400\big)\ \ \text{vehículos por segundo} \]\[ \begin{gathered} \Delta M = \operatorname{clip}\!\big(M^{*}(t) - M,\ -400,\ 400\big) \\ \text{vehículos por segundo} \end{gathered} \]

Si faltan vehículos, despierta autos estacionados elegidos al azar, que salen desde la calle donde estaban. Si sobran, guarda vehículos que van por calles de \(\le 50\) km/h, como quien llega a su casa o a su trabajo; nunca estaciona a nadie en un bulevar. Los autos guardados se reparten en las calles de colonia en proporción a su longitud.

Día
autos particulares transporte de servicio
—
Máximo del día
—
Mínimo del día
—
Ahora en Puebla

Fig. 4 Vehículos circulando a lo largo del día según la ecuación (15), con las mismas curvas que usa el simulador. Pasa el cursor o el dedo sobre la gráfica para ver cada hora. La línea vertical marca la hora actual de Puebla cuando el día seleccionado es hoy.

Además del regulador, durante la hora pico un vehículo que entra a una calle lenta (\(v^{\max}_e \le 30\) km/h) dentro de la zona destino se estaciona con probabilidad \(0.015\), por un tiempo que depende del tipo de zona:

(17)\[ \tau \sim \begin{cases} \mathcal{U}(2\ \text{h},\ 8\ \text{h}) & \text{zona comercial} \\ \mathcal{U}(6\ \text{h},\ 14\ \text{h}) & \text{zona residencial} \end{cases} \]

Esto concentra los autos estacionados donde la gente llega a esa hora; el regulador compensa para que el total siga la curva. Un vehículo estacionado sale de la fila de su calle y no estorba a nadie. Si un vehículo llega a un callejón sin salida fuera de su zona destino, se reubica en una calle de su zona de origen, para que vuelva a hacer el viaje.

7 Del servidor al navegador

Enviar los 900 mil vehículos como tres flotantes de 32 bits ocuparía \(900{,}000 \times 12 \approx 10.8\) MB por actualización, cuatro veces por segundo. En cambio, cada navegador pide solo el recuadro que tiene en pantalla, \([\text{lat}_s, \text{lat}_n] \times [\text{lon}_o, \text{lon}_e]\), y cada vehículo viaja en 5 bytes: posición cuantizada a 16 bits relativa al recuadro y velocidad a 8 bits.

(18)\[ q_{\text{lat}} = \operatorname{round}\!\left( \frac{\text{lat} - \text{lat}_s}{\text{lat}_n - \text{lat}_s} \cdot \left(2^{16} - 1\right) \right), \qquad \varepsilon \le \frac{\text{lat}_n - \text{lat}_s}{2\left(2^{16} - 1\right)} \]\[ \begin{gathered} q_{\text{lat}} = \operatorname{round}\!\left( \frac{\text{lat} - \text{lat}_s}{\text{lat}_n - \text{lat}_s}\,(2^{16} - 1) \right) \\[10pt] \varepsilon \le \frac{\text{lat}_n - \text{lat}_s}{2\,(2^{16} - 1)} \end{gathered} \]

Con toda el área metropolitana en pantalla (0.46° de latitud, unos 51 km), el error máximo es \(0.46^\circ \times 111{,}320\ \text{m} / 131{,}070 \approx 0.4\) m; al acercarse a una colonia, milímetros. Si en el recuadro hay más de 12,000 vehículos, se envía uno de cada \(\lceil N/12{,}000 \rceil\) según su índice global, de modo que entre una actualización y otra se ven siempre los mismos vehículos y la muestra no parpadea. La ciudad completa pesa unos 60 KB por actualización; una colonia, unos 25 KB. La posición de un auto estacionado se calcula una sola vez, cuando se estaciona.

8 Limitaciones

  • No hay carriles físicos, cambios de carril ni rebases (sección 2).
  • En cruces sin semáforo nadie cede el paso: todos los vehículos pasan sin detenerse.
  • Las rutas son locales: cada vehículo decide esquina por esquina, sin un destino final.
  • El frenado es ideal, sin tiempo de reacción.
  • Todos los vehículos se mueven igual: una combi o un camión se comportan como un auto, y no hay paradas de transporte público.
  • La flota y las curvas de la sección 6 son estimaciones a partir del registro vehicular y de encuestas de movilidad, no conteos de Puebla.
  • Los semáforos los propone la gente desde el mapa y las zonas las dibujo a mano desde el editor; el modelo es tan bueno como esos datos.

La última limitación es la que más pesa y la única que no se resuelve con código. El mapa arrancó sin semáforos y se está completando a mano, cruce por cruce, con la ayuda de quien conoce su colonia: cada semáforo que alguien propone y que pasa la revisión hace que la simulación se parezca un poco más a la ciudad real.

Referencias
  1. Gipps, P. G. (1981). A behavioural car-following model for computer simulation. Transportation Research Part B, 15(2), 105–111.
  2. Treiber, M., & Kesting, A. (2013). Traffic Flow Dynamics: Data, Models and Simulation. Springer.
  3. Webster, F. V. (1958). Traffic Signal Settings. Road Research Technical Paper No. 39. HMSO, Londres.
  4. Colaboradores de OpenStreetMap. Red vial de Puebla, México. openstreetmap.org, licencia ODbL.
  5. INEGI (2018). Encuesta Origen Destino en Hogares de la Zona Metropolitana del Valle de México 2017.
  6. Conapo (2023). Índice de motorización de la zona metropolitana Puebla-Tlaxcala, citado en La Jornada, 25 de agosto de 2025.

Ayúdame a poner los semáforos de Puebla

¿Falta un semáforo en tu calle o en tu ruta diaria? Entra a la simulación, toca 📍 Mi zona para ir a tu colonia y luego 🚦 Proponer semáforo. Lo pruebo en la simulación y, si cuadra, se queda con tu nombre.

Proponer un semáforo →

Implementación: Node.js · arreglos tipados · Flask · Leaflet · Canvas · datos OpenStreetMap

El Laboratorio

La serie donde documento los sistemas, los modelos y las herramientas que construyo. Aquí las matemáticas se ven por dentro.

→ Ver todo El Laboratorio