路径规划 | 图解遗传(GA)算法(附ROS C++仿真)

2024-06-12 13:36

本文主要是介绍路径规划 | 图解遗传(GA)算法(附ROS C++仿真),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

  • 0 专栏介绍
  • 1 从进化论说起
  • 2 遗传算法基本概念
  • 3 遗传算法流程
  • 4 遗传算法ROS实现

0 专栏介绍

🔥附C++/Python/Matlab全套代码🔥课程设计、毕业设计、创新竞赛必备!详细介绍全局规划(图搜索、采样法、智能算法等);局部规划(DWA、APF等);曲线优化(贝塞尔曲线、B样条曲线等)。

🚀详情:图解自动驾驶中的运动规划(Motion Planning),附几十种规划算法


在这里插入图片描述

1 从进化论说起

从仿生学的角度来看,遗传算法(Genetic Algorithm, GA)是模拟自然界中生物进化过程的一种计算方法。它借鉴了达尔文的进化论中的许多概念,并将这些概念应用到解决优化问题上,例如

  • 基因编码: 在遗传算法中,问题的解被编码成为一串基因序列,类似于生物体的染色体。这种编码方式可以直接映射到生物体的基因结构,每个基因对应于解空间中的一个特定参数或变量。
  • 种群与个体: 遗传算法通过维护一个包含多个个体(解)的种群来模拟自然种群的概念。每个个体都代表了解决问题的一个可能方案,类似于自然界中的个体生物。
  • 适应度评估: 遗传算法中的适应度评估类似于生物体在自然选择过程中的适应度。每个个体根据其解决方案在问题空间中的表现被赋予一个适应度分数,用于评价其优劣。
  • 选择与交叉: 通过选择和交叉操作,遗传算法模拟了生物繁殖过程中的自然选择和基因交换。适应度较高的个体更有可能被选择为父代,并且它们的基因会通过交叉操作进行组合,产生新的后代个体。
  • 变异: 变异操作在遗传算法中引入了个体基因的随机变化,类似于自然界中的基因突变。这种变异可以增加种群的多样性,从而有助于避免陷入局部最优解。

在这里插入图片描述

从这些角度来看,遗传算法可以被视为一种模仿生物进化过程的计算方法,它通过模拟生物体的繁殖、变异和适应度评估等过程,来寻找问题空间中的最优解。这种仿生学的视角不仅帮助我们理解遗传算法的原理,也为我们提供了一种全新的优化问题求解思路。

2 遗传算法基本概念

遗传算法的基本概念如下:

  • M M M:种群数量;
  • x \boldsymbol{x} x:染色体,其对应可行域中的一个可行解,染色体分量 称为基因片段,基因片段是发生交叉、变异的基本单位;
  • f i t ( ⋅ ) fit\left( \cdot \right) fit():个体适应度函数,使目标函数越小的染色体对应的适应度越高;
  • 选择算子:通过适应度从当前种群中筛选较优的染色体集合,并将其特性遗传到下一代种群,实现“优胜劣汰”的进化机制,筛选算法有轮盘赌筛选、精英筛选、排序筛选等,本文采用分层筛选法;
  • 交叉算子:以一定的概率将两个匹配染色体中的部分基因片段互换,产生两个新的染色体,实现“同源染色体交叉互换”的进化特征,提高算法搜索能力,交叉算法有:均匀交叉、单点交叉、多点交叉等,本文采用多点交叉;
  • 变异算子:以一定的概率将染色体的部分基因进行突变,产生新染色体,实现“基因突变”的进化特征,增强种群遗传因子多样性,缓解算法进入局部最优的概率,变异算法有:高斯变异、基本位变异、均匀变异等,本文采用基本位变异。

3 遗传算法流程

遗传算法基本原理如下所示

在这里插入图片描述

4 遗传算法ROS实现

核心代码如下所示

bool GA::plan(const Node& start, const Node& goal, std::vector<Node>& path, std::vector<Node>& expand)
{// variable initializationdouble init_fitness;Genets best_genet;PositionSequence init_positions;std::vector<Genets> genets_swarm;std::vector<Genets> genets_parent;std::vector<Genets> genets_children;// Generate initial position of genets swarminitializePositions(init_positions, start, goal, init_mode_);// genets initializationfor (int i = 0; i < n_genets_; ++i){std::vector<std::pair<int, int>> init_position;if ((i < n_inherited_) && (inherited_genets_.size() == n_inherited_))init_position = inherited_genets_[i].best_pos;elseinit_position = init_positions[i];// Calculate fitnessinit_fitness = calFitnessValue(init_position);if ((i == 0) || (init_fitness > best_genet.fitness)){best_genet.fitness = init_fitness;best_genet.position = init_position;}// Create and add genets objects to containersgenets_swarm.emplace_back(init_position, init_fitness);}// random datastd::random_device rd;std::mt19937 gen(rd());// Iterative optimizationfor (size_t iter = 0; iter < max_iter_; iter++){selection(genets_swarm, genets_parent);genets_children = genets_parent;std::rotate(genets_children.begin(), genets_children.begin() + 1, genets_children.end());std::vector<std::thread> genets_list = std::vector<std::thread>(genets_parent.size());for (size_t i = 0; i < genets_parent.size(); ++i)genets_list[i] = std::thread(&GA::optimizeGenets, this, std::cref(genets_parent[i]), std::ref(genets_children[i]),std::ref(best_genet), i, std::ref(gen), std::ref(expand));for (size_t i = 0; i < genets_parent.size(); ++i)genets_list[i].join();// Copy the elements from genets_parent and genets_children to genets_swarmstd::copy(genets_children.begin(), genets_children.end(), genets_swarm.begin());std::copy(genets_parent.begin(), genets_parent.end(), genets_swarm.begin() + genets_children.size());}// Generating Paths from Optimal Genets...return !path.empty();
}

