- Регистрация
- 21.07.20
- Сообщения
- 40.408
- Реакции
- 1
- Репутация
- 0
В хорошем подмосковном городе есть плохой железнодорожный переезд. В час пик встает не только он, но и соседние перекрестки и дороги. Проезжая в очередной раз, я задался вопросом — какая у него пропускная способность и можно ли что-то изменить?
Для ответа мы немного углубимся в нормативы и теорию транспортных потоков, проанализируем данные GPS и акселерометра с помощью Python и сравним теоретические расчеты с экспериментальными данными.
Содержание
1. Исходные данные
Мы имеет одноколейный железнодорожный переезд с плохим качеством дороги, скорость на котором примерно 10 км/ч. Из подручных средств современный смартфон и ноутбук.
Весь код и данные доступны в формате Jupyter Notebook на моем
Нам понадобятся следующие библиотеки:
import pandas as pd
import numpy as np
import glob
#!pip install utm
import utm
from sklearn.decomposition import PCA
from scipy import interpolate
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(rc={'figure.figsize'12, 8)})
import plotly.express as px
# Токен Mapbox для карт в Plotly
mapbox_token = open('mapbox_token', 'r').read()
2. Теория транспортного потока
Для начала определимся с терминами.
Плотность движения $inline$\rho$inline$ — Число автомобилей на 1 км дороги.
$inline$v$inline$ — скорость АТС.
Интенсивность движения $inline$Q(\rho)$inline$ — Количество транспортных средств, проходящие в единицу времени через определенное сечение дороги.
Пропускная способность $inline$P$inline$ — Максимальное число автомобилей, которое может пропустить участок дороги в единицу времени в одном или двух направлениях в рассматриваемых дорожных и погодно-климатических условиях.
Плотность движения и интенсивность связаны формулой:
$$display$$Q = V \cdot \rho$$display$$
Зависимость $inline$Q(\rho)$inline$ часто называют фундаментальной диаграммой.
Так на графике ниже отображены экспериментальные данные «Центра исследования транспортной инфраструктуры» г. Москвы, собранные в течение одного дня в 2005 г. по четырем полосам на участке третьего транспортного кольца от Автозаводской улицы до Варшавского шоссе, и сагрегированные на одну полосу.
Оценка пропускной способности
Основным документом при оценке пропускной способности дорог и их элементов является документ
Для железнодорожных переездов выделен целый раздел, и пропускная способность в разных дорожных условиях рассчитывается по формуле:
$$display$$P_{ж.п.}=P_д \cdot \beta^{ж.п.}_1 \cdot \beta^{ж.п.}_2 \cdot \beta^{ж.п.}_3 \cdot \beta^{ж.п.}_4 \cdot \beta^{ж.п.}_5,$$display$$
где $inline$\beta^{ж.п.}_1,\beta^{ж.п.}_2,\beta^{ж.п.}_3,\beta^{ж.п.}_4,\beta^{ж.п.}_5$inline$ — коэффициенты снижения пропускной способности, учитывающие состав движения, характеристики железнодорожных переездов и дорожные условия в зоне переезда, которые определяются по приведенным таблицам.
Рассчитаем пропускную способность, исходя из наших условий:
$$display$$P_{ж.п.}=1500 \cdot 0.93 \cdot 0.66 \cdot 0.8 \cdot 1 \cdot 1 = 736.56 авт./ч = 12.3 авт./мин$$display$$
Мы получили теоретическую оценку, теперь перейдем к тому, что есть на самом деле.
В реальных условиях я использовал 2 метода оценки пропускной способности:
В качестве функционала можно использовать простые модели:
$inline$\rho(v)=\frac{1}{d(v)}$inline$,
$inline$d(v)= L+ c_1 v+ c_2 v^2$inline$,
где $inline$d(v)$inline$ – среднее (безопасное) расстояние между АТС, $inline$L$inline$ – средняя длина АТС, $inline$c_1$inline$ – время, характеризующее реакцию водителя, $inline$c_2$inline$ — коэффициент пропорциональности тормозному пути. При нормальных условиях (сухой асфальт): $inline$L=5.7 м, c_1=0.504 c, c_2=0.0285 с^2/м$inline$.
$inline$\rho= \rho_{max} (1 - \frac{v}{v_{max}})$inline$,
где $inline$\rho_{max}$inline$ — максимальная плотность потока (при отсутствии движения), $inline$v_{max}$inline$ — максимальная (желаемая) скорость движения АТС (при пустой дороге). Эти данные можно взять из того же ОДМ 218.2.020-2012 — $inline$\rho_{max} = 85 авт./км, v_{max}=60 км/ч$inline$
Код для графиков
# Загрузка данных для Диаграммы уравнения потока
diagram1 = pd.read_csv('Диаграмма уравнения потока.csv', sep=';', header=None, names=['P', 'V'], decimal=',')
diagram1_func = interpolate.interp1d(diagram1['P'], diagram1['V'], kind='cubic')
diagram1_xnew = np.arange(diagram1['P'].min(), diagram1['P'].max())
# Загрузка данных для Фундаментальной диаграммы
diagram2 = pd.read_csv('Фундаментальная диаграмма.csv', sep=';', header=None, names=['P', 'Q'], decimal=',')
diagram2_func = interpolate.interp1d(diagram2['P'], diagram2['Q'], kind='cubic')
diagram2_xnew = np.arange(diagram2['P'].min(), diagram2['P'].max())
def density_Tanaka(V):
# Функция плотности для модели Танака
V = V * 1000 / 60 / 60 # переводим км/ч в м/с
L = 5.7 # м
c1 = 0.504 # с
c2 = 0.0285 #с**2/м
return 1000 / (L + c1 * V + c2 * V**2) # авт./км
def density_Grindshilds(V):
# Функция плотности для модели Гриндшилдса
pmax = 85 # авт./км
vmax = 60 # км/ч
return pmax * (1 - V / vmax) # авт./км
# Построение графиков
V = np.arange(1, 80) # км/ч
V1 = np.arange(1, 61) # км/ч
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 8))
ax1.plot(density_Tanaka(V), V, label="Модель Танака")
ax1.plot(density_Grindshilds(V1), V1, label="Модель Гриндшилдса")
ax1.plot(diagram1_xnew, diagram1_func(diagram1_xnew), label="Экспер. данные ТТК")
ax1.set_xlabel(r'Плотность $\rho$, авт/км')
ax1.set_ylabel(r'Скорость $V$, км/ч')
ax1.legend()
ax2.plot(density_Tanaka(V), density_Tanaka(V) * V, label="Модель Танака")
ax2.plot(density_Grindshilds(V1), density_Grindshilds(V1) * V1, label="Модель Гриндшилдса")
ax2.plot(diagram2_xnew, diagram2_func(diagram2_xnew), label="Экспер. данные ТТК")
ax2.set_xlabel(r'Плотность $\rho$, авт/км')
ax2.set_ylabel(r'Интенсивность $Q$, авт/ч')
ax2.legend()
plt.show()
Модель Гриндшилдса с исходными данными для переезда существенно занижает интенсивность по сравнению с экспериментальными данными для обычной дороги. Давайте сравним эту модель с реальностью.
3. Сбор и анализ данных
3.1 Ручной подсчет интенсивности движения
Я не стал усложнять и применять нейронные сети для распознавания машин, а просто написал кейлогер с сохранением времени и нажатой клавиши. Чтобы после каждого нажатия не вводить Enter, код немного усложнился:
Код кейлогера
%%writefile "key-logger.py"
import pandas as pd
import time
import datetime
class _GetchUnix:
# from
def __init__(self):
import tty, sys
def __call__(self):
import sys, tty, termios
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
def logging():
path = 'logs/keylog/'
filename = f"{time.strftime('%Y-%m-%d %H-%M-%S')}.csv"
path_to_file = path + filename
db = []
getch = _GetchUnix()
print('Процесс...')
while True:
key = getch()
if key == 'c':
break
else:
db.append((datetime.datetime.now(), key))
df = pd.DataFrame(db, columns=['time', 'click'])
print(df)
df.to_csv(path_to_file, index=False)
print(f"\nSaved to {filename}")
if __name__ == "__main__":
logging()
Пришлось посидеть возле переезда 20 минут и внимательно смотреть за потоком. Я записал 2 периода сразу после проезда поезда, т. е. при загрузке переезда на 100%:
files = glob.glob('logs/keylog/*.csv')
keylogger_data = []
print(f'Количество файлов - {len(files)} шт.')
for filename in files:
df = pd.read_csv(filename, parse_dates=['time'])
keylogger_data.append(df)
keylogger_data = pd.concat(keylogger_data, ignore_index=True)
keylogger_data.head()
Для ответа мы немного углубимся в нормативы и теорию транспортных потоков, проанализируем данные GPS и акселерометра с помощью Python и сравним теоретические расчеты с экспериментальными данными.
Содержание
-
You must be registered for see links
-
You must be registered for see links
-
You must be registered for see links
-
You must be registered for see links
-
You must be registered for see links
-
You must be registered for see links
-
You must be registered for see links
-
-
You must be registered for see links
-
-
You must be registered for see links
1. Исходные данные
Мы имеет одноколейный железнодорожный переезд с плохим качеством дороги, скорость на котором примерно 10 км/ч. Из подручных средств современный смартфон и ноутбук.
Весь код и данные доступны в формате Jupyter Notebook на моем
You must be registered for see links
.Нам понадобятся следующие библиотеки:
import pandas as pd
import numpy as np
import glob
#!pip install utm
import utm
from sklearn.decomposition import PCA
from scipy import interpolate
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(rc={'figure.figsize'12, 8)})
import plotly.express as px
# Токен Mapbox для карт в Plotly
mapbox_token = open('mapbox_token', 'r').read()
2. Теория транспортного потока
Для начала определимся с терминами.
Плотность движения $inline$\rho$inline$ — Число автомобилей на 1 км дороги.
$inline$v$inline$ — скорость АТС.
Интенсивность движения $inline$Q(\rho)$inline$ — Количество транспортных средств, проходящие в единицу времени через определенное сечение дороги.
Пропускная способность $inline$P$inline$ — Максимальное число автомобилей, которое может пропустить участок дороги в единицу времени в одном или двух направлениях в рассматриваемых дорожных и погодно-климатических условиях.
Плотность движения и интенсивность связаны формулой:
$$display$$Q = V \cdot \rho$$display$$
Зависимость $inline$Q(\rho)$inline$ часто называют фундаментальной диаграммой.
Так на графике ниже отображены экспериментальные данные «Центра исследования транспортной инфраструктуры» г. Москвы, собранные в течение одного дня в 2005 г. по четырем полосам на участке третьего транспортного кольца от Автозаводской улицы до Варшавского шоссе, и сагрегированные на одну полосу.
Оценка пропускной способности
Основным документом при оценке пропускной способности дорог и их элементов является документ
You must be registered for see links
"Методические рекомендации по оценке пропускной способности автомобильных дорог".Для железнодорожных переездов выделен целый раздел, и пропускная способность в разных дорожных условиях рассчитывается по формуле:
$$display$$P_{ж.п.}=P_д \cdot \beta^{ж.п.}_1 \cdot \beta^{ж.п.}_2 \cdot \beta^{ж.п.}_3 \cdot \beta^{ж.п.}_4 \cdot \beta^{ж.п.}_5,$$display$$
где $inline$\beta^{ж.п.}_1,\beta^{ж.п.}_2,\beta^{ж.п.}_3,\beta^{ж.п.}_4,\beta^{ж.п.}_5$inline$ — коэффициенты снижения пропускной способности, учитывающие состав движения, характеристики железнодорожных переездов и дорожные условия в зоне переезда, которые определяются по приведенным таблицам.
Рассчитаем пропускную способность, исходя из наших условий:
$$display$$P_{ж.п.}=1500 \cdot 0.93 \cdot 0.66 \cdot 0.8 \cdot 1 \cdot 1 = 736.56 авт./ч = 12.3 авт./мин$$display$$
Мы получили теоретическую оценку, теперь перейдем к тому, что есть на самом деле.
В реальных условиях я использовал 2 метода оценки пропускной способности:
- Непосредственный подсчет проехавших через переезд АТС;
- Вычисление средней скорости движения АТС в выделенной нами области и применение различных функционалов для определения плотности.
В качестве функционала можно использовать простые модели:
- Модель Танака:
$inline$\rho(v)=\frac{1}{d(v)}$inline$,
$inline$d(v)= L+ c_1 v+ c_2 v^2$inline$,
где $inline$d(v)$inline$ – среднее (безопасное) расстояние между АТС, $inline$L$inline$ – средняя длина АТС, $inline$c_1$inline$ – время, характеризующее реакцию водителя, $inline$c_2$inline$ — коэффициент пропорциональности тормозному пути. При нормальных условиях (сухой асфальт): $inline$L=5.7 м, c_1=0.504 c, c_2=0.0285 с^2/м$inline$.
- Модель Гриндшилдса:
$inline$\rho= \rho_{max} (1 - \frac{v}{v_{max}})$inline$,
где $inline$\rho_{max}$inline$ — максимальная плотность потока (при отсутствии движения), $inline$v_{max}$inline$ — максимальная (желаемая) скорость движения АТС (при пустой дороге). Эти данные можно взять из того же ОДМ 218.2.020-2012 — $inline$\rho_{max} = 85 авт./км, v_{max}=60 км/ч$inline$
Код для графиков
# Загрузка данных для Диаграммы уравнения потока
diagram1 = pd.read_csv('Диаграмма уравнения потока.csv', sep=';', header=None, names=['P', 'V'], decimal=',')
diagram1_func = interpolate.interp1d(diagram1['P'], diagram1['V'], kind='cubic')
diagram1_xnew = np.arange(diagram1['P'].min(), diagram1['P'].max())
# Загрузка данных для Фундаментальной диаграммы
diagram2 = pd.read_csv('Фундаментальная диаграмма.csv', sep=';', header=None, names=['P', 'Q'], decimal=',')
diagram2_func = interpolate.interp1d(diagram2['P'], diagram2['Q'], kind='cubic')
diagram2_xnew = np.arange(diagram2['P'].min(), diagram2['P'].max())
def density_Tanaka(V):
# Функция плотности для модели Танака
V = V * 1000 / 60 / 60 # переводим км/ч в м/с
L = 5.7 # м
c1 = 0.504 # с
c2 = 0.0285 #с**2/м
return 1000 / (L + c1 * V + c2 * V**2) # авт./км
def density_Grindshilds(V):
# Функция плотности для модели Гриндшилдса
pmax = 85 # авт./км
vmax = 60 # км/ч
return pmax * (1 - V / vmax) # авт./км
# Построение графиков
V = np.arange(1, 80) # км/ч
V1 = np.arange(1, 61) # км/ч
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 8))
ax1.plot(density_Tanaka(V), V, label="Модель Танака")
ax1.plot(density_Grindshilds(V1), V1, label="Модель Гриндшилдса")
ax1.plot(diagram1_xnew, diagram1_func(diagram1_xnew), label="Экспер. данные ТТК")
ax1.set_xlabel(r'Плотность $\rho$, авт/км')
ax1.set_ylabel(r'Скорость $V$, км/ч')
ax1.legend()
ax2.plot(density_Tanaka(V), density_Tanaka(V) * V, label="Модель Танака")
ax2.plot(density_Grindshilds(V1), density_Grindshilds(V1) * V1, label="Модель Гриндшилдса")
ax2.plot(diagram2_xnew, diagram2_func(diagram2_xnew), label="Экспер. данные ТТК")
ax2.set_xlabel(r'Плотность $\rho$, авт/км')
ax2.set_ylabel(r'Интенсивность $Q$, авт/ч')
ax2.legend()
plt.show()
Модель Гриндшилдса с исходными данными для переезда существенно занижает интенсивность по сравнению с экспериментальными данными для обычной дороги. Давайте сравним эту модель с реальностью.
3. Сбор и анализ данных
3.1 Ручной подсчет интенсивности движения
Я не стал усложнять и применять нейронные сети для распознавания машин, а просто написал кейлогер с сохранением времени и нажатой клавиши. Чтобы после каждого нажатия не вводить Enter, код немного усложнился:
Код кейлогера
%%writefile "key-logger.py"
import pandas as pd
import time
import datetime
class _GetchUnix:
# from
You must be registered for see links
def __init__(self):
import tty, sys
def __call__(self):
import sys, tty, termios
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
def logging():
path = 'logs/keylog/'
filename = f"{time.strftime('%Y-%m-%d %H-%M-%S')}.csv"
path_to_file = path + filename
db = []
getch = _GetchUnix()
print('Процесс...')
while True:
key = getch()
if key == 'c':
break
else:
db.append((datetime.datetime.now(), key))
df = pd.DataFrame(db, columns=['time', 'click'])
print(df)
df.to_csv(path_to_file, index=False)
print(f"\nSaved to {filename}")
if __name__ == "__main__":
logging()
Пришлось посидеть возле переезда 20 минут и внимательно смотреть за потоком. Я записал 2 периода сразу после проезда поезда, т. е. при загрузке переезда на 100%:
files = glob.glob('logs/keylog/*.csv')
keylogger_data = []
print(f'Количество файлов - {len(files)} шт.')
for filename in files:
df = pd.read_csv(filename, parse_dates=['time'])
keylogger_data.append(df)
keylogger_data = pd.concat(keylogger_data, ignore_index=True)
keylogger_data.head()
time | click |
---|