无人机区域目标探寻路径规划的优化方案【附代码】

博主简介:擅长数据搜集与处理、建模仿真、程序设计、仿真代码、论文写作与指导,毕业论文、期刊论文经验交流。

 ✅ 具体问题可以私信或扫描文章底部二维码。


针对无人机在大范围区域执行目标探寻与巡检任务时面临的任务时间、覆盖率和复杂环境避障等多重挑战,本研究旨在突破传统路径规划算法在效率、质量和适应性方面的局限。核心方案聚焦于构建一个分层协同的规划框架,该框架将全局任务点序列优化与局部精细轨迹生成相结合,并引入环境感知与语义理解能力,以全面提升无人机在未知或动态环境中的自主作业效能

(1) 构建融合全局序列优化与局部避障的双层规划架构。针对遍历多个分散任务点(如林区巡检点、监测点)的需求,首要问题是确定最优访问序列以最小化总飞行距离。本研究在全局层采用改进的遗传算法(GA)解决此旅行商问题(TSP)。与传统GA相比,改进之处在于设计了面向三维空间的染色体编码与适应度函数,确保算法能在包含高度信息的环境中直接规划,并优先生成能量消耗更低的序列

。在获得最优任务点序列后,路径规划并未结束。由于真实环境存在树木、建筑等障碍,必须为每两个相邻任务点生成可飞行的无碰撞路径。为此,局部层引入改进的快速随机扩展树(RRT)算法。通过设计“靶心”采样策略,使随机树的生长更有方向性地朝向目标点,大幅提高搜索效率;同时采用“绕树”策略进行碰撞检测,并实施连续父节点选择策略以消除避障产生的冗余转折点,使初步路径更加平滑。最终,通过多次B样条曲线优化,将分段路径拟合为一条整体平滑、符合无人机动力学约束的最终轨迹。仿真与实地实验表明,该融合算法在巡检点增多时,搜索时间增长率和最终路径耗散均显著低于单一的粒子群算法(PSO)、蚁群算法(ACO)或基础RRT算法

(2) 设计环境自适应的实时轨迹优化与决策机制。在动态未知环境中,仅依赖预设的全局路径可能导致任务失败。为此,本研究提出一种结合全局战略规划与局部战术优化的融合框架

。全局规划器采用增强型A*算法,其创新在于代价函数中综合考虑了无人机定位不确定性和区域障碍物密度等多重约束,从而在规划初期就倾向于选择更安全、成本更低的走廊。局部规划器则采用二次规划(QP)方法,以前端全局路径为参考,在滚动时域控制(RHC)框架下进行在线重规划。二次规划以最小化轨迹抖动(如加速度变化率)为目标,同时严格满足无人机的运动学、动力学约束(如最大速度、加速度)以及实时感知的避障约束,生成一条运动学可行的平滑轨迹。这种“粗规划+精优化”的模式,确保了无人机在遭遇未标定障碍或环境变化时,能在保证飞行安全的前提下,动态调整出最优的局部轨迹,实现了安全性与经济性的统一

(3) 集成语义理解与概率地图增强跨尺度导航能力。为应对开放世界环境中长距离导航与具体语义任务(如“检查某棵异常的树”)结合的挑战,本研究引入语言驱动与概率地图融合的协同导航策略

。系统利用无人机实时获取的正射影像,通过深度学习模型(如CLIP)进行语义分割,构建一张全局概率地图。这张地图不仅标注了地形可通行性,还融合了任务相关的语义信息(如疑似目标区域),为路径规划提供高层级的引导。在接收到自然语言指令(如GPT等大语言模型解析)后,全局规划器基于此概率地图生成指向语义目标的粗略路径。局部规划器则采用扩散模型等高级生成模型,结合实时传感器数据,在全局路径的引导下进行细粒度、动态的避障和轨迹生成。这种“语言-全局地图-局部执行”的闭环,使无人机不仅能进行几何避障,还能理解任务语义,实现了从单纯路径规划到智能任务执行的跨越。实验证明,该方法在结构化和非结构化环境中的路径效率较传统方法有显著提升

import numpy as np
import random
from scipy.spatial.distance import euclidean
import matplotlib.pyplot as plt

class ImprovedGA:
    def __init__(self, points, pop_size=50, elite_size=10, mutation_rate=0.02, generations=200):
        self.points = np.array(points)
        self.num_points = len(points)
        self.pop_size = pop_size
        self.elite_size = elite_size
        self.mutation_rate = mutation_rate
        self.generations = generations
        self.best_path = None
        self.best_fitness = float('inf')

    def create_individual(self):
        individual = list(range(self.num_points))
        random.shuffle(individual)
        return individual

    def calculate_fitness(self, individual):
        total_distance = 0.0
        for i in range(self.num_points):
            from_point = self.points[individual[i]]
            to_point = self.points[individual[(i + 1) % self.num_points]]
            total_distance += euclidean(from_point, to_point)
        return total_distance

    def rank_selection(self, population, fitnesses):
        ranked_indices = np.argsort(fitnesses)
        selection_probs = np.linspace(1.0, 0.1, len(population))
        selection_probs = selection_probs / np.sum(selection_probs)
        selected_idx = np.random.choice(ranked_indices, size=2, p=selection_probs, replace=False)
        return population[selected_idx[0]], population[selected_idx[1]]

    def order_crossover(self, parent1, parent2):
        size = len(parent1)
        start, end = sorted(random.sample(range(size), 2))
        child = [None] * size
        child[start:end] = parent1[start:end]
        pointer = end
        for gene in parent2:
            if gene not in child:
                if pointer >= size:
                    pointer = 0
                child[pointer] = gene
                pointer += 1
        return child

    def mutate(self, individual):
        if random.random() < self.mutation_rate:
            i, j = random.sample(range(self.num_points), 2)
            individual[i], individual[j] = individual[j], individual[i]
        return individual

    def evolve(self):
        population = [self.create_individual() for _ in range(self.pop_size)]
        for gen in range(self.generations):
            fitnesses = np.array([self.calculate_fitness(ind) for ind in population])
            elite_indices = np.argsort(fitnesses)[:self.elite_size]
            elites = [population[i] for i in elite_indices]
            current_best_fitness = fitnesses[elite_indices[0]]
            if current_best_fitness < self.best_fitness:
                self.best_fitness = current_best_fitness
                self.best_path = population[elite_indices[0]].copy()
            new_population = elites
            while len(new_population) < self.pop_size:
                parent1, parent2 = self.rank_selection(population, fitnesses)
                child = self.order_crossover(parent1, parent2)
                child = self.mutate(child)
                new_population.append(child)
            population = new_population
        return self.best_path, self.best_fitness

