碰撞检测 | 图解视线生成Bresenham算法(附ROS C++/Python/Matlab实现)

目录

  • 0 专栏介绍
  • 1 Bresenham算法介绍
  • 2 图解Bresenham算法
  • 3 算法流程
  • 4 仿真实现
    • 4.1 ROS C++实现
    • 4.2 Python实现
    • 4.3 Matlab实现

0 专栏介绍

🔥课设、毕设、创新竞赛必备!🔥本专栏涉及更高阶的运动规划算法轨迹优化实战,包括:曲线生成、碰撞检测、安全走廊、优化建模(QP、SQP、NMPC、iLQR等)、轨迹优化(梯度法、曲线法等),每个算法都包含代码实现加深理解

🚀详情:运动规划实战进阶:轨迹优化篇


1 Bresenham算法介绍

Bresenham视线生成算法是一种高效的算法,用于在二维网格上绘制直线。它是由Jack Bresenham在1962年提出的,广泛应用于计算机图形学和游戏开发中。该算法的主要优点是只使用整数运算,因此速度较快且易于实现。下面是该算法的动图案例

在这里插入图片描述

Bresenham算法可以巧妙地应用在栅格地图中进行一维碰撞检测:首先确定起点和终点,然后使用Bresenham算法绘制从起点到终点的线段,接着检查该路径上每个栅格点是否与障碍物重叠。

2 图解Bresenham算法

Bresenham碰撞测试在三种类型的移动中访问单元格:

  • x x x方向移动
  • y y y方向移动
  • 对角线移动

在栅格地图中,碰撞检测点连线经过若干离散栅格,因此每次移动都将产生非连续误差,Bresenham算法要求下一个移动偏差最小。通过迭代即可访问检测线经过的所有栅格,判断这些栅格的代价是否超过阈值即可完成碰撞检测。

具体地,设需要检测节点 v v v w w w间的连线是否经过障碍物,定义缩放误差分别为 δ x = ∣ w . x − v . x ∣ \delta _x=\left| w.x-v.x \right| δx=w.xv.x δ y = ∣ w . y − v . y ∣ \delta _y=\left| w.y-v.y \right| δy=w.yv.y;扩展误差分别为 e x e_x ex e y e_y ey;方向增量分别为 Δ x = s g n ( w . x − v . x ) \varDelta x=sgn\left( w.x-v.x \right) Δx=sgn(w.xv.x) Δ y = s g n ( w . y − v . y ) \varDelta y=sgn \left( w.y-v.y \right) Δy=sgn(w.yv.y)。下面考虑 δ x > δ y \delta _x>\delta _y δx>δy的情形, δ x ⩽ δ y \delta _x\leqslant \delta _y δxδy时可对称导出。

在这里插入图片描述

如图所示,根据三角形相似关系可得

