Python布雷森汉姆直线算法RViz可视化ROS激光占位网格映射

2023-11-05

使用对数赔率映射已知姿势算法(ROS 包)。

布雷森汉姆直线算法

布雷森汉姆直线算法是一种线绘制算法,它确定应选择的 n 维栅格的点,以便形成两点之间的直线的近似值。 它通常用于在位图图像中(例如在计算机屏幕上)绘制线条图元,因为它仅使用整数加法、减法和位移,所有这些在常用的计算机指令集(如 x86_64)中都是非常便宜的操作。 它是一种增量误差算法,是计算机图形学领域最早开发的算法之一。

Python 实现算法

给定两点 A(x1, y1) 和 B(x2, y2) 的坐标。在像素的计算机屏幕上找到绘制线 AB 所需的所有中间点的任务。请注意,每个像素都有整数坐标。 例子:

Input  : A(0,0), B(4,4)
Output : (0,0), (1,1), (2,2), (3,3), (4,4)

Input  : A(0,0), B(4,2)
Output : (0,0), (1,0), (2,1), (3,1), (4,2)

以下是一些保持算法简单的假设。

  1. 我们从左到右画线。
  2. x1 < x2 和 y1< y2
  3. 线的斜率在 0 和 1 之间。我们从左下角到右上角画一条线。

让我们首先考虑幼稚的方式来理解这个过程。

// A naive way of drawing line
void naiveDrawLine(x1, x2, y1, y2)
{
   m = (y2 - y1)/(x2 - x1)
   for (x  = x1; x <= x2; x++) 
   {    
      // Assuming that the round function finds
      // closest integer to a given float.
      y = round(mx + c);    
      print(x, y); 
   }
}

上述算法有效,但速度很慢。 布雷森汉姆算法的思想是避免浮点乘法和加法计算mx+c,然后在每一步计算(mx+c)的取整值。 在布雷森汉姆的算法中,我们以单位间隔在 x 轴上移动。

  1. 我们总是将 x 加 1,然后选择下一个 y,是需要去 y+1 还是留在 y 上。换句话说,从任何位置 (Xk, Yk) 我们需要在 (Xk + 1, Yk) 和 (Xk + 1, Yk + 1) 之间进行选择。

  2. 我们想选择与更接近原始线的点对应的 y y y 值(在 Y ∗ k + 1 \mathrm{Y}*{\mathrm{k}}+1 Yk+1 Y ∗ k \mathrm{Y}*{\mathrm{k}} Yk 中)。

    我们需要一个决策参数来决定是选择 Y ∗ k + 1 \mathrm{Y}*{\mathrm{k}}+1 Yk+1 还是 Y ∗ k \mathrm{Y}*{\mathrm{k}} Yk 作为下一个点。 这个想法是跟踪从先前增量到 y y y 的斜率误差。 如果斜率误差大于 0.5,我们知道这条线已经向上移动了一个像素,我们必须增加 y y y 坐标并重新调整误差,以表示到新像素顶部的距离——这是通过减去一个来完成的 从错误。

    // Modifying the naive way to use a parameter
    // to decide next y.
    void withDecisionParameter(x1, x2, y1, y2)
    {
       m = (y2 - y1)/(x2 - x1)
       slope_error = [Some Initial Value]
       for (x = x1, y = y1; x = 0.5)  
       {       
          y++;       
          slope_error  -= 1.0;    
       }
    }
    

上述算法仍然包括浮点运算。为避免浮点运算,请考虑低于值 m m m 的值。

m = (y2 – y1)/(x2 – x1)

我们将两边乘以 (x2 – x1)。

我们还将 slope_error 更改为 slope_error * (x2 – x1)。为了避免与 0.5 比较,我们进一步将其更改为 slope_error * (x2 – x1) * 2。

此外,通常首选与 0 进行比较而不是 1。

// Modifying the above algorithm to avoid floating 
// point arithmetic and use comparison with 0.
void bresenham(x1, x2, y1, y2)
{
   m_new = 2 * (y2 - y1)
   slope_error_new = [Some Initial Value]
   for (x = x1, y = y1; x = 0)  
   {       
      y++;       
      slope_error_new  -= 2 * (x2 - x1);    
   }
}

slope_error_new 的初始值为 2*(y2 – y1) – (x2 – x1)。请参阅此处,以获取此值的证明。下面是上述算法的实现。

# Python 3 program for Bresenham’s Line Generation
# Assumptions :
# 1) Line is drawn from left to right.
# 2) x1 < x2 and y1 < y2
# 3) Slope of the line is between 0 and 1.
# We draw a line from lower left to upper
# right.

