SLAM从入门到精通(bresenham绘制算法)

news2025/4/17 7:06:06

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

        前面我们说过,学术界和工业界对于slam的要求是不一样的。前者要求robot在运动的过程中,同步实现定位和制图的操作。但是工业界中,一般两者是分开来的。首先进行制图,一旦制图完成之后就专注于定位操作。但是这两者之间没有明显的差别。

1、学术slam和工业slam的关系

        整理来说,完全可以把工业界的应用看成是slam的一个特例。真正的slam一般是这样的,首先在robot开始的位置设置为原点,lidar扫描的地方,绘制出一个地图。接着,通过遥控按钮操作robot,这个时候robot就走到了一个新的位置。借助于odom数据、lidar数据和之前的地图数据,我们可以求解出robot新位置的坐标。这样,我们通过robot的新位置、lidar扫描数据,又可以绘制出新的地图了。循环往复,不断重复上面的过程,最终就会可以得到一个完整的地图。这就是slam的基本原理。

2、slam和定位的转换

        有了上面的分析,大家也就明白了为什么很多论文都是讲slam算法,但是不谈具体的定位算法。这主要就是因为如果把slam算法中的制图删除、定位算法中的地图直接换成全局地图,这本身就是一个相对完整的定位算法方案了。

3、制图的算法

        有了准确的位姿之后,制图就不复杂了。前面我们说过,制图其实就是绘制很多的射线。雷达无法扫描到的地方一般被认为是灰色。没有达到最远测量距离,提前返回来的地方,那就是黑色,也就是有障碍物的地方。而lidar和障碍物之间的区域,这就是白色,可以被认为是能够自由活动的区域。

        上面这些描述,都是建立在lidar和base_link基本一致的基础上得出来的。如果两者不一致,那么还需要做一个tf转换。所以大家看到得是地图文件,实际上是通过一条、一条得射线绘制出来的。

4、bresenham算法

        这个算法本身是属于计算机图形学的一个基本算法。我们平时在绘制直线的时候,很容易遇到浮点数。但是计算机屏幕上面是没有浮点数的,每一个x、y坐标都是一个整数。那么怎么把这些直线上的数据在屏幕上面显示出来,这就是bresenham算法所要解决的事情。

        希望了解算法详细内容的同学,可以看下这个wiki连接,讲的还是很仔细的,

https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm

5、编译和测试

        不喜欢看算法,想直接看代码的同学也可以直接github上查找对应的代码。网上有很多bresenham算法的实现代码,这里给出一个链接,

https://gist.github.com/nowke/965fed0d5191bf373f1262be584207bb

        如果链接也不想看,这里给出一个可以编译版本的代码方案。主要是头文件需要修改下,

#include <GL/glut.h>
#include <stdio.h>

int x1, y1, x2, y2;

void myInit() {
	glClear(GL_COLOR_BUFFER_BIT);
	glClearColor(0.0, 0.0, 0.0, 1.0);
	glMatrixMode(GL_PROJECTION);
	gluOrtho2D(0, 500, 0, 500);
}

void draw_pixel(int x, int y) {
	glBegin(GL_POINTS);
	glVertex2i(x, y);
	glEnd();
}

void draw_line(int x1, int x2, int y1, int y2) {
	int dx, dy, i, e;
	int incx, incy, inc1, inc2;
	int x,y;

	dx = x2-x1;
	dy = y2-y1;

	if (dx < 0) dx = -dx;
	if (dy < 0) dy = -dy;
	incx = 1;
	if (x2 < x1) incx = -1;
	incy = 1;
	if (y2 < y1) incy = -1;
	x = x1; y = y1;
	if (dx > dy) {
		draw_pixel(x, y);
		e = 2 * dy-dx;
		inc1 = 2*(dy-dx);
		inc2 = 2*dy;
		for (i=0; i<dx; i++) {
			if (e >= 0) {
				y += incy;
				e += inc1;
			}
			else
				e += inc2;
			x += incx;
			draw_pixel(x, y);
		}

	} else {
		draw_pixel(x, y);
		e = 2*dx-dy;
		inc1 = 2*(dx-dy);
		inc2 = 2*dx;
		for (i=0; i<dy; i++) {
			if (e >= 0) {
				x += incx;
				e += inc1;
			}
			else
				e += inc2;
			y += incy;
			draw_pixel(x, y);
		}
	}
}

void myDisplay() {
	draw_line(x1, x2, y1, y2);
	glFlush();
}

