树莓派4B ROS SLAM 超全总结

摘要

随着树莓派的普及以及4B版本推出,我们小组也决定由我负责树莓派相关部分,可惜网上的资源大多并不齐全,在操作中浪费了大量的时间。因此本文将详细总结笔者这些天的工作,力争形成全面的系统化的文章。本方法的所有相关资源都将放到附录部分,有需要可以自行下载。没有CSDN会员的可以私聊我,传邮箱也可以。不过可能回复不是很及时。
另外:本文由于内容过多,将采取链接形式,将所有我自己操作可行的文章链接替换长篇大论,但对于链接中不足的地方将详细讲解。本文的重点将放在目前任何博客没有给出解决方案的”软件包安装“上面。
由于本文是在本人尝试编译SLAM后第四天开始动笔的,所以之前可能有错误未能及时记录,有相关问题可以评论区讨论解决方法,欢迎大佬们的补充。

树莓派系统的使用

拿到树莓派时一般都会有对应的说明书,网上也有许多相关安装方法,安装部分不再赘述,后文会附带相关资源,但如果有希望后期用Respi系统来安装ROS,这里就要强调一下:本方法只支持burst版本,bullsyes等我花了许久也没有研究出对应的安装方法,主要区别在于bullsyes没有gcc-5的编译器以及在安装ROS时会产生python版本不匹配,安装对应版本又报错对应python编译器不匹配,但未找到安装方法。如果有那位大佬成功了,欢迎评论区留言。

树莓派GPIO的使用

笔者采用的是C++编程,如果想看python程序可以参考http://huishao.cc/ 的文章,他在这方面写的很详细。(由于一开始是安装bullsyes,还未测试burst系统是否足够兼容,应该是没有问题的)
更加全面的函数讲解可以参考http://wiringpi.com/ 里面有所有函数的使用方法。
对于芯片L293D,可以参考https://zhuanlan.zhihu.com/p/340063310

  1. 头文件 ,基本包含这几个头文件即可完成绝大多数的功能
    #include <wiringPi.h>
    #include <wiringPiI2C.h>
    #include <softPwm.h>
    #include <softTone.h>
  2. 代码逻辑,首先要开始的是wiringPiSetup(),先于所有函数,然后就是根据需要的引脚类型去设置,GPIO引脚用pinMode初始化,其他的软件引脚调用对应的create函数,I2C调用setup函数,特别注意:setup函数会返回文件句柄,在后面的操作中必须要使用这个文件句柄来操作。接着就是需要的话设置对应中断,在while循环中检测中断处理的情况,main函数中去读写GPIO,I2C等引脚信息。
  3. 函数使用,详细函数解释可以查看参考文献,或者发评论区询问细节。
  1. 注意事项,init函数中一定要检查返回值是否正常,不正常要立刻退出,否则会出问题。连线的时候一定要注意,C++对应的只有wiringPi编码格式,一般杜邦板上的编码是BCM编码,注意转换。
  2. 目前就想到这几种常见的错误,有任何问题都可以评论区私聊,我觉得我的经验应该足够。附上一个代码和对应的简化后的接线图。各位可以根据需要调整。附录附带演示视频。
using namespace std;
#include <iostream>
#include <wiringPi.h>
#include <wiringPiI2C.h>
#include <softPwm.h>
#include <softTone.h>

#define HW_011 0x48
#define HC_SR04_Echo 2
#define HC_SR04_Trig 3
#define SWITCH 0
#define L293D_EN 21
#define L293D_IN1 22
#define L293D_IN2 23
#define GongFang 24
#define FengMing 1
#define JQC3FFSZ 4
#define LED_R 29
#define LED_B 27
#define LED_G 28

