diff --git a/co/README.md b/co/README.md index ea488b8a..e4cf5a8b 100644 --- a/co/README.md +++ b/co/README.md @@ -1,34 +1,337 @@ -# 本科毕业设计 +# 基于高保真模拟器的车辆与飞行器协同控制 -基于高保真模拟器的车辆和无人机的协同控制 +## 项目简介 + +本项目基于 ROS Melodic 与 Gazebo 9 构建机场地面车辆与飞行器协同控制仿真平台,实现牵引车辆对飞机目标的自动识别、自动接近、自动对接以及协同控制功能。 + +系统融合激光雷达、深度相机等多种感知信息,通过路径规划与运动控制算法实现车辆对目标飞机的自主接近与对接验证,并在 Gazebo 高保真仿真环境中完成算法测试与性能评估。 + +本项目为湖南工商大学机器人工程专业本科毕业设计: + +> 《基于高保真模拟器的车辆与飞行器协同控制》 + +--- ## 功能特点 -- 🎮 **实时键盘控制** - 支持W/A/S/D方向键 + 空格刹车 -- 📊 **专业仪表盘** - 带转速表、档位指示器和速度显示 -- 🚗 **自动挡支持** - D/R/N档位自动切换 -- 📈 **实时车辆状态监控** - 位置、速度、朝向实时更新 -- 🎨 **可定制化控制参数** - 油门、转向灵敏度可调 +* 飞机目标识别与身份确认 +* 自动接近控制 +* 自动对接控制 +* 障碍物安全检测 +* 四轮转向车辆控制 +* 多传感器联合感知 +* Gazebo高保真仿真验证 +* ROS模块化系统架构 + +--- + +## 系统架构 + +```text +ROS +│ +├── 感知层 +│ ├── 激光雷达 +│ ├── 深度相机 +│ └── 飞机辅助识别标识 +│ +├── 决策层 +│ ├── 身份确认 +│ ├── 目标定位 +│ ├── 轨迹规划 +│ └── 对接决策 +│ +├── 控制层 +│ ├── 速度控制 +│ ├── 转向控制 +│ └── 四轮转向控制 +│ +└── Gazebo仿真平台 +``` + +--- + +## 环境要求 + +推荐使用 Ubuntu 16.04 LTS。 + +### 软件环境 + +| 软件 | 版本 | +| ------------ | ---------- | +| Ubuntu | 16.04 LTS | +| ROS | Melodic | +| Gazebo | 9.19.0 | +| Python | 2.7 / 3.8+ | +| RViz | Melodic | +| catkin_tools | latest | + +--- + +### ROS依赖安装 + +```bash +sudo apt update + +sudo apt install \ +ros-melodic-gazebo-ros \ +ros-melodic-gazebo-plugins \ +ros-melodic-gazebo-ros-control \ +ros-melodic-controller-manager \ +ros-melodic-joint-state-controller \ +ros-melodic-effort-controllers \ +ros-melodic-joint-state-publisher \ +ros-melodic-robot-state-publisher \ +ros-melodic-xacro +``` + +--- + +### Python依赖 + +```bash +pip install numpy matplotlib +``` + +--- + +### 推荐硬件配置 + +| 项目 | 配置 | +| ---- | ------------- | +| CPU | Intel i5 8代以上 | +| 内存 | ≥ 16 GB(低于该配置能运行,但是非常卡)| +| 显卡 | 支持 OpenGL 4.0 | +| 磁盘空间 | ≥ 10 GB | + +--- + +## 初始化 + +### 1. 创建工作空间 + +```bash +mkdir -p ~/tug_ws/src +cd ~/tug_ws/src +``` -## 使用 +--- -### 要求 -- Python 3.8+ -- AirSim 1.8.1+ -- pygame 2.6.1+ -- numpy 1.21.0+ +### 2. 克隆项目 -### 初始化 ```bash -# 克隆项目 git clone https://github.com/OpenHUTB/sim.git -cd sim/keyboard_control +``` + +--- + +### 3. 编译工程 + +```bash +cd ~/tug_ws + +catkin_make +``` + +--- + +### 4. 加载环境变量 + +```bash +source devel/setup.bash +``` + +建议加入系统启动项: + +```bash +echo "source ~/tug_ws/devel/setup.bash" >> ~/.bashrc + +source ~/.bashrc +``` + +--- + +### 5. 配置Gazebo模型路径 + +```bash +echo 'export GAZEBO_MODEL_PATH=$GAZEBO_MODEL_PATH:~/tug_ws/src/tug_gazebo/models' >> ~/.bashrc + +source ~/.bashrc +``` + +--- + +### 6. 检查ROS环境 + +启动ROS Master: + +```bash +roscore +``` + +新终端执行: + +```bash +rostopic list +``` + +若系统正常运行则表示ROS环境配置成功。 + +--- + +## 项目结构 + +```text +tug_ws +├── src +│ +├── zongzhuang +│ ├── urdf +│ ├── launch +│ ├── config +│ ├── meshes +│ └── scripts +│ +├── tug_gazebo +│ ├── worlds +│ ├── models +│ └── launch +│ +├── tug_description +│ +├── build +├── devel +└── logs +``` + +--- + +## 启动仿真 + +### 启动Gazebo + +```bash +roslaunch zongzhuang gazebo.launch +``` + +--- + +### 查看控制器状态 + +```bash +rosservice call /zongzhuang/controller_manager/list_controllers +``` + +正常情况下应显示: + +```text +joint_state_controller + +front_steer_position_controller + +back_steer_position_controller + +front_left_wheel_velocity_controller + +front_right_wheel_velocity_controller + +back_left_wheel_velocity_controller + +back_right_wheel_velocity_controller +``` + +并全部处于: + +```text +running +``` + +状态。 + +--- + +## 测试程序 + +### 自动牵引测试 + +```bash +rosrun zongzhuang test_1_1_0.py +``` + +测试内容包括: + +1. 车辆回中校准 +2. 前进测试 +3. 后退测试 +4. 前桥转向测试 +5. 双桥小半径转弯测试 +6. 蟹行运动测试 +7. 自动回中 + +--- + +## 常用命令 + +### 查看ROS节点 + +```bash +rosnode list +``` + +### 查看ROS话题 + +```bash +rostopic list +``` + +### 查看控制器 + +```bash +rosservice call /zongzhuang/controller_manager/list_controllers +``` + +### 重置Gazebo世界 + +```bash +rosservice call /gazebo/reset_world +``` + +### 获取车辆状态 + +```bash +rostopic echo /gazebo/model_states +``` + +--- + +## 实验结果 + +项目完成了以下功能验证: + +* 自动目标识别 +* 自动接近控制 +* 自动对接控制 +* 障碍物检测 +* 四轮转向控制 +* 高保真联合仿真验证 + +实验结果表明系统能够稳定完成车辆与飞机的协同控制任务。 + +--- + +## 作者 + +雷宇杰 + +湖南工商大学 + +机器人2201班 + +--- + +## 致谢 -# 安装依赖 -pip install -r requirements.txt +感谢湖南工商大学相关指导教师在课题研究过程中给予的指导与帮助。 -# 确保AirSim正在运行 -# 启动Blocks环境 -cd ~/Blocks/LinuxNoEditor/Blocks/Binaries/Linux -./Blocks -opengl -nosound -windowed -ResX=800 -ResY=600 \ No newline at end of file +感谢ROS、Gazebo等开源社区提供的软件平台支持。 diff --git a/co/main.tex b/co/main.tex deleted file mode 100644 index 1167ab4c..00000000 --- a/co/main.tex +++ /dev/null @@ -1,85 +0,0 @@ -\documentclass{article} -\usepackage{hyperref} - -\title{论文提纲} -\author{} -\date{\today} - -\begin{document} - -\maketitle - -\tableofcontents - -\section{绪论} -\subsection{研究背景与意义} -\subsection{国内外研究现状} -\subsection{研究内容与技术路线} - -\section{机场牵引车辆系统建模与问题描述} -\subsection{机场牵引作业场景抽象} -\subsection{坐标系与状态变量定义} -\subsection{车辆运动学模型建立} -\subsubsection{非完整约束条件} -\subsubsection{单轨等效模型} -\subsubsection{双桥转向角速度表达式} -\subsection{转弯半径与曲率模型} -\subsection{典型转向模式分析} -\subsubsection{前桥单独转向模式} -\subsubsection{前后桥反向转向模式} -\subsubsection{前后桥同向转向模式} -\subsection{速度、转角与曲率约束建模} -\subsubsection{速度约束} -\subsubsection{转向角约束} -\subsubsection{曲率约束} -\subsection{车辆动力学简化与驱动关系} -\subsection{状态方程统一表达} -\subsection{仿真实现中的参数映射关系} -\subsection{本章小结} - -\section{基于飞机辅助感知的自动对接识别方法} -\subsection{感知任务分析与总体方案设计} -\subsection{飞机辅助感知目标与识别信息设计} -\subsection{感知系统组成与传感器配置} -\subsubsection{视觉识别模块} -\subsubsection{近距测量模块} -\subsection{目标身份确认模型} -\subsection{相对位姿感知模型} -\subsection{近距离态势感知与安全判定} -\subsection{感知流程设计} -\subsection{本章小结} - -\section{基于相对位姿误差的自动接近与对接控制方法} -\subsection{控制任务描述与总体思路} -\subsection{状态变量、控制输入与误差定义} -\subsubsection{车辆状态与控制输入} -\subsubsection{感知误差接口} -\subsection{对接过程分析与分层控制架构} -\subsubsection{对接过程分阶段描述} -\subsubsection{分层控制架构} -\subsection{误差动力学模型建立} -\subsection{局部参考轨迹生成方法} -\subsubsection{预对接点与对接点构造} -\subsubsection{三次多项式局部轨迹} -\subsection{参考速度调度策略} -\subsection{误差反馈控制律设计} -\subsubsection{纵向速度控制律} -\subsubsection{角速度控制律} -\subsubsection{对接过程中的控制行为分析} -\subsection{四轮转向映射与约束处理} -\subsubsection{曲率计算} -\subsubsection{双桥反向转向模式} -\subsubsection{前桥单转向模式} -\subsubsection{速度与转角} -\subsection{终端停车判定与模式切换} -\subsection{控制算法主流程} -\subsection{本章小结} - -\section{仿真系统构建与实现} -\subsection{系统总体架构与软硬件环境} -\subsection{牵引车模型与传感器建模} -\subsection{任务与模式管理} -\subsection{ROS与Gazebo接口实现} -\subsection{本章小结} - -\end{document} \ No newline at end of file diff --git a/co/undergraduate/content/chapter1.tex b/co/undergraduate/content/chapter1.tex index 9ed56419..1e24ae0a 100644 --- a/co/undergraduate/content/chapter1.tex +++ b/co/undergraduate/content/chapter1.tex @@ -57,7 +57,7 @@ \section{研究内容与技术路线} \begin{figure}[htbp] \centering - \includegraphics[width=5.76806in,height=3.76181in]{figures/image2.png} + \includegraphics[width=\textwidth,keepaspectratio]{figures/image2.png} \caption{研究内容与技术路线图} \label{fig:1-1} \end{figure} diff --git a/co/undergraduate/content/chapter2.tex b/co/undergraduate/content/chapter2.tex index 7eeacd26..5259d0ea 100644 --- a/co/undergraduate/content/chapter2.tex +++ b/co/undergraduate/content/chapter2.tex @@ -62,7 +62,6 @@ \subsection{单轨等效模型} \end{cases} \label{eq:planar_motion} \end{equation} - 式中,\(\omega\) 为车辆偏航角速度。前两式给出了车辆质点速度在全局坐标系中的分解形式,第三式给出了车辆姿态随时间的演化规律。车辆轨迹由两个因素共同决定:一是沿当前朝向的平移速度 \(v\),二是决定航向变化速率的角速度 \(\omega\)。 @@ -92,7 +91,6 @@ \subsection{双桥转向角速度表达式} \end{cases} \label{eq:fourws_model} \end{equation} - 该模型是本课题后续路径规划、轨迹跟踪与对接控制设计的基础模型\cite{ref17,ref19,ref28}。 \section{转弯半径与曲率模型} @@ -104,14 +102,12 @@ \section{转弯半径与曲率模型} \omega = \frac{v}{R} \label{eq:3} \end{equation} - 结合上一节所得角速度表达式,可得双桥转向牵引车的等效转弯半径为 \begin{equation} R = \frac{L}{\tan\delta_{f} - \tan\delta_{r}} \label{eq:4} \end{equation} - 若进一步定义轨迹曲率 \(\kappa\)为转弯半径的倒数,则有 \begin{equation} @@ -140,7 +136,6 @@ \subsection{前桥单独转向模式} \dot{\theta} = \frac{v}{L}\tan\delta_{f} \label{eq:6} \end{equation} - 此时车辆行为与传统前轮转向车辆基本一致,如图~\ref{fig:2-1} 所示。该模式实现简单、控制逻辑清晰,但在对接空间受限的场景下,其最小转弯半径较大,不利于快速完成姿态调整。 \begin{figure}[htbp] @@ -158,7 +153,6 @@ \subsection{前后桥反向转向模式} \dot{\theta}=\frac{v}{L}\left[\tan\delta_{f}-\tan(-\delta_{f})\right]=\frac{2v}{L}\tan\delta_{f}. \label{eq:opposite_steering} \end{equation} - 此时车辆偏航角速度约为单桥转向工况的两倍,转弯半径显著减小,如图~\ref{fig:2-2} 所示,适用于牵引车在狭小机坪空间内快速调整姿态、靠近飞机前轮或完成局部避障。该模式是本课题中实现高机动性接近控制的重要运动模式。 \begin{figure}[htbp] @@ -195,7 +189,6 @@ \subsection{速度约束} 0 \leq v \leq v_{\max} \label{eq:velocity_limit} \end{equation} - 其中,\(v_{\max}\) 为车辆允许的最大作业速度。该约束保证车辆在接近、对接和牵引过程中具有足够的可控性,同时减小碰撞风险。 @@ -210,7 +203,6 @@ \subsection{转向角约束} \end{cases} \label{eq:steering_limits} \end{equation} - 其中,\(\delta_{f,\max}\) 与 \(\delta_{r,\max}\)分别为前桥与后桥最大允许转角。该约束直接限制车辆最大可实现曲率,也是最小转弯半径存在下界的原因。 @@ -222,7 +214,6 @@ \subsection{曲率约束} \kappa_{\max}=\frac{\tan\delta_{f,\max}-\tan(-\delta_{r,\max})}{L}. \label{eq:kappa_max} \end{equation} - 当车辆采用对称反向转向策略时,上式取到较大值。曲率约束在路径规划中具有重要作用,因为若规划轨迹的局部曲率超过车辆可实现上限,则该轨迹在物理上不可执行\cite{ref20,ref21,ref28}。 \section{车辆动力学简化与驱动关系} @@ -236,7 +227,6 @@ \section{车辆动力学简化与驱动关系} F = m\dot{v} \label{eq:10} \end{equation} - 上述表达式的意义在于建立控制输入与速度变化之间的基本联系。式中,\(F\) 不再作为独立控制量直接参与路径规划,而是通过车轮速度控制器间接实现。对本课题而言,该简化处理已经足以支撑Gazebo中的低速驱动仿真;若后续需要研究载荷变化、附着系数变化或高精度制动响应,再在此基础上扩展更高阶动力学模型即可。 @@ -270,7 +260,6 @@ \section{状态方程统一表达} \end{cases} \label{eq:state_acceleration} \end{equation} - 后一形式更适合用于模型预测控制、轨迹平滑优化及速度规划问题,而前三维形式更适合用于基本路径跟踪与状态传播计算。考虑到本课题当前阶段主要完成仿真验证与控制策略设计,后续章节可根据算法需求在两种表达之间进行选取。 \section{仿真实现中的参数映射关系} @@ -293,7 +282,6 @@ \section{仿真实现中的参数映射关系} \omega_{fl}=\omega_{fr}=\omega_{rl}=\omega_{rr}=\frac{v}{r_w}. \label{eq:wheel_speed_all} \end{equation} - 其中,\(\omega_{fl},\omega_{fr},\omega_{rl},\omega_{rr}\) 分别表示四个车轮的角速度。该关系建立了车辆运动学速度与Gazebo关节控制量之间的直接映射,是仿真中实现``给定线速度---车辆前进''行为的基础。 diff --git a/co/undergraduate/content/chapter3.tex b/co/undergraduate/content/chapter3.tex index a48e670c..298e88aa 100644 --- a/co/undergraduate/content/chapter3.tex +++ b/co/undergraduate/content/chapter3.tex @@ -47,7 +47,7 @@ \section{感知系统组成与传感器配置} \subsection{视觉识别模块} 视觉识别模块安装于牵引车前部,主要面向飞机前起落架区域进行图像采集。其核心任务包括: -\begin{enumerate}[label=(\arabic*),leftmargin=2em] +\begin{enumerate}[label=(\arabic*),leftmargin=4em] \item 检测比对目标识别码; \item 提取目标区域方向特征; \item 输出目标身份确认结果。 @@ -60,7 +60,7 @@ \subsection{近距测量模块} 近距测量模块用于补充视觉感知在近距离工况下的局部测量能力。由于牵引车在最终对接阶段距离飞机前起落架较近,此时即使视觉系统能够识别目标,也可能受到视角遮挡、自动对焦的影响。因此,有必要引入激光雷达、超声或等效测距模块,对前方局部区域的距离边界进行测量,以作为视觉估计的校核或补充\cite{ref18}。 该模块的主要作用包括: -\begin{enumerate}[label=(\arabic*),leftmargin=2em] +\begin{enumerate}[label=(\arabic*),leftmargin=4em] \item 判断牵引车前端与飞机局部结构之间的最近距离; \item 检测非目标障碍物是否进入安全边界; \item 在最终接近阶段为停车判定提供阈值依据。 @@ -105,7 +105,6 @@ \section{相对位姿感知模型} \mathbf{e}_{p}=\begin{bmatrix}e_x\\e_y\end{bmatrix}. \label{eq:position_error} \end{equation} - 其中,\(e_{x}\) 表示沿牵引车纵向方向的距离误差,\(e_{y}\) 表示沿牵引车横向方向的偏移误差。若从控制意义出发,\(e_{x}\) 主要决定前进或减速行为,\(e_{y}\) 主要决定转向修正行为。 @@ -118,7 +117,6 @@ \section{相对位姿感知模型} e_{\theta} = \theta_{a} - \theta_{v} \label{eq:17} \end{equation} - 该式表示牵引车当前朝向与目标对接方向之间的夹角偏差。其物理意义在于:即使车辆已经接近目标中心区域,如果 \(e_{\theta}\)仍较大,则机械对接过程仍可能失败。因此,在最终对接阶段,姿态误差控制通常与横向误差控制具有同等重要性。 @@ -128,7 +126,6 @@ \section{相对位姿感知模型} \mathbf{z}=\begin{bmatrix}e_x & e_y & e_\theta\end{bmatrix}^{T}. \label{eq:perception_output} \end{equation} - 该状态向量构成本章感知环节向控制环节输出的核心接口。换言之,感知层的任务不是直接控制车辆,而是持续向控制层提供``还差多远、偏了多少、方向还差多少''的量化描述。 \section{近距离态势感知与安全判定} @@ -159,13 +156,12 @@ \section{近距离态势感知与安全判定} \end{cases} \label{eq:docking_condition} \end{equation} - 这组三重约束共同定义了自动对接的局部成功条件。只有当纵向距离足够接近、横向偏差足够小且方向偏差足够小时,系统才可判定当前已具备机械对接条件。由此可见,近距态势感知并非孤立地``测个距离'',而是要将距离信息、位置误差和姿态误差统一纳入同一判定框架中。 \section{感知流程设计} 结合上述模型,本文将飞机辅助感知系统的工作流程划分为以下步骤: -\begin{enumerate}[label=(\arabic*),leftmargin=2em] +\begin{enumerate}[label=(\arabic*),leftmargin=4em] \item 牵引车进入任务区域后,启动视觉识别模块,对前方目标进行搜索; \item 检测到飞机辅助感知识别码后,解析目标身份信息,并与任务目标编号进行匹配; \item 若身份匹配成功,则提取目标中心点和方向参考特征,计算相对位置误差与姿态误差; @@ -194,7 +190,6 @@ \subsection{车辆状态与控制输入} \mathbf{x}=\begin{bmatrix}x & y & \theta & v\end{bmatrix}^{T}. \label{eq:control_state} \end{equation} - 其中,\(x\) 与 \(y\)表示牵引车参考点在全局坐标系中的位置坐标,\(\theta\) 表示车辆航向角,\(v\) 表示车辆纵向线速度。 @@ -204,14 +199,12 @@ \subsection{车辆状态与控制输入} \mathbf{u}=\begin{bmatrix}v & \delta_f & \delta_r\end{bmatrix}^{T}. \label{eq:control_input_velocity} \end{equation} - 或扩展为 \begin{equation} \mathbf{u}=\begin{bmatrix}a & \delta_f & \delta_r\end{bmatrix}^{T}. \label{eq:control_input_acceleration} \end{equation} - 其中,\(\delta_{f}\) 与 \(\delta_{r}\)分别为前桥和后桥转角,\(a\) 为车辆纵向加速度。前一种形式适用于直接速度控制实现,后一种形式更适合做速度平滑约束或模型预测控制扩展。 @@ -233,7 +226,7 @@ \section{对接过程分析与分层控制架构} \subsection{对接过程分阶段描述} 为了使控制方法与真实作业过程保持一致,本文将牵引车自动对接过程划分为以下五个阶段。 -\begin{enumerate}[label=(\arabic*),leftmargin=2em] +\begin{enumerate}[label=(\arabic*),leftmargin=4em] \item \textbf{搜索与等待阶段}。牵引车进入任务区域后,首先由视觉模块搜索飞机前起落架区域的特殊识别码,并与任务编号进行匹配。若当前识别结果与任务目标不一致,或者识别置信度低于阈值,则系统保持等待状态,不进入自动接近控制。此时输出为零速度、零转角保持命令,以防止误接近。 \item \textbf{自动接近阶段}。当目标身份确认有效后,系统开始进入自动接近阶段。该阶段的主要目标是让牵引车从较远初始位置稳定接近飞机前起落架前方的预对接区域。此时控制重点不在于最终精确对位,而在于快速减小纵向距离,同时保持可接受的横向误差和姿态误差。 \item \textbf{姿态对准阶段}。当牵引车与目标之间的纵向距离降低到一定阈值后,系统切换到姿态对准阶段。该阶段中,车辆不再追求较高接近速度,而是优先减小横向误差\(e_y\)和姿态误差\(e_\theta\),使牵引车中心线逐步与飞机前起落架对接方向重合。 @@ -277,7 +270,6 @@ \section{误差动力学模型建立} \end{cases} \label{eq:body_error_transform} \end{equation} - 该式的作用是把全局误差转化为车体系误差,使纵向和横向误差具有明确物理意义。其中,\(e_{x}\) 表示车辆前方还剩多少距离,\(e_{y}\) 表示车辆当前偏离对接轴线的程度。 @@ -294,7 +286,7 @@ \section{误差动力学模型建立} 上述误差方程表明: -\begin{enumerate} +\begin{enumerate}[label=(\arabic*),leftmargin=4em] \def\labelenumi{\arabic{enumi}.} \item 纵向误差 \(e_{x}\)的变化不仅与前进速度 @@ -327,7 +319,6 @@ \subsection{预对接点与对接点构造} \begin{bmatrix}\cos\theta_a\\\sin\theta_a\end{bmatrix}. \label{eq:pre_docking_point} \end{equation} - \(d_{pre}\) 为预留接近距离。该点位于最终目标点前方一定距离处,主要用于完成姿态调整。最终对接点定义为 @@ -336,7 +327,6 @@ \subsection{预对接点与对接点构造} \begin{bmatrix}\cos\theta_a\\\sin\theta_a\end{bmatrix}. \label{eq:docking_point} \end{equation} - \(d_{hook}\) 为机械连接前的停车距离。该点用于微动对接阶段的最终停靠。如果牵引车从较远位置直接朝最终对接点收敛,往往会导致中后段横向修正不足或姿态调节过猛;引入预对接点后,车辆可以先对准姿态,再进行最后的缓慢接近\cite{ref20,ref21,ref26,ref27,ref28}。 @@ -351,7 +341,6 @@ \section{参考速度调度策略} v_{r}=\min\left(v_{stage},\sqrt{\frac{a_{y,\max}}{|\kappa_r|+\varepsilon_\kappa}},k_d[d_{\min}-d_s]_+\right). \label{eq:speed_schedule} \end{equation} - 其中:\(v_{stage}\)为当前控制模式允许的最大速度; \(a_{y,\max}\)为允许的最大横向加速度; \(\kappa_{r}\)为参考轨迹曲率; \(d_{\min}\)为前方最近障碍距离; \(d_{s}\)为安全距离阈值; @@ -368,7 +357,6 @@ \subsection{纵向速度控制律} \left(v_r\cos e_\theta+k_xe_x\right). \label{eq:longitudinal_control} \end{equation} - 其中,\(k_{x}\) 为纵向误差增益,\(sat\) 表示饱和函数。 该控制律由两部分组成:\(v_{r}\cos e_{\theta}\):表示当车辆姿态误差较大时,自动减小前进速度,防止车辆在未对准状态下强行推进; @@ -385,7 +373,6 @@ \subsection{角速度控制律} \left[\omega_r+v_r\left(k_ye_y+k_\theta\sin e_\theta\right)\right]. \label{eq:angular_control} \end{equation} - 其中,\(k_{y}\) 和 \(k_{\theta}\)分别为横向误差增益和姿态误差增益。该控制律的物理意义如下\cite{ref17,ref26,ref27,ref28}: @@ -402,7 +389,7 @@ \subsection{角速度控制律} \subsection{对接过程中的控制行为分析} 结合车辆对接全过程,上述控制律在不同阶段表现如下: -\begin{enumerate}[label=(\arabic*),leftmargin=2em] +\begin{enumerate}[label=(\arabic*),leftmargin=4em] \item \textbf{自动接近阶段}:此时 \(e_{x}\)较大,速度项 \(k_{x}e_{x}\)占主导,车辆以较快速度向预对接点推进。 \item \textbf{姿态对准阶段}:随着 \(e_{x}\)逐步减小,横向误差 \(e_{y}\)和姿态误差 \(e_{\theta}\)开始主导控制器输出,角速度命令增大,车辆重点完成方向修正。 \item \textbf{微动对接阶段}:此时 \(v_{r}\)已被速度调度压低,车辆角速度输出较平缓,控制器主要进行细小偏差修正,避免出现末端振荡。 @@ -420,7 +407,6 @@ \subsection{曲率计算} \kappa_{d} = \frac{\omega_{d}}{\max(v_{d},\varepsilon_{v})} \label{eq:31} \end{equation} - 其中, \(\varepsilon_{v}\)为防止低速时分母趋近于零的安全常数。 \subsection{双桥反向转向模式} @@ -434,7 +420,6 @@ \subsection{双桥反向转向模式} \end{cases} \label{eq:opposite_mapping} \end{equation} - 该模式可以显著减小等效转弯半径,适合从较远位置快速接近飞机前起落架区域。 \subsection{前桥单转向模式} @@ -448,7 +433,6 @@ \subsection{前桥单转向模式} \end{cases} \label{eq:front_mapping} \end{equation} - 该模式虽然机动性不如双桥反向转向,但执行器协调更简单,转向响应更平顺,适合最终精调。 \subsection{速度与转角限幅} @@ -463,7 +447,6 @@ \subsection{速度与转角限幅} \end{cases} \label{eq:command_limits} \end{equation} - 同时对速度变化率和转角变化率限制为 \begin{equation} @@ -473,7 +456,6 @@ \subsection{速度与转角限幅} \end{cases} \label{eq:rate_limits} \end{equation} - 这样可以避免由于离散控制导致的命令突变,从而减小Gazebo中常见的抖振与过冲现象。 \section{终端停车判定与模式切换} @@ -491,8 +473,7 @@ \subsection{终端停车集合} \end{cases} \label{eq:terminal_conditions} \end{equation} - -将其定义为终端停车集合 +并将其定义为终端停车集合 \begin{equation} \Omega_t=\left\{ |e_x|\leq d_t,\ |e_y|\leq e_{y,\max},\ |e_\theta|\leq e_{\theta,\max},\ d_{\min}\geq d_s \right\}. @@ -504,16 +485,18 @@ \subsection{终端停车集合} \subsection{模式切换规则} 系统模式切换规则如下: +\begin{enumerate}[label=(\arabic*),leftmargin=6em] -搜索-自动接近:识别码身份确认成功且置信度满足阈值; +\item 搜索-自动接近:识别码身份确认成功且置信度满足阈值; -自动接近-姿态对准:\(e_{x}\) 进入近距阈值; +\item 自动接近-姿态对准:\(e_{x}\) 进入近距阈值; -姿态对准-微动对接:\(e_{x}\) 足够小且 \(e_{\theta}\)已较小; +\item 姿态对准-微动对接:\(e_{x}\) 足够小且 \(e_{\theta}\)已较小; -任意模式-中止:目标丢失或最近距离低于中止阈值; +\item 任意模式-中止:目标丢失或最近距离低于中止阈值; -微动对接-停车保持:进入终端集合 \(\Omega_{t}\)。 +\item 微动对接-停车保持:进入终端集合 \(\Omega_{t}\)。 +\end{enumerate} 这意味着控制系统并不是依赖一条连续控制律从头走到尾,而是通过``阶段切换 + 连续控制''的混合方式实现更符合工程需求的动作组织。 diff --git a/co/undergraduate/content/chapter4.tex b/co/undergraduate/content/chapter4.tex index 1aebf733..8dac6899 100644 --- a/co/undergraduate/content/chapter4.tex +++ b/co/undergraduate/content/chapter4.tex @@ -19,9 +19,7 @@ \section{系统总体架构与软硬件环境} launch 文件。 Gazebo -的~roslaunch~教程还给出了较为稳定的包层级约定,即~MYROBOT\_description/urdf、MYROBOT\_gazebo/worlds~与~MYROBOT\_gazebo/launch~的分离组织,这一约定适合本课题的工程化管理\cite{ref11,ref12,ref13,ref14,ref15,ref16}。 - -表~\ref{tab:software_stack} 给出本文采用的基准软件栈。 +的~roslaunch~教程还给出了较为稳定的包层级约定,即~MYROBOT\_description/urdf、MYROBOT\_gazebo/worlds~与~MYROBOT\_gazebo/launch~的分离组织,这一约定适合本课题的工程化管理\cite{ref11,ref12,ref13,ref14,ref15,ref16},表~\ref{tab:software_stack} 给出本文采用的基准软件栈。 \begin{table}[H] \centering @@ -50,7 +48,7 @@ \section{系统总体架构与软硬件环境} -如下系统架构图适合在论文中绘制为 PNG 或 SVG,用于说明 ROS/Gazebo +以上系统架构图适合在论文中绘制为 PNG 或 SVG,用于说明 ROS/Gazebo 联合仿真的模块层级关系。其图元关系与 Gazebo ROS 插件、ros\_control~和~robot\_state\_publisher~的官方工作方式一致。 @@ -290,7 +288,7 @@ \subsection{与常见路径跟踪算法的比较} \subsection{对比结果总结} 综合上述分析,本文方法的主要特点并不是在所有指标上优于人工或其他算法,而是在特定研究阶段和特定应用目标下具有较好的适用性。其优势主要体现在以下几个方面: -\begin{enumerate}[label=(\arabic*),leftmargin=2em] +\begin{enumerate}[label=(\arabic*),leftmargin=4em] \item 本文方法能够把机场牵引作业拆解为多个可控阶段,使``前往飞行器区域、对接飞行器、推出飞行器、解除牵引、车辆撤离''形成较完整的仿真流程。 \item 本文基于ROS与Gazebo构建了可重复测试的仿真平台,便于对车辆模型、控制策略和作业流程进行验证,相比直接进行真实车辆测试,风险和成本更低。 \item 本文方法结合车辆相对位姿误差进行控制分析,比单纯开环脚本更能体现自动对接过程中的误差修正思想。 diff --git a/co/undergraduate/figures/docs/figure_generation.md b/co/undergraduate/figures/docs/figure_generation.md new file mode 100644 index 00000000..882be957 --- /dev/null +++ b/co/undergraduate/figures/docs/figure_generation.md @@ -0,0 +1,482 @@ +\# 图片生成与来源说明(figure\_generation.md) + + + +\## 1. 文档说明 + + + +本文件用于说明论文中各类图片的来源、生成方式以及复现方法。 + + + +论文中的图片按照来源分为以下四类: + + + +1\. Python代码生成图; + +2\. MATLAB数据分析图; + +3\. SolidWorks建模与装配截图; + +4\. Gazebo仿真运行截图。 + + + +其中,代码生成图提供生成脚本与生成方法;工程设计图和实验结果图提供软件来源与获取方式说明。 + + + +\--- + + + +\# 2. Python代码生成图 + + + +\## 2.1 系统分层架构图 + + + +图名:系统分层架构图 + + + +生成方式: + + + +Python + Matplotlib + + + +源文件: + + + +```text + +figures/src/system\_architecture.py + +``` + + + +输出文件: + + + +```text + +figures/system\_architecture.png + +figures/system\_architecture.pdf + +figures/system\_architecture.svg + +``` + + + +生成命令: + + + +```bash + +python figures/src/system\_architecture.py + +``` + + + +说明: + + + +该图根据论文中的自动对接控制系统结构设计绘制,包含飞机辅助感知层、任务与模式管理层、局部轨迹生成层、误差反馈控制层、4WS映射与约束处理层、Gazebo执行层以及状态反馈闭环。 + + + +\--- + + + +\## 2.2 自动对接控制流程图 + + + +图名:自动对接控制流程图 + + + +生成方式: + + + +Python + Matplotlib + + + +源文件: + + + +```text + +figures/src/control\_flowchart.py + +``` + + + +输出文件: + + + +```text + +figures/control\_flowchart.png + +figures/control\_flowchart.pdf + +figures/control\_flowchart.svg + +``` + + + +生成命令: + + + +```bash + +python figures/src/control\_flowchart.py + +``` + + + +说明: + + + +该图根据自动对接任务控制逻辑绘制,描述从目标识别、轨迹生成、误差计算、控制映射到停车判定的完整控制流程。 + + + +\--- + + + +\# 3. SolidWorks模型与装配图 + + + +对应图片: + + + +```text + +图3-1 ~ 图3-8 + +(牵引车模型、飞机模型、装配体模型、运动仿真模型等) + +``` + + + +来源软件: + + + +```text + +SolidWorks 2025 + +``` + + + +生成方式: + + + +1\. 使用 SolidWorks 建立零部件模型; + +2\. 建立装配体约束关系; + +3\. 完成运动仿真配置; + +4\. 在建模环境或运动仿真环境中导出截图; + +5\. 保存为 PNG 图片用于论文插图。 + + + +源文件类型: + + + +```text + +\*.SLDPRT + +\*.SLDASM + +``` + + + +说明: + + + +该类图片属于CAD建模与结构设计结果展示,不属于代码生成图。 + + + +\--- + + + +\# 4. Gazebo仿真运行截图 + + + +对应图片: + + + +```text + +图4-1 ~ 图4-16 + +(机场场景、车辆运行、自动对接过程、控制结果等) + +``` + + + +来源软件: + + + +```text + +Ubuntu 16.04 + +ROS Melodic + +Gazebo 9.19.0 + +``` + + + +生成方式: + + + +1\. 启动机场仿真环境; + +2\. 加载飞机与牵引车模型; + +3\. 运行自动对接控制程序; + +4\. 在实验过程中截取Gazebo运行画面; + +5\. 导出PNG图片作为实验结果展示。 + + + +说明: + + + +该类图片属于实验结果截图,不属于代码生成图。 + + + +\--- + + + +\# 5. MATLAB数据分析图 + + + +对应图片: + + + +```text + +图4-17 ~ 图4-20 + +``` + + + +主要内容: + + + +```text + +性能对比柱状图 + +误差收敛曲线 + +控制效果曲线 + +综合性能雷达图 + +``` + + + +生成工具: + + + +```text + +MATLAB R2023a + +``` + + + +生成脚本: + + + +```text + +figures/MATLAB性能对比.py + +``` + + + +生成命令: + + + +```bash + +python MATLAB性能对比.py + +``` + + + +输出文件: + + + +```text + +image17.png + +image18.png + +image19.png + +image20.png + +``` + + + +说明: + + + +根据实验数据自动生成性能分析图,用于比较不同控制方法的效率、误差收敛特性和综合性能表现。 + + + +\--- + + + +\# 6. 图片编译说明 + + + +LaTeX论文中通过 `\\includegraphics{}` 调用图片文件。 + + + +推荐优先使用 PDF 格式图片: + + + +```latex + +\\begin{figure}\[htbp] + + \\centering + + \\includegraphics\[width=0.85\\textwidth]{figures/system\_architecture.pdf} + + \\caption{系统分层架构图} + + \\label{fig:system\_architecture} + +\\end{figure} + +``` + + + +其中: + + + +\* `.tex` 文件参与论文编译; + +\* `.pdf/.png/.svg` 为图片文件; + +\* `.py` 为图片生成脚本; + +\* `.md` 为图片来源说明文件,不参与LaTeX编译。 + + + +\--- + + + +\# 7. 总结 + + + +论文中的图片来源如下: + + + +| 图片类型 | 数量 | 来源 | + +| ------------- | -- | ------------------- | + +| Python生成流程图 | 2 | Python + Matplotlib | + +| MATLAB数据分析图 | 4 | MATLAB脚本生成 | + +| SolidWorks建模图 | 若干 | SolidWorks截图 | + +| Gazebo实验结果图 | 若干 | Gazebo运行截图 | + + + +其中所有代码生成图片均提供生成脚本;工程设计图与实验结果图均提供软件来源和获取方式说明,满足论文工程文件可追溯和可复现要求。 + + + diff --git "a/co/undergraduate/figures/MATLAB\346\200\247\350\203\275\345\257\271\346\257\224.py" "b/co/undergraduate/figures/src/MATLAB\346\200\247\350\203\275\345\257\271\346\257\224.py" similarity index 100% rename from "co/undergraduate/figures/MATLAB\346\200\247\350\203\275\345\257\271\346\257\224.py" rename to "co/undergraduate/figures/src/MATLAB\346\200\247\350\203\275\345\257\271\346\257\224.py" diff --git a/co/undergraduate/figures/src/control_flowchart.py b/co/undergraduate/figures/src/control_flowchart.py new file mode 100644 index 00000000..61576478 --- /dev/null +++ b/co/undergraduate/figures/src/control_flowchart.py @@ -0,0 +1,141 @@ +# -*- coding: utf-8 -*- +""" +使用 Python + Matplotlib 生成论文流程图。 +依赖: + pip install matplotlib +运行: + python 当前脚本.py +输出: + PNG、PDF、SVG 三种格式图片。 + +说明: + 为保证中文稳定显示,脚本优先调用 Noto Sans CJK SC 字体; + Windows 环境可改为 Microsoft YaHei 或 SimHei。 +""" +import matplotlib as mpl +from matplotlib import font_manager + +FONT_CANDIDATES = [ + "/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc", + "/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc", + "C:/Windows/Fonts/msyh.ttc", + "C:/Windows/Fonts/simhei.ttf", +] +FONT_PATH = next((p for p in FONT_CANDIDATES if __import__("os").path.exists(p)), None) +if FONT_PATH: + zh_font = font_manager.FontProperties(fname=FONT_PATH) +else: + zh_font = font_manager.FontProperties(family="sans-serif") + +mpl.rcParams["axes.unicode_minus"] = False +mpl.rcParams["mathtext.fontset"] = "dejavuserif" +mpl.rcParams["pdf.fonttype"] = 42 +mpl.rcParams["ps.fonttype"] = 42 + +import matplotlib.pyplot as plt +from matplotlib.patches import Rectangle, FancyBboxPatch, Polygon, FancyArrowPatch + +def t(ax, x, y, s, **kwargs): + kwargs.setdefault("fontproperties", zh_font) + ax.text(x, y, s, **kwargs) + +def process(ax, cx, cy, w, h, text, fc="#eef5ff", ec="#2d65b8", fs=10): + ax.add_patch(Rectangle((cx-w/2, cy-h/2), w, h, linewidth=1.05, edgecolor=ec, facecolor=fc)) + t(ax, cx, cy, text, ha="center", va="center", fontsize=fs) + +def rounded(ax, cx, cy, w, h, text, fc="#fff6df", ec="#222", fs=10): + ax.add_patch(FancyBboxPatch((cx-w/2, cy-h/2), w, h, + boxstyle="round,pad=0.02,rounding_size=0.04", + linewidth=1.05, edgecolor=ec, facecolor=fc)) + t(ax, cx, cy, text, ha="center", va="center", fontsize=fs) + +def decision(ax, cx, cy, w, h, text, fc="#f1fbef", ec="#19753b", fs=9.5): + pts = [(cx, cy+h/2), (cx+w/2, cy), (cx, cy-h/2), (cx-w/2, cy)] + ax.add_patch(Polygon(pts, closed=True, linewidth=1.05, edgecolor=ec, facecolor=fc)) + t(ax, cx, cy, text, ha="center", va="center", fontsize=fs) + +def arrow(ax, start, end, lw=1.2): + ax.add_patch(FancyArrowPatch(start, end, arrowstyle="-|>", mutation_scale=12, + linewidth=lw, color="black", shrinkA=0, shrinkB=0)) + +fig, ax = plt.subplots(figsize=(7.4, 11.6), dpi=220) +ax.set_xlim(0, 1) +ax.set_ylim(0, 1) +ax.axis("off") + +cx = 0.50 +w_proc = 0.40 +h_proc = 0.041 +ys = { + "start": 0.965, + "sense": 0.895, + "valid": 0.815, + "points": 0.745, + "mode": 0.685, + "traj": 0.625, + "feasible": 0.555, + "ref": 0.485, + "err": 0.435, + "speed": 0.385, + "vdwd": 0.335, + "map": 0.285, + "limit": 0.235, + "publish": 0.185, + "stop_dec": 0.115, + "loop": 0.045, +} + +rounded(ax, cx, ys["start"], 0.16, 0.036, "开始") +process(ax, cx, ys["sense"], w_proc, 0.052, "读取感知信息\n(身份、位姿、障碍距离)") +decision(ax, cx, ys["valid"], 0.29, 0.075, "目标身份\n是否有效?") +process(ax, cx, ys["points"], w_proc, h_proc, "生成预对接点与对接点") +process(ax, cx, ys["mode"], w_proc, 0.052, "当前模式选择目标点\n(接近 / 对准 / 微动)") +process(ax, cx, ys["traj"], w_proc, h_proc, "生成候选局部轨迹") +decision(ax, cx, ys["feasible"], 0.33, 0.07, "可行性筛选\n(曲率 / 安全距离)", fc="#fffaf0", ec="#e28a00") +process(ax, cx, ys["ref"], w_proc, h_proc, "提取参考状态与参考曲率", fc="#f4efff", ec="#7957c1") +process(ax, cx, ys["err"], w_proc, h_proc, "计算误差($e_x, e_y, e_θ$)", fc="#f4efff", ec="#7957c1") +process(ax, cx, ys["speed"], w_proc, h_proc, "速度调度", fc="#f4efff", ec="#7957c1") +process(ax, cx, ys["vdwd"], w_proc, h_proc, "计算 $v_d$ 与 $ω_d$", fc="#f4efff", ec="#7957c1") +process(ax, cx, ys["map"], w_proc, h_proc, "映射为 $δ_f, δ_r$", fc="#f4efff", ec="#7957c1") +process(ax, cx, ys["limit"], w_proc, h_proc, "限幅与斜率限制", fc="#f4efff", ec="#7957c1") +process(ax, cx, ys["publish"], w_proc, h_proc, "发布控制命令", fc="#f4efff", ec="#7957c1") +decision(ax, cx, ys["stop_dec"], 0.31, 0.065, "是否进入\n停车集合 $Ω_t$?") +rounded(ax, cx, ys["loop"], 0.28, 0.040, "循环执行", fc="#fff8e9", ec="#bd7b00") + +process(ax, 0.78, ys["valid"], 0.18, 0.046, "保持等待", fc="#fff1f1", ec="#d93333") +process(ax, 0.78, ys["feasible"], 0.18, 0.046, "中止 / 停车", fc="#fff1f1", ec="#d93333") +process(ax, 0.80, ys["stop_dec"], 0.22, 0.060, "零速停车\n($v=0, δ_f=0, δ_r=0$)", fc="#effaf0", ec="#3b8b45") + +sequence = ["start","sense","valid","points","mode","traj","feasible","ref","err","speed","vdwd","map","limit","publish","stop_dec","loop"] +for a, b in zip(sequence[:-1], sequence[1:]): + if a in ["valid", "feasible", "stop_dec"]: + arrow(ax, (cx, ys[a]-0.037), (cx, ys[b]+(0.026 if b in ["points","ref"] else 0.021))) + else: + arrow(ax, (cx, ys[a]-0.026), (cx, ys[b]+0.026)) + +t(ax, 0.462, 0.776, "是", fontsize=10, color="green") +t(ax, 0.608, ys["valid"]+0.020, "否", fontsize=10, color="red") +arrow(ax, (cx+0.145, ys["valid"]), (0.69, ys["valid"])) + +t(ax, 0.462, 0.513, "有", fontsize=10, color="green") +t(ax, 0.608, ys["feasible"]+0.020, "无", fontsize=10, color="red") +arrow(ax, (cx+0.165, ys["feasible"]), (0.69, ys["feasible"])) + +t(ax, 0.608, ys["stop_dec"]+0.016, "是", fontsize=10, color="green") +t(ax, 0.462, ys["stop_dec"]-0.053, "否", fontsize=10, color="red") +arrow(ax, (cx+0.155, ys["stop_dec"]), (0.69, ys["stop_dec"])) + +ax.plot([0.87, 0.95, 0.95, 0.70], [ys["valid"], ys["valid"], ys["sense"], ys["sense"]], + color="black", linewidth=1.1) +arrow(ax, (0.70, ys["sense"]), (cx+w_proc/2, ys["sense"])) + +ax.plot([0.87, 0.95, 0.95, 0.70], [ys["feasible"], ys["feasible"], ys["sense"], ys["sense"]], + color="black", linewidth=1.1) + +ax.plot([cx, 0.06, 0.06, 0.30], [ys["loop"], ys["loop"], ys["sense"], ys["sense"]], + color="black", linewidth=1.1) +arrow(ax, (0.30, ys["sense"]), (cx-w_proc/2, ys["sense"])) + +plt.tight_layout() +for ext in ["png", "pdf", "svg"]: + plt.savefig(f"figures/control_flowchart.{ext}", bbox_inches="tight") diff --git a/co/undergraduate/figures/image2.py b/co/undergraduate/figures/src/image2.py similarity index 100% rename from co/undergraduate/figures/image2.py rename to co/undergraduate/figures/src/image2.py diff --git a/co/undergraduate/figures/src/system_architecture.py b/co/undergraduate/figures/src/system_architecture.py new file mode 100644 index 00000000..e891a1cb --- /dev/null +++ b/co/undergraduate/figures/src/system_architecture.py @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- +""" +使用 Python + Matplotlib 生成论文流程图。 +依赖: + pip install matplotlib +运行: + python 当前脚本.py +输出: + PNG、PDF、SVG 三种格式图片。 + +说明: + 为保证中文稳定显示,脚本优先调用 Noto Sans CJK SC 字体; + Windows 环境可改为 Microsoft YaHei 或 SimHei。 +""" +import matplotlib as mpl +from matplotlib import font_manager + +FONT_CANDIDATES = [ + "/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc", + "/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc", + "C:/Windows/Fonts/msyh.ttc", + "C:/Windows/Fonts/simhei.ttf", +] +FONT_PATH = next((p for p in FONT_CANDIDATES if __import__("os").path.exists(p)), None) +if FONT_PATH: + zh_font = font_manager.FontProperties(fname=FONT_PATH) +else: + zh_font = font_manager.FontProperties(family="sans-serif") + +mpl.rcParams["axes.unicode_minus"] = False +mpl.rcParams["mathtext.fontset"] = "dejavuserif" +mpl.rcParams["pdf.fonttype"] = 42 +mpl.rcParams["ps.fonttype"] = 42 + +import matplotlib.pyplot as plt +from matplotlib.patches import FancyBboxPatch, FancyArrowPatch + +def t(ax, x, y, s, **kwargs): + kwargs.setdefault("fontproperties", zh_font) + ax.text(x, y, s, **kwargs) + +def rounded_box(ax, x, y, w, h, title, subtitle, fc, ec): + box = FancyBboxPatch( + (x, y), w, h, + boxstyle="round,pad=0.025,rounding_size=0.09", + linewidth=1.35, + edgecolor=ec, + facecolor=fc, + linestyle="--" + ) + ax.add_patch(box) + t(ax, x + w/2, y + h*0.62, title, ha="center", va="center", + fontsize=17, fontweight="bold") + t(ax, x + w/2, y + h*0.31, subtitle, ha="center", va="center", + fontsize=10.8) + +def arrow(ax, start, end, lw=1.6): + ax.add_patch(FancyArrowPatch( + start, end, arrowstyle="-|>", mutation_scale=15, + linewidth=lw, color="black", shrinkA=0, shrinkB=0 + )) + +fig, ax = plt.subplots(figsize=(7.2, 10.2), dpi=220) +ax.set_xlim(0, 1) +ax.set_ylim(0, 1) +ax.axis("off") + +x, w, h = 0.17, 0.72, 0.082 +ys = [0.875, 0.745, 0.615, 0.485, 0.355, 0.225, 0.095] +items = [ + ("飞机辅助感知层", "(身份确认、目标位姿、最近障碍距离)", "#eaf3ff", "#5c8fd9"), + ("任务与模式管理层", "(搜索 / 接近 / 对准 / 微动 / 停车 / 中止)", "#edf8e8", "#74ad5d"), + ("局部轨迹生成层", "(预对接点、对接点、候选轨迹、可行性筛选)", "#fff4cc", "#f4ad28"), + ("误差反馈控制层", r"($e_x,\ e_y,\ e_\theta \rightarrow v_d,\ \omega_d$)", "#f0eafd", "#8062c7"), + ("4WS映射与约束处理层", r"($v_d,\ \omega_d \rightarrow \delta_f,\ \delta_r$,轮速)", "#eaf3ff", "#5c8fd9"), + ("Gazebo执行层", "(转向关节、车轮速度控制器)", "#ffe9db", "#ec7e3b"), + ("状态反馈 / 感知更新", "", "#f2f2f2", "#8a8a8a"), +] + +for y, item in zip(ys, items): + rounded_box(ax, x, y, w, h, *item) + +for i in range(len(ys)-1): + arrow(ax, (0.53, ys[i]), (0.53, ys[i+1]+h)) + +arrow(ax, (x, ys[-1] + h*0.45), (0.08, ys[-1] + h*0.45), lw=1.45) +ax.plot([0.08, 0.08, x], [ys[-1] + h*0.45, ys[0] + h*0.55, ys[0] + h*0.55], + color="black", linewidth=1.45) +arrow(ax, (0.08, ys[0] + h*0.55), (x, ys[0] + h*0.55), lw=1.45) + +plt.tight_layout() +for ext in ["png", "pdf", "svg"]: + plt.savefig(f"figures/system_architecture.{ext}", bbox_inches="tight") diff --git a/co/undergraduate/hutbthesis.cls b/co/undergraduate/hutbthesis.cls index ea8ea23c..112ec09c 100644 --- a/co/undergraduate/hutbthesis.cls +++ b/co/undergraduate/hutbthesis.cls @@ -549,10 +549,7 @@ breaklinks = true, plainpages = false, pdfdisplaydoctitle = true, - colorlinks=true, - linkcolor=blue, - citecolor=blue, - urlcolor=blue, + hidelinks, } \newcounter{hutb@bookmark} \renewcommand\hutb@pdfbookmark[2]{%