void main(int argc, char **argv) {

	printf( "Enter (x1, y1, x2, y2)\n");
	scanf("%d %d %d %d", &x1, &y1, &x2, &y2);

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
	glutInitWindowSize(500, 500);
	glutInitWindowPosition(0, 0);
	glutCreateWindow("Bresenham's Line Drawing");
	myInit();
	glutDisplayFunc(myDisplay);
	glutMainLoop();
}

        这里的编译命令是在ubuntu 20.04上实现的,如果有glut.h文件无法找到的错误,可以先安装一下这个库,

sudo apt-get install libglfw3-dev libgl1-mesa-dev libglu1-mesa-dev

        安装好库之后,就可以用命令gcc来编译了,

gcc draw.c -lglut -lGL -lGLEW -lGLU -o draw

        一切顺利的话,就可以生成./draw文件。执行后,会看到一个提示,要求我们输入起点和终点的坐标,

feixiaoxing@feixiaoxing-VirtualBox:~/Desktop$ ./draw
Enter (x1, y1, x2, y2)
100 3 200 500

        老老实实输入坐标后,按回车就可以看到对应的直线显示了,

        整个算法借助于opengl实现了显示过程。有兴趣的同学可以单步调试一下。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

罗德施瓦兹频谱仪使用笔记

本文主要介绍罗德频谱仪的两个重要参数RBW和VBW&#xff0c;以及测量设置&#xff0c;以帮助初学者理解频谱解析以及频谱仪的具体使用。 一、什么是RBW和VBW&#xff0c;它们对测量得到结果的影响。 在罗德施瓦兹频谱仪的频谱测量中&#xff0c;有两个参数设置用得比较多&…

机器视觉工程师越学习越谦虚-庆幸自己始终保持清醒

目录 ​这么多年的职场生涯&#xff0c;不断的学习&#xff0c;不断的进取&#xff0c;不断追求新的梦想。一直学习&#xff0c;越学习&#xff0c;越感觉自己的不足&#xff0c;自我感觉越无知&#xff0c;越谦虚。所以孔子讲“不耻下问”、“三人行必有我师”&#xff0c;像释…

芯片学习记录MP2144

MP2144 芯片介绍 MP2144是一款具有内部功率MOSFET的单片降压开关模式转换器。它可以从2.5V到-5.5V的输入电压实现高达2A的连续输出电流&#xff0c;具有出色的负载和线路调节。输出电压可以调节到低至0.6V。 恒定导通时间控制方案提供快速瞬态响应并简化环路稳定。故障状态保…

__main__文件学习测试如下

参考博客 https://www.jb51.net/article/251567.htm test01.py # https://www.jb51.net/article/251567.htmdef step():print(__name__)print("step1 买菜""step2 洗菜""step3 切菜""step4 炒菜")if __name__ __main__:print(准备制…

【统计学概念】初学者指南:了解置信区间

一、说明 什么是置信区间&#xff1f;如何将概率转化成信心度&#xff1f;信心度如何去工作&#xff1f;这些初步的统计概念需要明晰&#xff0c;然后才能应用统计模型&#xff0c;然后是贝叶斯推理&#xff0c;我们将逐步深入这些概念。 二、总体与样本个体统计 总体是研究人…

自定义Docker镜像--Jupyterlab

概述 自定义Jupyterlab镜像&#xff0c;为deployment做准备 步骤 下载基础镜像&#xff1a;centos:7.9.2009 docker search centos:7.9.2009 docker pull centos:7.9.2009 启动容器 部署应用 # 启动容器 docker run -it --name test centos:7.9.2009 bash# 在容器内部署…

windows 10LTSC安装微软应用商店(理论上适用于所有windows10)

LTSC-Add-MicrosoftStore-2019.zip官方版下载丨最新版下载丨绿色版下载丨APP下载-123云盘123云盘为您提供LTSC-Add-MicrosoftStore-2019.zip最新版正式版官方版绿色版下载,LTSC-Add-MicrosoftStore-2019.zip安卓版手机版apk免费下载安装到手机,支持电脑端一键快捷安装https://w…

习题2.17

很简单的一个提 代码如下 (defn last-pair[a](if (empty? (rest a))(first a)(last-pair (rest a) ))) 获取列表最后一个元素&#xff0c;递归的办法如上。

WLAN 无线案例(AC配置模板)

实验说明&#xff1a; 无线用户VLAN 30 192.168.30.0/24 AP和AC用VLAN 20 192.168.20.0/24 有线网段 VLAN 10 192.168.10.0/24 步骤一&#xff1a;全网互通 sw1&#xff1a; sysname sw1 # vlan batch 10 20 30 # dhcp enable # ip pool 20 gateway-list 192.168.20.1…

PHP基础语法(上)

