Spaces:
Sleeping
Sleeping
| from multiprocessing import Process, Queue | |
| import gradio as gr | |
| from app_backend import bistatic_radar_model | |
| TIMEOUT = 10 # если столько секунд нет ответа от функции - возвращаем пользователю сообщение об ошибке. | |
| BG_CHOICES = ("Задать значение", "Выбрать из модели Кулемина") | |
| KULEMIN = { | |
| "лес летом": [-20, 10, 6], | |
| "лес зимой": [-40, 10, 6], | |
| "луг высокотравный": [-21, 10, 6], | |
| "луг низкотравный": [-28, 10, 6], | |
| "пашня": [-37, 18, 15], | |
| "снег": [-34, 25, 15], | |
| } | |
| LOGOS_HEADER = """ | |
| <style> | |
| .logo-container { | |
| display: flex; | |
| gap: 20px; /* расстояние между логотипами */ | |
| align-items: center; | |
| } | |
| /* По умолчанию (светлая тема) показываем дневные варианты */ | |
| #iu-day, #ai-day { | |
| display: block; | |
| } | |
| #iu-night, #ai-night { | |
| display: none; | |
| } | |
| /* Для тёмной темы — наоборот, показываем ночные варианты */ | |
| @media (prefers-color-scheme: dark) { | |
| #iu-day, #ai-day { | |
| display: none; | |
| } | |
| #iu-night, #ai-night { | |
| display: block; | |
| } | |
| } | |
| </style> | |
| <div class="logo-container"> | |
| <img id="iu-day" src='gradio_api/file=./img/iu_day.png' alt='УНИВЕРСИТЕТ ИННОПОЛИС' width=200> | |
| <img id="iu-night" src='gradio_api/file=./img/iu_night.png' alt='УНИВЕРСИТЕТ ИННОПОЛИС' width=200> | |
| <img id="ai-day" src='gradio_api/file=./img/ai_day.png' alt='ЦЕНТР ИСКУССТВЕННОГО ИНТЕЛЛЕКТА' width=200> | |
| <img id="ai-night" src='gradio_api/file=./img/ai_night.png' alt='ЦЕНТР ИСКУССТВЕННОГО ИНТЕЛЛЕКТА' width=200> | |
| </div> | |
| """ | |
| def run_model_with_timeout(timeout, *args, **kwargs): | |
| def target(q, *args, **kwargs): | |
| try: | |
| res = bistatic_radar_model(*args, **kwargs) | |
| q.put(res) | |
| except Exception as e: | |
| q.put(e) | |
| q = Queue() | |
| p = Process(target=target, args=(q, *args), kwargs=kwargs) | |
| p.start() | |
| p.join(timeout) | |
| if p.is_alive(): | |
| p.terminate() | |
| p.join() | |
| return None # Таймаут | |
| if q.empty(): | |
| return None | |
| result = q.get() | |
| if isinstance(result, Exception): | |
| raise result | |
| return result | |
| def main(i): | |
| try: | |
| kwargs = dict( | |
| v=i[speed], | |
| h=i[height], | |
| uav_interval=i[uav_interval], | |
| psi_t=i[psit], | |
| psi_r=i[psir], | |
| srcs=i[bg_type] if i[bg_mode] == BG_CHOICES[1] else i[bg_value], | |
| cloud_base=i[cloud_base], | |
| cloud_thickness=i[cloud_thickness], | |
| rain_rate=i[rain_intensivity], | |
| q_fill=i[q_fill], | |
| bandwidth=i[bandwidth], | |
| wavelength=i[wavelength], | |
| antenna_gain=i[antenna_gain], | |
| antenna_length=i[antenna_length], | |
| noise_factor=i[noise_factor], | |
| peak_power=i[peak_power], | |
| polarization_tilt_angle=0 if i[polar_type] == "H" else 90, | |
| ) | |
| # Запускаем с таймаутом 5 секунд | |
| out = run_model_with_timeout(TIMEOUT, **kwargs) | |
| if out is None: | |
| # Таймаут — возвращаем значения по умолчанию или сообщение об ошибке | |
| return ["Обновите страницу или исправьте параметры: время ожидания ответа от сервера истекло"] * 3 | |
| return f"{out['dx']:.3f}", f"{out['dy']:.3f}", f"{out['snr']:.1f}" | |
| except Exception: | |
| return ["ОШИБКА: недопустимая комбинация входных параметров"] * 3 | |
| def update_visibility(radio): | |
| if radio == BG_CHOICES[0]: | |
| return gr.update(visible=True), gr.update(visible=False) | |
| return gr.update(visible=False), gr.update(visible=True) | |
| input_set = set() | |
| # Create the Gradio pyinterface | |
| with gr.Blocks( | |
| title="РЛС-калькулятор", | |
| # css="footer{display:none !important}", | |
| # theme=gr.themes.Ocean(), | |
| ) as demo: | |
| gr.HTML(LOGOS_HEADER) | |
| gr.Markdown( | |
| "# Калькулятор оценки параметров качества радиолокационного изображения двухпозиционной РЛС" | |
| ) | |
| with gr.Row(): | |
| with gr.Column(): | |
| gr.Markdown( | |
| """ | |
| Калькулятор позволяет рассчитать параметры качества радиолокационного изображения (РЛИ), формируемого в передней зоне обзора двухпозиционной полуактивной радиолокационной станции (РЛС) авиационного базирования. | |
| В рассматриваемой схеме главный лепесток диаграммы направленности антенны (ДНА) на излучение активной компоненты РЛС подсвечивает область в передней зоне обзора, тогда как главный лепесток ДНА на прием направлен так, чтобы существовала возможность фиксации отраженного эхо-сигнала. Формирование РЛИ происходит на пересечении областей земной поверхности в пределах главных лепестков ДНА на излучение и на прием. | |
| Каждая одиночная РЛС использует одинаковую передающую и приемную антенны, вследствие чего равны угловые размеры главных лепестков на излучение и на прием. | |
| """ | |
| ) | |
| with gr.Column(): | |
| gr.HTML( | |
| "<img src='gradio_api/file=./img/bistatic_radar.jpg' alt='Схема относительного расположения РЛС на паре БВС' width=640>" | |
| ) | |
| # v - скорость полета, h - высота полета, dl - размер базы между РЛС, psir - угол курса оси главного лепестка ДНА на прием | |
| with gr.Row(): | |
| with gr.Column(): | |
| gr.Markdown("## Параметры бортовой РЛС") | |
| psir = gr.Slider( | |
| minimum=10, | |
| maximum=60, | |
| value=30, | |
| step=0.1, | |
| label="Угол курса оси главного лепестка ДНА на прием, град", | |
| ) | |
| input_set.add(psir) | |
| psit = gr.Slider( | |
| minimum=-60, | |
| maximum=-10, | |
| value=-30, | |
| step=0.1, | |
| label="Угол курса оси главного лепестка ДНА на излучение, град", | |
| ) | |
| input_set.add(psit) | |
| antenna_length = gr.Slider( | |
| minimum=0.05, | |
| maximum=0.3, | |
| value=0.1, | |
| step=0.01, | |
| label="Длина антенны, м", | |
| ) | |
| input_set.add(antenna_length) | |
| antenna_gain = gr.Slider( | |
| minimum=5, | |
| maximum=20, | |
| value=10, | |
| step=0.1, | |
| label="Коэффициент усиления антенны, дБ", | |
| ) | |
| input_set.add(antenna_gain) | |
| wavelength = gr.Slider( | |
| minimum=0.02, | |
| maximum=0.04, | |
| value=0.03, | |
| step=0.001, | |
| label="Длина волны, м", | |
| ) | |
| input_set.add(wavelength) | |
| peak_power = gr.Slider( | |
| minimum=1, | |
| maximum=10, | |
| value=5, | |
| step=0.1, | |
| label="Пиковая мощность, ВТ", | |
| ) | |
| input_set.add(peak_power) | |
| bandwidth = gr.Slider( | |
| minimum=500, | |
| maximum=2000, | |
| value=1000, | |
| step=1, | |
| label="Полоса пропускания, МГц", | |
| ) | |
| input_set.add(bandwidth) | |
| noise_factor = gr.Slider( | |
| minimum=1, | |
| maximum=3, | |
| value=2, | |
| step=0.01, | |
| label="Шум-фактор, дБ", | |
| ) | |
| input_set.add(noise_factor) | |
| gr.Markdown("## Параметры режима работы РЛС") | |
| with gr.Row(): | |
| q_fill = gr.Slider( | |
| minimum=0.05, | |
| maximum=0.25, | |
| value=0.1, | |
| step=0.001, | |
| label="Коэффициент заполнения", | |
| ) | |
| input_set.add(q_fill) | |
| polar_type = gr.Radio( | |
| choices=["H", "V"], label="Тип поляризации", value="H" | |
| ) | |
| input_set.add(polar_type) | |
| with gr.Column(): | |
| gr.Markdown("## Траекторные параметры") | |
| speed = gr.Slider( | |
| minimum=5, | |
| maximum=30, | |
| value=20, | |
| step=0.1, | |
| label="Скорость полета, м/с", | |
| ) | |
| input_set.add(speed) | |
| height = gr.Slider( | |
| minimum=200, | |
| maximum=2000, | |
| value=1000, | |
| step=1, | |
| label="Высота полета, м", | |
| ) | |
| input_set.add(height) | |
| uav_interval = gr.Slider( | |
| minimum=200, | |
| maximum=2000, | |
| value=1000, | |
| step=1, | |
| label="Длина базы между РЛС, м", | |
| ) | |
| input_set.add(uav_interval) | |
| gr.Markdown("## Параметры условий местности") | |
| cloud_base = gr.Slider( | |
| minimum=0, | |
| maximum=1500, | |
| value=750, | |
| step=1, | |
| label="Высота нижней границы облаков, м", | |
| ) | |
| input_set.add(cloud_base) | |
| cloud_thickness = gr.Slider( | |
| minimum=0, maximum=6000, value=3000, step=1, label="Толщина облаков, м" | |
| ) | |
| input_set.add(cloud_thickness) | |
| rain_intensivity = gr.Slider( | |
| minimum=0, | |
| maximum=80, | |
| value=40, | |
| step=1, | |
| label="Интенсивность дождя, мм/ч", | |
| ) | |
| input_set.add(rain_intensivity) | |
| bg_mode = gr.Radio( | |
| choices=BG_CHOICES, label="УЭПР фона поверхности", value=BG_CHOICES[0] | |
| ) | |
| input_set.add(bg_mode) | |
| bg_value = gr.Slider( | |
| minimum=-30, maximum=10, value=0, step=0.1, label="", visible=True | |
| ) | |
| input_set.add(bg_value) | |
| bg_type = gr.Dropdown( | |
| choices=KULEMIN.keys(), visible=False, label="", filterable=False | |
| ) | |
| input_set.add(bg_type) | |
| with gr.Column(): | |
| gr.Markdown("## Предельные параметры качества РЛИ") | |
| # Output displays | |
| output_hr = gr.Text(label="Разрешение по горизонтальной дальности, м") | |
| output_ar = gr.Text(label="Разрешение по азимуту, м") | |
| output_snr = gr.Text(label="Отношение сигнал/шум, дБ") | |
| with gr.Row(): | |
| gr.Markdown( | |
| "*Калькулятор оценки параметров качества радиолокационного изображения двухпозиционной РЛС подготовлен за счет средств гранта, предоставленного по договору от 30.10.2024 № 70-2024-001319, заключенному АНО ВО «Университет Иннополис» с Фондом поддержки проектов Национальной технологической инициативы*" | |
| ) | |
| # Set up the event listeners for real-time updates | |
| output_list = [output_hr, output_ar, output_snr] | |
| bg_mode.change(fn=update_visibility, inputs=bg_mode, outputs=[bg_value, bg_type]) | |
| for inp in input_set: | |
| inp.change(fn=main, inputs=input_set, outputs=output_list) | |
| if __name__ == "__main__": | |
| demo.launch(share=False, allowed_paths=["."], server_name="0.0.0.0") | |