
1. 项目概述与核心价值最近几年无人机编队飞行从技术演示逐渐走向了实际应用无论是表演灯光秀还是执行协同作业任务都离不开一个核心问题如何让一群无人机在没有GPS或者GPS信号不佳的环境下还能精确地知道彼此的位置并保持队形这正是“纯方位无源定位”要解决的硬核难题。它不依赖外部信号发射源无源仅通过机载传感器测量队友的方向纯方位来推算自身在编队中的相对位置。这听起来有点像我们蒙上眼睛只通过听周围朋友说话的声音方向来脑补出自己站在房间的哪个位置。2022年高教社杯全国大学生数学建模竞赛的B题就把这个前沿又极具挑战性的问题抛给了广大参赛者。题目要求为无人机编队设计纯方位无源定位模型和位置调整方案这不仅仅是出一道数学题更是对参赛者将理论模型、算法编程和工程思维融合解决实际问题能力的一次全面考察。对于无人机、自动化、电子信息等相关领域的学生和爱好者而言深入理解这道题的解题思路其价值远超比赛本身。它为你打开了一扇窗让你能窥见多智能体协同、分布式估计、传感器融合这些前沿技术的核心逻辑。无论你是想夯实数学建模功底还是为未来的科研或工程项目做准备拆解这道赛题都是一次绝佳的实战演练。2. 问题拆解与核心思路解析面对“纯方位无源定位”这个命题我们首先要把它分解成几个可以逐步攻克的关键子问题。不能一上来就想用一个复杂的公式解决所有问题那样很容易陷入思维混乱。2.1 核心需求与约束条件分析题目通常会设定一个典型场景假设有若干架无人机组成一个编队其中只有少数几架比如2架知道自己的精确位置称为“FY00”和“FY01”或参考机其他无人机称为“未知位置无人机”则完全不知道自己的坐标。所有无人机都装有一个能够测量相对方向的传感器例如视觉相机、定向天线也就是说每架无人机都能“看到”或“感知到”编队中其他部分无人机的方位角也许还有俯仰角。我们需要解决的核心问题有两个层次定位问题在初始时刻仅根据少数已知位置无人机提供的“锚点”信息以及其他无人机相互之间的方位观测计算出每一架未知无人机的初始位置。调整问题编队需要从初始的随机或偏离状态通过一系列移动调整到一个预设的理想队形比如锥形、圆形、一字形。在调整过程中无人机仍然只能依靠纯方位信息进行相对定位并据此决策自己的移动方向。约束条件非常明确无全局定位如GPS、无距离信息、通信可能受限。这迫使我们必须利用角度观测值之间存在的几何约束关系来求解位置。2.2 整体解决思路框架基于上述分析一个经典且有效的解决框架可以分为“离线条”和“在线条”两部分离线条静态定位模型构建与求解这一阶段对应问题的第一问或初始定位阶段。我们把所有无人机在某一时刻的方位观测数据“冻结”起来构建一个全局的优化模型。思路是每两个无人机之间的方位观测比如无人机A测到无人机B的方向在二维或三维空间中会形成一条“射线”。如果A和B的位置都正确那么B点应该位于从A点出发沿该方向的这条射线上。由于观测存在误差B点可能不严格在射线上。因此我们可以建立一个最小二乘模型目标是让所有无人机的估计位置与所有方位观测射线之间的“距离”总和最小。这是一个典型的非线性优化问题。注意这里存在一个“可观测性”问题。如果已知位置的无人机锚点太少或者无人机之间的观测拓扑结构不好比如所有未知无人机都只和同一个锚点有观测那么整个系统可能无法唯一确定所有位置。这就好比给你一张地图但上面只标了一个点和你到其他点的方向你是无法确定自己位置的。通常需要至少两个非共线的锚点并且观测网络要尽可能连通。在线条动态位置调整方案设计这一阶段对应编队形成或保持队形的问题。我们无法一次性算出完美队形而是需要设计一个分布式的控制律让每架无人机根据自己实时估计的邻居位置通过纯方位定位模块不断更新与期望队形中邻居位置的偏差来计算出自己下一步应该朝哪个方向飞、飞多快。一个常见的思路是“一致性控制”或“梯度下降法”。每架无人机将期望队形中它与邻居的相对位置向量作为目标将当前通过定位估计出的相对位置作为现状计算出一个驱使现状向目标靠近的控制力速度向量。所有无人机同时执行这样的计算和移动整个编队就会逐渐收敛到期望形状。关键在于这个控制律必须是分布式的、仅依赖局部信息邻居的方位或估计位置并且要能处理定位本身存在的误差和延迟。3. 核心模型纯方位无源定位的数学原理与实现理解了整体框架我们来深入最核心的静态定位模型。这是整个问题的基础定位不准后续调整全是空谈。3.1 坐标系与观测模型建立首先我们需要建立一个统一的坐标系。通常以某个已知点如FY00为坐标原点建立二维平面直角坐标系。假设有N架无人机其中前M架M≥2位置已知为锚点。对于任意两架无人机i和j假设无人机i上的传感器可以测量到无人机j相对于自身的方位角 θ_ij。这个角度通常是相对于无人机i自身机体坐标系某个轴如机头方向的夹角。但在全局定位中我们需要统一到全局坐标系。因此观测模型可以表示为tan(θ_ij α_i) (y_j - y_i) / (x_j - x_i)其中(x_i, y_i)和(x_j, y_j)分别是无人机i和j在全局坐标系中的坐标α_i是无人机i的机头方向与全局坐标系X轴的夹角即无人机的偏航角。这里出现了一个关键点如果无人机自身的姿态α_i未知那么它观测到的方位角θ_ij就无法直接转换到全局坐标系。这是纯方位定位中的一个主要难点。为了简化在不少解题思路中会做一个重要假设所有无人机的机头方向一致即α_i相同或已知。例如假设所有无人机在定位阶段都朝向同一个方向比如正北这样α_i就是一个已知常数如0观测方程就简化为tan(θ_ij) (y_j - y_i) / (x_j - x_i)这个简化大大降低了问题复杂度也是初版模型常用的方法。但需要意识到在实际中这需要通过磁罗盘或视觉同步等手段来保证是一个很强的假设。3.2 非线性最小二乘优化模型在简化观测模型下对于每一对存在方位观测的无人机(i, j)我们可以根据它们的估计坐标写出一个残差方程r_ij (y_j - y_i) - tan(θ_ij) * (x_j - x_i)理想情况下如果坐标和观测都完美所有r_ij应为0。但由于观测噪声和估计误差r_ij不为零。我们的目标是找到所有未知无人机的位置坐标X [x_{M1}, y_{M1}, ..., x_N, y_N]^T使得所有观测残差的平方和最小。这就构成了一个非线性最小二乘问题min_X F(X) Σ_{(i,j) in Obs} r_ij^2其中Obs是所有有效方位观测对的集合。已知锚点的坐标作为常数代入不参与优化。3.3 模型求解从理论到代码求解上述非线性最小二乘问题通常采用迭代优化算法。Levenberg-Marquardt (L-M)算法是解决这类问题的利器它在梯度下降和高斯-牛顿法之间自适应切换兼具收敛速度和稳定性。算法步骤简述初始化给所有未知无人机一个初始位置猜测。这个初始值很重要如果离真实解太远算法可能收敛到局部最优或发散。一个简单的策略是利用锚点和方位角进行粗略的三角测量或者直接在锚点附近随机初始化。迭代更新在每次迭代k计算当前参数X_k下的残差向量r(X_k)和雅可比矩阵J(X_k)。雅可比矩阵包含了每个残差对每个待估参数的偏导数它描述了残差随参数变化的敏感度。求解增量L-M算法求解一个线性方程组(J^T J λ I) δ -J^T r。其中λ是阻尼因子I是单位矩阵。当λ很大时更新方向接近梯度下降步长小但稳定当λ很小时接近高斯-牛顿法收敛快。判断更新用求得的增量δ更新参数X_{k1} X_k δ。计算新的目标函数值F(X_{k1})。如果F减小则接受这次更新并减小λ否则拒绝更新增大λ并重新计算δ。收敛判断重复步骤2-4直到增量δ的范数小于某个阈值或者目标函数F的变化很小或者达到最大迭代次数。代码实现要点以Python为例import numpy as np from scipy.optimize import least_squares def residual_function(params, anchor_positions, unknown_indices, observations): 计算残差的函数。 params: 一维数组包含所有未知无人机的位置 [x1, y1, x2, y2, ...] anchor_positions: 已知锚点的坐标列表 [(x_a1, y_a1), (x_a2, y_a2), ...] unknown_indices: 未知无人机编号到params中索引的映射。 observations: 列表每个元素为 (i, j, theta_ij)表示无人机i观测到j的方位角。 # 1. 重构完整位置向量 full_positions anchor_positions.copy() # 假设先放锚点 # 将params中的值按顺序填入未知无人机位置 for idx, (uav_id, param_idx) in enumerate(unknown_indices.items()): full_positions[uav_id] (params[2*idx], params[2*idx1]) residuals [] for i, j, theta in observations: xi, yi full_positions[i] xj, yj full_positions[j] # 计算残差 (yj - yi) - tan(theta) * (xj - xi) # 注意处理角度为90度时tan无穷大的问题可用sin/cosin形式避免 # 更稳定的形式 sin(theta)*(xj-xi) - cos(theta)*(yj-yi) 0 # 对应的残差 r sin(theta)*(xj-xi) - cos(theta)*(yj-yi) r np.sin(theta) * (xj - xi) - np.cos(theta) * (yj - yi) residuals.append(r) return np.array(residuals) # 假设数据准备 anchor_pos {0: (0, 0), 1: (10, 0)} # 锚点0和1的位置 observations_list [(0, 2, np.deg2rad(30)), (1, 2, np.deg2rad(150)), ...] # 观测数据 unknown_ids [2, 3, 4] # 未知无人机编号 # 构建未知索引映射和初始猜测 initial_guess [] for uid in unknown_ids: # 简单初始猜测例如置于所有锚点的平均位置附近 avg_x np.mean([p[0] for p in anchor_pos.values()]) avg_y np.mean([p[1] for p in anchor_pos.values()]) initial_guess.extend([avg_x np.random.randn()*2, avg_y np.random.randn()*2]) # 调用优化器 result least_squares(residual_function, initial_guess, args(anchor_pos, unknown_ids, observations_list), methodlm, # 使用L-M算法 verbose2) estimated_params result.x实操心得scipy.optimize.least_squares函数封装了L-M算法非常方便。关键在于正确构建残差函数。使用sinθ * Δx - cosθ * Δy的形式比直接使用tanθ更数值稳定因为它避免了角度接近90度时的奇异性问题。另外初始值的设置对收敛影响很大如果简单初始化不奏效可以尝试多次随机初始化并选取最优解。4. 编队位置调整分布式控制策略设计在获得或持续估计无人机之间的相对位置关系后下一步就是驱动它们形成目标队形。这是一个典型的多智能体编队控制问题。4.1 基于一致性理论的编队控制一致性理论的核心思想是让每个智能体只根据邻居的信息调整自己的状态最终使整个群体的某个状态量达成一致。对于编队控制我们通常关心的是相对位置的一致性。定义期望队形用一个图G(V, E)表示顶点V对应无人机边E表示期望的邻居关系。每条边(i, j)关联一个期望的相对位置向量d_ij从i指向j在队形中的向量。实际相对位置在飞行过程中无人机i通过其定位模块估计出它与邻居j的实际相对位置向量p_ij p_j_est - p_i_est其中p_i_est是无人机i对自身位置的估计可能包含误差。控制目标设计一个控制律使得对于所有边(i, j)实际相对位置p_ij渐近收敛到期望相对位置d_ij。4.2 分布式控制律设计与实现一个广泛使用的、简单有效的控制律是基于位移偏差的线性反馈控制对于无人机i其控制输入即速度指令u_i设计为所有邻居相对位置偏差的加权和u_i -k * Σ_{j in N_i} (p_ij - d_ij)其中N_i是无人机i的邻居集合根据通信或感知范围确定。p_ij p_j_est - p_i_est是当前估计的相对位置。d_ij是期望的相对位置。k 0是控制增益决定了收敛速度。这个公式的直观理解无人机i检查它和每个邻居j的当前相对位置与期望相对位置的差距(p_ij - d_ij)。这个差距向量可以理解为“j相对于i站错了多远”。然后i会朝着缩小这个差距的方向移动。对所有邻居的差距求和意味着i在综合协调它与所有邻居的关系。负号表示运动方向与差距方向相反从而减小差距。注意这里有一个关键点p_ij和d_ij都是从i指向j的向量。因此当p_ij - d_ij指向某个方向时意味着j相对于i的实际位置比期望位置更偏向那个方向。为了缩小这个差距i应该向相反方向移动公式中的负号或者等价地j应该向那个方向移动。在分布式控制中每架无人机只负责自己的移动所以这个控制律驱使i移动来补偿它感知到的所有相对误差。离散时间下的位置更新 在实际仿真或控制中我们通常在离散时间步长Δt下更新位置p_i(t1) p_i(t) u_i(t) * Δt4.3 仿真实现与可视化将控制律在仿真中实现可以清晰地观察编队收敛过程。以下是基于Python的简化仿真框架import numpy as np import matplotlib.pyplot as plt class UAV: def __init__(self, uav_id, initial_pos): self.id uav_id self.true_pos np.array(initial_pos, dtypefloat) # 真实位置仿真中用于生成观测 self.est_pos np.array(initial_pos, dtypefloat) # 估计位置由定位算法提供 self.control_gain 0.05 def compute_control_input(self, neighbors_info, formation_graph): 根据邻居信息和期望队形计算控制输入。 neighbors_info: 字典 {邻居id: (估计的相对位置向量)} formation_graph: 字典 {邻居id: 期望的相对位置向量)} control_vec np.zeros(2) for nid, rel_pos_est in neighbors_info.items(): if nid in formation_graph: desired_rel_vec formation_graph[nid] error_vec rel_pos_est - desired_rel_vec control_vec - self.control_gain * error_vec # 公式中的负号已包含 return control_vec def simulate_formation(agents, formation_graph, total_steps200, dt0.1): 编队控制主仿真循环。 agents: UAV对象列表。 formation_graph: 列表的列表或字典的字典表示每个智能体的期望邻居相对位置。 positions_history [] for step in range(total_steps): # 1. 模拟基于当前真实位置生成方位观测并运行定位算法更新est_pos # 此处简化假设定位是完美的即 est_pos true_pos noise for agent in agents: # 模拟定位噪声 agent.est_pos agent.true_pos np.random.randn(2) * 0.02 # 2. 每架无人机根据其估计位置和期望队形计算控制量 for i, agent_i in enumerate(agents): # 获取邻居信息简化假设所有其他无人机都是邻居 neighbors_info {} for j, agent_j in enumerate(agents): if i ! j: # 计算估计的相对位置 est_rel_pos agent_j.est_pos - agent_i.est_pos neighbors_info[j] est_rel_pos # 计算控制输入 u agent_i.compute_control_input(neighbors_info, formation_graph[i]) # 3. 更新真实位置模拟动力学一阶积分器模型 agent_i.true_pos u * dt # 记录历史位置用于绘图 positions_history.append([agent.true_pos.copy() for agent in agents]) return positions_history # 初始化5架无人机随机初始位置 np.random.seed(42) num_uavs 5 agents [UAV(i, np.random.randn(2)*5) for i in range(num_uavs)] # 定义期望队形一个正五边形 center np.array([0, 0]) radius 8 desired_positions [] for i in range(num_uavs): angle 2 * np.pi * i / num_uavs pos center radius * np.array([np.cos(angle), np.sin(angle)]) desired_positions.append(pos) # 构建formation_graph每个智能体期望与所有其他智能体保持特定相对位置 formation_graph {} for i in range(num_uavs): formation_graph[i] {} for j in range(num_uavs): if i ! j: # 期望的相对位置向量从i指向j formation_graph[i][j] desired_positions[j] - desired_positions[i] # 运行仿真 history simulate_formation(agents, formation_graph, total_steps150) # 可视化 plt.figure(figsize(12, 5)) # 初始队形 plt.subplot(1, 2, 1) init_pos history[0] for pos in init_pos: plt.scatter(pos[0], pos[1], cred, s50) plt.title(Initial Random Formation) plt.axis(equal) plt.grid(True) # 最终队形 plt.subplot(1, 2, 2) final_pos history[-1] for pos in final_pos: plt.scatter(pos[0], pos[1], cblue, s50) # 画出期望队形顶点 for pos in desired_positions: plt.scatter(pos[0], pos[1], cgreen, s50, markerx, linewidths2) plt.title(Final Formation (Blue) vs Desired (Green X)) plt.axis(equal) plt.grid(True) plt.show()注意事项与技巧控制增益k的选择增益k太大可能导致系统震荡甚至发散太小则收敛速度慢。需要通过仿真调试通常与时间步长Δt相关满足kΔt 1以保证稳定性。邻居定义上述仿真假设全连接每个无人机感知所有其他无人机。现实中通信或感知范围有限formation_graph和neighbors_info应只包含在有效范围内的邻居。这要求算法能处理时变的邻居拓扑。定位误差的影响仿真中我们简单添加了噪声。在实际控制回路中定位误差会导致est_rel_pos不准确进而产生控制误差。一种增强鲁棒性的方法是在控制律中加入滤波如对估计位置进行低通滤波或使用更复杂的鲁棒控制设计。避障考虑基本的控制律没有考虑无人机之间的碰撞避免。在实际应用中必须在控制指令上叠加一个排斥力场当两架无人机距离过近时产生排斥速度。5. 常见问题、挑战与进阶优化思路在实际实现和解题过程中你会遇到一系列挑战。以下是一些典型问题及其应对思路。5.1 定位模型中的病态问题与初始化问题描述非线性优化求解失败结果不收敛或收敛到明显错误的值。原因分析观测数据不足或几何构型差例如所有未知无人机都只与同一个锚点有观测或者所有观测线几乎平行导致问题不可观或病态。初始值太差初始猜测离真实解太远优化算法陷入了局部极小值。观测噪声过大噪声淹没了真实的几何关系。解决策略增加观测冗余度确保每个未知无人机至少能被两个非共线的锚点观测到并且无人机之间也有相互观测。观测网络越稠密定位越鲁棒。改进初始化方法两步法先利用锚点观测通过三角测量或几何约束为每个未知无人机求一个粗略解可能有多解作为初始值。松弛法先求解一个更简单的、凸的问题例如忽略角度缠绕问题或使用半定规划松弛将其解作为非线性优化的初值。多起点优化从多个随机初始点开始运行优化选择目标函数值最小的解作为最终结果。使用鲁棒的损失函数将最小二乘中的平方损失r^2替换为Huber损失等可以减少粗大观测误差野值的影响。5.2 编队控制中的震荡与发散问题描述无人机在调整队形时来回振荡无法稳定甚至飞散。原因分析控制增益过大这是最常见的原因。过大的增益放大了误差和噪声导致系统超调和不稳定。定位更新延迟控制指令基于过时的位置估计形成了滞后的反馈容易引发振荡。理想队形与动力学约束冲突期望的队形变化过于剧烈无人机最大速度和加速度无法跟上。解决策略增益调参与滤波仔细调整控制增益k从小值开始逐步增加观察系统响应。对估计的位置或计算出的控制指令进行低通滤波平滑高频噪声和突变。引入速度一致性项在控制律中不仅考虑位置偏差还考虑与邻居的速度差有助于阻尼振荡。控制律变为u_i -k_p * Σ(p_ij - d_ij) - k_v * Σ(v_j - v_i)其中v是速度估计。分层控制与轨迹规划不要直接让无人机“跳变”到目标队形。可以先规划一条平滑的参考轨迹让编队中心或领航机沿轨迹运动其他无人机再通过相对位置控制跟踪自己的期望位置。这分解了问题降低了动态压力。5.3 从二维到三维的扩展原题通常是二维平面但无人机编队实际是三维的。扩展到三维主要带来两个变化观测模型方位信息需要两个角方位角azimuth和俯仰角elevation。观测方程变为球面几何关系。队形定义期望相对位置向量d_ij变为三维向量。三维定位模型 残差方程需要基于单位观测向量和位置差向量的点积或叉积来构建。例如假设无人机i测得无人机j的单位方向向量为s_ij由方位角和俯仰角计算得出。在全局坐标系下从i到j的向量应为(p_j - p_i)。理想情况下单位化的(p_j - p_i)应与s_ij平行。因此残差可以用它们的叉积模长来定义r_ij || (p_j - p_i) / ||p_j - p_i|| × s_ij ||。最小化所有残差平方和同样构成非线性最小二乘问题但变量和方程维度增加了。三维控制律 控制律形式完全不变只是所有向量位置、相对位置、速度都变为三维。分布式一致性理论在三维空间同样适用。5.4 融合其他传感器与信息纯方位定位的精度和鲁棒性有限。在实际工程中只要有可能就会融合其他信息惯性测量单元IMU提供自身的角速度和加速度信息通过积分可以估计短时间内的位移和姿态变化与方位观测进行融合如使用卡尔曼滤波器可以显著提高定位精度和频率并有助于估计自身的姿态角α_i从而放松“机头方向一致”的强假设。高度传感器气压计或激光测距仪可以提供绝对或相对高度信息在三维定位中这是一个非常宝贵的约束。有限的测距信息如果部分无人机间能测量到粗略距离例如通过信号强度RSSI即使不精确也能极大地改善定位问题的可观测性和精度。融合这些信息通常需要状态估计框架如扩展卡尔曼滤波EKF或因子图优化Factor Graph Optimization。这将是比静态非线性最小二乘更强大、更通用的解决方案能够处理动态场景和多种异构传感器数据。6. 项目总结与资源拓展回顾整个项目我们从一道赛题出发系统地拆解了“无人机纯方位无源定位与编队控制”这一复杂问题。核心路径非常清晰建立方位观测的几何模型 - 构建并求解非线性最小二乘问题实现静态定位 - 设计基于相对位置偏差的分布式控制律实现动态编队调整。这条路径完美地体现了“感知-估计-决策-控制”的经典机器人学闭环。在实战中有几个体会特别深刻 第一模型的简化与现实的权衡。“机头方向一致”的假设是打开问题局面的钥匙但也是后续工程化必须卸下的枷锁。在解题时用它快速得到可行解但要心里明白真正的系统必须融合IMU来估计和补偿这个姿态角。 第二数据决定了上限。无论模型多精巧如果观测几何构型太差比如所有无人机和锚点几乎共线定位精度必然惨不忍睹。在部署前花时间分析一下“什么样的队形和飞行路径能获得好的观测几何”是值得的。 第三控制是门艺术调参是门玄学。那个看起来简单的控制增益k背后连着系统的稳定性、收敛速度和抗噪能力。仿真时多试试不同的k观察系统的响应曲线你会对“阻尼”、“超调”、“收敛时间”这些概念有肌肉记忆般的理解。如果你想沿着这个方向继续深入我建议从以下几个开源项目和资源入手ROS与Gazebo仿真在ROS中搭建无人机模型使用Gazebo进行物理仿真可以更真实地测试你的定位和控制算法包括动力学模型、传感器噪声和通信延迟。Crazyflie开源无人机这是一个非常适合做集群研究的硬件平台。你可以在真实的Crazyflie上部署你的算法体验从仿真到实飞的巨大跨越。研究论文关键词搜索“Bearing-only Localization”、“Multi-agent Formation Control without Distance Measurement”、“Distributed Estimation and Control”等你会找到大量前沿的研究工作其中很多都提供了开源的代码。这个项目就像一把钥匙它打开的门后是分布式人工智能、协同感知与控制这一片广阔而迷人的领域。希望这份详细的思路拆解和代码参考能成为你探索这片领域的第一块坚实的垫脚石。