目录 前言 一、基础语法 1.1 标记 1.2 输出语句 1.2.1 echo 1.2.2 print 1.3 注释 1.3.1 单行注释 1.3.2 多行注释 1.4 标识符 1.5 关键字 二、数据与运算 2.1 常量 2.1.1 常量的定义和使用 2.1.2 预定义常量 2.2 变量 2.2.1 变量的赋值 2.2.2 超全局变量 2.3 数据类型 2.3.1 …

Python 中的 DNS 查找

本文将讨论 DNS 和 DNS 查找的概念。 之后&#xff0c;我们讨论使用 Python 进行 DNS 查找的方法。 什么是 DNS DNS&#xff08;域名系统&#xff09;将域名转换为公共IP地址。 DNS 服务器将任何网站的域名转换为该网站主机服务器的公共 IP。 DNS查询 DNS 查找是一个过程&…

微信小程序 uniapp+vue线上洗衣店业务管理系统演89iu2

本课题意在设计一种系统的、基于用户体验的线上洗衣服务模式&#xff0c;具有如下的研究意义: (1)为用户提供更简单、便捷的洗衣服务模式; (2)为智能柜的盈利模式提供了新的方向; (3)通过线上系统、智能柜与洗衣工厂结合的方式&#xff0c;为洗衣企业构建了一套节 省人力成本的…

X86_64 栈和函数调用

引言 大家都知道函数调用是通过栈来实现的&#xff0c;而且知道在栈中存放着该函数的局部变量。但是对于栈的实现细节可能不一定清楚。本文将介绍一下在 x86 平台下函数栈是如何实现的。 1、x86-64 汇编 Intel 系列处理器通常称为x86&#xff0c;目前常用的笔记本或台式机都是…

常见场景面试题:BitMap、布隆过滤器

typora-copy-images-to: imgs位图 BitMap BitMap 到底用于解决什么问题&#xff1f; BitMap 常常用于解决一些数据量比较大的问题&#xff0c;比如说对于1千万个整数&#xff0c;整数的范围在 1~100000000&#xff0c;对于一个整数 x &#xff0c;我们怎么知道在不在这1千万个整…

基于springboot实现医院急诊平台系统项目【项目源码】计算机毕业设计

基于springboot实现医院急诊平台系统演示 Spring Boot框架 Spring Boot是Pivotal团队的一个新框架&#xff0c;旨在简化新Spring应用程序的初始设置和开发。该框架使用特定的配置方法&#xff0c;无需开发人员定义样板配置。通过这种方式&#xff0c;Spring Boot旨在成为蓬勃发…

为什么直接用int转换 字符串内为小数类型的变量,会报错?直接转换失败?如何解决?

见图思考&#xff1a;为什么直接用int转换 字符串内为小数类型的变量&#xff0c;会报错&#xff1f;&#xff1f;&#xff1f;直接转换失败&#xff1f;&#xff1f;&#xff1f; 报错的意思就是&#xff1a;值异常&#xff0c;因为小数类型的字符串 ‘10.88’&#xff0c;不…

深度学习实战57-pytorch框架搭建LSTM+CNN模型与实现时间序列的预测过程

大家好,我是微学AI,今天给大家介绍一下深度学习实战57-pytorch框架搭建LSTM+CNN模型与实现时间序列的预测过程, 随着科技的进步,我们越来越依赖数据来理解世界,预测未来。特别是在金融、气候研究、交通管理等领域,时间序列预测已经成为了重要的工具。本文将介绍如何使用L…

Apifox 学习笔记 - 前置操作之:自定义变量给请求参数中使用

Apifox 学习笔记 - 前置操作之&#xff1a;动态更新请求体中的时间戳 1. 在前置操作中添加一个&#xff1a;自定义脚本或公共脚本2. 定义我们所需的环境变量。3. 在请求参数中使用【时间戳】4. 检验5. 示例自定义变量mock 参考资料 1. 在前置操作中添加一个&#xff1a;自定义脚…

如何下载GitHub上的代码

新建好要存储的文件夹 右键选择Git Bash Here ls是查看当前文件夹下的文件&#xff0c;可以忽略 git clone 地址 地址在这 直接点复制&#xff0c;粘贴的时候没办法粘贴 可以发现复制即为&#xff1a;CtrlIns&#xff1b;粘贴即为&#xff1a;ShiftIns 于是我们用ShiftIns…

开源ESP32智能小车机械臂控制板Baize_Carboard(支持mixly)

介绍 采用esp32做主控的Baize_Carboard&#xff0c;支持4路直流电机或者两路步进电机的控制&#xff0c;也可以用于控制两路直流闭环电机。输入电压范围5-12V&#xff0c;有时候电压5V起不来&#xff0c;要高一点。可以用于学习arduino或者ros编程&#xff0c;同时也可以将ros…