在这里插入图片描述

完整工程代码请联系下方博主名片获取


🔥 更多精彩专栏

  • 《ROS从入门到精通》
  • 《Pytorch深度学习实战》
  • 《机器学习强基计划》
  • 《运动规划实战精讲》

👇源码获取 · 技术交流 · 抱团学习 · 咨询分享 请联系👇

这篇关于路径规划 | 图解遗传(GA)算法(附ROS C++仿真)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1054358

相关文章

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

C++初始化数组的几种常见方法(简单易懂)

《C++初始化数组的几种常见方法(简单易懂)》本文介绍了C++中数组的初始化方法,包括一维数组和二维数组的初始化,以及用new动态初始化数组,在C++11及以上版本中,还提供了使用std::array... 目录1、初始化一维数组1.1、使用列表初始化(推荐方式)1.2、初始化部分列表1.3、使用std::

C++ Primer 多维数组的使用

《C++Primer多维数组的使用》本文主要介绍了多维数组在C++语言中的定义、初始化、下标引用以及使用范围for语句处理多维数组的方法,具有一定的参考价值,感兴趣的可以了解一下... 目录多维数组多维数组的初始化多维数组的下标引用使用范围for语句处理多维数组指针和多维数组多维数组严格来说,C++语言没

c++中std::placeholders的使用方法

《c++中std::placeholders的使用方法》std::placeholders是C++标准库中的一个工具,用于在函数对象绑定时创建占位符,本文就来详细的介绍一下,具有一定的参考价值,感兴... 目录1. 基本概念2. 使用场景3. 示例示例 1:部分参数绑定示例 2:参数重排序4. 注意事项5.

使用C++将处理后的信号保存为PNG和TIFF格式

《使用C++将处理后的信号保存为PNG和TIFF格式》在信号处理领域,我们常常需要将处理结果以图像的形式保存下来,方便后续分析和展示,C++提供了多种库来处理图像数据,本文将介绍如何使用stb_ima... 目录1. PNG格式保存使用stb_imagephp_write库1.1 安装和包含库1.2 代码解

C++实现封装的顺序表的操作与实践

《C++实现封装的顺序表的操作与实践》在程序设计中,顺序表是一种常见的线性数据结构,通常用于存储具有固定顺序的元素,与链表不同,顺序表中的元素是连续存储的,因此访问速度较快,但插入和删除操作的效率可能... 目录一、顺序表的基本概念二、顺序表类的设计1. 顺序表类的成员变量2. 构造函数和析构函数三、顺序表

使用C++实现单链表的操作与实践

《使用C++实现单链表的操作与实践》在程序设计中,链表是一种常见的数据结构,特别是在动态数据管理、频繁插入和删除元素的场景中,链表相比于数组,具有更高的灵活性和高效性,尤其是在需要频繁修改数据结构的应... 目录一、单链表的基本概念二、单链表类的设计1. 节点的定义2. 链表的类定义三、单链表的操作实现四、

使用C/C++调用libcurl调试消息的方式

《使用C/C++调用libcurl调试消息的方式》在使用C/C++调用libcurl进行HTTP请求时,有时我们需要查看请求的/应答消息的内容(包括请求头和请求体)以方便调试,libcurl提供了多种... 目录1. libcurl 调试工具简介2. 输出请求消息使用 CURLOPT_VERBOSE使用 C

C++实现获取本机MAC地址与IP地址

《C++实现获取本机MAC地址与IP地址》这篇文章主要为大家详细介绍了C++实现获取本机MAC地址与IP地址的两种方式,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 实际工作中,项目上常常需要获取本机的IP地址和MAC地址,在此使用两种方案获取1.MFC中获取IP和MAC地址获取

C/C++通过IP获取局域网网卡MAC地址

《C/C++通过IP获取局域网网卡MAC地址》这篇文章主要为大家详细介绍了C++如何通过Win32API函数SendARP从IP地址获取局域网内网卡的MAC地址,感兴趣的小伙伴可以跟随小编一起学习一下... C/C++通过IP获取局域网网卡MAC地址通过win32 SendARP获取MAC地址代码#i