int fd;
volatile int start;
unsigned int time0;
unsigned int time1;
// C璋冧綆闊?
int CL[] = {0, 131, 147, 165, 175, 196, 211, 248};
// C璋冧腑闊?
int CM[] = {0, 262, 294, 330, 350, 393, 441, 495};   
// C璋冮珮闊?
int CH[] = {0, 525, 589, 661, 700, 786, 882, 990};
int pu[] = {CM[3],CM[3],CM[2],CM[3],CM[3],CM[5],CM[3],CM[2],CM[3],\
            CM[1],CM[1],CM[2],CM[3],CM[5],CM[3],CM[2],CM[2],CM[1],CM[2],\
            CM[3],CM[5],CM[3],CM[6],CM[5],CM[6],CM[5],CM[5],CM[3],CM[5],\
	    CM[5],CM[3],CM[2],CM[3],CM[5],CM[3],CM[2],CM[2],CM[2],CM[1],CM[2],\
	    CM[3],CM[3],CM[2],CM[3],CM[3],CM[5],CM[3],CM[2],CM[3],\
            CM[1],CM[1],CM[2],CM[3],CM[5],CM[3],CM[2],CM[2],CM[1],CM[2],\
            CM[3],CM[5],CM[3],CM[6],CM[5],CM[6],CM[5],CM[5],CM[3],CM[5],\
	    CM[5],CM[3],CM[2],CM[3],CM[5],CM[3],CM[2],CM[2],CM[2],CM[1],CM[1]};
int len[] = {4,2,2,8,2,2,2,2,8,4,2,2,2,2,4,4,2,2,8,6,1,1,2,6,2,2,2,2,7,1,4,2,2,4,2,2,4,2,2,8,\
             4,2,2,8,2,2,2,2,8,4,2,2,2,2,4,4,2,2,8,6,1,1,2,6,2,2,2,2,7,1,4,2,2,4,2,2,4,2,2,8};
             
void init ()
{
	if (0 > wiringPiSetup())
	{
		cout<<"Setup Error\r\n";
		exit(-1);
	}
	fd = wiringPiI2CSetup(HW_011);
	if (fd == -1)
	{
		cout<<"I2C Setup Error\r\n";
		exit(-1);
	}
	if (softPwmCreate(L293D_EN,0,100) != 0)
	{
		cout<<"softPwm Setup Error\r\n";
		exit(-1);
	}
	if (softToneCreate(GongFang) != 0) 
	{
		cout<<"softTone Setup Error\r\n";
		exit(-1);
	}
	pinMode(SWITCH,INPUT);
	pinMode(HC_SR04_Trig,OUTPUT);
	pinMode(HC_SR04_Echo,INPUT);
	pinMode(L293D_IN1,OUTPUT);
	pinMode(L293D_IN2,OUTPUT);
	pinMode(FengMing,PWM_OUTPUT);
	pinMode(JQC3FFSZ,OUTPUT);
	pinMode(LED_R,OUTPUT);
	pinMode(LED_G,OUTPUT);
	pinMode(LED_B,OUTPUT);
}
void begin()
{
	start ++;
	cout<<"Switch has been touched\r\n";
	delay(1000);
}
void time()
{
	if (digitalRead(HC_SR04_Echo) == 1)
	{
		time0 = micros();
	}
	if (digitalRead(HC_SR04_Echo) == 0)
	{
		time1 = micros();
	}
}
int main(void)
{
	init();
	cout<<"init success, push switch to start\r\n";
	cout<<"It use interrupt to get information\r\n";
	wiringPiISR(SWITCH, INT_EDGE_RISING, begin);
	wiringPiISR(HC_SR04_Echo, INT_EDGE_BOTH, time);
	while (1) 
	{
		if (start == 0)
		{
			continue;
		}
		cout<<"First, let\'s open our LED by different color.\r\n";
		cout<<"It use digitalWrite to control LED\r\n";
		for (int i = 0; i <= 7; i ++)
		{
			digitalWrite(LED_R, (i & 1) ? HIGH : LOW);
			digitalWrite(LED_G, (i & 2) ? HIGH : LOW);
			digitalWrite(LED_B, (i & 4) ? HIGH : LOW);
			delay(500);
		}
		cout<<"Then, let\'s get the infomation from HW-011\r\n";
		cout<<"It use I2C wire to read or write data\r\n";
		wiringPiI2CWrite(fd, 0x04);   //in this way, it will check every interface one by one
		wiringPiI2CRead(fd);          //release the register
		delay(500);
		int i = 0;
		while (start < 2)
		{
			int value = wiringPiI2CRead(fd);
			switch (i & 3)
			{
				case 0: cout<<"0: "<<value<<"\t";
						break;
				case 1: cout<<"1: "<<value<<"\t";
						break;
				case 2: cout<<"2: "<<value<<"\t";
						break;
				case 3: cout<<"3: "<<value<<"\r\n";
						break;
			}
			i++;
			delay(500);
		}
		cout<<"After that, let\'s detect the distant from HC-SR04\r\n";
		cout<<"It use interrupt and digitalWrite to control to culculate distance\r\n";
		while (start < 3)
		{
			digitalWrite(HC_SR04_Trig, HIGH);
			delay(1000);
			digitalWrite(HC_SR04_Trig, LOW);
			while (time1 < time0)
				delay(10);
			cout<<"The distance is: "<<(time1 - time0) * 340.0 / 2.0<<"\r\n";
			time0 = time1 = 0;
			delay(500);
		}
		cout<<"Now, let\'s control the motor by different speed\r\n";
		cout<<"It use softPwm to control speed\r\n";
		cout<<"please input the speed percentege, to stop by more than 100 or less than -100\r\n";
		int speed;
		while (cin>>speed)
		{
			if (speed > 100 || speed < -100) {
				softPwmWrite(L293D_EN,0);
				break;
			}
			else if (speed > 0) {
				softPwmWrite(L293D_EN, speed);
				digitalWrite(L293D_IN1, HIGH);
				digitalWrite(L293D_IN2, LOW);
			} else {
				softPwmWrite(L293D_EN, -speed);
				digitalWrite(L293D_IN1, LOW);
				digitalWrite(L293D_IN2, HIGH);
			}
		}
		cout<<"How could we do if we want to use harder Pwm?\r\n";
		cout<<"Let\'s use GPIO 1 to control fengming mechine\r\n";
		for (int i = 0; i <= 1024; i += 64)
		{
			pwmWrite(FengMing, i);
			delay(500);
//			pwmWrite(FengMing, 0);
//			delay(500);
		}
		cout<<"At last, let\'s start our gongfang\r\n";
		cout<<"It use JQC3FFSZ to control it open and use softTone to control it frequency\r\n";
		delay(10000);
		digitalWrite(JQC3FFSZ, HIGH);
		cout<<"start music\r\n";
		for (int i = 0; i < 80; i ++)
		{
			softToneWrite(GongFang,pu[i]);
			delay(125 * len[i]);
			softToneWrite(GongFang, 0);
			delay(10);
		}
		delay(500);
		break;
	}
	cout<<"Goodbye!\r\n";
	return 0;
}

