【无标题】

博主会从以下几个大的步骤来逐步分解导航过程,教你手把手搭建导航内容

零部件的准备----------代码包讲解(cv工程师快速上手)----------数学层面原理讲解----------整体参数调试

架构思路

零部件的准备----------ubuntu操作系统,ROS环境搭建----------使用手柄进行遥控操作小车----------各个部件调试配置----------gmapping算法建图----------导航搭建
这里我们第一讲讲过了零部件的准备,其实准备什么零部件并不重要。但是各部位的东西你基本都要有,现在基本的几个大件你都有,那就可以开始搞了,我这里使用S1激光雷达作为我自己用的包
操作系统和ros环境网上一大堆教程,这个你都搞不定就别看这个了
初学者直接拿到代码跑起来再学是最快的了这里我直接提供一个基础的能够让你建图和导航都跑起来的框架就可以直接使用了

代码使用条件

1.up的tf变换如果你没有imu/雷达基于小车均是静态变换(简单来说就是imu和雷达都是固定在小车上的),如果是动态变换,那说明你的工作也比较进阶了,那也不需要看基础向的文章了
2.odom的部分我会详细介绍的,odom对于新手来说就是灵魂,建图算法,导航算法你都可以ros白嫖,但是odom绝对是你要自己量身定制的,你可以在我提供的基础上面修改,我的只适合新手,只适合新手,只适合新手,但是我会详细教你怎么改。

代码介绍

这个部分介绍一下:

请添加图片描述
最终的结果以该tf树为目标(不明白tf树的也没关系,这是个常用工具,描述转换关系的,这部分可以上网了解一下,我可能后面会更新)
在这里插入图片描述

一共有三个包组成,剩下的文件是使用方式,后面会贴出来一部分

car_slam建图包:

请添加图片描述
直接使用launch文件调用gmapping或cartographer,后续代码举例以gmapping为例
gmapping这个包ros已经给我们提供了,我们的第一目的是先把它用起来,你可以把gmapping理解成一个黑盒,我们给它提供一些东西,它给我们建图
gmapping主要就是需要雷达的输入,这里一共涉及两个部分:

