实现ros多机通讯 / c++的一点/ slam for dummies杂项

本周主要学习内容是:ros系统的多机通信,运行pibot平台,学习c++第三章,学习Slam for Dummies文章。
ros是一种分布式的软件框架,所以能够进行主机与从机的分离。也就是说可以在一台或者多台计算机上运行ros系统并进行相互之间的通信,实现信息传输的作用。
**

1、实现多机通讯:

**
1)首先是要将需要通讯的两台或者多台电脑进行连接,这个实现是通过配置两台计算机的IP地址来实现的,配置命令是:sudo gedit /etc/hosts 在打开的文件中按照格式输入需要通讯的计算机的主机名以及IP地址,之后使用 ping+主机名 命令测试两台计算机的网络是否连通。
2)之后设置ros的主从机的配置,因为ros运行是有一个rosmaster也就是主机进行任务管理与资源分配的因此只能够有一个rosmaster,确定好两台计算机的主从机后使用命令 export ROS_MASTER_URI=http://主机名:11311(当前终端有效)或是echo“export ROS_MASTER_URI=http://主机名:11311”>>~/.bashrc(所有终端有效) 命令设置从机端的计算机,这是使从机能够找到rosmaster的所在。完成后可以使用一个小乌龟的例子进行验证。

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

进行了tf坐标的学习,头发坐标转换是ros系统中比较重要的,ros中常用的坐标变化主要有:odom、baselink、laserscan等,由于机器人处于世界坐标系中同时机器人自身会存在基于其本体的坐标,如odom是里程计所产生的的坐标系,lasescan是雷达扫描的坐标,如何将其转化为可以使用的世界坐标是非常重要的。ros中配备了专门的坐标转换功能包可以实现坐标转换。命令如下:

sudo apt-get install ros-kinetic-turtle-tf
roslaunch turtle_tf turtlr_tf_demo.launch

这两个命令分别是安装tf转换功能包和它提供的例程。
也可以自己编写tf坐标的发布和订阅,运行效果如下。程序是通过广播第一只乌龟的坐标使第二只乌龟能够根据第一只乌龟所在位置调整自己的位置从而达到跟随第一只乌龟运行,最终两只乌龟的tf坐标重合。

2、运行pibot

学习完ros的基本操作后,查看了pibot机器人平台的源码,并运行了平台机器人。pibot源码较多,且相互之间关系较为复杂,且大多数使用C++语言进行编程,所以决定查看C++的相关内容。
**

3、C++学习**

学习C++第三章怎样使用类和对象。了解类的构造,对象的构造。以及多种使用类的方式和对象使用方法,这些在程序中经常会用到。
1)利用构造函数对类对象进行初始化:
因为类并不是一个实体,而是一种抽象类型,并不占用存储空间,只有在定义了一个类对象时系统才会给其分配内存空间,所以不能够直接在类中初始化数据。但对于类中的public成员可以在定义对象时对其进行初始化,如 Time t1{14,56,30}.但是对于private和protected成员来说这种方法是不可行的。所以我们引入构造函数对其进行初始化。
构造函数的名字是与类同名,不能够任意命名。如一个类的名字是Time,则它的构造函数的名字必须为Time(),这是为了系统能够识别它,并把它作为构造函数处理。下面是几点注意:

  1. 构造函数是在建立类对象的时候被调用。每建立一个对象就调用一次构造函数
    2.构造函数由于只是对数据成员进行初始化,所以没有返回值,也就不需要有函数类型类似:int Time()是不对的,应该是不需要int函数类型符的。
    3.构造函数不需要用户调用,也不能够被用户调用。
    4.可以用一个类对象初始化另一个类对象。
    2)带有类参数的构造函数
    构造函数的声明: 构造函数名(类型1 形参1 , 类型2 形参2,…)
    定义对象的格式: 类名 对象名(实参1,实参2,…)
    参数初始化表对数据成员的初始化:
    类名::构造函数名(参数表)[:成员初始化表]{构造函数体}
    例子:
class Box:
{
public:
    Box();//声明一个无参构造函数
    Box(int h,int w,int len);//声明一个有参构造函数
    Box(int h,int w,int len):height(h),width(w),length(len){ }//定义一个有参数构造函数并使用参数初始化表对数据成员进行初始化
}
Box::Box()//类外定义无参构造函数
{
    height=10;
    width=10;
    length=20;
}
Box::Box(int h,int w,int len)//类外定义you参构造函数
{
    height=h;
    width=w;
    length=len;
}//这里还用到构造函数的重载

使用默认参数的构造函数与有参构造函数类似,只是在定义时直接给形参赋予初值
Box(int h=10,int w=10,int len=10);