在这里插入图片描述

树莓派系统安装ROS-Melodic

首先确保你的系统是burst系列,最好是10版本
参考链接:https://blog.csdn.net/jzhd2015/article/details/108218350

注意事项

上面那个链接已经非常详细的讲述了如何安装ROS-Melodic,对于相关的资源也会在附录中提供。但rosdep init的部分对我已经不再适用了,我的办法是:进入/usr/lib/python2.7/dist-packages/ (这里要稍微注意一下python的版本,有的有可能是python3.7什么的,但操作思路都是一样的。依次输入命令:

cd /usr/lib/python2.7/dist-packages/
find . -type f | xargs grep “raw.githubusercontent”

这时会找出所有包含raw.githubusercontent的文件,将其中所有.py文件中的 https://raw.githubusercontent/.com/ros/rosdistro/master/ 替换成 https:/gitee.com/zhao-xuzuo/rosdistro/raw/master/ 这样就可以成功完成init和后续update的工作了。

这个链接中由于安装comm版本,所以只到roscore就结束了,但无法运行turtle节点测试,而且对于SLAM来说,comm的软件包是完全不够用的,经过本人连续一周的测试,重装系统,甚至拷贝ubuntu中的软件包都没有结果后,终于摸索出了如何安装软件包,将在下一个章节中详细讨论。

基于Raspi系统的ROS如何安装软件包

当出现诸如:

CMake Error at /opt/ros/hydro/share/genmsg/cmake/genmsg-extras.cmake:255 (message): Messages depends on unknown pkg: nav_msgs (Missing find_package(nav_msgs?)) Call Stack (most recent call first): ax2550/CMakeLists.txt:22 (generate_messages)
等错误时,如果简单的上网搜索,只会看到适用sudo apt-get install 。。。的方法,但是这个对于树莓派原生系统来说,已经不再有作用了。因为压根就没有对应的ros-melodic系列的软件包QAQ,直接拷贝是不行的,因为毕竟是.cpp代码,还需要编译的。。。。

解决方案(大多数)

对于大部分软件包(对于SLAM来说就是除了OpenCV、PCL、Ceres以外的软件包,这两个后面会讲),既然apt无法安装,那就可以退而求其次,适用rosinstall来安装嘛,如果有人想更加深入的理解其中的含义,可以搜索rosinstall和wstool的官网,相信更加深层次的官网讲的会比我好,这里我来教如何适用。
比如如果出现了类似下面这样的报错:
在这里插入图片描述
那么我们就可以在命令行中输入如下命令:

rosinstall_generator tf --rosdistro melodic --deps --tar > melodic-tf.rosinstall
wstool merge -t src melodic-tf.rosinstall

在这里插入图片描述
将第一个tf替换为报错中缺少的包,melodic_tf.rosintall替换为一个自己定义好的,不冲突命名的.rosinstall文件, wtool 命令替换为.rosinstall文件名。再输入:

wstool update -t src

在这里插入图片描述

没有报错就说明成功完成软件包的安装,再次编译会发现已经不再报这个文件找不到了。
上面那个说的是通解,但如果是需要编译SLAM的话,用下面这个集成的命令,会让编译更加快一些:

rosinstall_generator tf sensor_msgs nav_msgs image_transport geometry_msgs cv_bridge --rosdistro melodic --deps --tar > melodic_slam.rosinstall
wstool merge -t src melodic_slam.rosinstall
wstool update -t src

还有一个特殊的pcl_conversions,报错是这样的:
在这里插入图片描述
但是输入:

rosinstall_generator pcl_conversions --rosdistro melodic --deps --tar > melodic-pcl_conversions.rosinstall
wstool merge -t src melodic-pcl_conversions.rosinstall
wstool update -t src

出现类似界面:
在这里插入图片描述

但很奇怪并没有成功。。。大概是这并不是在编译时出现的问题,所以并不能靠这个方法解决吧。。。
网上也没有解决方法,只好把他们放到工作空间src,要用到pcl_conversions包(比如A-Loam-devel),include下面了。。。

解决方案(OpenCV)

没有能截图,但报错格式和上面的那个差不多。
OpenCV的编译时间很长,所以,尽量不要尝试去一个个试错。
而且目前网上没有一个是完全没有错误的。。。

  • 版本
    版本问题需要很注意,你的OpenCV到底是缺了那个版本,避免错误。对于4版本,可以参考https://mp.weixin.qq.com/s/w1Pz09t-MrWzygLiO5w6Qw 讲解的很好,有一个错误,后面讲。对于3版本,参考https://blog.csdn.net/simonforfuture/article/details/101716181 思路差不多。
  • 错误
    • 使用pip install安装。用此方法安装虽然确实可以在python中使用,但无法在catkin_make中编译成功,很遗憾,因为这个其实很方便。
    • 第一个个网站的错误是没有加入相应的包,在第二个网站和本文附录中都将解答并提供资源。方法就是把对应压缩包的东西全部放到opencv_contrib这个目录的子文件夹下,我一开始在opencv里面瞎找。。。。QAQ
    • 第二个网站的错误在后面都有解释(。。。没有往下翻的憨憨。。。。)写的挺好,就不再赘述了。就是笔者大概是笔误吧,第七步:编译OpenCV时前面创建的opencv文件夹没有用到哎,建议操作改成这样,实测可行(注意OPENCV_EXTRA_MODULES_PATH):

    cd ~/opencv-3.4.1/
    mkdir build
    cd build
    cmake -D CMAKE_BUILD_TYPE=RELEASE
    -D CMAKE_INSTALL_PREFIX=/usr/local
    -D INSTALL_C_EXAMPLES=ON
    -D INSTALL_PYTHON_EXAMPLES=ON
    -D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib-3.4.1/modules
    -D ENABLE_PRECOMPILED_HEADERS=OFF
    -D BUILD_EXAMPLES=ON …

解决方案(PCL)

错误截图:
在这里插入图片描述
这方面资源网上真的不是很多。。找到一个比较不错的网站,链接:https://blog.csdn.net/mush_room/article/details/78411846 里面大部分都是很适用的,文章后面也给出了树莓派的安装方法,但有几个小问题要声明一下。

  1. 里面对于安装pcl1.8.1没有解释,由于目前已经更新了pcl,所以如果还想安装的话,需要使用命令

git clone https://github.com/PointCloudLibrary/pcl.git -b pcl-1.8.1

用来切换到对应的分支上。
2. cmake那里会报两个错误,一个是

– The imported target “vtk” references the file
“/usr/bin/vtk”
but this file does not exist. Possible reasons include:

  • The file was deleted, renamed, or moved to another location.
  • An install or uninstall procedure did not complete successfully.
  • The installation package was faulty and contained
    “/usr/lib/cmake/vtk-6.2/VTKTargets.cmake”
    but not all the files it references

这里参考文章https://www.icode9.com/content-4-1055883.html
输入

sudo ln -s /usr/bin/vtk6 /usr/bin/vtk

还有一个是

No package ‘metslib’ found

这里参考https://blog.csdn.net/yunluoxiaobin/article/details/103078386就可以成功啦。
最后一个估计不是谁都会碰到,就是

Could NOT find Boost (missing: iostreams) (found suitable version “1.58.0”, minimum required is “1.40.0”) Call Stack (most recent call first):

如果遇到了,重新按照https://blog.csdn.net/jzhd2015/article/details/108218350编译安装一下boos_1.58.0就好了。
在这里插入图片描述
出现这样的标志就代表cmake完成了。

  1. 我的版本还是不是很好,有一个.h文件会报错,是一个类型不匹配的错误。这样修改一下就好了(找到这个文件,我的是pcl/segmentation/include/pcl/segmentation/plane_cofficent_comparator.h,在144行的位置加一个*号即可:
    在这里插入图片描述
    成功截图:
    在这里插入图片描述

解决方法(Ceres)

在这里插入图片描述
参考链接http://ceres-solver.org/installation.html
没什么好多说的,按着来就行,没有vpn的附录有资源。make install时别忘了sudo。

但是!!!
再最后会出现冲突,参考博客https://blog.csdn.net/qq_41586768/article/details/107541917
所以大家可以试着去弄这个博客的东西。。。亲测可行,不需要最后 6.编译ceres_curve_fiiting也是可以的。

最后的最后

在整整折腾了近一周后,几乎每天满载负荷,终于出现了这个
在这里插入图片描述
终于在不懈的努力下,我完成了编译!!!!!!!!!!!!!!!!!!!
真的是太不容易了,文章中的每一个报错几乎都折腾了许久,每一个一笔带过的地方都折腾了十几分钟到几天不等。。。。。。而且很多编译都是两三个小时以上QAQ

然而这一切并不算完成,运行时依旧会出现问题,比如rviz,gzbol等等的安装。本人会在后续继续补充这些内容。感谢各位的关注。怕什么真理无穷,进一寸有一寸欢喜!!!

附录:
1.树莓派对应burst系统:https://download.csdn.net/download/weixin_46238869/85171752
5. 树莓派烧录软件:https://download.csdn.net/download/weixin_46238869/85171768
6. 树莓派连接软件putty:https://download.csdn.net/download/weixin_46238869/85171821
7. s树莓派连接软件vnc:https://download.csdn.net/download/weixin_46238869/85171786
8. 硬件演示视频:https://download.csdn.net/download/weixin_46238869/85171846
9. OpenCV缺失包,boost.zip:https://download.csdn.net/download/weixin_46238869/85171796
10. ceres-solver软件包:https://download.csdn.net/download/weixin_46238869/85179317

  • 3
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
树莓派4B ROS镜像是为树莓派4B开发的一种特定操作系统(Raspberry Pi 4B ROS Image),它包含了ROS(机器人操作系统)的所有必要组件和库,以便在树莓派上进行机器人相关的开发和项目。 ROS(机器人操作系统)是一个开源的、灵活的机器人软件平台,它提供了一系列工具、库和规范,用于构建机器人系统和应用。ROS支持多种编程语言,如C++和Python,并提供了一系列功能包,以支持机器人导航、感知、控制等任务。 树莓派4B ROS镜像为树莓派的用户提供了一个方便且易用的环境,以便开展机器人相关的项目。借助这个镜像,用户可以在树莓派上运行ROS并访问ROS的各种功能和库。此外,该镜像还预先安装了一些常用的ROS功能包,如导航功能包、感知功能包等,以提供更多的开发选项和启动点。 树莓派4B ROS镜像的安装非常简单,只需下载镜像文件,并将其烧录到SD卡上,然后将SD卡插入树莓派即可。一旦完成安装,用户就可以开始使用ROS进行机器人相关的开发,并利用树莓派4B的性能和GPIO接口来实现物理控制和交互。 总结来说,树莓派4B ROS镜像提供了一个方便、易用的环境,使得在树莓派上进行机器人相关的开发变得更加便捷。它为用户提供了ROS的所有必要组件和库,并预先安装了一些常用的ROS功能包,以帮助用户快速开始开发机器人应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值