VFH避障流程以及策略

2023-05-16

VFH避障核心代码讲解,以及避障流程

VFH是一种由人工势场法改进而来的机器人导航算法。在机器人移动的过程中, 利用传感器探测周围障碍物信息(图1),生成极坐标直方图(图2)。图2中x轴是以机器人为中心感知到的障碍物的角度(逆时钟方向为正),y轴表示在该方向存在障碍物的障碍物密度值(距离越近,密度值越大;3个峰值ABC分别代表障碍物ABC)。低于阈值的波谷成为备选通过方案,再根据具体情况(如目标角度、当前朝向)选择通过的角度(1/2)。
避障主要分为两个阶段,第一个阶段是扫描障碍物距离信息,第二个阶段寻找合适的机器人驱动方向。

图1 在这里插入图片描述
图2

横坐标为0-360度的方向,纵轴坐标是该角度下的行进叠加。柱状图超越,表示向该方向行进的重叠取代,也表明越不可能通过。理论上,这个柱状图低的区域是合理行进的,但可能会改变目标方向。
需要一个平衡函数来平衡目标方向。最终,会选择一个相对最方便的方向行进。于是这个函数便是整个算法的核心。
它执行过程中针对移动机器人的周围环境创建了一个基于极坐标表示的局部直方图,这个局部使用直方图的表示方法,会被最近的一些传感器数据所更新、会根据这个直方图首先识别出允许机器人通过的足够大的所有空隙,然后对所有这些空隙计算其代价函数,
最终选择具有最低代价函数的通路通过。代价函数受三个因素影响:目标方向,机器人当前方向,之前选择的方向

障碍物扫描

将360度扫描范围 数据 存入一个宽度区间为30度向量,共12维。这个数据是利用优化过的数据,不是真实的距离数据。每30°一个统一数据。这个数据是对实际距离数据做的一个反向(最大值减去实际扫描值)。如果激光雷达实际探测距离越大,则该值越小。