class AdaptiveAStar:
    def __init__(self, grid_map):
        self.grid = grid_map
        self.rows, self.cols = grid_map.shape
        self.moves = [(-1, 0), (1, 0), (0, -1), (0, 1), (-1, -1), (-1, 1), (1, -1), (1, 1)]

    def heuristic(self, a, b, obstacle_coverage):
        dx, dy = abs(a[0] - b[0]), abs(a[1] - b[1])
        distance = (dx + dy) + (np.sqrt(2) - 2) * min(dx, dy)
        adaptive_weight = 1.0 + 0.5 * obstacle_coverage
        return distance * adaptive_weight

    def get_obstacle_coverage(self, node, radius=3):
        x, y = node
        count_total = 0
        count_obstacle = 0
        for i in range(-radius, radius+1):
            for j in range(-radius, radius+1):
                nx, ny = x + i, y + j
                if 0 <= nx < self.rows and 0 <= ny < self.cols:
                    count_total += 1
                    if self.grid[nx, ny] == 1:
                        count_obstacle += 1
        return count_obstacle / count_total if count_total > 0 else 0

    def prune_neighbors(self, current, parent, open_set, closed_set):
        pruned_neighbors = []
        dx = current[0] - parent[0]
        dy = current[1] - parent[1]
        direction = (np.sign(dx), np.sign(dy))
        for move in self.moves:
            neighbor = (current[0] + move[0], current[1] + move[1])
            if (0 <= neighbor[0] < self.rows and 0 <= neighbor[1] < self.cols and 
                self.grid[neighbor[0], neighbor[1]] == 0 and 
                neighbor not in closed_set):
                if direction == (0, 0) or move == direction:
                    pruned_neighbors.append(neighbor)
                else:
                    can_reach_directly = True
                    if direction[0] != 0 and direction[1] != 0:
                        intermediate1 = (parent[0] + move[0], parent[1])
                        intermediate2 = (parent[0], parent[1] + move[1])
                        if (self.grid[intermediate1[0], intermediate1[1]] == 1 or 
                            self.grid[intermediate2[0], intermediate2[1]] == 1):
                            can_reach_directly = False
                    if not can_reach_directly:
                        pruned_neighbors.append(neighbor)
        return pruned_neighbors

    def find_path(self, start, goal):
        open_set = []
        closed_set = set()
        g_score = {start: 0}
        f_score = {start: self.heuristic(start, goal, 0)}
        came_from = {}
        import heapq
        heapq.heappush(open_set, (f_score[start], start))
        while open_set:
            _, current = heapq.heappop(open_set)
            if current == goal:
                path = []
                while current in came_from:
                    path.append(current)
                    current = came_from[current]
                path.append(start)
                return path[::-1]
            closed_set.add(current)
            parent = came_from.get(current, start)
            neighbors = self.prune_neighbors(current, parent, open_set, closed_set)
            obstacle_coverage = self.get_obstacle_coverage(current)
            for neighbor in neighbors:
                tentative_g = g_score[current] + euclidean(current, neighbor)
                if neighbor not in g_score or tentative_g < g_score[neighbor]:
                    came_from[neighbor] = current
                    g_score[neighbor] = tentative_g
                    h = self.heuristic(neighbor, goal, obstacle_coverage)
                    f_score[neighbor] = tentative_g + h
                    if neighbor not in [i[1] for i in open_set]:
                        heapq.heappush(open_set, (f_score[neighbor], neighbor))
        return None

np.random.seed(42)
waypoints = np.random.rand(8, 2) * 100
ga_solver = ImprovedGA(waypoints, pop_size=30, generations=100)
best_sequence, best_dist = ga_solver.evolve()
print(f"GA优化后任务点访问序列: {best_sequence}")
print(f"预估总飞行距离: {best_dist:.2f}")

map_size = 50
obstacle_map = np.zeros((map_size, map_size))
obstacle_map[15:25, 10:20] = 1
obstacle_map[5:12, 30:40] = 1
start_pos = (5, 5)
goal_pos = (45, 45)
a_star_planner = AdaptiveAStar(obstacle_map)
path = a_star_planner.find_path(start_pos, goal_pos)
if path:
    print(f"A*规划路径节点数: {len(path)}")
else:
    print("路径规划失败!")


如有问题,可以直接沟通

👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

坷拉博士

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值