# function for line generation
def bresenham(x1,y1,x2, y2):

	m_new = 2 * (y2 - y1)
	slope_error_new = m_new - (x2 - x1)

	y=y1
	for x in range(x1,x2+1):
	
		print("(",x ,",",y ,")\\n")

		# Add slope to increment angle formed
		slope_error_new =slope_error_new + m_new

		# Slope error reached limit, time to
		# increment y and update slope error.
		if (slope_error_new >= 0):
			y=y+1
			slope_error_new =slope_error_new - 2 * (x2 - x1)
		
	

# driver function
if __name__=='__main__':
	x1 = 3
	y1 = 2
	x2 = 15
	y2 = 5
	bresenham(x1, y1, x2, y2)

#This code is contributed by ash264

输出

(3,2)
(4,3)
(5,3)
(6,3)
(7,3)
(8,4)
(9,4)
(10,4)
(11,4)
(12,5)
(13,5)
(14,5)
(15,5)

上面的解释是为了提供算法背后的粗略概念。详细的解释和证明,读者可以参考下面的参考资料。

上面的程序只有在直线的斜率小于 1 时才有效。这是任何斜率的程序实现。

#include <iostream>
//#include <graphics.h>
//Uncomment the graphics library functions if you are using it
using namespace std;

void plotPixel(int x1, int y1, int x2, int y2, int dx, int dy, int decide)
{
	//pk is initial decesion making parameter
	//Note:x1&y1,x2&y2, dx&dy values are intercganged
	//and passed in plotPixel function so
	//it can handle both cases when m>1 & m<1
	int pk = 2 * dy - dx;
	for (int i = 0; i <= dx; i++)
	{
		cout << x1 << "," << y1 << endl;
		//checking either to decrement or increment the value
		//if we have to plot from (0,100) to (100,0)
		x1 < x2 ? x1++ : x1--;
		if (pk < 0)
		{
			//decesion value will decide to plot
			//either x1 or y1 in x's position
			if (decide == 0)
			{
			// putpixel(x1, y1, RED);
				pk = pk + 2 * dy;
			}
			else
			{
				//(y1,x1) is passed in xt
			// putpixel(y1, x1, YELLOW);
				pk = pk + 2 * dy;
			}
		}
		else
		{
			y1 < y2 ? y1++ : y1--;
			if (decide == 0)
			{

				//putpixel(x1, y1, RED);
			}
			else
			{
			// putpixel(y1, x1, YELLOW);
			}
			pk = pk + 2 * dy - 2 * dx;
		}
	}
}

int main()
{
// int gd = DETECT, gm;
// initgraph(&gd, &gm, "xxx");
	int x1 = 100, y1 = 110, x2 = 125, y2 = 120, dx, dy, pk;
	//cin cout
	dx = abs(x2 - x1);
	dy = abs(y2 - y1);
	//If slope is less than one
	if (dx > dy)
	{
		//passing argument as 0 to plot(x,y)
		plotPixel(x1, y1, x2, y2, dx, dy, 0);
	}
	//if slope is greater than or equal to 1
	else
	{
		//passing argument as 1 to plot (y,x)
		plotPixel(y1, x1, y2, x2, dy, dx, 1);
	}
// getch();
}
视频演示(1m)
特征
  • ROS(输出 /map 和输入/scan)
  • 监听 map->base_link 变换
  • 演示包可用
  • 当 (x,y) 位置变化超过指定阈值时更新地图
  • 地图发布率有限
源代码

详情参阅 亚图跨际

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

Python布雷森汉姆直线算法RViz可视化ROS激光占位网格映射 的相关文章