void ComputeMV(vector<float> r) {//计算直方图
	float dist[360] = { 0 };
	ranges.clear();
	map_cv.clear();
	int range_size = r.size(); //有多少条激光

	for (size_t i = 0; i < range_size; i++)
	{
		//A non-zero value (true) if x is a NaN value; and zero (false) otherwise.

		//isinf A non-zero value (true) if x is an infinity; and zero (false) otherwise.
		if (!std::isnan(r[i]) && !std::isinf(r[i]))//取出有效值
		{
			float scan_distance = r[i];
			//0-30都是一个sector
			int sector_index = std::floor((i*angle_resolution) / sector_value);//(i*1)/30 sector_index:[0 12]
			if (scan_distance >= scan_distance_max || scan_distance < scan_distance_min)
				scan_distance = 0;
			else
				scan_distance = scan_distance_max - scan_distance;//距离为雷达探测最大距离减去扫描距离  做了一个反向。实际距离越大,scan_distence 越小

			dist[sector_index] += scan_distance; //设定柱状高度
		}
		ranges.push_back(r[i]);//ranges存放360度距离信息
	}

	for (int j = 0; j < (int)(360 / sector_value); j++)//把uav四周分为12个sector,每个sector的值越小,代表越安全。
	{
		map_cv.push_back(dist[j]);
	}

确定机头方向

首先会通过当前点与目标点的坐标值,计算目标点相对Uav的夹角,即与y轴的夹角。

其次对柱状图的高度进行统一处理。

当障碍物扫描后处理的数据小于0.1时,柱状图高度为0,

数据为0.1到0.3之间时,柱状图高度为2,

其他形式高度为4。


for (int i = 0; i < map_cv.size(); i++) //确定12个柱状图高度值,CV值越大,存在障碍物可能性越大
	{
		if (map_cv[i] < 0.1)
			mesh.push_back(0);
		else if (map_cv[i] >= 0.1 && map_cv[i] < 0.3)
			mesh.push_back(2);
		else
			mesh.push_back(4);
	}

将障碍物的距离在直方图处理以后,有12个直方柱,有11个波谷。其次是确定有哪几个波谷可以飞行,最后确定从第几个波谷走。

	for (int j = 0; j < mesh.size(); j++)
	{
		if (j == mesh.size() - 1) //if(j == 11)
		{
			if (mesh[0] + mesh[mesh.size() - 1] == 0)
				cand_dir.push_back(0.0);
		}
		else
		{
			if (mesh[j] + mesh[j + 1] == 0)//11个波谷
				cand_dir.push_back((j + 1)*sector_value);//寻找安全角度,机体坐标系下;即确定波谷
		}
	}

if (cand_dir.size() != 0) {
	vector<float> delta;
	for (auto &dir_ite : cand_dir) {
		float delte_theta1 = fabs(dir_ite - goal_ori);
		float delte_theta2 = 360 - delte_theta1;
		float delte_theta = delte_theta1 < delte_theta2 ? delte_theta1 : delte_theta2;
		delta.push_back(delte_theta);
	}//寻找接近目标区域的波谷
	int min_index = min_element(delta.begin(), delta.end()) - delta.begin();
	ori = cand_dir.at(min_index);//从第几个波谷走

	ori += heading;
	ori = (int)ori % 360;
	return ori;//确定机头方向
}

确定飞行速度

每次确定障碍物的飞行方向后,其次是确定无人机的飞行速度。

将机器人当前的飞行速度进行x和y轴的速度分解。


	mavros_msgs::PositionTarget pos_target;
					pos_target.coordinate_frame = 1;
		            pos_target.type_mask = 1 + 2 + 4 +/* 8 + 16 + 32 +*/ 64 + 128 + 256 + 512 + 1024 + 2048;
					pos_target.velocity.x = 0.5* cos(arc);
					pos_target.velocity.y = 0.5* sin(arc);
				local_pos_pub.publish(pos_target);

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

VFH避障流程以及策略 的相关文章

  • 固定翼位置控制_L1

    L1算法控制航向 飞机从现在位置到设定位置 xff0c 需要进行转弯 转弯需要一个横向的加速度来改变速度的方向 这里横向加速度的计算公式 a 61 V2R 又因为R 61 2 sin L1 可得 a 61 2 V2L1 sin L1是现在位
  • 存储过程懂不懂

    存储过程的官方定义是这么说的 xff1a 存储过程 xff08 Stored Procedure xff09 是一组为了完成特定功能的 SQL 语句集 xff0c 经编译后存储在数据库中 用户通过指定存储过程的名字并给出参数 xff08 如
  • PX4多旋翼位置控制

    多悬翼的位置控制由内外环控制 xff0c 外环P控制作用于位置差 xff0c 产生期望速度 xff0c 内环PID作用于速度差 xff0c 产生期望油门 xff0c 然后将油门解算成期望姿态 外环位置控制的三种控制源 1 Manual 手动
  • PX4混控器定义

    PX4混控 把输入指令 分配给电机以及舵机的执行器 信号传递 Actuators id 61 ORB ID actuator controls 0 0号控制组 Orb publish actuators id actuators 0 pub
  • Linux--Ubuntu18.04交叉编译链;多窗口终端;彻底删除不用的虚拟机镜像

    文章目录 建立共享文件夹交叉编译查看是否安装了交叉编译工具安装交叉编译工具链退出root模式 多窗口终端 Terminator彻底删除不用的虚拟机镜像 建立共享文件夹 实现windows系统与虚拟机中的ubuntu之间的文件共享 PC机新建
  • 准确率,召回率,mAP(mean average precision)解释

    准确率Precision 召回率Recall 其实这个翻译相当蛋疼 recall最合理的翻译应该是 查全率 而Precision的最合理的翻译应该是查准率 这样就很容易理解了 xff0c 假设一个班级有10个学生 xff0c 5男5女 你用
  • Android 开发使用 Java 8 中Lambda 表达式功能

    简介 Android开发支持所有 Java 7 语言功能 xff0c 以及一部分 Java 8 语言功能 xff08 具体因平台版本而异 xff09 注意 xff1a 在开发应用时 xff0c 可以选择使用 Java 8 语言功能 您可以将
  • 浅谈 for循环

    浅谈for循环 xff0c for循环习题讲解 文章多看几遍吧 相信你一定会收获不少哇 什么是循环 xff1f 我认为循环就是把一个步骤一直重复执行的操作 如果没有终止条件 xff0c 那么这一步骤就会一直执行下去 xff0c 直到地老天昏
  • 给Jetson Nano更换eMMC闪存(扩容)

    7月4日更新 xff1a 添加了有关问题的解释与探讨 xff08 文末 xff0c 下一篇文章 xff09 7月5日更新 xff1a 添加了效果图 xff08 文末 xff09 7月8日更新 xff1a 添加了视频 b站 xff1a BV1
  • Linux下安装Anaconda3,这个教程一定要看!

    前言 大家好 xff0c 我是爱写Bug的麦洛 由于工作需要 xff0c 要为客户搭建Python开发环境 作为从来没有接触过Python的小白 xff0c 为了完成任务 xff0c 也是破费周折 xff0c 请教了身边做Python的朋友
  • Stm32F303进入bootloader重新烧录程序

    STM32F3飞控或开发板无法进入bootloader重新进行烧录固件程序的解决方案 F3系列的MCU无法进入bootloader 前提准备开始F4和F3的不同 F3系列的MCU无法进入bootloader 前几日找了一块F3的飞控板 刷入
  • 存储过程进阶(vb.net+SQL Server2008环境)

    写过一篇 存储过程入门 的博客 xff0c 那仅仅是入门 xff0c 下面和大家一起深入学习存储过程 xff08 也许以后还会有更深入 xff09 以经典的注册为例子 xff0c 篇幅有限只写了核心部分 xff0c 其他略过 无参数无返回值
  • 【Spring Boot 2.0学习之旅-06-4】Servlet3.0注解的自定义原生Listener监听器实战

    第六章 SpringBoot拦截器实战和Servlet3 0自定义Filter和Listener 06 4 SpringBoot2 x自定义拦截器实战以及新旧配置对比 1 过滤器与拦截器的区别 过滤器与拦截器触发时机不一样 xff0c 过滤
  • 【Spring Boot 2.0学习之旅-07】SpringBoot常用starter介绍和整合模板Freemaker、Thymeleaf

    第七章 SpringBoot常用starter介绍和整合模板Freemaker thymeleaf 07 1 SpringBoot Starter讲解 1 Spring starter是什么 starter是SpringBoot中的一个新发
  • 【Spring Boot 2.0学习之旅-08】SpringBoot数据库操作之整合Mybatis和事务讲解

    第八章 数据库操作之整合Mybatis和事务讲解 08 1 Spring2 x持久化数据方式介绍 简介 xff1a 介绍近几年常用的访问数据库的方式和优缺点 1 原始java访问数据库 开发流程麻烦 1 注册驱动 加载驱动 Class fo

随机推荐