{ e y e x = ∣ Δ y ∣ t t δ y = ∣ Δ x ∣ δ x ⇒ e y e x = ∣ Δ y ∣ ∣ Δ x ∣ ⋅ δ x δ y = δ x δ y \begin{cases} \frac{e_y}{e_x}=\frac{\left| \varDelta y \right|}{t}\\ \frac{t}{\delta _y}=\frac{\left| \varDelta x \right|}{\delta _x}\\\end{cases}\Rightarrow \frac{e_y}{e_x}=\frac{\left| \varDelta y \right|}{\left| \varDelta x \right|}\cdot \frac{\delta _x}{\delta _y}=\frac{\delta _x}{\delta _y} {exey=tΔyδyt=δxΔxexey=ΔxΔyδyδx=δyδx

不妨令 e y = δ x e_y=\delta _x ey=δx e x = δ y e_x=\delta _y ex=δy,则沿 x x x方向移动将产生负向偏差 δ y \delta _y δy,沿 y y y方向移动将产生正向偏差 δ x \delta _x δx,根据最小化偏差原则选择移动方向

( x , y ) ← { ( x + Δ x , y ) , i f ∣ e + δ x ∣ > ∣ e − δ y ∣ ( x , y + Δ y ) , i f ∣ e + δ x ∣ < ∣ e − δ y ∣ ( x + Δ x , y + Δ y ) , i f ∣ e + δ x ∣ = ∣ e − δ y ∣ \left( x,y \right) \gets \begin{cases} \left( x+\varDelta x,y \right) , \mathrm{if} \left| e+\delta _x \right|>\left| e-\delta _y \right|\\ \left( x,y+\varDelta y \right) , \mathrm{if} \left| e+\delta _x \right|<\left| e-\delta _y \right|\\ \left( x+\varDelta x,y+\varDelta y \right) , \mathrm{if} \left| e+\delta _x \right|=\left| e-\delta _y \right|\\\end{cases} (x,y)(x+Δx,y),ife+δx>eδy(x,y+Δy),ife+δx<eδy(x+Δx,y+Δy),ife+δx=eδy

下图为Bresenham扩展节点的实例

在这里插入图片描述

3 算法流程

算法流程如下所示

在这里插入图片描述

4 仿真实现

4.1 ROS C++实现

核心代码如下所示

template <typename Point, typename F_is_obs>
static bool BresenhamCollisionDetection(const Point& pt1, const Point& pt2, F_is_obs func_is_obs)
{int s_x = (pt1.x() - pt2.x() == 0) ? 0 : (pt1.x() - pt2.x()) / std::abs(pt1.x() - pt2.x());int s_y = (pt1.y() - pt2.y() == 0) ? 0 : (pt1.y() - pt2.y()) / std::abs(pt1.y() - pt2.y());int d_x = std::abs(pt1.x() - pt2.x());int d_y = std::abs(pt1.y() - pt2.y());// check if any obstacle exists between pt1 and pt2if (d_x > d_y){int tau = d_y - d_x;int x = pt2.x(), y = pt2.y();int e = 0;while (x != pt1.x()){if (e * 2 > tau){x += s_x;e -= d_y;}else if (e * 2 < tau){y += s_y;e += d_x;}else{x += s_x;y += s_y;e += d_x - d_y;}if (func_is_obs(Point(x, y)))// obstacle detectedreturn true;}}else{// similar. swap x and yint tau = d_x - d_y;int x = pt2.x(), y = pt2.y();int e = 0;while (y != pt1.y()){if (e * 2 > tau){y += s_y;e -= d_x;}else if (e * 2 < tau){x += s_x;e += d_y;}else{x += s_x;y += s_y;e += d_y - d_x;}if (func_is_obs(Point(x, y)))// obstacle detectedreturn true;}}return false;
}

4.2 Python实现

核心代码如下所示

def BresenhamCollisionDetection(self, node1: Node, node2: Node) -> bool:if node1.current in self.obstacles or node2.current in self.obstacles:return Falsex1, y1 = node1.currentx2, y2 = node2.currentif x1 < 0 or x1 >= self.env.x_range or y1 < 0 or y1 >= self.env.y_range:return Falseif x2 < 0 or x2 >= self.env.x_range or y2 < 0 or y2 >= self.env.y_range:return Falsed_x = abs(x2 - x1)d_y = abs(y2 - y1)s_x = 0 if (x2 - x1) == 0 else (x2 - x1) / d_xs_y = 0 if (y2 - y1) == 0 else (y2 - y1) / d_yx, y, e = x1, y1, 0# check if any obstacle exists between node1 and node2if d_x > d_y:tau = (d_y - d_x) / 2while not x == x2:if e > tau:x = x + s_xe = e - d_yelif e < tau:y = y + s_ye = e + d_xelse:x = x + s_xy = y + s_ye = e + d_x - d_yif (x, y) in self.obstacles:return False# swap x and yelse:tau = (d_x - d_y) / 2while not y == y2:if e > tau:y = y + s_ye = e - d_xelif e < tau:x = x + s_xe = e + d_yelse:x = x + s_xy = y + s_ye = e + d_y - d_xif (x, y) in self.obstacles:return Falsereturn True

4.3 Matlab实现

核心代码如下所示

function flag = BresenhamCollisionDetection(map, node1, node2)
% @breif: Judge collision when moving from node1 to node2 using Bresenham.if (map(node1(1), node1(2)) == 2) || (map(node2(1), node2(2)) == 2)flag = true;returnendx1 = node1(1); y1 = node1(2);x2 = node2(1); y2 = node2(2);d_x = abs(x2 - x1);d_y = abs(y2 - y1);if  (x2 - x1) == 0s_x = 0;elses_x = (x2 - x1) / d_x;endif  (y2 - y1) == 0s_y = 0;elses_y = (y2 - y1) / d_y;endx = x1; y = y1; e = 0;% check if any obstacle exists between node1 and node2if d_x > d_ytao = (d_y - d_x) / 2;while x ~= x2if e > taox = x + s_x;e = e - d_y;elseif e < taoy = y + s_y;e = e + d_x;elsex = x + s_x;y = y + s_y;e = e + d_x - d_y;endif map(x, y) == 2flag = true;return;endend% swap x and yelsetao = (d_x - d_y) / 2;while y ~= y2if e > taoy = y + s_y;e = e - d_x;elseif e < taox = x + s_x;e = e + d_y;elsex = x + s_x;y = y + s_y;e = e + d_y - d_x;endif map(x, y) == 2flag = true;return;endendendflag = false;
end

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


🔥 更多精彩专栏

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/441075.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

架构设计之解析CQRS架构模式!

文章首发到公众号&#xff1a;月伴飞鱼 文章内容收录到个人网站&#xff0c;方便阅读&#xff1a;http://hardyfish.top/ 文章内容收录到个人网站&#xff0c;方便阅读&#xff1a;http://hardyfish.top/ 文章内容收录到个人网站&#xff0c;方便阅读&#xff1a;http://har…

【可视化大屏】Python Flask框架介绍

为了能显示真实数据&#xff0c;使用flask快速搭建了一个web应用&#xff0c;然后连接数据库&#xff0c;读取数据库里的数据来进行大屏可视化显示&#xff08;btw&#xff1a;数据是从车主之家网站上爬虫爬的&#xff09; 家人们&#xff01;记得使用专业版的pycharm&#xf…

保证文件只能在公司打开,走出公司就打不开这一神操作如何实现?一文告诉你详情!

在现代企业中&#xff0c;信息安全已经成为一项至关重要的任务。随着企业数据量的不断增加&#xff0c;如何确保敏感信息不被泄露成为企业面临的重要挑战。 其中&#xff0c;一种常见的需求是确保文件只能在公司内部环境中打开&#xff0c;一旦离开公司就无法访问。 本文将详…

计算机组成原理实验三 数据寄存器组R0..R3, MAR, ST, OUT

实验目的和要求 目的&#xff1a;了解模型机中各种寄存器结构、工作原理及其控制方法。 要求&#xff1a;利用CP226 实验系统上的K16..K23 开关做为DBUS 的数据&#xff0c;其它开关做为控制信号&#xff0c;将数据写入寄存器&#xff0c;数据寄存器组R0..R3&#xff0c;地址…

stm32开发环境的配置

keli5的安装 安装上以后&#xff0c;用管理员身份打开软件 复制里面的CID到破解软件里面 将Target调到ARM&#xff0c;然后生成 将注册码复制进软件那个界面&#xff0c;然后AddLIC就破解成功了 调试工具STLink驱动的安装 如果发现带感叹号代表驱动没有安装&#xff0c;但是设…

JavaEE之多线程进阶-面试问题

一.常见的锁策略 锁策略不是指某一个具体的锁&#xff0c;所有的锁都可以往这些锁策略中套 1.悲观锁与乐观锁 预测所冲突的概率是否高&#xff0c;悲观锁为预测锁冲突的概率较高&#xff0c;乐观锁为预测锁冲突的概率更低。 2.重量级锁和轻量级锁 从加锁的开销角度判断&am…

【Python时序预测系列】基于GRU模型实现多变量时间序列预测(案例+源码)

这是我的第363篇原创文章。 一、引言 单站点多变量单步预测问题----基于GRU实现多变量时间序列预测股票价格。 二、实现过程 2.1 读取数据集 dfpd.read_csv("data.csv", parse_dates["Date"], index_col[0]) print(df.shape) print(df.head()) fea_num …

OJ在线评测系统 微服务 OpenFeign调整后端下 nacos注册中心配置 不给前端调用的代码 全局引入负载均衡器

OpenFeign内部调用二 4.修改各业务服务的调用代码为feignClient 开启nacos注册 把Client变成bean 该服务仅内部调用&#xff0c;不是给前端的 将某个服务标记为“内部调用”的目的主要有以下几个方面&#xff1a; 安全性: 内部API通常不对外部用户公开&#xff0c;这样可以防止…

【目标检测】木制地板缺陷破损数据集338张6类VOC+YOLO格式

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;3383 标注数量(xml文件个数)&#xff1a;3383 标注数量(txt文件个数)&#xff1a;3383 标注…

python爬虫案例——处理验证码登录网站(12)

文章目录 前言1、任务目标2、网页分析3、代码编写4、第三方验证码识别平台(超级鹰)前言 我们在爬取某些网站数据时,可能会遇到必须登陆才能获取网页内容的情况,而大部分网站登录都需要输入验证码才能登录成功,所以接下来我将会通过实际案例来讲解如何实现验证码登录网站 1…

前后端分离开发YApid

开头先声明以下&#xff0c;这篇主要用于概念的介绍…… 在当今的互联网应用开发中&#xff0c;前后端分离逐渐成为主流的开发模式。相比于传统的前后端混合开发&#xff0c;这种新模式在灵活性、可维护性和团队协作等方面具有显著优势。 前后端混合开发 在前后端混合开发模式…

气膜淤泥加工厂:创新土壤修复的绿色方案—轻空间

随着城市化进程的加快&#xff0c;土壤污染问题日益严重&#xff0c;淤泥处理成为环保领域亟待解决的重要课题。气膜淤泥加工厂应运而生&#xff0c;提供了一种高效、环保的解决方案&#xff0c;为土壤修复和环境保护注入了新的活力。 高效处理&#xff0c;保障环境安全 气膜淤…

什么是 HTTP 请求中的 options 请求?

在 Chrome 开发者工具中的 Network 面板看到的 HTTP 方法 OPTIONS&#xff0c;其实是 HTTP 协议的一部分&#xff0c;用于客户端和服务器之间进行“预检”或“协商”。OPTIONS 请求的作用是让客户端能够获取关于服务器支持的 HTTP 方法和其他跨域资源共享 (CORS) 相关的信息&am…

2-112基于matlab的协同干扰功率分配模型

基于matlab的协同干扰功率分配模型&#xff0c;带操作界面的功率分配GUI&#xff0c;可以实现对已有功率的分配优化&#xff0c;可以手动输入参数值。4个干扰山区分二批总干扰功率&#xff0c;每个扇区包括威胁总系数、综合压制概率、目标函数增量等。程序已调通&#xff0c;可…

Linux:进程调度算法和进程地址空间

✨✨✨学习的道路很枯燥&#xff0c;希望我们能并肩走下来! 文章目录 目录 文章目录 前言 一 进程调度算法 1.1 进程队列数据结构 1.2 优先级 ​编辑 1.3 活动队列 ​编辑 1.4 过期队列 1.5 active指针和expired指针 1.6 进程连接 二 进程地址空间 2.1 …

HCIP--以太网交换安全(二)

端口安全 一、端口安全概述 1.1、端口安全概述&#xff1a;端口安全是一种网络设备防护措施&#xff0c;通过将接口学习的MAC地址设为安全地址防止非法用户通信。 1.2、端口安全原理&#xff1a; 类型 定义 特点 安全动态MAC地址 使能端口而未是能Stichy MAC功能是转换的…

Day8:返回倒数第k个节点

题目&#xff1a; 实现一种算法&#xff0c;找出单向链表中倒数第k个节点。返回该结点的值。 示例&#xff1a; 输入&#xff1a;1->2->3->4->5和k2 输出&#xff1a;4 说明&#xff1a; 给定的k保证是有效的。 public int kthToLast(ListNode head,int k){…

【STM32-HAL库】AHT10温湿度传感器使用(STM32F407ZGT6配置i2c)(附带工程下载连接)

一、温湿度传感器&#xff1a; 温湿度传感器是一种能够检测环境中的温度和湿度&#xff0c;并将其转化为电信号输出的装置。它在智能家居、工业自动化、气象监测、农业等领域有着广泛的应用。 原理&#xff1a; 温湿度传感器通常基于不同的物理原理&#xff0c;以下是一些常见…

前端vue-配置基地址并发送请求

1.首先&#xff0c;在HBuilder的终端下载安装luch-request 2.创建一个目录utils&#xff0c;以及下面的http.js文件&#xff0c;导入安装包&#xff0c;在new一下request&#xff0c;配置接口的基地址 3.在测试文件目录里面进行测试&#xff0c;看看请求能否发送成功&#xff…

Activity

文章目录 1.启停活动页面1.Activity启动和结束2.Activity生命周期3. Activity启动模式 2.在活动之间传递信息1.显示Intent和隐式Intent显示Intent隐式Intent 2.向下一个Activity发送数据3.向上一个Activity返回数据 3.为活动补充附加信息1.利用资源文件配置字符串2.利用元数据传…