随机推荐

  • 《算法和数据结构》从语言到算法的过渡篇

    本文已收录于专栏 夜深人静写算法 前言 看到太多爆肝熬夜整合的内容 又是几万字 又是爆肝 我也来试试看能不能扛得住 试完后发现 果然还是扛不住啊 但是既然整理完了 那就把我的 算法学习路线 发出来吧 我把整个算法学习的阶段总结成了五个步骤
  • 现代C++教程 笔记

    写在前面 记录一下 现代C 教程 中的要点 现代C 是指C 11之后的语法特性 如无特别说明 下面的语法特性均是C 11后才可使用 一 语言可用性的强化 1 常量 1 1 nullptr 作用 代替NULL赋空指针 使用 char a nu
  • 《ESP32 学习笔记》 之 ESP32 引脚图 及 个引脚特定功能 概览

    ESP32 S 模组 NODEMCU 32S 原理图 各个IO口功能
  • Qt 多线程之线程事件循环(深入理解)

    Qt支持三种类型的信号 槽连接 1 直接连接 当signal发射时 slot立即调用 此slot在发射signal的那个线程中被执行 不一定是接收对象生存的那个线程 2 队列连接 当控制权回到对象属于的那个线程的事件循环时 slot被调用
  • 在pl/sql中执行动态sql

    动态sql就是把sql写在一个字符串里 在存储过程中解析字符串执行sql 这种动态sql很多时候会在别的语言里写 再连接数据库进行操作 这样的确方便很多 例如在java中使用JDBC 但是如果涉及到sql变化很多次 直接在存储过程中写动态s
  • Linux嵌入汇编1- 详解

    Linux上的 GNU C 编译器 GCC 使用 AT T UNIX 汇编语法 源操作数与目的操作数顺序 AT T 语法的操作数方向和 Intel 语法的刚好相反 在Intel 语法中 第一操作数为目的操作数 第二操作数为源操作数 然而在
  • python 使用node_vm2执行js

    有时候 一些js需要调用 之前都是用nodejs比较多 但是有些js会验证是否使用的是node 就比如某头条的加密 为了能本地调用扣下来的js 这里就不能用nodejs或者execjs 需要用到vm2 步骤 1 下载vm2 pip inst
  • 排序与查找代码总结-数据结构与算法python版

    代码来源于北京大学的数据结构与算法课 Python版 注释为本人自己加上的 可供学习使用 不可用于商业转载 有错误烦请指出 感谢 目录 二分查找 普通版 递归版 冒泡排序 普通版 加了是否发生交换的监测 选择排序 插入排序 希尔排序 归并排
  • C语言

    C 菜鸟教程 C 结构体位域
  • win7搭建虚拟pppoe服务器,Win7在桌面建立一个pppoe宽带自动连接器的方法

    本教程告诉大家如何在Win7在桌面建立一个pppoe宽带自动连接器教程 现在电脑已经普及使用了 每次开机都要连接宽带上网 很多用户说如何快速在Windows桌面建立一个PPPOE宽带连接 方便直接连接 之前在xp系统可以建立pppoe宽带自
  • 合并两个有序链表 c++

    LeetCode 21 合并两个有序链表 题目 21 合并两个有序链表 代码 Definition for singly linked list struct ListNode int val ListNode next ListNode
  • 哪些工具可以实现在线ps的需求

    在线Photoshop有哪些工具可以选择 在 Adobe 的官网上就能够实现 很惊讶吧 其实 Adobe 官方推出了在线版本的 Photoshop 的 尽管目前还是 Beta版本 但其实也开放了蛮久了 编辑切换为居中 添加图片注释 不超过
  • TCP协议及特性详解

    文章目录 TCP 确认应答 超时重传 连接建立与断开 三次挥手 四次挥手 四种常见状态 效率提升机制 滑动窗口 流量控制 拥塞控制 延时应答 捎带应答 粘包问题 TCP TCP 协议是一个有连接 可靠传输 面向字节流 全双工的传输层通信协议
  • Hive中数组的使用

    基本操作 创建文本 gt cat test txt 输入文本数据 12 23 23 34 what are this 34 45 34 23 12 who am i are 打开Hive 创建表 hive gt create table t
  • 常见几种滤波器的比较

    经典的数字滤波器有巴特沃斯滤波器 切比雪夫滤波器 椭圆滤波器和贝塞尔滤波器等 巴特沃斯滤波器的特点是通频带内的频率响应曲线最大限度平坦 没有起伏 而在阻频带则逐渐下降为零 在振幅的对数对角频率的波特图上 从某一边界角频率开始 振幅随着角频率
  • Linux FTP服务(只允许白名单用户访问FTP)

    目录 一 FTP服务器 二 FTP文化传输协议 FTP的传输模式有两种 三 Vsftpd服务程序 四 实验步骤 1 安装vsftpd软件包 2 备份主配置文件 3 去掉 号开头的行 4 创建黑 白名单的目的 约束 允许某些特定用户登录系统
  • 深入学习java源码之ArrayList.addAll()与ArrayList.retainAll()

    深入学习java源码之ArrayList addAll 与ArrayList retainAll 引入多态 List是接口 所以实现类要把接口中的抽象方法全部重写 在重写的时候父类中的方法的时候 操作的数据类型也是要与父类保持一致的 所以父
  • IPX9K IP69K:ISO 20653:2006

    IPX9K IP69K ISO 20653 2006 ISO 20653 2006 已由 ISO 20653 2013 标准代替 道路车辆 防护等级 IP 代码 电气设备对 外来物 水和接触的防护 参考编号 ISO 20653 2006 版
  • 古老的Solidity智能合约错误代码编写

    任何编程语言都有不完善的地方 而使用语言的过程中也可能产生一些逻辑上的Bug 在Solidity0 4 23版本的时候 有人在GitHub上列举了一些使用Solidity编写智能合约时常见的错误用法 虽然现在大家基本上都不会再写同样的问题代
  • Python布雷森汉姆直线算法RViz可视化ROS激光占位网格映射

    使用对数赔率映射已知姿势算法 ROS 包 布雷森汉姆直线算法 布雷森汉姆直线算法是一种线绘制算法 它确定应选择的 n 维栅格的点 以便形成两点之间的直线的近似值 它通常用于在位图图像中 例如在计算机屏幕上 绘制线条图元 因为它仅使用整数加法