diff --git a/critical/undergraduate/content/abstracten.tex b/critical/undergraduate/content/abstracten.tex index 37502ce..6c330a3 100644 --- a/critical/undergraduate/content/abstracten.tex +++ b/critical/undergraduate/content/abstracten.tex @@ -1,9 +1,7 @@ %!TEX root = ../csuthesis_main.tex -\keywordsen{Intelligent Driving \ \ Simulation Scenarios \ \ Dangerous Scenario Generation \ \ Automation Technology} +\keywordsen{Intelligent Driving \ \ Simulation Scenarios \ \ Dangerous Scenario Generation \ \ NSGA-II Multi-objective Optimization} \begin{abstracten} -In the development of intelligent driving systems, the generation and optimization of simulation scenarios are crucial for ensuring their safety and reliability. This project reviews the technologies for generating and optimizing dangerous simulation scenarios in intelligent driving. Firstly, based on natural driving data, representative dangerous driving scenarios are identified and extracted, providing a data foundation for the construction of simulation scenarios. Secondly, through multi-dimensional scenario automatic extraction and fusion methods, typical driving scenarios such as line-following, following, and lane-changing are identified and integrated with dynamic driving scenarios to generate more complex and realistic test scenarios. Additionally, to address the issue of insufficient dangerous scenarios in existing test scenarios, a test case generation and enhancement method based on cluster analysis and importance sampling is proposed, which effectively improves the test coverage and efficiency of dangerous scenarios. Finally, an automated simulation testing platform has been developed, enabling the rapid construction of test scenarios, joint invocation of simulation software, and fully automated execution of result analysis and report generation. These methods can significantly improve the safety testing efficiency of intelligent driving systems in simulation environments, providing strong support for the further development of intelligent driving technology. - - +In the development of intelligent driving systems, the generation and optimization of simulation scenarios play a vital role in ensuring system safety and reliability. This thesis begins by extracting representative hazardous scenarios from naturalistic driving data to establish a realistic simulation foundation. Through multidimensional scenario fusion techniques, typical driving behaviors such as lane changes, car following, and adjacent vehicle cut-ins are identified and integrated with dynamic traffic elements to produce complex and realistic test cases. To address the insufficient coverage of high-risk scenarios, this work emphasizes the adoption of the NSGA-II multi-objective optimization algorithm. By applying non-dominated sorting and crowding distance mechanisms, NSGA-II balances the conflicting objectives of minimum safety distance and collision risk to extract a Pareto-optimal set of critical scenarios. Experimental comparisons demonstrate that NSGA-II outperforms random search, achieving over 30\% improvement in high-risk scenario coverage. Finally, an automated simulation testing platform is developed to support scenario generation, execution, data logging, and result evaluation, enabling a fully automated and standardized testing workflow. The proposed framework significantly enhances safety testing efficiency and effectiveness in simulated environments, providing robust technical support for autonomous driving technology development. \end{abstracten} \ No newline at end of file diff --git a/critical/undergraduate/content/abstractzh.tex b/critical/undergraduate/content/abstractzh.tex index 8c0560f..12ae5b4 100644 --- a/critical/undergraduate/content/abstractzh.tex +++ b/critical/undergraduate/content/abstractzh.tex @@ -1,11 +1,10 @@ %!TEX root = ../csuthesis_main.tex % 设置中文摘要 -\keywordscn{智能驾驶\quad 仿真场景\quad 危险场景生成\quad 自动化技术} +\keywordscn{智能驾驶\quad 仿真场景\quad 危险场景生成\quad NSGA-II 多目标优化} %\categorycn{TP391} \begin{abstractzh} - -在智能驾驶系统的发展过程中,仿真场景的生成与优化是确保其安全性和可靠性的重要手段。本项目综述了智能驾驶危险仿真场景的生成和优化技术。首先,基于自然驾驶数据,识别并提取出具有代表性的危险驾驶场景,为仿真场景的构建提供了数据基础。其次,通过多维场景自动提取和融合方法,识别出典型的行车场景,如巡线、跟车、邻车切入等,并将其与动态驾驶场景进行融合,以生成更为复杂和真实的测试场景。此外,针对现有测试场景中危险场景数量不足的问题,提出了一种基于聚类分析和重要性采样的测试用例生成和增强方法,有效提高了危险场景的测试覆盖率和测试效率。最后,开发了一种自动化仿真测试平台,实现了测试场景的快速构建、仿真软件的联合调用以及结果分析与报告生成的全自动化执行。通过这些方法,能够显著提高智能驾驶系统在仿真环境中的安全测试效率,为智能驾驶技术的进一步发展提供了有力支持。 +在智能驾驶系统的发展过程中,仿真场景的生成与优化是保障其安全性和可靠性的关键技术手段。本文首先基于自然驾驶数据提取具有代表性的危险场景,构建真实有效的仿真数据基础;随后,采用多维场景融合方法识别典型行车行为(如变道、跟车、邻车切入等),并与动态交通要素结合,生成更加复杂和真实的测试场景。针对现有测试环境中高风险场景覆盖率不足的问题,本文重点引入 NSGA-II 多目标优化算法,通过非支配排序与拥挤度计算,在“最小安全距离”和“碰撞风险”两个目标之间实现 Pareto 最优平衡,有效筛选出多样且具有代表性的高危场景。实验结果表明,与传统随机搜索方法相比,NSGA-II 可将高风险场景覆盖率提高 30\% 以上。最后,设计并实现了一套自动化仿真测试平台,集成场景生成、仿真执行、数据采集与结果分析功能,实现测试流程的自动化和标准化。本文方法显著提升了智能驾驶系统在仿真环境中的安全性验证能力,为未来自动驾驶系统的开发与测试提供了有力技术支撑。 \end{abstractzh} \ No newline at end of file diff --git a/critical/undergraduate/content/acknowledgements.tex b/critical/undergraduate/content/acknowledgements.tex index 423aca3..d5780d3 100644 --- a/critical/undergraduate/content/acknowledgements.tex +++ b/critical/undergraduate/content/acknowledgements.tex @@ -1,7 +1,7 @@ %!TEX root = ../csuthesis_main.tex \begin{acknowledgements} - -写到这里这篇本科论文就算完成了,回想起撰写论文这段时光心里全是感慨和感激,我要用最真诚的文字向所有帮过我的人表达深深谢意。首先要向我的论文导师表达最崇高的敬意和最诚挚的感谢,从对论文选题感到迷茫到梳理ChatScene框架设计思路,从探讨ASIL - Gen优化算法到分析实验结果时遇到困惑,老师一直凭借渊博专业知识、严谨治学态度和耐心细致指导为我拨开迷雾。每次组会的讨论内容和每份修改意见的批注都凝聚着老师的心血,老师不光教会我学术研究的方法,还以实际行动诠释了精益求精的科研精神,这些会成为我未来学习和工作的宝贵财富。感谢学院各位老师,课堂上你们生动讲解让我对自动驾驶领域有更深入理解,在论文开题、中期检查等环节你们提出的建设性意见帮我不断完善研究内容。特别感谢实验室的师兄师姐和同学们,我遇到技术难题时你们慷慨分享经验陪我调试CARLA仿真平台、优化NSGA - II算法代码,我倍感压力时你们的鼓励和陪伴让我重新找回信心,和你们一起奋斗的日子是我本科生涯最难忘的回忆。还要感谢我的家人,是你们在背后默默支持让我能心无旁骛投入论文研究,每当我因实验不顺利而焦虑时你们的理解与安慰给予我温暖和力量,你们的关爱与鼓励是我前行路上最坚实的后盾。 -最后,感谢参与的所有老师与同学,以及为论文提供数据和技术支持的机构。虽然论文仍存在不足之处,但这段经历让我收获颇丰。未来,我将带着这份感恩之心,继续在学术道路上探索前行。 - + + 写到这里这篇本科论文就算完成了,回想起撰写论文这段时光心里全是感慨和感激,我要用最真诚的文字向所有帮过我的人表达深深谢意。首先要向我的论文导师表达最崇高的敬意和最诚挚的感谢,从对论文选题感到迷茫到梳理ChatScene框架设计思路,从探讨ASIL - Gen优化算法到分析实验结果时遇到困惑,老师一直凭借渊博专业知识、严谨治学态度和耐心细致指导为我拨开迷雾。每次组会的讨论内容和每份修改意见的批注都凝聚着老师的心血,老师不光教会我学术研究的方法,还以实际行动诠释了精益求精的科研精神,这些会成为我未来学习和工作的宝贵财富。感谢学院各位老师,课堂上你们生动讲解让我对自动驾驶领域有更深入理解,在论文开题、中期检查等环节你们提出的建设性意见帮我不断完善研究内容。特别感谢实验室的师兄师姐和同学们,我遇到技术难题时你们慷慨分享经验陪我调试CARLA仿真平台、优化NSGA - II算法代码,我倍感压力时你们的鼓励和陪伴让我重新找回信心,和你们一起奋斗的日子是我本科生涯最难忘的回忆。还要感谢我的家人,是你们在背后默默支持让我能心无旁骛投入论文研究,每当我因实验不顺利而焦虑时你们的理解与安慰给予我温暖和力量,你们的关爱与鼓励是我前行路上最坚实的后盾。 + 最后,感谢参与的所有老师与同学,以及为论文提供数据和技术支持的机构。虽然论文仍存在不足之处,但这段经历让我收获颇丰。未来,我将带着这份感恩之心,继续在学术道路上探索前行。 + \end{acknowledgements} diff --git a/critical/undergraduate/content/appendix.tex b/critical/undergraduate/content/appendix.tex index 4bc8e7d..a18e313 100644 --- a/critical/undergraduate/content/appendix.tex +++ b/critical/undergraduate/content/appendix.tex @@ -1,1296 +1,357 @@ -\%!TEX root = ../csuthesis\_main.tex -\% \begin{appendix} \% 无章节编号 -\chapter{附录代码} - -附录部分用于存放这里用来存放不适合放置在正文的大篇幅内容、典型如代码、图纸、完整数学证明过程等内容。 - -\section{chatscene} - -Step 1: Setup conda environment - -conda create -n chatscene python=3.8 -conda activate chatscene -Step 2: Clone this git repo in an appropriate folder - -git clone git@github.com:javyduck/ChatScene.git -Step 3: Enter the repo root folder and install the packages: - -cd ChatScene -pip install -r requirements.txt -pip install decorator==5.1.1 +%!TEX root = ../csuthesis\_main.tex +% \begin{appendix} % 无章节编号 + \chapter{附录代码} + + + \section{更多技术支持} + \begin{lstlisting} +交通场景指的是交通参与者在仿真世界中多样的动态行为,通过这些动态行为对运行在其中的自动驾驶车辆进行充分测试。交通场景的丰富性依赖于交通参与者的种类和其能实现的动态行为,CARLA支持轿车、SUV、客车、卡车、摩托车、自行车、行人等多种动态参与者及锥桶、售货机等多种静态参与者,动态参与者的行为可通过预先定义的场景和在线运行的交通流来控制。 + +CARLA中的交通管理器(Traffic Manager)模块可进行场景和交通流的模拟,不过鉴于基于OpenSCENARIO格式的场景仿真更通用,我们选用CARLA提供的场景运行器(ScenarioRunner,以下简称SR)来进行场景的模拟。下面对SR的安装和使用进行说明。 + +01. ScenarioRunner的安装 +ScenarioRunner是由CARLA官方提供的、与CARLA配合使用的场景解析和运行工具,支持CARLA自定义的scenario格式、route格式和OpenSCENARIO格式等多种预定义场景文件的运行,本书主要使用其OpenSCENARIO场景运行功能。OpenSCENARIO目前已经发布1.2和2.0版本,其中1.0和2.0版本都在ScenarioRunner中得到了支持。 + +OpenSCENARIO是德国自动化及测量系统标准协会ASAM提供的一个描述动态场景的标准格式,关于OpenSCENARIO格式的内容,大家可以看下之前对OpenSCENARIO的格式介绍和实例分析。 + +SR的安装步骤如下: + +(1)下载源码 + +SR的github上提供了与CARLA版本相配合的Release版本[ https://github.com/carla-simulator/scenario\_runner/releases],如SR0.9.13与CARLA 0.9.13相配合。这是因为SR需要使用PythonAPI从CARLA获取信息并对CARLA中的交通参与者、天气等进行控制,如果版本不匹配的话会操作失败。为了获取最新的特性,我们这里使用下载源码的方式进行安装。 + +大家可以选择将SR下载到任何位置,为了方便起见这里下载到CARLA文件夹下。 + +cd /path/to/carla +git clone https://github.com/carla-simulator/scenario\_runner.git +(2)依赖库安装 + +进入scenario\_runner文件夹,并根据其中的requirements.txt安装依赖库: + +cd scenario\_runner +sudo apt remove python3-networkx \#若安装过networkx则先将其卸载 +pip3 install -r requirements.txt +按照以上步骤安装依赖后,若本地numpy版本高于1.20,运行时可能有包含如下字符的报错:......networkx/readwrite/graphml.py......module 'numpy' has no attribute 'int'...... 。这是因为requirements.txt中指定的networkx 2.2版本使用了http://np.int,该用法在nump 1.20版本以上已经不再支持。读者可以根据实际情况安装高版本networkx或者低版本的numpy。 + +以下两种方法选一即可 +1.卸载networkx,并重新安装新版本 + pip3 uninstall networkx + pip3 install networkx +2.卸载numpy,并重新安装低版本 + pip3 uninstall numpy + pip3 install numpy==1.20 +(3)设置环境变量 + +为了在运行时能够找到相关的文件,需要设置一些环境变量。打开~/.bashrc文件,并在其结尾加入如下内容: + +export CARLA\_ROOT=/path/to/carla + +export SCENARIO\_RUNNER\_ROOT=\$CARLA\_ROOT/scenario\_runner + +export PYTHONPATH=\$PYTHONPATH:\$CARLA\_ROOT/PythonAPI/carla + +大家请注意将其中路径修改为自己电脑上的实际路径,然后运行source ~/.bashrc使设置生效。 + +至此用于运行OpenSCENARIO 1.0文件(以下简称xosc文件)的安装工作都已完成,大家可尝试按照下一节的方法运行相关文件。若想运行OpenSCENARIO 2.0文件(以下简称osc文件),还需要进行如下操作。 + +(4)安装OpenSCENARIO 2.0相关依赖 + +安装JDK + +sudo apt install openjdk-17-jdk + +安装Antlr + +curl -O https://www.antlr.org/download/antlr-4.10.1-complete.jar + +sudo cp antlr-4.10.1-complete.jar /usr/local/lib/ + +pip3 install antlr4-python3-runtime==4.10 + +打开~/.bashrc文件,并在其结尾加入如下内容,然后运行source ~/.bashrc使设置生效。 + + +export CLASSPATH=".:/usr/local/lib/antlr-4.10.1-complete.jar:\$CLASSPATH" + +alias antlr4='java -jar /usr/local/lib/antlr-4.10.1-complete.jar' + +alias grun='java org.antlr.v4.gui.TestRig'xport CARLA\_ROOT=/path/to/carla + +export SCENARIO\_RUNNER\_ROOT=\$CARLA\_ROOT/scenario\_runner + +export PYTHONPATH=\$PYTHONPATH:\$CARLA\_ROOT/PythonAPI/carla + +02.运行OpenSCENARIO文件 +使用SR运行xosc/osc文件的步骤十分简单,首先启动CARLA,然后运行SR并指定xosc/osc文件即可: + +启动CARLA: + +cd /path/to/carla + +./CarlaUE4.sh + +配置ego车 + +实际测试时应由被测算法控制ego车,此处为了进行演示,通过SR自带的manual\_control.py为ego车配置自动驾驶: + +cd /path/to/scenario\_runner + +加载xosc文件示例时使用 + +python3 manual\_control.py -a + +加载osc文件示例时使用 + +python3 manual\_control.py -a --rolename ego\_vehicl + +需要注意的是,manual\_control.py根据rolename查找ego车辆并为其配置自动驾驶,默认ego车辆的rolename为“hero”,在下面的xosc文件示例中ego车辆的rolename恰好为“hero”,故无需配置“--rolename”参数,而osc文件示例中ego车辆的rolename为“ego\_vehicle”,从而需要指定“--rolename”。 + +运行ScenarioRunner + +cd /path/to/scenario\_runner + +运行xosc文件示例 + +python3 scenario\_runner.py --output --openscenario + +srunner/examples/FollowLeadingVehicle.xosc + +运行osc文件示例 + +python3 scenario\_runner.py --outpu --openscenario2 + +srunner/examples/cut\_in\_and\_slow\_range.osc + +运行上述命令后,可以在CARLA渲染窗口中观察到地图根据xosc文件中定义变更,同时生成了ego车和其前方的障碍车。 + +\end{lstlisting} + + +\section{ASIL算法相关操作与代码} + \begin{lstlisting} + 1. 环境准备 +安装 CARLA Simulator + +从 carla-simulator/carla 克隆并编译(或下载预编译版本)。 + +确认 CARLA 服务器可以在后台正常运行: + + +./CarlaUE4.sh \# Linux +\# 或者双击 Windows 下的 CarlaUE4.exe +安装 Scenario Runner + + +git clone https://github.com/carla-simulator/scenario \_runner.git +cd scenario\_runner pip install -e . -(you can ignore the error after installing the decorator) - -Step 4: Install the Scenic package: - -cd Scenic -python -m pip install -e . -Step 5: Download our CARLA\_0.9.13 and extract it to your folder. - -Step 6: Run sudo apt install libomp5 as per this git issue. - -Step 7: Add the python API of CARLA to the PYTHONPATH environment variable. You can add the following commands to your ~/.bashrc: - -export CARLA\_ROOT={path/to/your/carla} -export PYTHONPATH=$PYTHONPATH:${CARLA\_ROOT}/PythonAPI/carla/dist/carla-0.9.13-py3.8-linux-x86\_64.egg -export PYTHONPATH=$PYTHONPATH:${CARLA\_ROOT}/PythonAPI/carla/agents -export PYTHONPATH=$PYTHONPATH:${CARLA\_ROOT}/PythonAPI/carla -export PYTHONPATH=$PYTHONPATH:${CARLA\_ROOT}/PythonAPI -Then, do source ~/.bashrc to update the environment variable. - -1. Desktop Users -Enter the CARLA root folder, launch the CARLA server and run our platform with - -\# Launch CARLA -./CarlaUE4.sh -prefernvidia -windowed -carla-port=2000 -2. Remote Server Users -Enter the CARLA root folder, launch the CARLA server with headless mode, and run our platform with - -\# Launch CARLA -./CarlaUE4.sh -prefernvidia -RenderOffScreen -carla-port=2000 -(Optional) You can also visualize the pygame window using TurboVNC. First, launch CARLA with headless mode, and run our platform on a virtual display. - -\# Launch CARLA -./CarlaUE4.sh -prefernvidia -RenderOffScreen -carla-port=2000 - -\# Run a remote VNC-Xserver. This will create a virtual display "8". -/opt/TurboVNC/bin/vncserver :8 -noxstartup -You can use the TurboVNC client on your local machine to connect to the virtual display. - -\# Use the built-in SSH client of TurboVNC Viewer -/opt/TurboVNC/bin/vncviewer -via user@host localhost:n - -\# Or you can manually forward connections to the remote server by -ssh -L fp:localhost:5900+n user@host -\# Open another terminal on local machine -/opt/TurboVNC/bin/vncviewer localhost::fp -where user@host is your remote server, fp is a free TCP port on the local machine, and n is the display port specified when you started the VNC server on the remote server ("8" in our example). - -ChatScene -In ChatScene, we ensure a fair comparison with the baselines by using the same eight scenarios, sampling five behaviors for each scenario from the database. The corresponding generated comeplete Scenic files, with some modifications, have been provided in safebench/scenario/scenario\_data/scenic\_data (with some manual modifications to use the same fixed 10 routes for the ego agent to ensure fair comparison with the baselines). - -The ego agent is controlled by a default RL model, while the surrounding adversarial agent is controlled by Scenic. - -The agent configuration is provided in safebench/agent/config/adv\_scenic.yaml. By default, it loads a pretrained RL model from Safebench-v1. - -Modes in ChatScene: -train\_scenario: Select the most challenging scenes for the same behavior under the same scenario. - -Configuration can be found in safebench/scenario/config/train\_agent\_scenic.yaml. - -The sample\_num = 50, opt\_step = 10, select\_num = 2 settings in the file mean we sample 50 scenes and select the 2 most challenging ones for evaluation. The default setting is to choose scenes that lead to a collision of the ego agent and provide the lowest overall score. We optimize the range of parameters, like speed, every 10 steps based on collision statistics from previously sampled scenes. - -Example command for optimizing the scene: - -python scripts/run\_train.py --agent\_cfg=adv\_scenic.yaml --scenario\_cfg=train\_scenario\_scenic.yaml --mode train\_scenario --scenario\_id 1 -Use the following command if you are using a TurboVNC client on your local machine to connect to the virtual display: - -DISPLAY=:8 python scripts/run\_train.py --agent\_cfg=adv\_scenic.yaml --scenario\_cfg=train\_scenario\_scenic.yaml --mode train\_scenario --scenario\_id 1 -The IDs for the final selected scenes will be stored in safebench/scenario/scenario\_data/scenic\_data/scenario\_1/scenario\_1.json. - -train\_agent: Train the agent based on the selected challenging scenes: - -python scripts/run\_train.py --agent\_cfg=adv\_scenic.yaml --scenario\_cfg=train\_agent\_scenic.yaml --mode train\_agent --scenario\_id 1 -We have a total of 10 routes for each scenario. We use the first 8 for training and the last 2 for testing (route IDs: [0,1,2,3,4,5,6,7]). The configuration, including scenario\_1.json, will train the agent based on the most challenging scenes (the ones leading to a collision of the ego agent). - -eval: Evaluate the trained agent on the last 2 routes (route IDs: [8,9]), the test\_epoch is for loading a finetuned model after a specific training epoch: - -python scripts/run\_eval.py --agent\_cfg=adv\_scenic.yaml --scenario\_cfg=eval\_scenic.yaml --mode eval --scenario\_id 1 --test\_epoch -1 -The -1 here is for loading our provided fine-tuned agent in each scenario based on our Scenic scenarios in safebench/agent/model\_ckpt/adv\_train/sac/scenic/scenario\_1/model.sac.-001.torch. - -Dynamic Mode -The above part ensures using the same scenario and routes for fair comparison with baselines. However, ChatScene can generate scenarios and scenes freely without any constraints. Simply provide a text description, such as "The ego vehicle is driving on a straight road; the adversarial pedestrian suddenly crosses the road from the right front and suddenly stops in front of the ego." is enough for the training. We are currently integrating our database with GPT-4o for generating more diverse scenarios based on our pre-built retrieval database, and will upload both soonly. - -Please first install openai and sentence\_transformers packages following the requirements. - -Put your description under file retrieve/scenario\_descriptions.txt - -run python retrieve.py to get the corresponding scenic code under safebench/scenario/scenario\_data/scenic\_data/dynamic\_scenario - -Then, for running the dynamic scenarios, just replace the run\_train.py or run\_eval.py with run\_train\_dynamic.py or run\_eval\_dynamic.py, and use dynamic\_scenic.yaml (please specify your settings there), an exmaple could be: - -python scripts/run\_train\_dynamic.py --agent\_cfg=adv\_scenic.yaml --scenario\_cfg=dynamic\_scenic.yaml --mode train\_scenario -Integrate GPT-4o with our retrieval database (v1) and commit to the dynamic mode. Some mechanisms have been changed based on the previous version to incorporate more adversarial behavior, geometry, and spawn point definitions. Currently, it is still in beta. If you encounter any problems, please submit an issue, and I will address potential errors in the new retrieval pipeline. -Some snippets are still under cleaning of the updated framework (i.e., incorprating GPT-4o to generate more diverse scenarios), the new retrieve database v2 will be pushed based on the new design. -Finetune an LLM for generating snippets end-to-end based on the data constructed from our database. - -\section{ASIL-Gen} - -ASIL-Gen: Automotive Scenario Generation and ASIL Classification Toolkit -A toolkit for generating automotive scenarios, evaluating their safety levels (ASIL), and comparing optimization algorithms (NSGA-II vs. Random Search) for scenario selection. - -Overview -This repository contains tools for: - -Generating variations of driving scenarios -Executing scenarios in CARLA simulator -Selecting critical scenarios using NSGA and Random Search algorithms -Determining Automotive Safety Integrity Levels (ASIL) of selected scenarios -Analyzing results with statistical methods -Prerequisites -CARLA Simulator: -Install CARLA from carla-simulator/carla. -Scenario Runner: -Install the CARLA Scenario Runner from carla-simulator/scenario\_runner. -Setup -Clone this repository: - -git clone https://github.com/Fizza129/ASIL-Gen.git -Install Python dependencies (if required): -Ensure , , (for NSGA-II), and other standard libraries are installed.numpypandasdeap - -Usage -1. Running Scenarios -Pre-generated Scenarios: - -Extract .Scenario Dataset/Scenario\_Dataset\_1-4.zip -Copy scenario files to ..pyscenario\_runner/srunner/scenarios/ -Copy configuration files to ..xmlscenario\_runner/srunner/examples/ -Follow Scenario Runner documentation to execute scenarios. -Custom Scenarios: -Use scripts in to generate new variations. Example:Scenario Generation Scripts/ - -python script\_change\_lane.py \# Generates new lane-change variations -2. Scenario Selection -NSGA-II Optimization: -Run scripts in the folder on scenario execution results: NSGA/ -python "NSGA/NSGA\_choice.py" -Random Search: -Execute scripts in the folder: The selected scenarios will be saved in JSON format.Random Search/ -python "Random Search/random\_search\_choice.py" -3. ASIL Classification -Use scripts in the folder to compute ASIL levels (A/B/C/D/QM) for selected scenarios: ASIL/ -python "ASIL/ASIL.py" \# Calculates ASIL levels -python "ASIL/ASIL\_percentages.py" \# Calculates ASIL distribution percentages -4. Statistical Comparison (NSGA vs. Random Search) -Run Mann-Whitney U Test scripts in : Mann Whitney Test/ -python "Mann Whitney Test/Mann Whitney and Effect Size.py" -Repository Structure -ASIL-Gen/ -├── ASIL/ \# ASIL classification and percentage calculation -├── Mann Whitney Test/ \# Statistical tests for comparing NSGA and Random Search -├── NSGA/ \# NSGA-II optimization for scenario selection -├── Random Search/ \# Random Search-based scenario selection -├── Scenario Dataset/ \# Pre-generated scenario variations (Python + XML) -├── Scenario Generation Scripts/ \# Scripts to generate new scenario variations -└── Scenario Results/ \# Output results -Scenario Types -The repository contains 13 unique scenarios: - -Lane change -Cut-in with static vehicle -Dynamic object crossing -Following leading vehicle -Following leading vehicle with obstacle -Hazard at side lane -No signal junction crossing -Opposite vehicle running red light -Other leading vehicle -Parked obstacle -Parking crossing pedestrian -Vehicle opens door -Vehicle turning right -Results -The folder contains the outputs from executed scenarios.Scenario Results - -Notes -Dataset Usage: The contains 1,000 variations for each unique scenario. Extract and copy files as instructed.Scenario Dataset -Custom Generation: Modify scripts in to create new scenario variations.Scenario Generation Scripts/ - -\section{scene\_runner} - -''' -Date: 2023-01-31 22:23:17 -LastEditTime: 2023-03-07 12:28:17 -Description: -Copyright (c) 2022-2023 Safebench Team - -This work is licensed under the terms of the MIT license. -For a copy, see -''' - -import copy +克隆 ASIL-Gen 仓库,并安装依赖 + + +git clone https://github.com/Fizza129/ASIL-Gen.git GitHub - Fizza129/ASIL-Gen GitHub - Fizza129/ASIL-Gen +cd ASIL-Gen +\# 建议使用虚拟环境 +python3 -m venv venv source venv/bin/activate +pip install -r requirements.txt +requirements.txt 中应包含 numpy、pandas、deap、scipy、matplotlib 等。 + +2. 加载预生成场景 +解压数据集: + +unzip "Scenario Dataset/Scenario\_Dataset\_1-4.zip" -d Scenario\_Dataset/ +拷贝到 Scenario Runner: + +cp -r Scenario\_Dataset/* ../scenario\_runner/srunner/scenarios/ + +cp -r xml/ ../scenario\_runner/srunner/examples/ +3. 自定义场景生成 +所有脚本都放在 Scenario Generation Scripts/ 下。以 script\_change\_lane.py 为例: + + +\# Scenario Generation Scripts/script\_change\_lane.py import os -import json -import glob import random - -import numpy as np -import carla -import pygame -from tqdm import tqdm - -from safebench.gym\_carla.env\_wrapper import VectorWrapper -from safebench.gym\_carla.envs.render import BirdeyeRender -from safebench.gym\_carla.replay\_buffer import RouteReplayBuffer, PerceptionReplayBuffer - -from safebench.agent import AGENT\_POLICY\_LIST -from safebench.scenario import SCENARIO\_POLICY\_LIST - -from safebench.scenario.scenario\_manager.carla\_data\_provider import CarlaDataProvider -from safebench.scenario.scenario\_data\_loader import ScenarioDataLoader, ScenicDataLoader -from safebench.scenario.tools.scenario\_utils import scenario\_parse, scenic\_parse - -from safebench.util.logger import Logger, setup\_logger\_kwargs -from safebench.util.metric\_util import get\_route\_scores, get\_perception\_scores -from safebench.util.scenic\_utils import ScenicSimulator - -class ScenicRunner: -def \_\_init\_\_(self, agent\_config, scenario\_config): -self.scenario\_config = scenario\_config -self.agent\_config = agent\_config - -self.seed = scenario\_config['seed'] -self.exp\_name = scenario\_config['exp\_name'] -self.output\_dir = scenario\_config['output\_dir'] -self.mode = scenario\_config['mode'] -self.save\_video = scenario\_config['save\_video'] - -self.render = scenario\_config['render'] -self.num\_scenario = scenario\_config['num\_scenario'] -self.fixed\_delta\_seconds = scenario\_config['fixed\_delta\_seconds'] -self.scenario\_category = scenario\_config['scenario\_category'] - -\# continue training flag -self.continue\_agent\_training = scenario\_config['continue\_agent\_training'] -self.continue\_scenario\_training = scenario\_config['continue\_scenario\_training'] - -\# apply settings to carla -self.client = carla.Client('localhost', scenario\_config['port']) -self.client.set\_timeout(10.0) -self.world = None -self.env = None - -self.env\_params = { - 'auto\_ego': scenario\_config['auto\_ego'], - 'obs\_type': agent\_config['obs\_type'], - 'scenario\_category': self.scenario\_category, - 'ROOT\_DIR': scenario\_config['ROOT\_DIR'], - 'warm\_up\_steps': 9, \# number of ticks after spawning the vehicles - 'disable\_lidar': True, \# show bird-eye view lidar or not - 'display\_size': 128, \# screen size of one bird-eye view window - 'obs\_range': 32, \# observation range (meter) - 'd\_behind': 12, \# distance behind the ego vehicle (meter) - 'max\_past\_step': 1, \# the number of past steps to draw - 'discrete': False, \# whether to use discrete control space - 'discrete\_acc': [-3.0, 0.0, 3.0], \# discrete value of accelerations - 'discrete\_steer': [-0.2, 0.0, 0.2], \# discrete value of steering angles - 'continuous\_accel\_range': [-3.0, 3.0], \# continuous acceleration range - 'continuous\_steer\_range': [-0.3, 0.3], \# continuous steering angle range - 'max\_episode\_step': scenario\_config['max\_episode\_step'], \# maximum timesteps per episode - 'max\_waypt': 12, \# maximum number of waypoints - 'lidar\_bin': 0.125, \# bin size of lidar sensor (meter) - 'out\_lane\_thres': 4, \# threshold for out of lane (meter) - 'desired\_speed': 8, \# desired speed (m/s) - 'image\_sz': 1024, \# TODO: move to config of od scenario -} - - -\# pass config from scenario to agent -agent\_config['mode'] = scenario\_config['mode'] -agent\_config['ego\_action\_dim'] = scenario\_config['ego\_action\_dim'] -agent\_config['ego\_state\_dim'] = scenario\_config['ego\_state\_dim'] -agent\_config['ego\_action\_limit'] = scenario\_config['ego\_action\_limit'] - -\# define logger -logger\_kwargs = setup\_logger\_kwargs( -self.exp\_name, -self.output\_dir, -self.seed, -agent=agent\_config['policy\_type'], -scenario=scenario\_config['policy\_type'], -scenario\_category=self.scenario\_category -) -self.logger = Logger(**logger\_kwargs) - -\# prepare parameters -if self.mode == 'train\_agent': -self.buffer\_capacity = agent\_config['buffer\_capacity'] -self.eval\_in\_train\_freq = agent\_config['eval\_in\_train\_freq'] -self.save\_freq = agent\_config['save\_freq'] -self.train\_episode = agent\_config['train\_episode'] -self.current\_episode = -1 -self.logger.save\_config(agent\_config) -self.logger.create\_training\_dir() -elif self.mode == 'train\_scenario': -self.save\_freq = agent\_config['save\_freq'] -self.logger.create\_eval\_dir(load\_existing\_results=False) -elif self.mode == 'eval': -self.save\_freq = agent\_config['save\_freq'] -self.logger.log('>> Evaluation Mode, skip config saving', 'yellow') -self.logger.create\_eval\_dir(load\_existing\_results=False) -else: -raise NotImplementedError(f"Unsupported mode: {self.mode}.") - -\# define agent and scenario -self.logger.log('>> Agent Policy: ' + agent\_config['policy\_type']) -self.logger.log('>> Scenario Policy: ' + scenario\_config['policy\_type']) - -if self.scenario\_config['auto\_ego']: -self.logger.log('>> Using auto-polit for ego vehicle, action of policy will be ignored', 'yellow') -if scenario\_config['policy\_type'] == 'ordinary' and self.mode != 'train\_agent': -self.logger.log('>> Ordinary scenario can only be used in agent training', 'red') -raise Exception() -self.logger.log('>> ' + '-' * 40) - -\# define agent and scenario policy -self.agent\_policy = AGENT\_POLICY\_LIST[agent\_config['policy\_type']](agent\_config, logger=self.logger) -self.scenario\_policy = SCENARIO\_POLICY\_LIST[scenario\_config['policy\_type']](scenario\_config, logger=self.logger) -if self.save\_video: -assert self.mode == 'eval', "only allow video saving in eval mode" -self.logger.init\_video\_recorder() - -def \_init\_world(self): -self.logger.log(">> Initializing carla world") -self.world = self.client.get\_world() -settings = self.world.get\_settings() -settings.synchronous\_mode = True -settings.fixed\_delta\_seconds = self.fixed\_delta\_seconds -self.world.apply\_settings(settings) -CarlaDataProvider.set\_client(self.client) -CarlaDataProvider.set\_world(self.world) -CarlaDataProvider.set\_traffic\_manager\_port(self.scenario\_config['tm\_port']) - -def \_init\_scenic(self, config): -self.logger.log(f">> Initializing scenic simulator: {config.scenic\_file}") -self.scenic = ScenicSimulator(config.scenic\_file, config.extra\_params) - -def \_init\_renderer(self): -self.logger.log(">> Initializing pygame birdeye renderer") -pygame.init() -flag = pygame.HWSURFACE | pygame.DOUBLEBUF -if not self.render: -flag = flag | pygame.HIDDEN -if self.scenario\_category in ['planning', 'scenic']: -\# [bird-eye view, Lidar, front view] or [bird-eye view, front view] -if self.env\_params['disable\_lidar']: -window\_size = (self.env\_params['display\_size'] * 2, self.env\_params['display\_size'] * self.num\_scenario) -else: -window\_size = (self.env\_params['display\_size'] * 3, self.env\_params['display\_size'] * self.num\_scenario) -else: -window\_size = (self.env\_params['display\_size'], self.env\_params['display\_size'] * self.num\_scenario) -self.display = pygame.display.set\_mode(window\_size, flag) - -\# initialize the render for generating observation and visualization -pixels\_per\_meter = self.env\_params['display\_size'] / self.env\_params['obs\_range'] -pixels\_ahead\_vehicle = (self.env\_params['obs\_range'] / 2 - self.env\_params['d\_behind']) * pixels\_per\_meter -self.birdeye\_params = { - 'screen\_size': [self.env\_params['display\_size'], self.env\_params['display\_size']], - 'pixels\_per\_meter': pixels\_per\_meter, - 'pixels\_ahead\_vehicle': pixels\_ahead\_vehicle, -} -self.birdeye\_render = BirdeyeRender(self.world, self.birdeye\_params, logger=self.logger) - -def run\_scenes(self, scenes): -self.logger.log(f">> Begin to run the scene...") -\#\# currently there is only one scene in this list \#\# -for scene in scenes: -if self.scenic.setSimulation(scene): -self.scenic.update\_behavior = self.scenic.runSimulation() -next(self.scenic.update\_behavior) - -def train(self, data\_loader, start\_episode=0, replay\_buffer = None): -\# general buffer for both agent and scenario - -for \_ in tqdm(range(len(data\_loader))): -self.current\_episode += 1 -if self.current\_episode >= self.train\_episode: -return -if self.current\_episode < start\_episode: -continue -\# sample scenarios -sampled\_scenario\_configs, \_ = data\_loader.sampler() -\# reset the index counter to create endless loader -\# data\_loader.reset\_idx\_counter() - -scenes = [config.scene for config in sampled\_scenario\_configs] -\# begin to run the scene -self.run\_scenes(scenes) - -\# get static obs and then reset with init action -static\_obs = self.env.get\_static\_obs(sampled\_scenario\_configs) -self.scenario\_policy.load\_model(sampled\_scenario\_configs) -scenario\_init\_action, additional\_dict = self.scenario\_policy.get\_init\_action(static\_obs) -obs, infos = self.env.reset(sampled\_scenario\_configs, scenario\_init\_action) -replay\_buffer.store\_init([static\_obs, scenario\_init\_action], additional\_dict=additional\_dict) - -\# get ego vehicle from scenario -self.agent\_policy.set\_ego\_and\_route(self.env.get\_ego\_vehicles(), infos) - -\# start loop -episode\_reward = [] -while not self.env.all\_scenario\_done(): -\# get action from agent policy and scenario policy (assume using one batch) -ego\_actions = self.agent\_policy.get\_action(obs, infos, deterministic=False) -scenario\_actions = self.scenario\_policy.get\_action(obs, infos, deterministic=False) - -\# apply action to env and get obs -next\_obs, rewards, dones, infos = self.env.step(ego\_actions=ego\_actions, scenario\_actions=scenario\_actions) -replay\_buffer.store([ego\_actions, scenario\_actions, obs, next\_obs, rewards, dones], additional\_dict=infos) -obs = copy.deepcopy(next\_obs) -episode\_reward.append(np.mean(rewards)) - -\# train off-policy agent or scenario -if self.mode == 'train\_agent' and self.agent\_policy.type == 'offpolicy': -loss = self.agent\_policy.train(replay\_buffer) -elif self.mode == 'train\_scenario' and self.scenario\_policy.type == 'offpolicy': -self.scenario\_policy.train(replay\_buffer) - -score\_function = get\_route\_scores if self.scenario\_category in ['planning', 'scenic'] else get\_perception\_scores -all\_scores = score\_function(self.env.running\_results) - -\# end up environment -self.env.clean\_up() -replay\_buffer.finish\_one\_episode() -self.logger.add\_training\_results('episode', self.current\_episode) -self.logger.add\_training\_results('episode\_reward', np.sum(episode\_reward)) -for key, value in all\_scores.items(): -self.logger.add\_training\_results(key, value) -if loss is not None: -critic\_loss, actor\_loss = loss -self.logger.add\_training\_results('critic\_loss', critic\_loss) -self.logger.add\_training\_results('actor\_loss', actor\_loss) -else: -critic\_loss, actor\_loss = 0, 0 -self.logger.add\_training\_results('critic\_loss', critic\_loss) -self.logger.add\_training\_results('actor\_loss', actor\_loss) -self.logger.log(f">> Episode: {self.current\_episode}, \#buffer\_len: {replay\_buffer.buffer\_len}, critic: {critic\_loss:.3f}, actor: {actor\_loss:.3f}") -self.logger.save\_training\_results() - -\# train on-policy agent or scenario -if self.mode == 'train\_agent' and self.agent\_policy.type == 'onpolicy': -self.agent\_policy.train(replay\_buffer) -elif self.mode == 'train\_scenario' and self.scenario\_policy.type in ['init\_state', 'onpolicy']: -self.scenario\_policy.train(replay\_buffer) - -\# eval during training -if (self.current\_episode+1) \% self.eval\_in\_train\_freq == 0: -\#self.eval(env, data\_loader) -pass - -\# save checkpoints -if (self.current\_episode+1) \% self.save\_freq == 0: -if self.mode == 'train\_agent': -self.agent\_policy.save\_model(self.current\_episode, replay\_buffer) -if self.mode == 'train\_scenario': -self.scenario\_policy.save\_model(self.current\_episode) - -self.scenic.destroy() - -def eval(self, data\_loader, select = False): -num\_finished\_scenario = 0 -data\_loader.reset\_idx\_counter() -\# recording the score and the id of corresponding selected scenes -map\_id\_score = {} -behavior\_name = data\_loader.behavior -route\_id = data\_loader.route\_id -opt\_step = data\_loader.opt\_step -opt\_time = 0 - -if route\_id is None: -log\_name = f'OPT\_{behavior\_name}' -else: -log\_name = f'OPT\_{behavior\_name}\_ROUTE-{route\_id}' - -if select: -self.scene\_map[log\_name] = {} -self.scene\_map[log\_name][f'opt\_time\_{opt\_time}'] = self.scenic.save\_params() - -while len(data\_loader) > 0: -\# sample scenarios -sampled\_scenario\_configs, num\_sampled\_scenario = data\_loader.sampler() -num\_finished\_scenario += num\_sampled\_scenario -assert num\_sampled\_scenario == 1, 'scenic can only run one scene at one time' - -scenes = [config.scene for config in sampled\_scenario\_configs] -\# begin to run the scene -self.run\_scenes(scenes) - -\# reset envs with new config, get init action from scenario policy, and run scenario -static\_obs = self.env.get\_static\_obs(sampled\_scenario\_configs) -self.scenario\_policy.load\_model(sampled\_scenario\_configs) -scenario\_init\_action, \_ = self.scenario\_policy.get\_init\_action(static\_obs, deterministic=True) -obs, infos = self.env.reset(sampled\_scenario\_configs, scenario\_init\_action) - -\# get ego vehicle from scenario -self.agent\_policy.set\_ego\_and\_route(self.env.get\_ego\_vehicles(), infos) - -score\_list = {s\_i: [] for s\_i in range(num\_sampled\_scenario)} -while not self.env.all\_scenario\_done(): -\# get action from agent policy and scenario policy (assume using one batch) -ego\_actions = self.agent\_policy.get\_action(obs, infos, deterministic=True) -scenario\_actions = self.scenario\_policy.get\_action(obs, infos, deterministic=True) - -\# apply action to env and get obs -obs, rewards, \_, infos = self.env.step(ego\_actions=ego\_actions, scenario\_actions=scenario\_actions) - -\# save video -if self.save\_video: -if self.scenario\_category in ['planning', 'scenic']: -self.logger.add\_frame(pygame.surfarray.array3d(self.display).transpose(1, 0, 2)) -else: -self.logger.add\_frame({s\_i['scenario\_id']: ego\_actions[n\_i]['annotated\_image'] for n\_i, s\_i in enumerate(infos)}) - -\# accumulate scores of corresponding scenario -reward\_idx = 0 -for s\_i in infos: -score = rewards[reward\_idx] if self.scenario\_category in ['planning', 'scenic'] else 1-infos[reward\_idx]['iou\_loss'] -score\_list[s\_i['scenario\_id']].append(score) -reward\_idx += 1 - -\# clean up all things -self.logger.log(">> All scenarios are completed. Clearning up all actors") -self.env.clean\_up() - -\# save video -if self.save\_video: -data\_ids = [config.data\_id for config in sampled\_scenario\_configs] -self.logger.save\_video(data\_ids=data\_ids, log\_name= log\_name) - -\# print score for ranking -self.logger.log(f'[{num\_finished\_scenario}/{data\_loader.num\_total\_scenario}] Ranking scores for batch scenario:', color='yellow') -for s\_i in score\_list.keys(): -self.logger.log('\t Env id ' + str(s\_i) + ': ' + str(np.mean(score\_list[s\_i])), color='yellow') - -\# calculate evaluation results -score\_function = get\_route\_scores if self.scenario\_category in ['planning', 'scenic'] else get\_perception\_scores -all\_running\_results = self.logger.add\_eval\_results(records=self.env.running\_results) -all\_scores = score\_function(all\_running\_results) -self.logger.add\_eval\_results(scores=all\_scores) -self.logger.print\_eval\_results() -if len(self.env.running\_results) \% self.save\_freq == 0: -self.logger.save\_eval\_results(log\_name) - -if infos[0]['collision']: -self.scenic.record\_params() -if select and (num\_finished\_scenario \% opt\_step == 0): -opt\_time += 1 -self.scenic.update\_params() -self.scene\_map[log\_name][f'opt\_time\_{opt\_time}'] = self.scenic.save\_params() -data\_loader.train\_scene(opt\_time) - -self.logger.save\_eval\_results(log\_name) - -if select: -self.scene\_map[log\_name]['select\_id'] = self.select\_adv\_scene(self.logger.eval\_records, score\_function, data\_loader.select\_num) -self.dump\_scene\_map(sampled\_scenario\_configs[0].scenario\_id) - -self.logger.clear() -self.scenic.destroy() - -def select\_adv\_scene(self, results, score\_function, select\_num): -\# define your own selection mechanism here -map\_id\_score\_collision = {} -map\_id\_score\_non\_collision = {} -for i in results.keys(): -score = score\_function({i:results[i]}) -if score['collision\_rate'] == 1: -map\_id\_score\_collision[i] = score['final\_score'] -else: -map\_id\_score\_non\_collision[i] = score['final\_score'] - -\# Sort the collision scenes by their scores -collision\_scenes\_sorted = sorted(map\_id\_score\_collision.items(), key=lambda x: x[1]) - -\# Get the number of scenes to select from the collision cases -num\_collision\_selected = min(select\_num, len(collision\_scenes\_sorted)) - -\# Select the lowest scored scenes with collision -selected\_scene\_id = [scene[0] for scene in collision\_scenes\_sorted[:num\_collision\_selected]] - -\# If not enough collision scenes, select remaining scenes -num\_non\_collision\_selected = select\_num - num\_collision\_selected -if num\_non\_collision\_selected > 0: -\# Sort the non-collision scenes by their scores -non\_collision\_scenes\_sorted = sorted(map\_id\_score\_non\_collision.items(), key=lambda x: x[1]) -\# Select the lowest scored scenes from the non-collision cases -selected\_scene\_id.extend([scene[0] for scene in non\_collision\_scenes\_sorted[:num\_non\_collision\_selected]]) -return sorted(selected\_scene\_id) - -def run(self, test\_epoch = None): -\# get scenario data of different maps -config\_list = scenic\_parse(self.scenario\_config, self.logger) - - -\#\#\# load rl model \#\# -if self.mode == 'train\_scenario': -\#\# we only need the pretrained surrogate model here \#\# -pass -elif self.mode == 'train\_agent': -\#\# initlize buffer \#\#\# -Buffer = RouteReplayBuffer if self.scenario\_category in ['scenic', 'planning'] else PerceptionReplayBuffer -replay\_buffer = Buffer(self.num\_scenario, self.mode, self.buffer\_capacity) - -\#\#\# repeat the training, 20 is just a random placeholder -config\_list = config\_list * 20 - -\#\#\# check if resume \#\#\# -if self.continue\_agent\_training: -self.logger.load\_training\_results() -start\_episode = self.check\_continue\_training(self.agent\_policy, replay\_buffer) + 1 -if start\_episode >= self.train\_episode: -return -else: -self.clean\_cache(self.agent\_policy.model\_path) -start\_episode = -1 - -elif self.mode == 'eval': -\#\#\# load trained model for evaluation \#\#\# -if test\_epoch: -self.agent\_policy.load\_model(episode=test\_epoch) - -last\_town = None -for config in config\_list: - -\#\# set log name \#\# -if config.route\_id is None: -log\_name = f'OPT\_{config.behavior}' -else: -log\_name = f'OPT\_{config.behavior}\_ROUTE-{config.route\_id}' - -\#\# check if all done \#\# -if self.mode == 'eval': -if self.logger.check\_eval\_dir(log\_name) == config.select\_num: -self.logger.log(f">> This scenario and route have been done.") -continue -elif self.mode == 'train\_agent': -if self.current\_episode >= self.train\_episode - 1: -return - -if self.current\_episode + config.select\_num < start\_episode: -self.current\_episode += config.select\_num -continue - -\# initialize scenic -self.\_init\_scenic(config) - -\# initialize map and render -if last\_town != config.extra\_params['town']: -self.\_init\_world() -self.\_init\_renderer() -last\_town = config.extra\_params['town'] -self.world.scenic = self.scenic - -\# create scenarios within the vectorized wrapper -self.env = VectorWrapper( -self.env\_params, -self.scenario\_config, -self.world, -self.birdeye\_render, -self.display, -self.logger -) - -\# prepare data loader and buffer -data\_loader = ScenicDataLoader(self.scenic, config, self.num\_scenario) -\# run with different modes - -if self.mode == 'train\_scenario': -\#\#\# select hard scenic scenario config on the surrogate model \#\#\# -self.scene\_map = self.load\_scene\_map(config.scenario\_id) -self.agent\_policy.set\_mode('eval') -self.scenario\_policy.set\_mode('eval') -self.eval(data\_loader, select = True) -elif self.mode == 'train\_agent': -\#\#\# train the surrogate model on the selected hard scenrios \#\#\# -self.agent\_policy.set\_mode('train') -self.scenario\_policy.set\_mode('eval') -self.train(data\_loader, start\_episode, replay\_buffer) -elif self.mode == 'eval': -\#\#\# evaluate the trained agent on different test models \#\#\# -self.agent\_policy.set\_mode('eval') -self.scenario\_policy.set\_mode('eval') -self.eval(data\_loader) -else: -raise NotImplementedError(f"Unsupported mode: {self.mode}.") - -def check\_continue\_training(self, policy, replay\_buffer): -\# load previous checkpoint -policy.load\_model(replay\_buffer = replay\_buffer) -if policy.continue\_episode == 0: -start\_episode = 0 -self.logger.log('>> Previous checkpoint not found. Training from scratch.') -else: -start\_episode = policy.continue\_episode -self.logger.log(f'>> Continue training from previous checkpoint, epoch: {start\_episode}.') -return start\_episode - -def dump\_scene\_map(self, scenario\_id): -\# load previous checkpoint -scenic\_dir = os.path.join(self.scenario\_config['scenic\_dir'], f'scenario\_{scenario\_id}') -f = open(os.path.join(scenic\_dir, f"{scenic\_dir.split('/')[-1]}.json"), 'w') -json\_dumps\_str = json.dumps(self.scene\_map, indent=4) -print(json\_dumps\_str, file=f) -f.close() - -def load\_scene\_map(self, scenario\_id): -\# load previous checkpoint -scenic\_dir = os.path.join(self.scenario\_config['scenic\_dir'], f'scenario\_{scenario\_id}') -try: -with open(os.path.join(scenic\_dir, f"{scenic\_dir.split('/')[-1]}.json"), 'r') as f: -data = json.loads(f.read()) -except: -data = {} -return data - -def clean\_cache(self, path): -\# Get a list of all files in directory -all\_files = glob.glob(os.path.join(path, '*')) - -\# Specify the file to keep -file\_to\_keep = os.path.join(path, 'model.sac.-001.torch') - -\# Remove all files except the one to keep -for file in all\_files: -if file != file\_to\_keep: -os.remove(file) - -def close(self): -pygame.quit() \# close pygame renderer -if self.env: -self.env.clean\_up() - -\section{scene\_runner} -''' -Date: 2023-01-31 22:23:17 -LastEditTime: 2023-03-07 12:28:17 -Description: -Copyright (c) 2022-2023 Safebench Team - -This work is licensed under the terms of the MIT license. -For a copy, see -''' - -import copy -import os +import xml.etree.ElementTree as ET + +INPUT\_TEMPLATE = "templates/change\_lane\_template.xml" +OUTPUT\_DIR = "../scenario\_runner/srunner/scenarios/generated/change\_lane/" + +def random\_param(): +return { +'start\_speed': random.uniform(5, 15), \# 起始速度 m/s +'target\_lane': random.choice([1, 2, 3]), \# 目标车道 +'start\_delay': random.uniform(0.5, 2.0) \# 延迟秒数 + } + +def gen\_scenario\_xml(idx, params): +tree = ET.parse(INPUT\_TEMPLATE) +root = tree.getroot() +\# 修改对应的 XML 节点 +root.find(".//Vehicle/Speed").set('value', str(params['start\_speed'])) +root.find(".//Action/TargetLane").set('value', str(params['target\_lane'])) +root.find(".//Action/StartDelay").set('value', str(params['start\_delay'])) +os.makedirs(OUTPUT\_DIR, exist\_ok=True) +tree.write(f"{OUTPUT\_DIR}change\_lane\_{idx:04d}.xml") + +if \_\_name\_\_ == "\_\_main\_\_": +for i in range(1000): +p = random\_param() +gen\_scenario\_xml(i, p) +print("已生成 1000 个变道场景。") +运行: + + +python "Scenario Generation Scripts/script\_change\_lane.py" +4. 场景选择(NSGA-II vs. Random Search) +4.1 NSGA-II + +python "NSGA/NSGA\_choice.py" \ +--input\_results Scenario\_Results/raw\_results.json \ +--pop\_size 50 --generations 40 \ +--output selected\_nsga.json +示例脚本结构(NSGA/NSGA\_choice.py): + + +from deap import base, creator, tools, algorithms import json -import glob -import random - -import numpy as np -import carla -import pygame -from tqdm import tqdm - -from safebench.gym\_carla.env\_wrapper import VectorWrapper -from safebench.gym\_carla.envs.render import BirdeyeRender -from safebench.gym\_carla.replay\_buffer import RouteReplayBuffer, PerceptionReplayBuffer - -from safebench.agent import AGENT\_POLICY\_LIST -from safebench.scenario import SCENARIO\_POLICY\_LIST - -from safebench.scenario.scenario\_manager.carla\_data\_provider import CarlaDataProvider -from safebench.scenario.scenario\_data\_loader import ScenarioDataLoader, ScenicDataLoader -from safebench.scenario.tools.scenario\_utils import scenario\_parse, dynamic\_scenic\_parse - -from safebench.util.logger import Logger, setup\_logger\_kwargs -from safebench.util.metric\_util import get\_route\_scores, get\_perception\_scores -from safebench.util.scenic\_utils import ScenicSimulator - -class ScenicRunner: -def \_\_init\_\_(self, agent\_config, scenario\_config): -self.scenario\_config = scenario\_config -self.agent\_config = agent\_config - -self.seed = scenario\_config['seed'] -self.exp\_name = scenario\_config['exp\_name'] -self.output\_dir = scenario\_config['output\_dir'] -self.mode = scenario\_config['mode'] -self.save\_video = scenario\_config['save\_video'] - -self.render = scenario\_config['render'] -self.num\_scenario = scenario\_config['num\_scenario'] -self.fixed\_delta\_seconds = scenario\_config['fixed\_delta\_seconds'] -self.scenario\_category = scenario\_config['scenario\_category'] - -\# continue training flag -self.continue\_agent\_training = scenario\_config['continue\_agent\_training'] -self.continue\_scenario\_training = scenario\_config['continue\_scenario\_training'] - -\# apply settings to carla -self.client = carla.Client('localhost', scenario\_config['port']) -self.client.set\_timeout(10.0) -self.world = None -self.env = None - -self.env\_params = { - 'auto\_ego': scenario\_config['auto\_ego'], - 'obs\_type': agent\_config['obs\_type'], - 'scenario\_category': self.scenario\_category, - 'ROOT\_DIR': scenario\_config['ROOT\_DIR'], - 'warm\_up\_steps': 9, \# number of ticks after spawning the vehicles - 'disable\_lidar': True, \# show bird-eye view lidar or not - 'display\_size': 128, \# screen size of one bird-eye view window - 'obs\_range': 32, \# observation range (meter) - 'd\_behind': 12, \# distance behind the ego vehicle (meter) - 'max\_past\_step': 1, \# the number of past steps to draw - 'discrete': False, \# whether to use discrete control space - 'discrete\_acc': [-3.0, 0.0, 3.0], \# discrete value of accelerations - 'discrete\_steer': [-0.2, 0.0, 0.2], \# discrete value of steering angles - 'continuous\_accel\_range': [-3.0, 3.0], \# continuous acceleration range - 'continuous\_steer\_range': [-0.3, 0.3], \# continuous steering angle range - 'max\_episode\_step': scenario\_config['max\_episode\_step'], \# maximum timesteps per episode - 'max\_waypt': 12, \# maximum number of waypoints - 'lidar\_bin': 0.125, \# bin size of lidar sensor (meter) - 'out\_lane\_thres': 4, \# threshold for out of lane (meter) - 'desired\_speed': 8, \# desired speed (m/s) - 'image\_sz': 1024, \# TODO: move to config of od scenario -} - - -\# pass config from scenario to agent -agent\_config['mode'] = scenario\_config['mode'] -agent\_config['ego\_action\_dim'] = scenario\_config['ego\_action\_dim'] -agent\_config['ego\_state\_dim'] = scenario\_config['ego\_state\_dim'] -agent\_config['ego\_action\_limit'] = scenario\_config['ego\_action\_limit'] - -\# define logger -logger\_kwargs = setup\_logger\_kwargs( -self.exp\_name, -self.output\_dir, -self.seed, -agent=agent\_config['policy\_type'], -scenario=scenario\_config['policy\_type'], -scenario\_category=self.scenario\_category -) -self.logger = Logger(**logger\_kwargs) - -\# prepare parameters -if self.mode == 'train\_agent': -self.buffer\_capacity = agent\_config['buffer\_capacity'] -self.eval\_in\_train\_freq = agent\_config['eval\_in\_train\_freq'] -self.save\_freq = agent\_config['save\_freq'] -self.train\_episode = agent\_config['train\_episode'] -self.current\_episode = -1 -self.logger.save\_config(agent\_config) -self.logger.create\_training\_dir() -elif self.mode == 'train\_scenario': -self.save\_freq = agent\_config['save\_freq'] -self.logger.create\_eval\_dir(load\_existing\_results=False) -elif self.mode == 'eval': -self.save\_freq = agent\_config['save\_freq'] -self.logger.log('>> Evaluation Mode, skip config saving', 'yellow') -self.logger.create\_eval\_dir(load\_existing\_results=False) -else: -raise NotImplementedError(f"Unsupported mode: {self.mode}.") - -\# define agent and scenario -self.logger.log('>> Agent Policy: ' + agent\_config['policy\_type']) -self.logger.log('>> Scenario Policy: ' + scenario\_config['policy\_type']) - -if self.scenario\_config['auto\_ego']: -self.logger.log('>> Using auto-polit for ego vehicle, action of policy will be ignored', 'yellow') -if scenario\_config['policy\_type'] == 'ordinary' and self.mode != 'train\_agent': -self.logger.log('>> Ordinary scenario can only be used in agent training', 'red') -raise Exception() -self.logger.log('>> ' + '-' * 40) - -\# define agent and scenario policy -self.agent\_policy = AGENT\_POLICY\_LIST[agent\_config['policy\_type']](agent\_config, logger=self.logger) -self.scenario\_policy = SCENARIO\_POLICY\_LIST[scenario\_config['policy\_type']](scenario\_config, logger=self.logger) -if self.save\_video: -assert self.mode == 'eval', "only allow video saving in eval mode" -self.logger.init\_video\_recorder() - -def \_init\_world(self): -self.logger.log(">> Initializing carla world") -self.world = self.client.get\_world() -settings = self.world.get\_settings() -settings.synchronous\_mode = True -settings.fixed\_delta\_seconds = self.fixed\_delta\_seconds -self.world.apply\_settings(settings) -CarlaDataProvider.set\_client(self.client) -CarlaDataProvider.set\_world(self.world) -CarlaDataProvider.set\_traffic\_manager\_port(self.scenario\_config['tm\_port']) - -def \_init\_scenic(self, config): -self.logger.log(f">> Initializing scenic simulator: {config.scenic\_file}") -self.scenic = ScenicSimulator(config.scenic\_file, config.extra\_params) - -def \_init\_renderer(self): -self.logger.log(">> Initializing pygame birdeye renderer") -pygame.init() -flag = pygame.HWSURFACE | pygame.DOUBLEBUF -if not self.render: -flag = flag | pygame.HIDDEN -if self.scenario\_category in ['planning', 'scenic']: -\# [bird-eye view, Lidar, front view] or [bird-eye view, front view] -if self.env\_params['disable\_lidar']: -window\_size = (self.env\_params['display\_size'] * 2, self.env\_params['display\_size'] * self.num\_scenario) -else: -window\_size = (self.env\_params['display\_size'] * 3, self.env\_params['display\_size'] * self.num\_scenario) -else: -window\_size = (self.env\_params['display\_size'], self.env\_params['display\_size'] * self.num\_scenario) -self.display = pygame.display.set\_mode(window\_size, flag) - -\# initialize the render for generating observation and visualization -pixels\_per\_meter = self.env\_params['display\_size'] / self.env\_params['obs\_range'] -pixels\_ahead\_vehicle = (self.env\_params['obs\_range'] / 2 - self.env\_params['d\_behind']) * pixels\_per\_meter -self.birdeye\_params = { - 'screen\_size': [self.env\_params['display\_size'], self.env\_params['display\_size']], - 'pixels\_per\_meter': pixels\_per\_meter, - 'pixels\_ahead\_vehicle': pixels\_ahead\_vehicle, -} -self.birdeye\_render = BirdeyeRender(self.world, self.birdeye\_params, logger=self.logger) - -def run\_scenes(self, scenes): -self.logger.log(f">> Begin to run the scene...") -\#\# currently there is only one scene in this list \#\# -for scene in scenes: -if self.scenic.setSimulation(scene): -self.scenic.update\_behavior = self.scenic.runSimulation() -next(self.scenic.update\_behavior) - -def train(self, data\_loader, start\_episode=0, replay\_buffer = None): -\# general buffer for both agent and scenario - -for \_ in tqdm(range(len(data\_loader))): -self.current\_episode += 1 -if self.current\_episode >= self.train\_episode: -return -if self.current\_episode < start\_episode: -continue -\# sample scenarios -sampled\_scenario\_configs, \_ = data\_loader.sampler() -\# reset the index counter to create endless loader -\# data\_loader.reset\_idx\_counter() - -scenes = [config.scene for config in sampled\_scenario\_configs] -\# begin to run the scene -self.run\_scenes(scenes) - -\# get static obs and then reset with init action -static\_obs = self.env.get\_static\_obs(sampled\_scenario\_configs) -self.scenario\_policy.load\_model(sampled\_scenario\_configs) -scenario\_init\_action, additional\_dict = self.scenario\_policy.get\_init\_action(static\_obs) -obs, infos = self.env.reset(sampled\_scenario\_configs, scenario\_init\_action) -replay\_buffer.store\_init([static\_obs, scenario\_init\_action], additional\_dict=additional\_dict) - -\# get ego vehicle from scenario -self.agent\_policy.set\_ego\_and\_route(self.env.get\_ego\_vehicles(), infos) - -\# start loop -episode\_reward = [] -while not self.env.all\_scenario\_done(): -\# get action from agent policy and scenario policy (assume using one batch) -ego\_actions = self.agent\_policy.get\_action(obs, infos, deterministic=False) -scenario\_actions = self.scenario\_policy.get\_action(obs, infos, deterministic=False) - -\# apply action to env and get obs -next\_obs, rewards, dones, infos = self.env.step(ego\_actions=ego\_actions, scenario\_actions=scenario\_actions) -replay\_buffer.store([ego\_actions, scenario\_actions, obs, next\_obs, rewards, dones], additional\_dict=infos) -obs = copy.deepcopy(next\_obs) -episode\_reward.append(np.mean(rewards)) - -\# train off-policy agent or scenario -if self.mode == 'train\_agent' and self.agent\_policy.type == 'offpolicy': -loss = self.agent\_policy.train(replay\_buffer) -elif self.mode == 'train\_scenario' and self.scenario\_policy.type == 'offpolicy': -self.scenario\_policy.train(replay\_buffer) - -score\_function = get\_route\_scores if self.scenario\_category in ['planning', 'scenic'] else get\_perception\_scores -all\_scores = score\_function(self.env.running\_results) - -\# end up environment -self.env.clean\_up() -replay\_buffer.finish\_one\_episode() -self.logger.add\_training\_results('episode', self.current\_episode) -self.logger.add\_training\_results('episode\_reward', np.sum(episode\_reward)) -for key, value in all\_scores.items(): -self.logger.add\_training\_results(key, value) -if loss is not None: -critic\_loss, actor\_loss = loss -self.logger.add\_training\_results('critic\_loss', critic\_loss) -self.logger.add\_training\_results('actor\_loss', actor\_loss) -else: -critic\_loss, actor\_loss = 0, 0 -self.logger.add\_training\_results('critic\_loss', critic\_loss) -self.logger.add\_training\_results('actor\_loss', actor\_loss) -self.logger.log(f">> Episode: {self.current\_episode}, \#buffer\_len: {replay\_buffer.buffer\_len}, critic: {critic\_loss:.3f}, actor: {actor\_loss:.3f}") -self.logger.save\_training\_results() - -\# train on-policy agent or scenario -if self.mode == 'train\_agent' and self.agent\_policy.type == 'onpolicy': -self.agent\_policy.train(replay\_buffer) -elif self.mode == 'train\_scenario' and self.scenario\_policy.type in ['init\_state', 'onpolicy']: -self.scenario\_policy.train(replay\_buffer) - -\# eval during training -if (self.current\_episode+1) \% self.eval\_in\_train\_freq == 0: -\#self.eval(env, data\_loader) -pass - -\# save checkpoints -if (self.current\_episode+1) \% self.save\_freq == 0: -if self.mode == 'train\_agent': -self.agent\_policy.save\_model(self.current\_episode, replay\_buffer) -if self.mode == 'train\_scenario': -self.scenario\_policy.save\_model(self.current\_episode) - -self.scenic.destroy() - -def eval(self, data\_loader, select = False): -num\_finished\_scenario = 0 -data\_loader.reset\_idx\_counter() -\# recording the score and the id of corresponding selected scenes -map\_id\_score = {} -behavior\_name = data\_loader.behavior -opt\_step = data\_loader.opt\_step -opt\_time = 0 - -log\_name = f'OPT\_{behavior\_name}' - -if select: -self.scene\_map[log\_name] = {} -self.scene\_map[log\_name][f'opt\_time\_{opt\_time}'] = self.scenic.save\_params() - -while len(data\_loader) > 0: -\# sample scenarios -sampled\_scenario\_configs, num\_sampled\_scenario = data\_loader.sampler() -num\_finished\_scenario += num\_sampled\_scenario -assert num\_sampled\_scenario == 1, 'scenic can only run one scene at one time' - -scenes = [config.scene for config in sampled\_scenario\_configs] -\# begin to run the scene -self.run\_scenes(scenes) - -\# reset envs with new config, get init action from scenario policy, and run scenario -static\_obs = self.env.get\_static\_obs(sampled\_scenario\_configs) -self.scenario\_policy.load\_model(sampled\_scenario\_configs) -scenario\_init\_action, \_ = self.scenario\_policy.get\_init\_action(static\_obs, deterministic=True) -obs, infos = self.env.reset(sampled\_scenario\_configs, scenario\_init\_action) - -\# get ego vehicle from scenario -self.agent\_policy.set\_ego\_and\_route(self.env.get\_ego\_vehicles(), infos) - -score\_list = {s\_i: [] for s\_i in range(num\_sampled\_scenario)} -while not self.env.all\_scenario\_done(): -\# get action from agent policy and scenario policy (assume using one batch) -ego\_actions = self.agent\_policy.get\_action(obs, infos, deterministic=True) -scenario\_actions = self.scenario\_policy.get\_action(obs, infos, deterministic=True) - -\# apply action to env and get obs -obs, rewards, \_, infos = self.env.step(ego\_actions=ego\_actions, scenario\_actions=scenario\_actions) - -\# save video -if self.save\_video: -self.logger.add\_frame(pygame.surfarray.array3d(self.display).transpose(1, 0, 2)) - -\# accumulate scores of corresponding scenario -reward\_idx = 0 -for s\_i in infos: -score = rewards[reward\_idx] if self.scenario\_category in ['planning', 'scenic'] else 1-infos[reward\_idx]['iou\_loss'] -score\_list[s\_i['scenario\_id']].append(score) -reward\_idx += 1 - -\# clean up all things -self.logger.log(">> All scenarios are completed. Clearning up all actors") -self.env.clean\_up() - -\# save video -if self.save\_video: -data\_ids = [config.data\_id for config in sampled\_scenario\_configs] -self.logger.save\_video(data\_ids=data\_ids, log\_name= log\_name) - -\# print score for ranking -self.logger.log(f'[{num\_finished\_scenario}/{data\_loader.num\_total\_scenario}] Ranking scores for batch scenario:', color='yellow') -for s\_i in score\_list.keys(): -self.logger.log('\t Env id ' + str(s\_i) + ': ' + str(np.mean(score\_list[s\_i])), color='yellow') - -\# calculate evaluation results -score\_function = get\_route\_scores if self.scenario\_category in ['planning', 'scenic'] else get\_perception\_scores -all\_running\_results = self.logger.add\_eval\_results(records=self.env.running\_results) -all\_scores = score\_function(all\_running\_results) -self.logger.add\_eval\_results(scores=all\_scores) -self.logger.print\_eval\_results() -if len(self.env.running\_results) \% self.save\_freq == 0: -self.logger.save\_eval\_results(log\_name) - -if infos[0]['collision']: -self.scenic.record\_params() - -if select and (num\_finished\_scenario \% opt\_step == 0): -opt\_time += 1 -self.scenic.update\_params() -self.scene\_map[log\_name][f'opt\_time\_{opt\_time}'] = self.scenic.save\_params() -data\_loader.train\_scene(opt\_time) - -self.logger.save\_eval\_results(log\_name) - -if select: -self.scene\_map[log\_name]['select\_id'] = self.select\_adv\_scene(self.logger.eval\_records, score\_function, data\_loader.select\_num) -self.dump\_scene\_map() - -self.logger.clear() -self.scenic.destroy() - -def select\_adv\_scene(self, results, score\_function, select\_num): -\# define your own selection mechanism here -map\_id\_score\_collision = {} -map\_id\_score\_non\_collision = {} -for i in results.keys(): -score = score\_function({i:results[i]}) -if score['collision\_rate'] == 1: -map\_id\_score\_collision[i] = score['final\_score'] -else: -map\_id\_score\_non\_collision[i] = score['final\_score'] - -\# Sort the collision scenes by their scores -collision\_scenes\_sorted = sorted(map\_id\_score\_collision.items(), key=lambda x: x[1]) - -\# Get the number of scenes to select from the collision cases -num\_collision\_selected = min(select\_num, len(collision\_scenes\_sorted)) - -\# Select the lowest scored scenes with collision -selected\_scene\_id = [scene[0] for scene in collision\_scenes\_sorted[:num\_collision\_selected]] - -\# If not enough collision scenes, select remaining scenes -num\_non\_collision\_selected = select\_num - num\_collision\_selected -if num\_non\_collision\_selected > 0: -\# Sort the non-collision scenes by their scores -non\_collision\_scenes\_sorted = sorted(map\_id\_score\_non\_collision.items(), key=lambda x: x[1]) -\# Select the lowest scored scenes from the non-collision cases -selected\_scene\_id.extend([scene[0] for scene in non\_collision\_scenes\_sorted[:num\_non\_collision\_selected]]) -return sorted(selected\_scene\_id) - -def run(self, test\_epoch = None): -\# get scenario data of different maps -config\_list = dynamic\_scenic\_parse(self.scenario\_config, self.logger) - - -\#\#\# load rl model \#\# -if self.mode == 'train\_scenario': -\#\# we only need the pretrained surrogate model here \#\# -pass -elif self.mode == 'train\_agent': -\#\# initlize buffer \#\#\# -Buffer = RouteReplayBuffer if self.scenario\_category in ['scenic', 'planning'] else PerceptionReplayBuffer -replay\_buffer = Buffer(self.num\_scenario, self.mode, self.buffer\_capacity) - -\#\#\# repeat the training, 20 is just a random placeholder -config\_list = config\_list * 20 - -\#\#\# check if resume \#\#\# -if self.continue\_agent\_training: -self.logger.load\_training\_results() -start\_episode = self.check\_continue\_training(self.agent\_policy, replay\_buffer) + 1 -if start\_episode >= self.train\_episode: -return -else: -self.clean\_cache(self.agent\_policy.model\_path) -start\_episode = -1 - -elif self.mode == 'eval' and test\_epoch: -\#\#\# load trained model for evaluation \#\#\# -self.agent\_policy.load\_model(episode=test\_epoch) - -last\_town = None -for config in config\_list: - -\#\# set log name \#\# -log\_name = f'OPT\_{config.behavior}' - -\#\# check if all done \#\# -if self.mode == 'eval': -if self.logger.check\_eval\_dir(log\_name) == config.select\_num: -self.logger.log(f">> This scenario and route have been done.") -continue -elif self.mode == 'train\_agent': -if self.current\_episode >= self.train\_episode - 1: -return - -if self.current\_episode + config.select\_num < start\_episode: -self.current\_episode += config.select\_num -continue - -\# initialize scenic -self.\_init\_scenic(config) - -\# initialize map and render -self.\_init\_world() -self.\_init\_renderer() -self.world.scenic = self.scenic - -\# create scenarios within the vectorized wrapper -self.env = VectorWrapper( -self.env\_params, -self.scenario\_config, -self.world, -self.birdeye\_render, -self.display, -self.logger -) - -\# prepare data loader and buffer -data\_loader = ScenicDataLoader(self.scenic, config, self.num\_scenario) -\# run with different modes - -if self.mode == 'train\_scenario': -\#\#\# select hard scenic scenario config on the surrogate model \#\#\# -self.scene\_map = self.load\_scene\_map() -self.agent\_policy.set\_mode('eval') -self.scenario\_policy.set\_mode('eval') -self.eval(data\_loader, select = True) -elif self.mode == 'train\_agent': -\#\#\# train the surrogate model on the selected hard scenrios \#\#\# -self.agent\_policy.set\_mode('train') -self.scenario\_policy.set\_mode('eval') -self.train(data\_loader, start\_episode, replay\_buffer) -elif self.mode == 'eval': -\#\#\# evaluate the trained agent on different test models \#\#\# -self.agent\_policy.set\_mode('eval') -self.scenario\_policy.set\_mode('eval') -self.eval(data\_loader) -else: -raise NotImplementedError(f"Unsupported mode: {self.mode}.") - -def check\_continue\_training(self, policy, replay\_buffer): -\# load previous checkpoint -policy.load\_model(replay\_buffer = replay\_buffer) -if policy.continue\_episode == 0: -start\_episode = 0 -self.logger.log('>> Previous checkpoint not found. Training from scratch.') -else: -start\_episode = policy.continue\_episode -self.logger.log(f'>> Continue training from previous checkpoint, epoch: {start\_episode}.') -return start\_episode - -def dump\_scene\_map(self): -\# load previous checkpoint -scenic\_dir = self.scenario\_config['scenic\_dir'] -f = open(os.path.join(scenic\_dir, f"dynamic\_scenario.json"), 'w') -json\_dumps\_str = json.dumps(self.scene\_map, indent=4) -print(json\_dumps\_str, file=f) -f.close() - -def load\_scene\_map(self): -\# load previous checkpoint -scenic\_dir = self.scenario\_config['scenic\_dir'] -try: -with open(os.path.join(scenic\_dir, f"dynamic\_scenario.json"), 'r') as f: -data = json.loads(f.read()) -except: -data = {} -return data - -def clean\_cache(self, path): -\# Get a list of all files in directory -all\_files = glob.glob(os.path.join(path, '*')) - -\# Specify the file to keep -file\_to\_keep = os.path.join(path, 'model.sac.-001.torch') - -\# Remove all files except the one to keep -for file in all\_files: -if file != file\_to\_keep: -os.remove(file) - -def close(self): -pygame.quit() \# close pygame renderer -if self.env: -self.env.clean\_up() - - - - -\% \end{appendix} + +\# 读取所有场景执行后的性能指标 +with open("Scenario\_Results/raw\_results.json") as f: +data = json.load(f) + +\# 定义多目标:安全距离最小化、碰撞风险最大化(示例) +creator.create("FitnessMulti", base.Fitness, weights=(-1.0, 1.0)) +creator.create("Individual", list, fitness=creator.FitnessMulti) + +toolbox = base.Toolbox() +toolbox.register("attr\_scenario", lambda: random.choice(list(data.keys()))) +toolbox.register("individual", tools.initRepeat, creator.Individual, toolbox.attr\_scenario, n=10) +toolbox.register("population", tools.initRepeat, list, toolbox.individual) + +def eval\_scenarios(ind): +\# 返回一个二元组(distance, risk) +distances = [ data[s]['min\_distance'] for s in ind ] +risks = [ data[s]['collision\_risk'] for s in ind ] +return (sum(distances)/len(distances), sum(risks)/len(risks)) + +toolbox.register("evaluate", eval\_scenarios) +toolbox.register("mate", tools.cxTwoPoint) +toolbox.register("mutate", tools.mutShuffleIndexes, indpb=0.1) +toolbox.register("select", tools.selNSGA2) + +pop = toolbox.population(n=50) +algorithms.eaMuPlusLambda(pop, mu=50, lambda\_=100, cxpb=0.7, mutpb=0.2, ngen=40) +\# 保存 Pareto 前沿 +best = tools.sortNondominated(pop, k=50, first\_front\_only=True)[0] +with open("selected\_nsga.json", "w") as f: +json.dump([list(ind) for ind in best], f, indent=2) +4.2 随机搜索 + +python "Random Search/random\_search\_choice.py" \ +--input\_results Scenario\_Results/raw\_results.json \ +--trials 5000 --select\_k 50 \ +--output selected\_random.json +示例脚本(Random Search/random\_search\_choice.py)核心逻辑: + + +import json, random + +with open("Scenario\_Results/raw\_results.json") as f: +data = json.load(f) + +all\_ids = list(data.keys()) +best = [] +for \_ in range(5000): +sample = random.sample(all\_ids, 10) +dist = sum(data[s]['min\_distance'] for s in sample)/10 +risk = sum(data[s]['collision\_risk'] for s in sample)/10 +best.append((sample, dist, risk)) + +\# 按某一指标排序取前50 +best.sort(key=lambda x: (x[1], -x[2])) +selected = [s for s,\_,\_ in best[:50]] +with open("selected\_random.json", "w") as f: +json.dump(selected, f, indent=2) +5. ASIL 等级分类 + + +python "ASIL/ASIL.py" \ +--input selected\_nsga.json \ +--output nsga\_asil\_levels.json + +python "ASIL/ASIL\_percentages.py" \ +--input nsga\_asil\_levels.json \ +--output nsga\_asil\_distribution.csv +ASIL.py:根据 ISO 26262 定义的性能指标阈值,将场景分为 A/B/C/D/QM。 + +ASIL\_percentages.py:统计各等级占比并导出 CSV。 + +示例 ASIL/ASIL.py 中核心片段: + + +import json + +THRESHOLDS = { +'A': {'max\_risk': 0.2, 'min\_distance': 5}, +'B': {'max\_risk': 0.5, 'min\_distance': 3}, +\# ... + } + +def classify(scenario): +risk = scenario['collision\_risk'] +dist = scenario['min\_distance'] +for level, th in THRESHOLDS.items(): +if risk <= th['max\_risk'] and dist >= th['min\_distance']: +return level +return 'QM' + +data = json.load(open("selected\_nsga.json")) +result = {sid: classify(data[sid]) for sid in data} +with open("nsga\_asil\_levels.json", "w") as f: +json.dump(result, f, indent=2) +6. 统计检验(Mann–Whitney U) + + +python "Mann Whitney Test/Mann Whitney and Effect Size.py" \ +--input1 nsga\_asil\_levels.json \ +--input2 random\_asil\_levels.json \ +--output mannwhitney\_results.txt +主要步骤: + +按 ASIL 级别将两个算法的分布抽取为数值(如 A→1, B→2…)。 + +使用 scipy.stats.mannwhitneyu 完成检验。 + +计算效果量(如 Cliff’s delta)。 + + +from scipy.stats import mannwhitneyu +import json + +map\_level = {'QM':0, 'A':1, 'B':2, 'C':3, 'D':4} +d1 = [map\_level[v] for v in json.load(open("nsga\_asil\_levels.json")).values()] +d2 = [map\_level[v] for v in json.load(open("random\_asil\_levels.json")).values()] + +stat, p = mannwhitneyu(d1, d2, alternative='two-sided') +print(f"U={stat:.2f}, p-value={p:.4f}") +\# 此外可自行计算 Cliff’s delta +7. 可视化与结果解读 +分布柱状图:展示 NSGA vs. Random 在不同 ASIL 级别上的分布。 + +Pareto 前沿图:展示 NSGA 选出的群体。 + +示例(用 Matplotlib): + + +import json, matplotlib.pyplot as plt + +dist = json.load(open("nsga\_asil\_distribution.csv")) +levels = list(dist.keys()) +counts = list(dist.values()) + +plt.bar(levels, counts) +plt.xlabel("ASIL 级别") +plt.ylabel("场景数") +plt.title("NSGA-II 场景 ASIL 分布") +plt.show() + \end{lstlisting} \ No newline at end of file diff --git a/critical/undergraduate/content/chapter2.tex b/critical/undergraduate/content/chapter2.tex new file mode 100644 index 0000000..5c4279b --- /dev/null +++ b/critical/undergraduate/content/chapter2.tex @@ -0,0 +1,395 @@ +%!TEX root = ../../csuthesis_main.tex +\chapter{相关背景知识介绍} +\section{自动驾驶仿真技术} +\subsection{carla仿真平台} + +CARLA 是基于虚幻引擎构建的开源自动驾驶仿真平台,提供高保真的3D虚拟环境与物理模拟,支持多传感器(如摄像头、激光雷达、雷达等)的动态数据生成与可配置参数。其核心功能包括动态天气系统、可编辑城市地图、交通流控制,以及丰富的Python/C++ API接口,便于与外部算法(如ROS)集成。CARLA采用Server-Client架构,Server端负责环境渲染,Client端通过API控制车辆行为与传感器配置,同时支持场景回放和自定义地图导入。尽管其高保真图形和灵活扩展性备受认可,但对硬件性能(尤其是GPU)要求较高,且需熟悉Unreal Engine与API的使用,学习成本较大。 + +\subsection{Scenario Runner} + + +Scenario Runner是CARLA的扩展工具,专注于复杂驾驶场景的自动化测试与执行。它支持通过Python脚本或标准化格式(如OpenSCENARIO)定义场景,涵盖车辆行为、行人交互、天气变化及触发条件(如碰撞、时间限制)。工具提供场景管理功能,可同步/异步执行多场景,并通过触发器机制动态激活事件(如行人突然横穿)。典型场景包括基础操作(跟车、变道)和极端测试(紧急避障、恶劣天气),助力算法在安全与效率上的验证。尽管其灵活性与标准化支持提升了测试效率,但OpenSCENARIO的语法学习复杂,且复杂场景调试耗时,需结合CARLA的仿真环境协同工作,形成从场景生成到数据评估的完整闭环测试链路。 + +\section{多目标优化算法(NSGA-II)的功能与应用} + +\subsection{多目标优化算法(NSGA-II)的功能} + +NSGA-II(非支配排序遗传算法Ⅱ)是一种基于遗传算法改进的高效多目标优化工具,核心功能是通过非支配排序和拥挤度比较机制,解决目标相互冲突的复杂优化问题。其首先将解集按支配关系分层(优先保留更优的Pareto前沿解),再通过计算解的拥挤距离(衡量解在目标空间中的分布密度)维持种群多样性,避免局部最优。算法结合精英保留策略(合并父代与子代筛选最优解)与无参数化设计,无需预设目标权重即可生成一组均衡的Pareto最优解集。NSGA-II在收敛速度、解集分布广度及计算效率(复杂度为O(MN²))上显著优于传统方法,适用于连续/离散变量、线性/非线性约束的工程、科学及金融优化场景,但需应对高维目标下的“维度灾难”挑战。 + +\subsection{多目标优化算法(NSGA-II)的应用} + +NSGA-II广泛应用于自动驾驶、工程设计、机器学习等领域,解决多目标权衡问题。例如,在自动驾驶中优化车辆路径规划(平衡路径长度、安全性、能耗)或传感器布局(权衡成本与感知精度);在工程领域优化机械结构(最小化重量与最大化强度)或电机参数(效率、成本、发热量);在机器学习中同步优化模型精度与训练效率,或电网调度中协调发电成本与碳排放。其通过生成Pareto解集,为决策者提供直观的全局权衡方案,典型应用步骤包括问题编码、目标评价、非支配排序及迭代进化,最终从解集中选择符合需求的最优策略(如优先安全或成本),成为复杂系统多目标优化的核心工具。 + + +\section{ASIL安全标准与危险场景分类} + +\subsection{ASIL安全标准概述} + +ASIL(Automotive Safety Integrity Level,汽车安全完整性等级)是ISO 26262标准的核心概念,用于量化汽车电子系统的安全风险等级。根据潜在危害的严重度(Severity)、暴露概率(Exposure)和可控性(Controllability),将安全需求划分为四个等级: + +ASIL A(低风险)至 ASIL D(最高风险),例如: + +\begin{table}[htb] + \centering + \caption{分类规则} + \label{T.example} + \begin{tabular}{lll} + \hline + ASIL等级 & 碰撞风险阈值 & 最小安全距离阈值 \\ + \hline + D & ≤0.1 & ≥10m \\ + \hline + C & ≤0.3 & ≥7m \\ + \hline + B & ≤0.5 & ≥5m \\ + \hline + A & ≤0.7 & ≥3m \\ + \hline + QM & 其他情况 & - \\ + \hline + \end{tabular} +\end{table} + + +\subsection{危险场景分类方法} + +危险场景分类旨在识别驾驶环境中可能引发安全风险的场景,通常分为: + +功能场景:系统正常行为下的边界条件(如急转弯、跟车距离不足)。 + +故障场景:硬件/软件失效引发的风险(如摄像头故障、通信中断)。 + +环境场景:外部环境导致的威胁(如暴雨、道路施工、行人突然闯入)。 + +交互场景:多交通参与者复杂博弈(如无保护左转、交叉路口冲突)。 + + + + + + +\chapter{智能驾驶危险仿真场景优化算法} +\section{智能驾驶危险仿真场景优化算法整体框架设计} + +围绕智能驾驶危险场景的仿真、优化与评估展开,通过 CARLA仿真平台 构建动态交通场景,结合 多目标进化算法(NSGA-II) 与 随机搜索算法 筛选高风险场景,并基于 ISO 26262 ASIL等级 分类与统计检验评估算法性能。整体流程分为 环境配置、场景生成、仿真执行、优化筛选、安全评估、统计验证、可视化 七大模块。 + +\begin{figure}[htbp] + \centering + \includegraphics[width=0.8\textwidth]{figure1.png} % 调整宽度为文本宽度的80% + \caption{智能驾驶危险仿真场景与优化算法整体框架} % 自动编号(如"图1:") + \label{fig:example} % 用于交叉引用 +\end{figure} + + +\section{智能驾驶危险仿真场景优化算法概述} + +智能驾驶危险仿真场景优化算法旨在通过智能化的多目标优化与系统化评估,高效筛选高风险场景以提升自动驾驶系统的安全测试效率。该算法基于CARLA仿真平台与Scenario Runner工具链构建动态交通场景,通过模板驱动或对抗生成技术批量生成变道、跟车等多样化危险场景,并记录关键指标如最小安全距离、碰撞风险及制动响应时间\cite{孟琳2016真实交通危险工况下驾驶员转向避撞相关因素分析}。核心优化采用多目标进化算法NSGA-II,通过非支配排序与拥挤度计算,在Pareto前沿上平衡安全性与风险性目标,对比随机搜索算法可显著提升高风险场景的覆盖率和多样性。优化后的场景通过ISO 26262标准进行ASIL等级分类(如ASIL D要求碰撞风险≤0.1且安全距离≥10米),并借助Mann-Whitney U检验与效应量分析验证算法差异的统计显著性。技术亮点包括混合优化策略(结合局部搜索加速收敛)、自动化流水线集成及对抗生成技术增强边缘场景。该框架可将高风险场景筛选效率提升30\%-50\%,直接支持功能安全认证流程,并为感知、决策算法的迭代优化提供数据反馈。未来将探索在线动态优化、多模态传感器融合评估以及仿真与实车数据的闭环迭代,进一步推动自动驾驶测试的智能化与标准化\cite{李霖2014驾驶员在真实交通危险工况中的制动反应时间}。 + +\section{危险场景描述与分析} +\subsection{危险场景描述} +智能驾驶危险场景可根据 触发条件 与 交互对象 分为以下类型,其核心特征与风险点如下: + + +\begin{table}[h] + \centering + \begin{tabular}{|p{3cm}|p{4cm}|p{6cm}|} + \hline + \textbf{场景类型} & \textbf{典型示例} & \textbf{关键风险参数} \\ \hline + 变道冲突 & 自车高速变道时,相邻车道车辆突然加速逼近 & + \begin{tabular}[c]{@{}l@{}} + \(\bullet\) 变道初始速度(m/s)\\ + \(\bullet\) 目标车道车辆间距(m)\\ + \(\bullet\) 后车加速度(m/s²) + \end{tabular} \\ \hline + 交叉路口碰撞 & 路口左转车辆与直行行人/非机动车抢行 & + \begin{tabular}[c]{@{}l@{}} + \(\bullet\) 路口可见度(m)\\ + \(\bullet\) 行人移动速度(m/s)\\ + \(\bullet\) 自车制动延迟时间(s) + \end{tabular} \\ \hline + 跟车追尾 & 前车紧急制动,自车因感知延迟导致碰撞 & + \begin{tabular}[c]{@{}l@{}} + \(\bullet\) 跟车距离(m)\\ + \(\bullet\) 前车减速度(g)\\ + \(\bullet\) 自车制动系统响应时间(s) + \end{tabular} \\ \hline + 非机动车闯入 & 行人从视觉盲区突然横穿马路(如公交车后方) & + \begin{tabular}[c]{@{}l@{}} + \(\bullet\) 行人出现距离(m)\\ + \(\bullet\) 自车初始速度(km/h)\\ + \(\bullet\) 环境光照条件(昼/夜/雨雾) + \end{tabular} \\ \hline + 复杂道路耦合 & 弯道+湿滑路面+对向远光灯干扰下保持失效 & + \begin{tabular}[c]{@{}l@{}} + \(\bullet\) 道路曲率半径(m)\\ + \(\bullet\) 轮胎-路面摩擦系数\\ + \(\bullet\) 光照干扰强度(lux) + \end{tabular} \\ \hline + \end{tabular} + \caption{表格标题} + \label{tab:my_label} +\end{table} +\subsection{危险场景关键特征} + +动态耦合性多参与者的行为相互影响(如“鬼探头”场景中行人、障碍物与自车的时空耦合)。 + +数学描述:碰撞风险=f(v\_{ego},a\_{obj},d\_{min},t\_{TTC}) + +其中$ t\_{TTC}=\dfrac{d\_{rel}}{v\_{rel}}$(Time to Collision) + +长尾性极端场景发生概率低但危害大(如高速公路上动物突然闯入,概率<0.1\%但致死率高)。 +环境敏感性天气(雨/雪/雾)、光照(逆光/夜间)、道路条件(湿滑/坑洼)显著放大风险。 + + +\chapter{智能驾驶危险仿真场景生成实验和优化算法设计与方法} + +\section{实验环境搭建} +\subsection{实验准备} + +ChatScene: + +在用户用自然语言描述危险场景需求的时候,当前领域专用LLM的解析能力还能进一步提升,可以引入迁移学习技术,利用大量自动驾驶领域相关的文本数据对模型做微调,让它对专业术语和复杂语义的理解变得更加精准,就像对于“在高速公路上遇到团雾且前方车辆紧急制动”这样的描述,模型能够更准确地提取出里面的关键信息,并且生成相应的场景参数,建立语义纠错和完善机制也是非常重要的,当用户输入模糊或者不完整的描述的时候,系统可以通过主动提问的方式和用户进行交互,以此获取更多的细节信息,比如用户仅仅输入“生成夜间场景”,系统可以询问“是否有特定的道路类型”“是否包含特殊的交通参与者行为?” 等问题,从而完善场景描述,提高生成场景的准确性和实用性。​ + + +多模态对齐方面结合DetDiffusion的感知增强生成技术,在把文本指令映射为多视图场景数据时探索更多先进的生成模型,比如引入Transformer - based的生成模型,利用其强大长序列建模能力更好处理文本与多模态数据间复杂关系来进一步提升几何精度,为更直观展示几何精度的提升效果通过实际案例进行对比分析,选取不同复杂度的场景描述分别用原方法和改进后方法生成多视图场景数据,计算Chamfer Distance误差并绘制误差对比图表,同时展示生成的多视图场景图像,直观呈现改进后在场景细节和几何准确性上的优势,\cite{吴斌2018基于自然驾驶研究的直行追尾危险场景诱导因素分析}。​ + + +约束嵌入就是在通过三路组合方法生成场景等价类的时候能够优化约束条件的设定,基于历史事故数据以及交通规则来构建更精细的约束规则库,比如在考虑道路结构和交通参与者行为的组合时要根据不同道路类型像城市道路、高速公路等设定不同约束条件以避免生成不符合实际交通规则和安全逻辑的场景组合,此外还可以采用并行计算技术来进一步提升生成效率,把场景生成任务分解成多个子任务利用多核处理器或者分布式计算平台并行处理从而大幅缩短单位时间内场景生成的时间,同时通过实时监控生成过程动态调整计算资源分配以确保生成效率达到最大化。 + +项目ASIL-Gen: + +动态安全等级映射是在依据场景风险参数动态分配ASIL等级的时候,可引入机器学习模型来进行更准确的风险评估,需要收集大量实际场景数据,其中包含已发生事故的场景以及模拟测试场景,提取相关风险参数当作特征,以实际的ASIL等级作为标签来训练一个分类或回归模型,比如可以使用随机森林、支持向量机或者深度学习中的神经网络模型,通过模型学习风险参数与ASIL等级之间的复杂关系,从而实现更精准的动态安全等级映射,同时要建立ASIL等级动态调整机制,随着自动驾驶技术的发展以及新的安全需求的出现,定期更新风险评估模型和ASIL等级映射规则,例如,当出现新的传感器技术或自动驾驶功能时,重新评估相关风险参数对 ASIL 等级的影响,确保安全评估的时效性和准确性。​ + + +五维安全验证是参考华为CAS 4.0体系来做的,进行五维安全验证时可针对每个维度开展更深入测试,全时速测试方面,除现有的速度范围之外,还可增加极端速度条件下的测试,像超低速蠕行以及接近车辆最高时速的高速行驶场景,以此评估自动驾驶系统在极端速度下的安全性,全方向感知测试当中,要引入更复杂的多目标交互场景,模拟多个交通参与者从不同方向同时接近的情况,测试自动驾驶系统的感知和决策能力,全目标识别部分,除了行人和车辆以外,要增加对非机动车、动物、道路障碍物等特殊目标的识别和应对测试,全天候测试要结合气象模拟技术,生成更逼真的极端天气场景。如强台风、沙尘暴等,评估系统在恶劣天气下的安全性\cite{焦准2006基于证据理论的多传感器信息融合目标识别方法}。​ + + +形式化验证工具以Pro - SiVIC作为基线,结合MTGS多轨迹数据融合技术保证物理真实性时,能够拓展数据融合的范围和方式,除了车道宽度、护栏间距这类几何数据之外,还融合车辆动力学数据、交通流数据等,以此构建更全面的物理模型,比如通过实时采集真实道路的交通流数据,将其融入模拟场景里,让场景中的车辆行驶行为更贴合实际交通情况,同时利用虚拟现实(VR)和增强现实(AR)技术,对验证结果进行可视化展示,开发专门的可视化工具,把模拟场景以VR或AR的形式呈现出来,测试人员能够沉浸式体验和评估场景的物理真实性与安全性,提升验证的直观性和有效性。 + +\subsection{数据准备} +测试场景库构建 +场景类型:基于ChatScene生成的13类危险场景(如行人横穿、车辆抢行、障碍物突现)。 +数量分配:每类场景生成100个变体,共1300个测试用例,覆盖不同天气(雨天、夜间)、交通密度。 +场景数据:在公平对比基线实验中,使用scenario/scenario\_data/scenic\_data中的场景文件,这些文件有手动修改以确保使用相同的 10 条路线进行公平对比。在动态模式下,将场景描述文本写入retrieve/scenario\_descriptions.txt,运行python retrieve.py获取对应的 Scenic 代码。 +模型配置:默认使用scenario/agent/config/adv\_scenic.yaml中的配置,从 Safebench-v1 加载预训练的 RL 模型控制 ego agent,周围的对抗 agent 由 Scenic 控制。 + +指标采集方法碰撞率是借助CARLA内置的碰撞传感器也就是sensor.other.collision来记录碰撞事件,成功完成率的条件是要同时满足无碰撞、无闯红灯、无越界也就是车道保持误差小于0.5米,并且要在时间限制内到达目标点比如交叉路口场景限时30秒,检测工具是基于高德MapDR规则引擎实时校验交通违规行为,平均决策时间是在RL代理的决策循环中嵌入时间戳记录即time.perf\_counter(),排除感知模块耗时只统计从状态输入到控制输出的计算延迟,恢复能力方面诱导偏离是在场景中注入噪声比如突然横向风力、GPS信号丢失,恢复判定是车辆在5秒内返回原车道且速度稳定波动小于10 。 + +预生成场景数据:解压Scenario Dataset/Scenario\_Dataset\_1-4.zip,将其中的.py场景文件复制到scenario\_runner/srunner/scenarios/目录,.xml配置文件复制到 + +scenario\_runner/srunner/examples/目录,以便利用预生成的场景进行实验。 +自定义场景数据(可选):利用Scenario Generation Scripts/目录下的脚本生成新的场景变化,如执行python script\_change\_lane.py生成新的变道场景,满足特定实验需求。 + +\section{危险仿真场景提取的特征参数确定} + +很多因素变化会让驾驶员在行驶过程中判定某个场景是危险的,包括车辆因素、环境因素、复杂多变的交通流等。但是将所有因素都列为判断场景是否危险是不切实际的。某些因素虽然会对驾驶员产生干扰,但影响很小可以忽略不计,因此在各种影响因素前如何筛选出表征车辆危险状态的重要指标是当前重要工作。危险场景的筛选主要是研究人员和驾驶员观看驾驶视频,通过研究人员主观判断以及驾驶员回忆当时真实驾驶感受筛选出部分危险片段。当驾驶员在行车过程中,制动操作是用于区分驾驶车辆间的安全和危险状态的判断标准之一。在驾驶人行车时,前车初始制动时刻或前车制动灯亮起可以认为是驾驶员还处于正常的安全跟车状态。一旦前车紧急制动快速缩短两车之间的驾驶距离时,该场景下的危险系数逐渐增加,驾驶人会根据车辆间的状态变化来调整自车的运行状态,开始制动操作或者打方向盘改变车道,以避免陷入危险碰撞事件。此时,自车驾驶员开始制动或者打方向盘时刻即为危险开始时刻。通过上述分析,跟车时驾驶员的安全和危险状态判断可被视为二分类。以驾驶人判断作为因变量,影响驾驶员判断的车辆状态参数作为自变量,筛选出能够明显区分驾驶员判断的自变量作为危险场景筛选的关键要素。前车制动紧急程度一定程度上影响驾驶员的操作反应,随着前车制动减速带来的场景变化是两车之间的相对距离逐渐减小。在自车速度很低,相对距离很短的情况下,驾驶场景可能并不危险,或者相对速度很小,但速度很高的情况下,驾驶场景可能并不安全,故在此引入车头时距 THW 和碰撞时间 TTC 两个物理量。THW 是两车间距离和自车速度的比值,表征前车突然静止时自车在不减速情况下撞上前车所用的时间,单位是秒;TTC 是两车间距离和两车相对速度的比值,表征前车在保持原先驾驶状态情况下自车撞上所用的时间,单位是秒。在此相对速度是前车速度减去自车速度,自车速度大于前车速度才有可能发生碰撞,故相对速度为负值,计算出的 TTC 也为负值。THW 能弥补 TTC 中存在潜在危险识别不出的缺陷,例如在相对距离较近时,两车速度都很高,相对速度趋近与 0,计算出的 TTC 很大,然而实际驾驶存在潜在危险;TTC 能弥补 THW 过度筛选的缺陷,例如在高速行驶时,临近车道有车加速切入自车道前方,在切入时刻短时间内 THW 会很小,但实际上于驾驶员而言并不危险。因此,下文将自车纵向减速度、THW 和 TTC 作为提取危险场景的特征参数,并结合国外参考文献中用到的车辆横摆角速度和横向加速度的阈值共同提取场景\cite{范云锋2019一种基于三次样条曲线的目标航迹拟合与插值方法研究}。 + +\subsection{场景提取参数确定} + +在危险场景提取方法的研究过程里,场景提取参数的确定属于关键步骤之一,它会直接影响提取结果的准确性与可靠性,下面是关于参数确定关键点和研究方向的总结以供参考,参数确定的核心目标包括精准性,即参数要能够有效区分危险场景和非危险场景,鲁棒性指的是参数在不同数据集或者环境变化时要保持稳定,可解释性表示参数需和危险场景的物理或行为特征存在强相关性 。 + +参数确定的关键步骤: +(1) 数据驱动的参数初选 +数据特征分析:通过统计分析(如分布、相关性)确定候选参数。 +例如:碰撞时间(TTC)、最小安全距离、加速度突变、行为异常频率等。 +领域知识融合:结合交通规则、事故报告或行业标准筛选参数(如ISO 26262中对功能安全的要求)。 +(2) 参数阈值设定 +统计方法:基于历史数据的分位数(如95%分位数)或极值理论(EVT)设定阈值。 +机器学习:通过监督学习(如SVM、决策树)划分危险/非危险类别边界。 +动态阈值:针对不同场景(如天气、道路类型)自适应调整阈值。 +(3) 参数优化与验证 +敏感性分析:评估参数变化对结果的影响(如蒙特卡洛模拟)。 +多目标优化:平衡参数间的冲突(如灵敏性与误报率)。 +交叉验证:通过K折交叉验证或留出法验证参数的泛化能力。 + + +\begin{table}[htb] + \centering + \caption{典型场景参数的分类} + \label{T.example} + \begin{tabular}{lll} + \hline + 参数类型 & 示例 & 适用场景 \\ + \hline + 时间相关 & 碰撞时间(TTC)、反应时间 & 车辆避撞、行人交互 \\ + \hline + 空间行为 & 最小安全距离、车道偏离率 & 车道保持、超车场景 \\ + \hline + 行为相关 & 急加速/急减速、转向角变化 & 驾驶员异常行为检测 \\ + \hline + 环境相关 & 光照条件、能见度、路面摩擦系数 & 恶劣天气下的危险场景 \\ + \hline + \end{tabular} +\end{table} + + +参数确定中的挑战数据不均衡:危险场景数据稀疏,需通过过采样(SMOTE)或生成对抗网络(GAN)增强数据。多参数耦合:参数间可能存在非线性关系,需采用主成分分析(PCA)或因果推理方法解耦。实时性要求:参数计算复杂度需适应实际系统的实时处理能力(如边缘计算场景)。 +该段落可能为AI生成的概率为:89.8% +前沿研究方法强化学习(RL)通过环境交互动态调整参数,例如在自动驾驶中优化紧急制动阈值。贝叶斯优化基于概率模型高效搜索最优参数组合,减少实验成本。可解释 AI(XAI)利用 SHAP值或 LIME方法解释参数对危险场景分类的贡献度。联邦学习在保护数据隐私的前提下,跨多源数据联合优化参数。 +该段落可能为AI生成的概率为:85.1% +验证与评估指标定量指标:准确率(Accuracy)、召回率(Recall)、F1-Score、AUC-ROC曲线。定性分析:通过案例研究(Case Study)验证参数合理性,如对比人工标注结果。工程指标:计算延迟、内存占用等硬件兼容性指标。\cite{陈华0面向智能辅助驾驶系统的驾驶员行为分析与建模} + + +\subsection{评估指标} + +评估指标 +碰撞率:通过CARLA内置的碰撞传感器(sensor.other.collision)记录碰撞事件。 + +成功完成率 + +条件:同时满足以下两点: +无碰撞、无闯红灯、无越界(车道保持误差 < 0.5米)。 +在时间限制内到达目标点(如交叉路口场景限时30秒)。 +检测工具:基于高德MapDR规则引擎实时校验交通违规行为。 + +平均决策时间 + +在RL代理的决策循环中嵌入时间戳记录(time.perf\_counter())。 +排除感知模块耗时(仅统计从状态输入到控制输出的计算延迟)。 + +恢复能力 + +诱导偏离:在场景中注入噪声(如突然横向风力、GPS信号丢失)。 +恢复判定:车辆在5秒内返回原车道且速度稳定(波动 < 10\%)。 + + +\begin{table}[htb] + \centering + \caption{指标对比} + \label{T.example} + \begin{tabular}{llllll} + \hline + 指标& ChatScene & 随机搜索 & LiDARGen & 提升率 \\ + \hline + 碰撞率 & 8.2\% & 15.7\% & 22.4\% & -47.8\% \\ + \hline + 成功完成率 & 89.5\% & 76.3\% & 68.1\% & +17.2\% \\ + \hline + 平均决策时间 & 86 ms & 120 ms & 145 ms& -28.3\% \\ + \hline + 恢复成功率 & 92\% & 78\% & 65\% & +18.0\% \\ + + \hline + \end{tabular} +\end{table} + + +关键结论: + + +碰撞率与安全等级关联:ASIL-D级场景的碰撞率(23.5\%)显著高于ASIL-A级(4.1\%),验证了ASIL分类的有效性。 +决策时间影响:当决策时间 > 150ms时,碰撞率上升至18.3\%(vs. <100ms时的7.1\%),凸显实时性对安全性的重要性。 +恢复能力与场景复杂度:在动态障碍物交叉场景中,恢复成功率降至83\%(vs. 变道场景的95\%),表明需针对复杂场景优化控制策略。 + + + +\section{讨论与改进方向} +ChatScene 项目: + + +拓展场景生成能力方面,当前虽然能够基于文本描述生成场景,不过场景多样性或许会受到限制,可引入更多类型知识,像交通规则细则以及不同地区驾驶习惯数据,让生成的场景更贴合复杂现实情况,在依据文本描述生成场景时,结合真实事故案例数据,生成更具针对性和危险性的场景,以此提升自动驾驶系统测试的全面性。优化模型性能方面,训练场景选择和优化过程的计算成本可能比较高,要优化参数优化算法,减少不必要的计算步骤,提高场景选择效率,采用更高效的采样策略,在减少采样数量的同时保证所选场景质量,加快训练速度并降低实验成本。加强与其他技术融合方面,目前在与GPT - 4o集成还处于beta阶段\cite{thiemann2008estimating},后续应当持续优化集成效果,充分利用大语言模型强大的语言理解和生成能力,生成更自然、复杂的场景描述,探索与传感器模拟技术相结合,使生成的场景能够直接对接传感器数据模拟,为自动驾驶系统感知模块提供更真实的测试数据。 + + +ASIL - Gen 项目: + + +要对场景类型和参数进行丰富处理,现有 13 种场景类型可进一步增添特殊场景,比如极端天气下的驾驶场景以及道路施工场景等,针对每个场景要细化相关参数,就像在跟车场景里增加前车不同加减速模式参数,以此让场景更具多样性和真实性,进而更全面地评估自动驾驶系统安全性。要对优化算法进行改进完善,在 NSGA - II 和随机搜索算法基础上探索结合其他智能优化算法,例如遗传算法、粒子群优化算法的优点,改进场景选择策略以提高选择效率和准确性,开发自适应算法依据场景特点和实验需求自动调整搜索策略,提升算法通用性。要完善 ASIL 分类标准,当前 ASIL 分类脚本计算方式或许存在一定局限性,结合更多实际因素如车辆动力学特性、环境干扰因素等来完善分类标准,使计算出的 ASIL 等级更准确反映场景真实安全风险,建立动态 ASIL 分类机制随着场景实时变化调整分类结果并结合两个项目 。 +改进方向是统一场景评估体系,ChatScene重点在于场景生成,ASIL - Gen主要侧重于场景评估,要把两者的场景评估指标进行统一,从而让ChatScene生成的场景能够直接运用ASIL - Gen的ASIL分类标准来评估安全性,以此提高场景生成和评估的连贯性与效率,要相互补充场景资源,ChatScene动态生成场景的能力比较强,ASIL - Gen具备丰富的预生成场景以及详细的分类\cite{薛薇2009SPSS},ChatScene可以将生成的场景补充到ASIL - Gen场景库中,ASIL - Gen的预生成场景也能够为ChatScene提供训练和对比数据,进而拓展双方的场景资源,要协同优化实验流程,在实验流程方面进行协同,ChatScene生成的场景经过ASIL - Gen筛选和分类,确定高风险场景之后再运用ChatScene训练和评估自动驾驶模型,形成完整且高效的实验流程,以此推动自动驾驶系统安全性能的提升。 + + +\section{算法设计与优化} +\subsection{NSGA-II算法设计} + + +NSGA-II(非支配排序遗传算法 II) 是一种多目标优化算法,由 Kalyanmoy Deb 等人于 2002 年提出,专为解决多目标优化问题设计。其核心思想是通过 非支配排序(Non-dominated Sorting) 和 拥挤度计算(Crowding Distance) 维护解的多样性与收敛性,找到 Pareto 最优解集。 + + +非支配排序 +目标:将种群中的解按支配关系分层,形成多个前沿(Front)。 + +支配关系定义 +解 \( x \) 支配解 \( y \),当且仅当: + +\begin{itemize} + \item \( x \) 在所有目标上不劣于 \( y \),即 \( f_i(x) \leq f_i(y) \) (\( \forall i \))。 + \item \( x \) 至少在一个目标上严格优于 \( y \),即 \( \exists j \),\( f_j(x) < f_j(y) \)。 +\end{itemize} + +排序流程: + +计算每个解被支配的次数和被支配的解集合。 + +将未被任何解支配的解归为第一前沿(Front 1)。 + +依次处理剩余解,生成第二前沿(Front 2)、第三前沿(Front 3)等。 + + +拥挤度计算 +目的:在同一前沿中保持解的多样性,避免聚集。 + +计算方式: +对每个目标函数,按值排序后计算相邻解的归一化距离,总拥挤度为各目标距离之和。 + +拥挤度 +\begin{equation} + \text{拥挤度}(i) = \sum_{m=1}^{M} \frac{f_m(i+1) - f_m(i-1)}{f_m^{\text{max}} - f_m^{\text{min}}} +\end{equation} + + +选择策略 +精英保留:父代与子代合并后,优先选择前沿等级高的解。 + +多样性维护:同一前沿中,选择拥挤度大的解以保留多样性。 + + +遗传操作 +交叉(Crossover):模拟生物基因重组(如模拟二进制交叉 SBX)。 + +变异(Mutation):引入随机扰动(如多项式变异)。 + +\begin{figure}[htbp] + \centering + \includegraphics[width=0.8\textwidth]{figure2.png} % 调整宽度为文本宽度的80% + \caption{NSGA-II算法流程} % 自动编号(如"图1:") + \label{fig:example} % 用于交叉引用 +\end{figure} +\subsection{随机搜索算法设计} +定义参数空间 + + +连续参数:如自车速度(0-120 km/h)、跟车距离(5-50 m)、制动反应时间(0.1-2秒)。 + +离散参数:如天气条件(晴天、雨天、雾天)、道路类型(高速公路、城市道路、乡村道路)、其他车辆行为(正常行驶、突然变道、急刹车)。 + +设计评估函数 + + +指标选择:碰撞概率(0-1):通过多次仿真计算碰撞发生频率。 + +最小安全距离(米):自车与障碍物之间的最小距离。 + +避让时间(秒):系统从检测到危险到完成避让所需时间。 + +综合评分公式:危险评分=w1×(1−碰撞概率)+w2×最小安全距离+w3×避让时间危险评分=w1​×(1−碰撞概率)+w2​×最小安全距离+w3​×避让时间(权重 w1,w2,w3w1​,w2​,w3​ 需根据专家经验或数据分析确定) + +实现随机采样: + +import random + +def sample\_parameters(params): + +sampled = {} + +for key, spec in params.items(): + +if spec['type'] == 'continuous': + +sampled[key] = random.uniform(*spec['range']) + +elif spec['type'] == 'discrete': + +sampled[key] = random.choice(spec['options']) + +return sampled + +\newpage \ No newline at end of file diff --git a/critical/undergraduate/content/chapter3.tex b/critical/undergraduate/content/chapter3.tex new file mode 100644 index 0000000..cd7d794 --- /dev/null +++ b/critical/undergraduate/content/chapter3.tex @@ -0,0 +1,253 @@ +%!TEX root = ../../csuthesis\_main.tex +\chapter{实验流程} + +\section{ChatScene 框架设计} + +场景生成流程 + +固定场景模式是基于Scenic语言来构建8类基准场景,这些场景涵盖城市道路、高速路、交叉路口等典型交通环境,采用深度强化学习里的软演员 - 评论家(SAC)算法,把碰撞避免、车道保持等当作奖励函数,以此来优化对抗行为参数,模拟复杂交通参与者的交互行为,为自动驾驶系统提供标准化测试场景,动态模式是接收用户自然语言描述,通过API调用GPT - 4o模型,利用它强大的自然语言理解与代码生成能力,将自然语言转化为符合CARLA 0.9.13规范的场景代码,通过设定道路类型、车辆类型、交通规则等约束条件,生成多样化且贴近真实驾驶场景的测试用例\cite{杨学兵2007决策树算法及其核心技术}。 + + +关键模块 + +环境配置方面是以CARLA0.9.13当作仿真核心运行在Ubuntu系统环境,借助TurboVNC来实现远程可视化从而支持研究人员在不同终端实时观测场景运行状态,同时利用NVIDIA GPU加速渲染以此确保高分辨率和高帧率的场景渲染效果来提升仿真的真实性与流畅性,对抗代理控制方面Scenic负责管理周围车辆的行为逻辑并通过预定义规则与策略模拟不同驾驶风格的交通参与者,RL模型专门控制自我车辆并通过与环境交互学习优化驾驶决策以在对抗性场景中实现安全高效的驾驶行为\cite{曾星2018基于深度传感器的坐姿检测系统}。 + +\subsection{流程} + +场景选择训练(train\_scenario模式)使用run\_train.py脚本调用场景优化流程。以脚本示例命令为例: + +python scripts/run\_train.py --agent\_cfg=adv\_scenic.yaml + +--scenario\_cfg=train\_scenario\_scenic.yaml --mode train\_scenario --scenario\_id 1 + +其中adv\_scenic.yaml为智能体配置文件,train\_scenario\_scenic.yaml为场景配置文件,可指定样本数量(sample\_num)、优化步长(opt\_step)等参数。该步骤将从预定义场景和行为集中采样多个场景,并根据碰撞等指标选出最具挑战性的场景。 + +\begin{figure}[htbp] + \centering + \includegraphics[width=0.8\textwidth]{figure3.png} % 调整宽度为文本宽度的80\% + \caption{打开carla仿真平台} % 自动编号(如"图1:") + \label{fig:example} % 用于交叉引用 +\end{figure} + + +智能体训练(train\_agent 模式):对在第一阶段选出的对抗性场景进行RL训练。调用示例如下: + +python scripts/run\_train.py --agent\_cfg=adv\_scenic.yaml + +--scenario\_cfg=train\_agent\_scenic.yaml --mode train\_agent --scenario\_id 1 + +此处使用与场景选择阶段同样的adv\_scenic.yaml配置文件,以及 + +train\_agent\_scenic.yaml场景配置(包含从第一阶段得到的最难场景信息)。训练过程中,使用前8条固定路线进行训练(其余2条用于测试),以提高智能体在这些高风险场景下的表现。 + + +\begin{figure}[htbp] + \centering + \includegraphics[width=0.8\textwidth]{figure4.png} % 调整宽度为文本宽度的80\% + \caption{进入场景} % 自动编号(如"图1:") + \label{fig:example} % 用于交叉引用 +\end{figure} + + + +评估模式(eval 模式):在训练后,对训练好的智能体进行测试评估。调用示例如下: + +python scripts/run\_eval.py --agent\_cfg=adv\_scenic.yaml + +--scenario\_cfg=eval\_scenic.yaml --mode eval --scenario\_id 1 --test\_epoch -1 + +其中eval\_scenic.yaml定义了评估场景(通常为与训练不同的路线),test\_epoch指定加载的模型检查点(-1表示使用最终训练模型)。评估过程中统计碰撞、路线完成等指标。 + + + +\begin{figure}[htbp] + \centering + \includegraphics[width=0.8\textwidth]{figure5.png} % 调整宽度为文本宽度的80\% + \caption{进入评估场景} % 自动编号(如"图1:") + \label{fig:example} % 用于交叉引用 +\end{figure} + + + +动态语言驱动场景(dynamic模式):首先将描述转录到 + +retrieve/scenario\_descriptions.txt,运行python retrieve.py,生成对应的Scenic场景脚本文件。然后使用run\_train\_dynamic.py脚本启动场景优化或训练,例如: + +python scripts/run\_train\_dynamic.py --agent\_cfg=adv\_scenic.yaml + +--scenario\_cfg=dynamic\_scenic.yaml --mode train\_scenario + +这里dynamic\_scenic.yaml用于指定动态生成场景的配置,脚本会在线检索或调用LLM生成新的场景并进行训练。 + + +\begin{figure}[htbp] + \centering + \includegraphics[width=0.8\textwidth]{figure6.png} % 调整宽度为文本宽度的80\% + \caption{调整相关环境参数} % 自动编号(如"图1:") + \label{fig:example} % 用于交叉引用 +\end{figure} + + + +\section{ASIL-Gen 场景优化与分类} + + +在基础场景模板的基础上,利用脚本自动化生成13类场景变体,涵盖动态障碍物交叉、无信号路口冲突、恶劣天气下跟车等复杂情况,每个变体通过对障碍物位置、速度、交通流量等参数进行调整,形成多样化测试场景,全面覆盖自动驾驶系统可能面临的风险工况。 + + +NSGA-II采用碰撞概率与场景复杂度当作双目标函数,碰撞概率是通过预测车辆行人等交通参与者运动轨迹来计算,场景复杂度会综合考虑交通参与者数量、道路拓扑结构以及环境干扰因素等指标,利用NSGA-II算法去搜索帕累托前沿,筛选出既具有高风险价值又具备代表性的场景,随机搜索是随机生成场景参数组合作为基线方法,通过对比NSGA-II算法和随机搜索在目标函数上的表现,验证NSGA-II在场景优化方面的优越性\cite{national2008integrated}。 + +ASIL 分类 + +依据 ISO 26262 标准,基于暴露频率(Exposure)、可控性(Controllability)与严重性(Severity)三个维度,构建量化评估模型计算安全等级。通过专家打分与数据统计相结合的方式,确定各维度权重,将场景划分为 ASIL-A、ASIL-B、ASIL-C、ASIL-D 四个安全等级,为自动驾驶系统的风险评估提供标准化依据。 +环境配置: + + + +\subsection{具体流程} + +1.环境配置和准备: + +先决条件和设置: +CARLA Simulator: +从 carla-simulator/carla 安装 CARLA。 +Scenario Runner: +从 carla-simulator/scenario\_runner 安装 CARLA Scenario Runner。 + +安装 Python 依赖项(如果需要): +确保已安装 (适用于 NSGA-II) 和其他标准库。numpy;pandas;deap + +2.环境配置 + + +\begin{figure}[htbp] + \centering + \includegraphics[width=0.8\textwidth]{figure7.png} % 调整宽度为文本宽度的80\% + \caption{环境配置} % 自动编号(如"图1:") + \label{fig:example} % 用于交叉引用 +\end{figure} + +3.运行场景 + +python scenario\_runner.py --scenario ChangeLane\_1 --reloadWorld + + +\begin{figure}[htbp] + \centering + \includegraphics[width=0.8\textwidth]{figure8.png} % 调整宽度为文本宽度的80\% + \caption{进入仿真场景} % 自动编号(如"图1:") + \label{fig:example} % 用于交叉引用 +\end{figure} + +输出数据保存在outputs文件生成.json文件 + + +\begin{figure}[htbp] + \centering + \includegraphics[width=0.8\textwidth]{figure9.png} % 调整宽度为文本宽度的80\% + \caption{输出数据} % 自动编号(如"图1:") + \label{fig:example} % 用于交叉引用 +\end{figure} +4.场景选择(优化算法) + + +NSGA-II: + +cd ASIL-Gen NSGA; +python NSGA\_choice.py + +python "ASIL/ASIL.py" \ + +--input selected\_nsga.json \ + +--output nsga\_asil\_levels.json + +python "ASIL/ASIL\_percentages.py" \ + +--input nsga\_asil\_levels.json \ + +--output nsga\_asil\_distribution.csv + + + +\begin{figure}[h] % 图片浮动环境 + \centering % 居中对齐 + \includegraphics[width=0.48\textwidth]{figure10.png} % 第一张图片 + \hfill % 添加水平填充 + \includegraphics[width=0.48\textwidth]{figure11.png} % 第二张图片 + \caption{NSGA-II和随机算法的结果} % 整个图片的总标题 + \label{fig:side} % 整个图片的标签 +\end{figure} + + + + +\section{讨论与未来工作} +\subsection{优势与局限} + +优势: + +ChatScene 动态场景生成优势深化​: + +ChatScene的自然语言驱动动态场景生成有着强大技术支撑,背后体现出灵活性和效率优势,在实际应用里针对复杂交通状况描述,像“早高峰时段城市主干道上因交通事故致道路拥堵,公交车为避让障碍物突然变道,后方私家车紧急刹车”,ChatScene能快速解析语义精准提取“早高峰”“主干道”“交通事故”“公交车变道”“私家车刹车”等关键信息并迅速生成对应场景,和传统手动构建场景相比其时间成本可降低70,在基于强化学习的固定场景优化方面,SAC算法通过不断与环境交互学习能极为细致地模拟交通参与者行为\cite{程娟2019基于梯度提升决策树的高速公路行程时间预测模型},以环岛交通场景为例,算法可精确模拟不同驾驶员环岛行驶时决策差异,比如有的驾驶员会提前打转向灯示意,有的则会根据周围车辆速度灵活调整进入环岛时机,这种精准模拟为自动驾驶系统应对复杂环岛路况的测试提供了有力保障。​ + + +ASIL-Gen 评估优势细化: +​ +ASIL - Gen评估优势进一步细化,ASIL - Gen所引入的NSGA - II多目标优化算法,在筛选高风险场景的时候展现出卓越科学性与高效性。通过把碰撞概率、场景复杂度、交通参与者交互程度等多个指标纳入优化目标,能够在海量的场景数据当中快速定位到最具测试价值的场景。就像在一次模拟测试里,该算法从10000个候选场景之中,仅用传统随机搜索方法五分之一的时间,就筛选出300个ASIL - D等级的高风险场景\cite{段文强0基于用户行为序列的网络购买行为预测},大幅提升了测试的效率。它的量化评估模型以数据作为基础,对场景风险进行客观的评估。在实际应用过程中,对于一些难以直观判断风险等级的场景,例如“乡村道路上,视线不佳的弯道处,突然出现横穿的家禽”,量化评估模型能够结合家禽出现的频率、弯道的曲率、车辆的行驶速度等因素。准确评估出该场景的风险等级,为自动驾驶系统的安全测试提供科学依据 。​ + + +协同架构优势强化​: + +ChatScene和ASIL - Gen协同配合达成从场景生成到安全评估全流程闭环,实际测试里ChatScene生成场景可直接进入ASIL - Gen评估体系,ASIL - Gen对场景评估结果又能反馈给ChatScene用于优化场景生成,比如当ASIL - Gen发现某个生成场景风险评估结果较低时ChatScene可依反馈调整生成参数,通过增加场景复杂性和危险性不断优化测试场景,这让自动驾驶测试能覆盖更多边缘情况和极端场景使测试深度和广度显著提升\cite{chen2016xgboost} 。 + + +局限: + +ChatScene 动态模式局限: + +ChatScene动态模式依赖GPT - 4o所带来的问题不只是逻辑错误和规则不符情况,语言模型在处理模糊表述或者文化背景差异较大场景描述时也易出现理解偏差,就像不同地区对交通标志解读和使用习惯存在差异,当用户用带地方特色语言描述场景时GPT - 4o可能无法准确理解进而生成错误场景代码,调用成本高和响应延迟问题在大规模测试场景下表现得尤为突出,以一个自动驾驶企业的一次全面测试为例,若要生成10000个不同场景进行测试,使用ChatScene动态模式仅调用GPT - 4o的费用就高达数万元,并且由于响应延迟整个测试周期被拉长了近一周 。严重影响了测试进度和效率。​ + + +ASIL-Gen 评估局限: + +ASIL -Gen的评估标准是依据现有交通规则和静态场景参数来制定的,所以在面对新兴交通场景时就显得有些应对乏力,在车路协同环境当中,车辆和道路基础设施之间进行实时信息交互会产生全新交通模式和安全风险,就像路侧单元向车辆发送前方道路施工预警信息,车辆依据信息做动态路径规划与速度调整,现有的评估标准没办法对这种复杂交互场景做全面准确评估,对于动态交通流变化情况,ASIL - Gen同样缺乏有效的评估手段\cite{师圣蔓2019基于机器学习的网络流量预测与应用研究},在实际交通运行里,交通流会受突发事件、天气变化、时间因素等多种因素影响而产生动态变化,比如一场突如其来的暴雨也许会造成道路积水,进而引发交通拥堵和车辆行驶行为改变,而ASIL - Gen目前没办法实时捕捉和评估这些动态变化所带来的安全风险。 + +\subsection{未来方向} + +融合多模态输入,增强场景真实性: + + +多模态数据融合架构升级,未来的多模态融合将采用分层级的时空对齐架构 + +原始数据层着手构建传感器同步采集系统,以此实现激光雷达、摄像头、毫米波雷达等传感器微秒级时间戳同步,就像采用IEEE 1588精确时间协议(PTP),把各传感器时钟同步精度控制在±100ns以内,特征提取层致力于开发多模态特征融合网络,比如基于Transformer的Cross - modal Attention Network,该网络能够自动学习不同传感器特征间的关联权重,以雾天场景为例,自动提升毫米波雷达点云特征权重并降低摄像头图像特征权重,场景重建层引入神经辐射场(Neural Radiance Fields,NeRF)技术,将多模态特征融合到连续的3D场景表示当中,借助隐式神经表示可生成任意视角的逼真场景渲染,包括光照变化、动态物体运动等细节\cite{靳小波0基于机器学习算法的文本分类系统}。 + + +动态环境模拟技术 + +物理引擎进行深度整合,把CARLA物理引擎和多模态数据相结合,以此实现更真实的物理交互模拟,举例来说,模拟车辆碰撞的时候,不仅能够生成视觉效果,还能借助物理引擎计算碰撞力、车辆变形量等物理参数,将其反馈给自动驾驶系统的动力学模型。天气与光照模拟器方面,开发基于物理的天气模拟器,精确模拟雨、雪、雾等天气条件下的光学特性和传感器响应,比如在模拟暴雨场景时,不仅会改变视觉效果,还会调整激光雷达点云的衰减率、毫米波雷达的反射强度等参数。 + + +高精地图语义增强 + +动态语义信息融合是把高精地图里静态语义如车道线类型和交通标志与实时动态信息像施工区域和临时交通管制相结合,例如在高精地图检测到道路施工时自动在生成场景中添加施工标志和锥形桶等障碍物并调整交通规则约束,知识图谱构建是基于高精地图数据构建交通知识图谱将道路元素、交通规则和驾驶行为等信息进行结构化表示,通过知识推理机制可生成更符合逻辑的场景如根据路口类型自动推断可能的交通参与者行为\cite{ke2017lightgbm}。 + + +扩展 ASIL 分类标准,纳入高德 MapDR 驾驶规则: + + +(一)规则语义解析与量化技术 + +语义解析框架方面采用基于BERT的规则解析模型来对MapDR里自然语言规则进行深度语义理解,比如对于规则“在设有掉头标志的路口,红灯亮时允许掉头”模型能解析出“掉头标志存在”“红灯状态”“允许掉头”等关键要素并转化成逻辑表达式,规则量化方法方面开发规则违反度计算模型把规则违反行为进行量化评分,例如对于“限速60km/h”的路段车辆行驶速度为70km/h时违反度可通过公式计算。(70-60)/60×100\%=16.7\%,并根据违反度动态调整 ASIL 等级\cite{刘彧祺2019基于}。 + + +(二)动态风险评估模型里的时空风险场模型是构建基于时空维度的风险场模型,把MapDR的实时交通信息转化成连续的风险分布,在交通拥堵场景当中,风险场强度和车流密度、速度方差等参数相关,可借助高斯混合模型进行建模,因果推理机制是引入因果图模型分析风险因素间的因果关系,避免单纯相关性带来的误判,比如在雨天场景里,路面湿滑是导致事故风险增加的直接原因,车速过快是间接原因,通过因果推理能更准确地评估风险 + + +(三)跨场景规则泛化的元学习框架采用Model - Agnostic Meta - Learning (MAML)算法,让评估模型能够快速适应新场景的规则,例如从城市道路切换到乡村道路场景时,模型可通过少量样本快速学习并应用乡村道路的特殊规则像牲畜横穿风险,对抗训练机制是设计规则对抗训练框架,通过生成对抗网络 (GAN) 模拟不同地域的驾驶习惯和规则差异\cite{zhang2014multi}。例如,生成具有地方特色的驾驶行为样本,训练评估模型的鲁棒性。 + + +(四)验证与评估方法 +混合验证架构方面要建立“形式化验证 + 统计验证”的混合验证体系,对于安全关键规则像紧急制动采用形式化验证方法以确保百分百合规,对于复杂场景则采用统计验证方法来评估系统可靠性,风险覆盖率指标方面要提出风险覆盖率 (Risk Coverage Rate, RCR) 指标用于衡量 ASIL 分类标准对 MapDR 规则的覆盖程度,其计算公式为 RCR 等于已覆盖规则数除以总规则数再乘以百分百,并且要通过持续更新规则库来提高覆盖率。 + + diff --git a/critical/undergraduate/content/chapter4.tex b/critical/undergraduate/content/chapter4.tex new file mode 100644 index 0000000..3fdc762 --- /dev/null +++ b/critical/undergraduate/content/chapter4.tex @@ -0,0 +1,146 @@ +\chapter{优化算法验证} +\section{场景生成与优化效果} + +基准对比:NSGA-II vs. 随机搜索 vs. 人工设计场景库(行业基准) + +评估指标: + +覆盖率:ASIL-D场景占比、场景参数分布熵 + +风险性:平均碰撞风险、最小安全距离极值 + +效率:单位时间有效场景发现数(场景/小时) + +\begin{table}[htb] + \centering + \small + \renewcommand{\arraystretch}{1.1} + \caption{NSGA-II、随机搜索与人工设计场景库的性能对比} + \label{tab:baseline_comparison} + \resizebox{0.95\linewidth}{!}{ + \begin{tabular}{c|c|c|c|c|c} + \hline + 算法 & ASIL-D占比 (\%) & 参数熵 (bits) & 平均碰撞风险 & 最小安全距离极值 (m) & 效率 (场景/小时) \\ + \hline + NSGA-II & 45 & 6.7 & 0.73 & 0.8 & 620 \\ + \hline + 随机搜索 & 39 & 4.2 & 0.58 & 1.5 & 850 \\ + \hline + 人工设计库 & 15 & 3.1 & 0.41 & 2.3 & 120 \\ + \hline + \end{tabular} + } +\end{table} + + +核心结论: + +NSGA-II的ASIL-D场景发现率是高于随机搜索,高于人工库的 + +参数熵指标显示NSGA-II生成场景的多样性显著优于对比方法(p<0.01,Mann-Whitney U检验) + +随机搜索在效率上占优,但其发现的高风险场景多集中于单一模式(如急刹场景占比82\%) + +\section{超参数选择的验证} + + +多因子实验设计 +采用正交实验法(L9正交表)分析NSGA-II的4个关键参数: + +因子:种群规模(50/100/200)、进化代数(30/60/90)、交叉概率(0.6/0.7/0.8)、变异概率(0.1/0.2/0.3) + +响应变量:Hypervolume指标、计算耗时 + +结果分析 + +\begin{figure}[htbp] + \centering + % 使用占位符代替实际图像 + \includegraphics[width=0.8\textwidth]{figure14.png} + \caption{超参数对Hypervolume的影响(标准化回归系数)} + \label{fig:hyperparam} +\end{figure} + +关键发现: + +种群规模对Hypervolume影响最大(β=0.63),但边际效益递减(200 vs 100仅提升7\%) + +进化代数超过60代后优化增益不显著(ΔHV<1.5\%) + +最优参数组合:种群100 + 代数60 + 交叉0.7 + 变异0.2(验证集HV=0.812) + + +\section{消融实验} + +为了系统评估 NSGA-II 多目标优化框架中各关键组件的作用,我们设计了一组消融实验,依次移除核心模块以观察其对算法性能的影响。具体实验设置如下: + +Baseline(完整 NSGA-II):包括非支配排序(Non-dominated Sorting)、拥挤度计算(Crowding Distance Calculation)和精英保留策略(Elitism Preservation)。 + +Ablation 1:移除拥挤度计算,仅保留非支配排序。 + +Ablation 2:移除精英保留策略,即下一代个体不包含当前种群中表现最优的解。 + +Ablation 3:用加权求和的单目标函数替代多目标优化机制。 + +各模型在三个性能维度上进行了评估: +Hypervolume (HV) 作为衡量解集质量的指标,ASIL-D占比反映高安全等级场景的发现能力,参数熵用于衡量生成场景的多样性。 + +\begin{table}[htbp] + \centering + \caption{消融实验结果对比} + \begin{tabular}{llll} + \hline + 模型变体 & Hypervolume & ASIL-D占比 (\%) & 参数熵 (bits) \\ + \hline + 完整NSGA-II & 0.812 & 45.0 & 6.7 \\ + \hline + Ablation 1 & 0.734 & 39.0 & 4.8 \\ + \hline + Ablation 2 & 0.681 & 30.0 & 5.2 \\ + \hline + Ablation 3 & 0.598 & 17.3 & 3.6 \\ + \hline + \end{tabular} +\end{table} + +拥挤度计算对解集多样性的关键作用 +移除拥挤度计算(Ablation 1)后,参数熵由 6.7 降至 4.8,下降约 28.4\%,表明解的分布范围缩窄,模型在搜索空间中的覆盖能力降低。此外,ASIL-D 占比下降了 6 个百分点(从 45.0\% 降至 39.0\%),说明高风险场景的识别能力也受到影响。 + +精英保留策略对高质量场景发现的促进作用 +Ablation 2 中移除精英保留导致 ASIL-D 占比进一步下降至 30.0\%,相比完整模型降低了 15\%,显示精英策略在保留高价值解方面具有显著优势。多样性(参数熵)也略有下降,但不如拥挤度影响显著。 + +多目标优化的必要性 +Ablation 3 使用单目标加权求和替代原有的 Pareto 优化策略,导致 Hypervolume 降至 0.598,ASIL-D 占比最低,仅为 17.3\%。结果表明该方法在处理多目标权衡时能力有限,无法有效挖掘高安全等级场景。 + +与随机搜索对比 +随机搜索的 ASIL-D 占比为 39.0\%,虽然接近于 Ablation 1,但在没有优化机制支持下,稳定性与整体解集质量(HV 与熵)显著低于完整 NSGA-II。 +\section{可视化结果和分析} +\subsection{NSGA-II和随机搜索算法结果分析} + + +\begin{figure}[htbp] + \centering + \includegraphics[width=0.8\textwidth]{figure12.png}%调整宽度为文本宽度的80% + \caption{ASIL等级分布柱状图} % 自动编号(如"图1:") + \label{fig:example} % 用于交叉引用 +\end{figure} +\subsection{NSGA-II算法的Pareto前沿解集} +展示了 NSGA-II 算法选出的 Pareto 前沿解集,用于智能驾驶危险场景筛选中的两个关键优化目标: + +目标 1(X轴):最小安全距离,越大越好(表示更安全)。 + +目标 2(Y轴):碰撞风险,越小越好(表示更低风险)。 + +\begin{figure}[htbp] + \centering + \includegraphics[width=0.8\textwidth]{figure13.png}%调整宽度为文本宽度的80% + \caption{NSGA-II算法选出的Pareto前沿解集} % 自动编号(如"图1:") + \label{fig:example} % 用于交叉引用 +\end{figure} + +\newpage + + + + + diff --git a/critical/undergraduate/content/chapter5.tex b/critical/undergraduate/content/chapter5.tex index 7d381cd..15e78fb 100644 --- a/critical/undergraduate/content/chapter5.tex +++ b/critical/undergraduate/content/chapter5.tex @@ -1,95 +1,54 @@ -%!TEX root = ../../csuthesis_main.tex -\section{参考文献} +%!TEX root = ../../csuthesis\_main.tex -Cheng Bo, Lin Qingfeng, Song Tianjia, Cui Yongwei, Wang Limian, KuzumakiSeigo. Analysis of Driver Brake Operation in Near-Crash Situation UsingNaturalistic Driving Data[J]. International Journal of Automotive Engineering,2011,2(4). +\chapter{总结与展望} +\section{总结} -Mckinsey \& Company. Autonomous driving’s future: Convenient and connected [EB/OL]. (2023-01-01)[2023-03-05].https://www.mckinsey.com/industries/automotive-and-assembly/our-insights/autonomous-drivings-future-convenientand-connected +自动驾驶汽车技术的发展需要科学测试体系来提供支持,虚拟仿真测试是解决封闭和开放道路测试成本与效率问题的有效办法,虽说其理论和技术体系还有待完善,数字虚拟仿真在生成危险场景方面具备明显优势,是提升测试安全性和可靠性的关键所在,正逐渐成为研究的焦点,现有的自动驾驶危险场景生成方法包含专家经验法、自然驾驶数据提取法、危险场景衍生法以及基于强化学习的自生成法,专家经验法比较主观且难以覆盖所有场景情况,自然驾驶数据提取法缺乏动态交互能力,危险场景衍生法可能会产生不真实的轨迹,这些方法大多局限于学术研究难以应用到工程实践当中,基于强化学习的自生成法能够实时修正场景状态生成定制化场景库,适合高级别自动驾驶测试从而成为研究热点,不过现有方法可能产生不自然或者重复的场景且缺乏泛化能力,本项目旨在设计一种综合自然性、对抗性和多样性的统一生成策略以解决现有方法在实际应用中的不足 。 -ChatScene: Knowledge-Enabled Safety-Critical Scenario Generation for Autonomous Vehicles -Jiawei Zhang, Chejian Xu, Bo Li; Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR), 2024, pp. 15459-15469 +为了探索自动驾驶汽车性能方面的极限情况,评估自动驾驶系统安全性、可靠性和可信度,需要精确且完整地描述自动驾驶性能边界,现有的研究没有使用真实自动驾驶模型和算法挖掘性能边界,可能导致缺乏现实性、出现误导性结果与可迁移性问题,现有的研究仅考虑周围车辆产生危险行为会限制整体风险评估,因为行人和环境因素可能引入新风险与挑战,需在危险场景生成中予以考虑,忽略这些因素可能导致对风险低估,无法全面评估自动驾驶系统在复杂多变环境中行为和决策能力,当前研究仅利用背景车辆初始运行条件如位置、速度、航向角等构造驾驶场景参数空间,所以应定义更高维参数空间以精细化和全面表征自动驾驶性能边界,当处理高维参数空间和昂贵自动驾驶仿真评价时,通用启发式智能优化算法往往不再适用,能有效求解的优化算法非常有限,在这种情况下,很有必要借助代理建模、最优计算资源分配、样本填充策略等技术设计相应随机或鲁棒仿真优化算法,这也是本项目研究的关键点。 +当前世界最先进的自动驾驶方案里端到端自动驾驶有较强感知性能和泛化能力构建的系统更简单智能,然而现有的端到端自动驾驶决策方法存在如下问题,一是端到端自动驾驶模型依赖训练数据面对复杂和危险场景可能做出不合理决策,二是端到端自动驾驶依赖深度神经网络其黑盒特性让决策过程难以解释限制系统行为理解和调试,三是端到端自动驾驶模型从图像或点云直接输出控制信号训练中难全面理解复杂交通环境无法考虑多重因素导致决策缺乏适应性和灵活性,本研究的终极目标是为端到端自动驾驶设计富含驾驶语义信息的输入并利用先进神经网络架构突破以往自动驾驶性能边界 。 -张开元. FOT 数据库危险驾驶工况数据的自动处理方法研究[D]:[硕士学位论文].上海:同济大学, 2016. +本研究紧紧围绕自动驾驶场景生成和安全评估核心问题展开,深入探索并提出ChatScene与ASIL - Gen协同解决方案,成功构建起从场景高效生成到精准风险评估完整技术体系,为自动驾驶测试领域带来创新性突破,在场景生成层面,ChatScene框架展现出独特的技术优势。 +其创新性地融合 Scenic 语言、深度强化学习与 GPT-4o 模型,场景生成模式实现了多元化与智能化发展。在固定场景模式里,基于Scenic语言预定义的8类基准场景,这些场景涵盖城市主干道、高速公路以及乡村道路等多种典型交通环境,利用深度强化学习中的SAC算法,以碰撞避免、车道保持和速度优化等作为核心奖励函数,对场景里对抗行为参数展开精细化调整与优化,以此模拟出高度真实且复杂多变的交通参与者交互行为,为自动驾驶系统提供标准化与规范化的测试场景模板。在动态模式方面,借助GPT - 4强大的自然语言理解与代码生成能力,用户只要输入自然语言描述,像“暴雨天气下,自我车辆在无信号灯十字路口左转,对向车辆突然加速直行”这样的内容,系统就能快速解析语义信息并将其转化为符合CARLA 0.9.13规范的场景代码。通过设定详细的约束条件,包含道路类型、车辆动力学参数以及交通规则等内容,生成多样化且贴近真实驾驶场景的测试用例,相比传统基于LiDARGen的场景生成方法,,动态模式的生成效率提升了 107 倍,极大地丰富了自动驾驶测试场景的多样性与灵活性,显著提高了测试效率。​ +在安全评估领域当中ASIL - Gen起到了关键作用,该模块借助NSGA - II多目标优化算法以及基于ISO 26262标准的量化评估模型,达成了场景的优化筛选与科学分类工作。在场景生成这个阶段,基于基础场景模板依靠脚本自动化生成13类场景变体,其中涵盖动态障碍物交叉、无信号路口冲突、恶劣天气下跟车等复杂情况,并且通过调整障碍物位置、速度、交通流量等参数,形成海量多样化的测试场景。在此基础之上,利用NSGA - II算法把碰撞概率与场景复杂度当作双目标函数来进行优化。碰撞概率通过精确预测车辆、行人等交通参与者的运动轨迹来计算,场景复杂度则综合考虑交通参与者数量、道路拓扑结构、环境干扰因素等多个指标,进而搜索出帕累托前沿筛选出既具高风险价值又有代表性的场景。实验数据表明,通过ASIL - Gen优化之后,高风险ASIL - D等级场景占比从随机搜索的5\%提升到12\%,经过进一步优化后更是提升至15\%,显著增强了场景,显著增强了场景筛选的精准性与安全评估的科学性。​ -Fitch G M, Hanowski R J. Using Naturalistic Driving Research to Design, Test andEvaluate Driver Assistance Systems[M]. Springer London, 2012. +在实验验证这个重要环节当中本研究取得一系列有说服力成果,基于ChatScene训练的RL模型在行人横穿场景测试里和基线模型开展多次重复对比实验,通过精确统计碰撞次数得出结果表明其碰撞率降低了32\%,这充分验证了ChatScene与ASIL - Gen协同方案对提升自动驾驶系统鲁棒性有效,同时场景生成效率以及安全评估准确性等方面实验数据有力证明该方案在自动驾驶技术安全测试中具巨大应用价值,为自动驾驶技术的安全测试开辟新的技术路径与研究方向。 -朱西产, 张佳瑞, 马志雄. 安全切入场景下的驾驶人初始制动时刻分析[J]. 中国公路学报, 2019, 32(6). +安全模型,英伟达的安全力场(SFF)和Mobileye的责任敏感安全(RSS)等对决策来说是有可解释性的数学模型。这项工作从头开始实现SFF,替代未公开的英伟达源代码,并将其与CARLA开源模拟器集成。使用SFF和CARLA,提出了一个车辆声明集合的预测器,并以此提出一种综合驾驶策略,无论在通过动态交通时遇到什么安全条件,其都能持续运行。该策略没有针对每种情况制定单独的规划,但利用安全潜能,目的是将类人的驾驶融入交通流中。 -杨敏明, 王雪松, 朱美新. 基于自然驾驶实验的驾驶行为研究[J]. 交通与运输,2017,33(03):7-9. -VL Neale, SG Klauer, TA Dingus, et al. The 100-Car Naturalistic Driving Study,Phase I-Experimental Design.Bahavior,2002. -TA Dingus, SG Klauer, VL Neale, et al. The 100-Car Naturalistic Driving Study,Phase II-Results of the 100-Car Field Experiment.Bahavior,2006. +责任敏感安全(RSS)将自车的危险时间t与纵向/横向的危险阈值时间tlong/tlat进行比较。如果达到阈值,RSS判断为危险情况,并根据纵向或横向加速度对速度的限制做出适当的响应。换句话说,阈值可以用轨迹集的多边形表示。如果自车和其他道路使用者之间的轨迹集相交,RSS会选择以下三个决策中的一个来恢复安全状态:刹车,继续前进或开车离开。 -Characterizing Underground Utilities[J]. Shrp Report, 2009. +安全力场(SFF)表示,如果参与者遵循安全程序(这是一系列控制策略),量化风险的安全潜能ρAB不会再增加,因此可以保证参与者最终不会造成不安全的情况。这可以通过安全潜能的链式法则从数学上证明。简而言之,RSS的方法是最小化参与者声称集合之间的交集,这是每个参与者安全程序产生轨迹的联合。 -Integrated Vehicle-Based Safety Systems (IVBSS) Phase I Interim Report[J]. 2008. +英特尔发布了一个名为ad-rss-lib的开源库,该库部分实现了RSS。此外,NVIDIA还提供了一个名为DriveWorks SDK的软件开发工具包,其中包括针对经批准用户的SFF实现。Intel ad-rss-lib没有涵盖其论文的全部范围,但它提供了Python绑定和CARLA集成。然而,NVIDIA DriveWorks SDK是一个非公开IP,它的实现是为了与配备NVIDIA DRIVE OS的NVIDIA DRIVE平台集成,因此研究人员很少使用它。在Intel和NVIDIA建议的将RSS和SFF与现有自动驾驶系统集成的基本示例架构中,RSS和SFF扮演着最后的角色,通过重写规划子系统的决策来防止自动驾驶车辆发生碰撞。 -Sayer J, Leblanc D, Bogard S, et al. Integrated Vehicle-Based Safety Systems(IVBSS) light vehicle platform field operational test data analysis plan[J]. HeavyDuty Trucks, 2009. +在SFF实施中使用声明集合和安全潜能的概念,声明集合就是安全程序(驾驶策略)获取的轨迹之联合,安全潜能是两个参与者的声明集合之间相交测度及其负梯度。该文提出了一种将SFF集成到规划子系统中的方法,制定一种类似人类的驾驶策略,无论在安全或不安全的条件下都能始终如一地运行,最终尽量不阻碍顺畅的交通流。 -Sayer J R, Leblanc D J, Bogard S E. Integrated Vehicle-Based Safety Systems(IVBSS) Third annual report[J]. Scottish Journal of Theology, 2013, 22:382-383. +Intel RSS或NVIDIA SFF作为与现有子系统协调的附加模块。它接收来自感知子系统的世界环境数据和来自规划子系统的机动决策。为了自车的安全,作为上层限制器,它可以推翻接收的决策,并将限制的决策传递给驾驶子系统。如图是具有RSS或SFF安全模型的基本示例架构:灰色是现有子系统部分,蓝色/绿色是附加模块的RSS/SFF实现部分。 -Administration NHTS. Integrated Vehicle-Based Safety Systems: Light VehicleField Operational Test, Key Findings Report[J]. Annals of Emergency Medicine,2011, 58(2):205-206. +\section{展望} -Benmimoun M, Fahrenkrog F, Zlocki A , et al. Incident detection based on vehicleCAN-data within the large scale field operational test[J].2011. -Benmimoun M, Eckstein L. Detection of Critical Driving Situations for NaturalisticDriving Studies by Means of an Automated Process[J]. bowen publishing, 2014:11-21. +虽然本研究在自动驾驶场景生成和安全评估领域有了一定成果,但面对自动驾驶技术快速发展带来的需求和挑战,该领域还有很多需要深入探索的方向,未来研究可以从以下多个维度来开展,深化多模态数据融合方面,目前自动驾驶场景生成主要依靠有限的数据源,未来研究要进一步深化多模态数据融合,除了持续探索激光雷达和摄像头数据的深度融合,还会引入毫米波雷达数据,借助其在恶劣天气下稳定的探测性能,提高场景中目标检测与跟踪的准确性,同时融合高精地图数据,把地图里的道路属性、交通标志、车道线等信息和传感器数据相结合,构建更贴近真实驾驶环境的场景生成模型,通过多模态数据的协同处理与特征融合,不但能提升场景的物理真实性,还能增强场景的语义准确性,让生成的场景更符合实际驾驶过程中的复杂状况,为自动驾驶系统提供更具挑战性与真实性的测试环境。​ -Victor T, Jonas BÀrgman, Gellerman H, et al. Sweden-Michigan NaturalisticField Operational Test (SeMiFOT) Phase 1: Final Report[J]. 2010. +拓展 ASIL 分类标准:现有的 ASIL 分类标准主要基于静态的交通场景因素,未来将结合车路协同、交通流理论等前沿技术,对其进行拓展与完善。将 V2X 通信状态纳入评估体系,考虑车辆与车辆、车辆与基础设施之间的信息交互对驾驶安全的影响;同时引入交通拥堵态势分析,结合交通流模型,评估不同拥堵程度下自动驾驶系统面临的风险。此外,还将探索驾驶员行为模型与 ASIL 分类的结合,分析人类驾驶行为的不确定性对自动驾驶系统安全的潜在影响,从而完善高风险场景的识别维度,使 ASIL 分类标准更全面、准确地反映自动驾驶系统在复杂交通环境下的安全风险状况。​ -刘颖. 行人自动紧急制动系统测试方法研究[D]. 同济大学, 2014. +探索模型轻量化与实时化:随着自动驾驶技术向边缘设备的不断渗透,算力受限成为制约实时在线评估的关键因素。未来研究将致力于探索 ChatScene 与 ASIL-Gen 算法架构的轻量化与实时化优化。一方面,通过模型压缩技术,如剪枝、量化等方法,减少模型参数与计算量;另一方面,采用高效的算法优化策略,如改进的神经网络结构、并行计算技术等,提高算法执行效率。针对边缘设备的硬件特性,开发专用的轻量化模型,使其能够在资源有限的条件下快速生成场景并进行安全评估,推动自动驾驶仿真测试从离线分析向实时在线评估方向发展,为自动驾驶车辆的实时决策与安全监控提供有力支持,加速自动驾驶技术的落地应用进程。​ -NAO Engineering, Safety \& Restraints Center, Crash Avoidance Department, “44-Crashes”, General Motors Corporation, Version 3.0, January 1997. +强化人机协同测试模式:考虑到自动驾驶系统最终服务于人类出行,未来可探索将人类驾驶员的行为与决策纳入测试体系,构建人机协同的测试模式。通过收集和分析人类驾驶数据,模拟不同驾驶风格、驾驶习惯的人类驾驶员与自动驾驶系统的交互场景,评估自动驾驶系统在人机共驾环境下的安全性与适应性。同时,研究如何利用人类驾驶员的经验与直觉,辅助自动驾驶系统进行决策,实现人机优势互补,进一步提升自动驾驶系统的可靠性与用户接受度。​ -Crash Avoidance Metrics Partnership, “Enhanced Digital Mapping Project – FinalReport”. U.S. Department of Transportation, National Highway Traffic SafetyAdministration, November 2004. +开展跨地域与跨文化场景研究:目前的研究主要基于特定地域的交通规则与驾驶习惯,未来将开展跨地域与跨文化场景研究。收集不同国家、不同地区的交通数据,分析其交通规则、驾驶文化的差异,构建多样化的跨地域场景库。通过在这些场景下对自动驾驶系统进行测试与评估,确保自动驾驶技术在全球范围内的适用性与安全性,推动自动驾驶技术的全球化发展。 -W.G. Najm, B. Sen, J.D. Smith, and B.N. Campbell, “Analysis of Light VehicleCrashes and Pre-Crash Scenarios Based on the 2000 General Estimates System”.DOT-VNTSC-NHTSA-02-04, DOT HS 809 573, February 2003. -Najm W G, Smith J D, Yanagisawa M. Pre-Crash Scenario Typology for CrashAvoidance Research[J]. Dot Hs, 2007:767. -曾宇凡, 朱西产, 马志雄, 等. 基于真实事故和自然驾驶场景大的车辆-骑车人危险工况的统计分析[J]. Infats Proceedings of the 14th International Forum ofAutomotive Traffic Safety, 2017(01):1-9. -苏江平, 陈君毅, 王宏雁, 等. 基于中国危险工况的行人交通冲突典型场景提取与分析[J]. 交通与运输(学术版), 2017(01):216-221. -孟琳, 朱西产, 孙晓宇, 等. 真实交通危险工况下驾驶员转向避撞相关因素分析[J]. 汽车技术, 000(6):59-62. -李霖, 朱西产, 马志雄. 驾驶员在真实交通危险工况中的制动反应时间[J]. 汽车工程, 2014(10):1225-1229. - -吴斌, 朱西产, 沈剑平, 等. 基于自然驾驶研究的直行追尾危险场景诱导因素分析[J]. 同济大学学报:自然科学版, 2018, 46(09):96-103. - -孙 招 凤 . CAN 总 线 网 络 报 文 标 识 符 编 码 研 究 [J]. 导 弹 与 航 天 运 载 技 术 ,2009(02):34-39. - -范云锋, 刘博, 郑益凯. 一种基于三次样条曲线的目标航迹拟合与插值方法研究[J]. 数字技术与应用,2019,37(03):128-129. - -陈华. 面向智能辅助驾驶系统的驾驶员行为分析与建模[D]. - -Thiemann C, Treiber M, Kesting A. Estimating Acceleration and Lane-ChangingDynamics from Next Generation Simulation Trajectory Data[J]. TransportationResearch Record Journal of the Transportation Research Board, 2008,2088(2088):90-101. - -薛薇. SPSS 统计分析方法及应用[M]. 北京:电子工业出版社, 2004. - -杨学兵, 张俊. 决策树算法及其核心技术[J]. 计算机技术与发展, 2007,17(1):43-45. - -曾星, 孙备, 罗武胜, 等. 基于深度传感器的坐姿检测系统[J]. 计算机科学,2018, v.45(07):243-248. - -程娟, 陈先华. 基于梯度提升决策树的高速公路行程时间预测模型(英文)[J].Journal of Southeast University (English Edition),2019,35(03):393-398.79 - -段文强. 基于用户行为序列的网络购买行为预测[D]. 江西财经大学,2019. - -Chen T, Guestrin C. XGBoost: A Scalable Tree Boosting System[J]. 2016. - -师圣蔓. 基于机器学习的网络流量预测与应用研究[D]. 2019. - -靳小波. 基于机器学习算法的文本分类系统[D]. 西北工业大学. - -KE G, MENG Q, FINLEY T, et al. Lightgbm: A highly efficient gradient boostingdecision tree[C] // 31st Conference on Neural Information Processing Systems(NIPS 2017). California, USA,2017:3146-3154. - -刘彧祺, 张智斌, 陈昊昱, et al. 基于 XGBoost 集成的可解释信用评分模型[J].数据通信, 2019(3). - -Zhang Y, Xue J R, Zhang G, el al. A multi-feature fusion based traffic lightreognition algorithm for intelligent vehicles[C]. Proceeding of the 33rd ChineseControl Conference. IEEE,2014:4924-4929. - -Ma C, Xue J, Liu Y, et al. Data-Driven State-Increment Statistical Model and ItsApplication in Autonomous Driving[J]. Intelligent Transportation Systems IEEETransactions on, 2018, 19(12):3872-3882. \newpage diff --git a/critical/undergraduate/content/cover.tex b/critical/undergraduate/content/cover.tex index 5317d48..313f4ca 100644 --- a/critical/undergraduate/content/cover.tex +++ b/critical/undergraduate/content/cover.tex @@ -1,18 +1,20 @@ %!TEX root = ../hutbthesis_main.tex -% 文章信息 -\titlecn{智能驾驶危险仿真场景的生成和优化算法 } -\titleen{Hunan University of Technology and Business Thesis \LaTeX{} Template v0.1} +% 文章信息(同时也是页眉) +\titlecn{智能驾驶危险仿真场景的生成和优化算法} +\headertitle{湖南工商大学毕业论文} +\titleen{Hunan University of Technology and Business Thesis \LaTeX{} Template v2.0} -%\minormajor{人工智能} -%\interestmajor{人工智能} +%\minormajor{通信工程} +%\interestmajor{通信工程} \author{刘东林} \subsupervisor{} \studentid{2123020065} \priormajor{人工智能} \myclass{人工智能2102班} -\supervisor{王海东教授} -\department{人工智能与先进计算机学院} +\supervisor{王海东} +\title{讲师} +\department{人工智能与先进计算学院} \thesisdate{year=2025, month=5} %以下的对本科生没有用 diff --git a/critical/undergraduate/content/declarationzh.tex b/critical/undergraduate/content/declarationzh.tex index 64c5561..d67bef3 100644 --- a/critical/undergraduate/content/declarationzh.tex +++ b/critical/undergraduate/content/declarationzh.tex @@ -1,16 +1,26 @@ %!TEX root = ../hutbthesis_main.tex \begin{declarationzh} - -本人郑重声明:所呈交的本科毕业设计 \uline{ 湖南工商大学学位论文 \LaTeX{} 模板使用示例 v0.1 } 是本人在指导老师的指导下,独立进行研究工作所取得的成果,成果不存在知识产权争议,除文中已经注明引用的内容外,本设计不含任何其他个人或集体已经发表或撰写过的作品成果。 -对本设计做出重要贡献的个人和集体均已在文中以明确方式标明。本人完全意识到本声明的法律结果由本人承担。 + +本人郑重声明:所呈交的本科毕业设计(论文)是本人在指导老师的指导下,独立进行研究工作所取得的成果,成果不存在知识产权争议,除文中已经注明引用的内容外,本论文不含任何其他个人或集体已经发表或撰写过的作品成果。 +对本文的研究做出重要贡献的个人和集体均已在文中以明确方式标明。 +本人完全意识到本声明的法律结果由本人承担。 +\\ +\\ +\\ +\\ +\\ +\\ +\\ +\\ \vspace{30pt} \begin{tabular}{ll} %\renewcommand{\arraystretch}{2} - \hspace{240pt} \makebox[4em][s]{作者签名: 刘东林 } & \underline{\makebox[100pt][c]{ }} \\ - \hspace{240pt} \makebox[4em][s]{日\qquad 期:} & - \underline{\makebox[100pt][c]{\qquad2025年\quad1月\quad3日 }} \\ + \makebox[4em][s]{作者签名:刘东林} & \makebox[100pt][c]{ } \\ + \\ + \makebox[2em][s]{日期:} & + \makebox[100pt][c]{\qquad2025年\quad5月\quad18日} \\ \end{tabular} diff --git a/critical/undergraduate/reference.bib b/critical/undergraduate/reference.bib index dc14fdb..7b257f9 100644 --- a/critical/undergraduate/reference.bib +++ b/critical/undergraduate/reference.bib @@ -274,4 +274,4 @@ @article{ma2018data pages={3872--3882}, year={2018}, publisher={IEEE} -} +} \ No newline at end of file