一.雷达相对小车的位置(因为移动的主体是小车:

我们提到的静态tf我们一般都是在功能包中实现(导航或者建图这种就叫功能包)这里我们实现一下:
这里共计两个tf变换,分别是描述imu—>小车,激光雷达—>小车之间的静态变换关系(args=后面的参数自己查一下对照一下,如果你跟我一样都在小车的中心点,参数你可以跟我一样都写0)

static_tf.launch(这个名字后面其他文件会引用)

<launch>
    <!--tf transform declare-->
    <!-- 根据自己的传感器安装方式修改静态坐标转换的参数 -->
    <node name="laser_to_base_link" pkg="tf2_ros" type="static_transform_publisher" args="0.0 0.0 0.0 0 0 0 base_link laser_link" />
    
    <!--无IMU的情况,下面这句话注释-->
    <node name="imu_to_base_link" pkg="tf2_ros" type="static_transform_publisher" args="0.0 0.0 0.0 0 0 0 base_link imu_link " />

</launch>
二.雷达的话题输入

然后我们实现gmapping包用的launch文件,这个文件主要是用于提前设置参数,参数的部分我都给你们预写好了,参数基本都注释了,我就不详细介绍了,有不明白的可以百度一下,这些参数后面我们介绍gmapping的实现的时候也会用到(这里主要修改上面的几个topic,我这里用的都是默认值,一般不会改的)------scan_topic/base_frame/odom_frame 这三个值

gmapping.launch(这个名字后面其他文件会引用)

<launch>
    <param name="use_sim_time" value="false"/>   <!-- 是否是仿真环境 -->

    <arg name="scan_topic"  default="scan" />          
    <arg name="base_frame"  default="base_link" />   <!-- 车身坐标系名称 --> 
    <arg name="odom_frame"  default="odom" />        <!-- 里程计odom坐标系名称-->

    <node pkg="gmapping" type="slam_gmapping" name="slam_gmapping" output="screen">

      <remap from="scan" to="scan"/>
      <param name="base_frame" value="$(arg base_frame)"/>
      <param name="odom_frame" value="$(arg odom_frame)"/>

      <param name="map_update_interval" value="5.0"/>  <!-- 地图更新时间间隔 -->
      <param name="maxUrange" value="12.0"/>   <!-- 激光雷达最大扫描距离,改为自己的lidar范围-->
      <param name="sigma" value="0.05"/>
      <param name="kernelSize" value="1"/>
      <param name="lstep" value="0.05"/>
      <param name="astep" value="0.05"/>
      <param name="iterations" value="5"/>
      <param name="lsigma" value="0.075"/>
      <param name="ogain" value="3.0"/>
      <param name="lskip" value="0"/>
      <!-- 里程计相关权重 -->
      <param name="srr" value="0.1"/><!-- 平移误差做为平移函数的入参 --> 
      <param name="srt" value="0.2"/><!-- 平移误差作为旋转函数的入参 -->
      <param name="str" value="0.1"/><!-- 旋转误差做为平移函数的入参 -->
      <param name="stt" value="0.2"/><!-- 旋转误差做为旋转函数的入参 -->
      
      <param name="linearUpdate" value="1.0"/> <!-- 机器人走了多远就扫描一次 -->
      <param name="angularUpdate" value="0.5"/>
      <param name="temporalUpdate" value="3.0"/>
      <param name="resampleThreshold" value="0.5"/><!-- 重采样门限 -->
      <!-- 滤波器中粒子的数目 -->
      <param name="particles" value="30"/>
      <!-- 地图初始尺寸大小 -->
      <param name="xmin" value="-50.0"/>
      <param name="ymin" value="-50.0"/>
      <param name="xmax" value="50.0"/>
      <param name="ymax" value="50.0"/>
      <!-- 地图分辨率 -->
      <param name="delta" value="0.05"/>

      <param name="llsamplerange" value="0.01"/><!-- 用于似然概率的平移采样距离 --> 
      <param name="llsamplestep" value="0.01"/><!-- 用于似然概率的平移采样步长 --> 
      <param name="lasamplerange" value="0.005"/><!-- 用于似然概率的角度采样距离 --> 
      <param name="lasamplestep" value="0.005"/><!-- 用于似然概率的角度采样步长 --> 
    </node>
</launch>
二.gmapping一键启动制作

这个部分主要就是把gmapping调度起来,把我们上面写的launch文件串起来,方便一点。

start_gmapping.launch

<launch>

    <!--static TF-->
    <include file="$(find car_slam)/launch/static_tf.launch" />
    <!-- launch gmapping node-->
    <include file="$(find car_slam)/launch/gmapping.launch" />
    
</launch>

car_odom 重中之重/前期代码的灵魂实现odom话题

gmapping订阅的是/scan 和/tf话题并不直接订阅里程计信息,我们需要自己写一个tf话题来表达里程计信息----odom。

odom_topic话题介绍

odom和odom_topic要做好区分
一个是坐标系,一个是根据编码器(或者视觉等)计算的里程计,两者有点关系不要混淆

一句话介绍版本:odom_topic描述了小车的运动状态
详细介绍版本:
odom 坐标系是一个世界固定坐标系。在odom 坐标系中移动平台的位姿可以任意移动,没有任何界限。这种移动使得odom 坐标系不能作为长期的全局参考。然而,在odom 坐标系中的机器人的姿态能够保证是连续的,这意味着在odom 坐标系中的移动平台的姿态总是平滑变化,没有跳变。
在一个典型设置中,odom 坐标系是基于测距源来计算的,如车轮里程计,视觉里程计或惯性测量单元。
odom 坐标系作为一种精确,作为短期的本地参考是很有用的,但偏移使得它不能作为长期参考,这里要区分开odom topic,这是两个概念,一个是坐标系,一个是根据编码器(或者视觉等)计算的里程计。但是两者也有关系,odom topic 转化得位姿矩阵是odom–>base_link的tf关系。这时可有会有疑问,odom和map坐标系是不是重合的?(这也是我写这个博客解决的主要问题)可以很肯定的告诉你,机器人运动开始是重合的。但是,随着时间的推移是不重合的,而出现的偏差就是里程计的累积误差。那map–>odom的tf怎么得到?就是在一些校正传感器合作校正的package比如gmapping会给出一个位置估计(localization),这可以得到map–>base_link的tf,所以估计位置和里程计位置的偏差也就是odom与map的坐标系偏差。所以,如果你的odom计算没有错误,那么map–>odom的tf就是0.

odom_topic如何实现

一般网上的教程都需要一个订阅者一个发布者(订阅和发布不明白的自己百度一下)
订阅者A:通常情况用于测试里程计的发布信息
发布者A:里程计的发布信息,通常与底层密切相连,直接接收底层的编码器数据转换成速度数据发布
里程计的信息格式是固定的,必须直接使用nav_msgs/Odometry消息格式进行发布
这里我们还需要实现:
订阅者B:用于订阅外来输入控制小车移动的信号{比如手柄控制小车移动或者后期使用导航控制小车移动},该部分也与底层密切相连,直接向底层发信息控制小车移动
代码部分基础玩家可以参考这里,介绍了最基础的发布A和订阅A:

https://blog.csdn.net/Cloud_H/article/details/125442783

我的odom代码直接在代码包中实现了(太长了就不展示了)
我这里一共实现了两个脚本,代码包文章结尾可以下载
fabuodom.cpp实现了发布者A和订阅者B
dingyueodom.cpp实现了订阅者A

在这里插入图片描述

我的代码没有编译部分,拿到以后可能需要自己编译,当然你也可以找我

car_nav导航包:

没写完后续更新

代码链接

链接:https://pan.baidu.com/s/1AqWFVh5QwscrOzhbTpWU8w?pwd=4we1 提取码:4we1

博主分享的代码是自己实现的代码,不含编译部分(这个部分有问题你可以自己解决,你也可以找我付费解决)
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值