3)对象数组
当所需要的对象很多时使用定义对象的方法会使得对象名复杂,程序可读性降低,所以建立对象数组,将所要用到的对象在一个数组中说明和定义,使得程序简单,以一个例子说明:
定义一个含有三个构造函数的数组:
Student stud[3]={Student(1001,18,87),//调用第一个元素的构造函数,向它提供3个实参
Student(1002,18,87),
Student(1003,18,87),
};

4)对象指针
定义指向对象的指针: 类名 *对象指针名
Time *pt;
Time t1;
pt=&t1;
(*pt).hour;
pt->hour;
(*pt).get_time()
pt->get_time()

定义指向对象数据成员的指针: 数据类型名 *指针类型名
int *p1;
p1=&t1.hour;

定义指向对象成员函数的指针: 数据类型名(类名::*指针变量名)(参数表列)
void (Time::*p2)();//定义p2为指向Time类中公用成员函数的指针变量
p2=&Time::get_time;

使指针指向一个公用成员函数的一般形式: 指针变量名=&类名::成员函数名;
5)共用数据的保护
定义常对象的一般格式: 类名 const 对象名(实参表);或是const 类名 对象名;
常对象必须有初值
如果一个对象被声明为常对象,则该对象只能调用它的常成员函数,而不能调用该对象的普通成员函数
常成员函数可以访问常对象中的数据成员,但不允许修改常对象中的数据成员。
常对象成员
常数据成员:const 数据类型 变量名;
只能通过构造函数的初始化表对数据成员进行初始化
常成员函数:类型名 函数名(参数表) const;
将成员函数声明为常成员函数,则只能引用本类中的数据成员,而不能修改他们。
指向对象的常指针: 类名 * const 指针变量名;eg:Time * const ptr; ptr=&t1;
指向对象的常指针在指定对象后不能修改其指向,但是可以修改指向对象的值
指向常对象的指针变量:const 类型名 * 指针变量名
指向对象的常指针在指定对象后能修改其指向,但是不可以修改指向对象的值
const Time *p=&t1;
p=&t2;//可以更改指向对象
p->hour=18;//错误,常对象指针在使用过程中是不允许修改对象的值的

**

4、Slam for Dummies

**
Slam for dummies 主要介绍了SLAM入门所涉及到的内容,讲解了整个slam过程是如何运行的,以及所涉及到的激光雷达数据与里程计数据的融合EKF算法,还有特征提取算法Spike算法和RANSAC算法(随机抽样一致性算法),并给出了特征提取算法的程序。文章详细介绍了关于EKF过程中的所用到的矩阵的具体含义以及构造过程,之后根据这些矩阵进行了EKF数据滤波计算,将整个机器人使用融合算法进行位置估计的方法介绍的比较详细。下图是文章中介绍的slam过程的概述图
在这里插入图片描述
Spike算法是通过提取物体的极值来寻找特征。通过找到两个激光数据值之差大于某一个阈值来决定选取的特征点。还有一种就是在ABC三个值,用AC分别减去B然后再相加得到的值作为确定特征的方法。当该值大于某一设定值时,确定B为特征点。该方法比之前的方法更能够确定极值,而不是驻点。但是上述的两种Spike方法在比较光滑的环境下会失效。
RANSAN (Random Sampling Consensus)方法是通过提取雷达扫描数据的线来确定特征。它通过随机提取激光雷达数据样本然后采用最小二乘法寻找最优拟合线。然后该算法检测有多少点落在了这条直线上,如果大于某一阈值则认为是扫描到一条线。这个阈值就叫做一致(Consensus)。
流程如下:

While 
         依旧没有关联的雷达数据点
         读取的数据点大于一致性阈值
         执行次数少于N次
         选择随机雷达数据读取

         在D度范围内随机采样S个点(例如 在十度的范围内随机选择5个读取的雷达数据)

         使用采样到的S个激光点计算最小二乘拟合线

         确定在最优拟合线上面有多少的激光雷达点

         如果点数大于一致性阈值C,则:

               计算新的最小二乘最佳拟合线基于所有激光读数确定位于旧的最佳拟合线。

              将这个最佳拟合线添加到我们提取的线中

              将横线上的读数从所有未关联的读数中移除。

End

EKF实现假定地标是从机器人位置开始的范围和方位。我们可以很容易地把一条直线转换成一个不动点,方法是在世界坐标中取另一个不动点,然后计算离这个不动点最近的直线上的点。利用机器人的位置和这个定点在直线上的位置,从这个位置计算一个距离和方位是很简单的。
用简单的三角函数就可以很容易地计算出这一点。这里用原点作为定点来说明:

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值