用Python复现数学建模竞赛题:手把手教你用Dijkstra和蚁群算法搞定无人机协同避障
用Python实战数学建模:Dijkstra与蚁群算法在无人机协同避障中的妙用
数学建模竞赛中,无人机协同避障问题一直是经典中的经典。这类问题不仅考验参赛者的数学功底,更检验将抽象模型转化为实际代码的能力。今天,我们就以2023年深圳杯C题为例,抛开繁琐的数学推导,直接动手用Python实现Dijkstra和蚁群算法,解决无人机航迹规划难题。
1. 问题理解与环境搭建
首先,我们需要明确题目要求:两架无人机分别从A、B两站出发,以10m/s的速度相向飞行,途中必须避开一个半径500米的圆形障碍物,且两机连线必须始终与障碍圆相交。此外,无人机转弯半径不得小于30米。
关键约束条件:
- 障碍圆半径:500米
- A站距圆心:1000米
- B站距圆心:3500米
- 无人机速度:10 m/s
- 最小转弯半径:30米
注意:实际编程时需要将距离单位统一,建议全部使用米(m)作为基本单位。
1.1 Python环境准备
我们需要以下Python库支持算法实现和数据可视化:
import numpy as np
import matplotlib.pyplot as plt
import heapq # Dijkstra算法优先队列
import random # 蚁群算法随机选择
from math import sqrt, sin, cos, atan2, pi # 几何计算
2. Dijkstra算法实现最短路径规划
Dijkstra算法是解决单源最短路径问题的经典算法。在无人机航迹规划中,我们可以将飞行区域离散化为网格,每个网格点作为图的一个顶点,顶点间的距离作为边权重。
2.1 网格化环境建模
首先建立坐标系:设圆心为原点(0,0),A站在x轴负方向(-1000,0),B站在x轴正方向(3500,0)。
def create_environment():
# 定义关键点坐标
circle_center = np.array([0, 0])
A_station = np.array([-1000, 0])
B_station = np.array([3500, 0])
circle_radius = 500
# 创建网格
x = np.linspace(-1500, 4000, 100) # x轴范围
y = np.linspace(-1000, 1000, 80) # y轴范围
X, Y = np.meshgrid(x, y)
return X, Y, circle_center, circle_radius, A_station, B_station
2.2 Dijkstra算法核心实现
def dijkstra(graph, start):
# 初始化距离字典
distances = {vertex: float('infinity') for vertex in graph}
distances[start] = 0
priority_queue = [(0, start)]
while priority_queue:
current_distance, current_vertex = heapq.heappop(priority_queue)
# 如果找到更短路径则跳过
if current_distance > distances[current_vertex]:
continue
for neighbor, weight in graph[current_vertex].items():
distance = current_distance + weight
# 发现更短路径时更新
if distance < distances[neighbor]:
distances[neighbor] = distance
heapq.heappush(priority_queue, (distance, neighbor))
return distances
2.3 路径可视化
def plot_path(path, X, Y, circle_center, circle_radius):
plt.figure(figsize=(12, 6))
# 绘制障碍圆
circle = plt.Circle(circle_center, circle_radius, color='r', alpha=0.3)
plt.gca().add_patch(circle)
# 绘制路径
path_x = [p[0] for p in path]
path_y = [p[1] for p in path]
plt.plot(path_x, path_y, 'b-', linewidth=2)
# 标记起点和终点
plt.plot(path[0][0], path[0][1], 'go', markersize=10)
plt.plot(path[-1][0], path[-1][1], 'ro', markersize=10)
plt.grid(True)
plt.axis('equal')
plt.show()
3. 蚁群算法实现协同避障
蚁群算法模拟蚂蚁觅食行为,适合解决路径优化问题。对于无人机协同避障,我们需要考虑两架无人机的路径协调。
3.1 蚁群算法参数设置
class ACOParameters:
def __init__(self):
self.ant_count = 20 # 蚂蚁数量
self.iterations = 100 # 迭代次数
self.alpha = 1.0 # 信息素重要程度
self.beta = 2.0 # 启发式信息重要程度
self.rho = 0.5 # 信息素挥发系数
self.Q = 100 # 信息素强度
self.min_tau = 0.1 # 最小信息素量
self.max_tau = 10 # 最大信息素量
3.2 信息素矩阵初始化
def init_pheromone_matrix(size):
return np.ones((size, size)) * 0.1
3.3 蚂蚁路径构建
def construct_path(ant, pheromone, distance_matrix, params):
path = []
visited = set()
current = ant.start_node
path.append(current)
visited.add(current)
while len(path) < ant.node_count:
next_node = select_next_node(current, visited, pheromone, distance_matrix, params)
path.append(next_node)
visited.add(next_node)
current = next_node
return path
3.4 信息素更新
def update_pheromone(pheromone, ants, params):
# 信息素挥发
pheromone *= (1 - params.rho)
# 添加新信息素
for ant in ants:
path = ant.path
path_length = ant.path_length
for i in range(len(path)-1):
u, v = path[i], path[i+1]
pheromone[u][v] += params.Q / path_length
pheromone[v][u] = pheromone[u][v] # 对称矩阵
# 限制信息素范围
pheromone = np.clip(pheromone, params.min_tau, params.max_tau)
return pheromone
4. 双机协同避障策略实现
两架无人机协同飞行时,除了各自避开障碍物,还需保持连线与障碍圆相交。这需要特殊的协调策略。
4.1 协同约束条件检查
def check_collision_avoidance(path1, path2, circle_center, circle_radius):
for p1, p2 in zip(path1, path2):
# 计算两机连线中点
mid_point = ((p1[0]+p2[0])/2, (p1[1]+p2[1])/2)
# 检查中点是否在障碍圆内
distance = sqrt((mid_point[0]-circle_center[0])**2 +
(mid_point[1]-circle_center[1])**2)
if distance < circle_radius:
return False # 违反约束
return True # 满足约束
4.2 协同路径优化算法
def cooperative_path_planning():
# 初始化参数
params = ACOParameters()
# 为两架无人机分别初始化蚁群
aco1 = ACOForDrone(drone=1)
aco2 = ACOForDrone(drone=2)
best_path1 = None
best_path2 = None
best_time = float('inf')
for iteration in range(params.iterations):
# 为每架无人机生成蚂蚁路径
paths1 = [aco1.construct_path() for _ in range(params.ant_count)]
paths2 = [aco2.construct_path() for _ in range(params.ant_count)]
# 评估所有路径组合
for p1 in paths1:
for p2 in paths2:
if check_collision_avoidance(p1, p2, circle_center, circle_radius):
time1 = calculate_path_time(p1)
time2 = calculate_path_time(p2)
max_time = max(time1, time2)
if max_time < best_time:
best_time = max_time
best_path1 = p1
best_path2 = p2
# 更新信息素
aco1.update_pheromone(best_path1)
aco2.update_pheromone(best_path2)
return best_path1, best_path2, best_time
5. 算法优化与性能提升
在实际应用中,我们需要考虑算法效率和路径质量之间的平衡。以下是几种优化策略:
5.1 启发式信息设计
def heuristic_info(distance_matrix):
# 使用距离的倒数作为启发式信息
eta = 1.0 / (distance_matrix + 1e-10) # 避免除以零
return eta
5.2 并行计算加速
from multiprocessing import Pool
def parallel_ant_run(ant):
return ant.construct_path()
# 在主循环中使用
with Pool(processes=4) as pool:
paths = pool.map(parallel_ant_run, ants)
5.3 动态参数调整
def adaptive_parameters(iteration, max_iterations):
# 随着迭代动态调整参数
rho = 0.1 + 0.4 * (iteration / max_iterations) # 逐渐增加挥发系数
alpha = 1.0 - 0.5 * (iteration / max_iterations) # 降低信息素重要性
return rho, alpha
6. 实际应用中的挑战与解决方案
在实现无人机协同避障算法时,会遇到各种实际问题。以下是几个典型挑战及应对方法:
6.1 转弯半径约束处理
无人机的物理限制要求路径转弯半径不小于30米。我们可以在路径平滑阶段加入这一约束:
def smooth_path_with_turn_constraint(path, min_turn_radius):
smoothed_path = [path[0]]
for i in range(1, len(path)-1):
# 计算三点形成的转弯半径
p1, p2, p3 = path[i-1], path[i], path[i+1]
radius = calculate_turn_radius(p1, p2, p3)
if radius >= min_turn_radius:
smoothed_path.append(p2)
else:
# 需要调整路径点以满足转弯半径
adjusted_point = adjust_point_for_turn(p1, p2, p3, min_turn_radius)
smoothed_path.append(adjusted_point)
smoothed_path.append(path[-1])
return smoothed_path
6.2 实时避障策略
当遇到动态障碍物时,需要实时调整路径:
def dynamic_obstacle_avoidance(current_path, obstacle_position, obstacle_radius):
# 检查路径是否与障碍物相交
collision_points = find_collision_points(current_path, obstacle_position, obstacle_radius)
if not collision_points:
return current_path # 无需调整
# 在碰撞点前后插入避障点
new_path = []
for i in range(len(current_path)-1):
new_path.append(current_path[i])
# 检查当前线段是否与障碍物相交
if is_segment_intersecting_circle(current_path[i], current_path[i+1],
obstacle_position, obstacle_radius):
# 计算避障点
avoid_point = calculate_avoidance_point(current_path[i], current_path[i+1],
obstacle_position, obstacle_radius)
new_path.append(avoid_point)
new_path.append(current_path[-1])
return new_path
6.3 多目标优化权衡
在问题2中,我们需要优化第二架无人机的到达时间。这需要权衡两架无人机的路径:
def multi_objective_optimization(paths):
# 计算各目标函数值
time1 = [calculate_path_time(p[0]) for p in paths]
time2 = [calculate_path_time(p[1]) for p in paths]
# 寻找Pareto前沿
pareto_front = []
for i in range(len(paths)):
dominated = False
for j in range(len(paths)):
if time1[j] <= time1[i] and time2[j] <= time2[i] and \
(time1[j] < time1[i] or time2[j] < time2[i]):
dominated = True
break
if not dominated:
pareto_front.append(paths[i])
return pareto_front
7. 完整案例演示
让我们通过一个完整的例子展示如何使用上述算法解决深圳杯C题的问题1:
def solve_problem1():
# 初始化环境
X, Y, circle_center, circle_radius, A_station, B_station = create_environment()
# 构建图结构
graph = build_graph(X, Y, circle_center, circle_radius)
# 为无人机A(A→B)寻找路径
path_A = dijkstra(graph, tuple(A_station), tuple(B_station))
# 为无人机B(B→A)寻找路径
path_B = dijkstra(graph, tuple(B_station), tuple(A_station))
# 检查协同约束
if not check_collision_avoidance(path_A, path_B, circle_center, circle_radius):
# 如果不满足约束,使用蚁群算法优化
path_A, path_B, _ = cooperative_path_planning()
# 可视化结果
plot_two_paths(path_A, path_B, circle_center, circle_radius)
# 计算到达时间
time_A = calculate_path_time(path_A)
time_B = calculate_path_time(path_B)
first_arrival = min(time_A, time_B)
print(f"第一架无人机到达时间: {first_arrival:.2f}秒")
print(f"无人机A路径长度: {calculate_path_length(path_A):.2f}米")
print(f"无人机B路径长度: {calculate_path_length(path_B):.2f}米")
return path_A, path_B
在实际项目中,我们发现Dijkstra算法虽然能找到最短路径,但在处理协同约束时灵活性不足。而蚁群算法虽然计算量较大,但能更好地处理复杂约束条件。将两种算法结合使用,往往能取得更好的效果。
更多推荐
所有评论(0)