【ROS栅格地图&节点发布地图示例&初识SLAM】

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


一、栅格地图

栅格地图的使用:
nav_msgs::OccupancyGrid中的/map话题
在nav_msgs::OccupancyGrid消息包中栅格地图是以数组的形式表达的;

可以在index.ros.org官网搜索map_server节点查看对应信息
关于地图的描述:
栅格地图里的数据都是int8类型的数据,按照行优先顺序,从栅格矩阵的(0,0)位置开始排列(栅格地图的左下角为起点);
栅格里的障碍物占据值的取值是从0到100,如果栅格里的障碍物状况未知,则栅格数值为-1;

地图的相关信息内容:
time_map load_time地图的加载时间
float32 resolution地图分辨率
uint32 width地图的长度
uint32 height地图的高度
geometry_msgs/Pose origin地图的原点位置

二、发布栅格地图

发布2X4(两行四列)的地图:
1.构建一个软件包map_pkg,依赖项里加上nav_msgs;
cd catkin_ws/src/
catkin_create_pkg map_pkg rospy roscpp nav_msgs
2.在map_pkg里创建map_pub_node节点;
3.在节点中发布话题/map,消息类型为nav_msgs::OccupancyGrid;
4.构建一个地图消息包nav_OccupancyGrid,并对其赋值;
5.将地图消息包发送到话题/map;

#include <ros/ros.h>
#include <nav_msgs/OccupancyGrid.h>

int main(int argc, char *argv[]) 
{
    
    
    ros::init(argc, argv, "map_pub_node");
    ros::NodeHandle nh;
    ros::Publisher map_pub = nh.advertise<nav_msgs::OccupancyGrid>("/map", 10);
   
    ros::Rate r(1); // publish at 10 Hz
    while (ros::ok()) 
    {
    
    
        nav_msgs::OccupancyGrid map;
        map.header.frame_id = "map";//坐标系id
        map.header.stamp = ros::Time::now(); // current time

        map.info.resolution = 1.0; // 地图分辨率
        map.info.width = 4; // number of cells in the x direction
        map.info.height = 2; // number of cells in the y direction

        map.data.resize(map.info.width * map.info.height); // allocate memory for map data
        map.data[0] = 100; 
        map.data[1] = 100; // cell 1 is occupied
        map.data[2] = 0; // cell 2 is free
        map.data[3] = 0; 
        map.data[4] = -1; // cell 3 is unknown

        // map.info.origin.position.x = 0;
        // map.info.origin.position.y = 0;
        // map.info.origin.orientation.w = 1.0;
        map_pub.publish(map);
        r.sleep();
    }

    return 0;
}

6.设置编译规则;

# add_executable(${
      
      PROJECT_NAME}_node src/map_pkg_node.cpp)
# target_link_libraries(${
      
      PROJECT_NAME}_node
#   ${
    
    catkin_LIBRARIES}
# )

复制到CmakeLists.txt文件末尾,修改如下:

add_executable(map_pub_node src/map_pub_node.cpp)
target_link_libraries(map_pub_node
  ${
    
    catkin_LIBRARIES}
)

7.编译运行节点;
cd catkin_ws/
catkin_make

启动ros
roscore
运行节点
rosrun map_pkg map_pub_node
运行rviz
rviz

8.启动RViz,订阅话题/map,显示地图;

确定地图原点:
1.在rviz界面添加一个坐标系标识
ADD-Axes
标识的位置即世界坐标系的原点
在这里插入图片描述2.添加地图显示
ADD-Map
将地图的话题设置成本章发布的话题/map
在这里插入图片描述在这里插入图片描述地图的标号如下:
[4] [5] [6] [7]
[0] [1] [2] [3]
对照下列赋值(100表示有障碍物,-1表示未知,0表示空白区域)
map.data[0] = 100;
map.data[1] = 100; // cell 1 is occupied
map.data[2] = 0; // cell 2 is free
map.data[3] = 0;
map.data[4] = -1; // cell 3 is unknown

三、初识SLAM

激光雷达发布/scan话题,SLAM节点(hector_mapping)只需要订阅该话题即可获取雷达测距数值,之后SLAM节点发布地图数据话题/map,使用rviz即可显示地图的形状。

关于hector_mapping

在index.ros.org官网可以搜索查看具体信息;
其订阅了如下话题:
/scan (sensor_msgs/LaserScan)
/syscommand (std_msgs/String,主要用来接收重新建图的指令)
其发布了如下话题:
/map_metadata(nav_msgs/String)地图数据描述信息:
time map_load_time地图加载时间
float32 resolution地图分辨率
uint32 width、height地图宽度、地图高度
geometry_msgs/Pose origin

/map(nav_msgs/OccupancyGrid)栅格地图数据

/slam_out_pose(geometry_msgs/PoseStamped)原始机器人定位信息

/poseupdate(geometry_msgs/PoseWithCovarianceStamped)矫正后的机器人定位信息

体验hector_mapping

安装hector(前面安装过wpr_simulation,默认已经安装好了hecor,如果没有就执行下列指令)
sudo apt install ros-noetic-hector-mapping

运行slam仿真环境
roslaunch wpr_simulation wpb_stage_slam.launch

运行SLAM节点(软件包名称和节点名称都是hector_mapping)
rosrun hector_mapping hector_mapping

打开rviz
直接输入rviz也行
rosrun rviz rviz

在rviz中添加机器人模型
ADD-RobotModel

在rviz中添加激光雷达的扫描测距点
在这里插入图片描述
此外激光雷达需要发布/scan话题
在这里插入图片描述
测距不明显,调节测距点大小
在这里插入图片描述
在rviz界面添加地图
ADD-Map
在这里插入图片描述
利用rqt_robot_steering工具让机器人动起来,观测地图构建过程;
rosrun rqt_robot_steering rqt_robot_steering
在这里插入图片描述

launch文件的使用

为了方便后续的调试,这里可以编写launch文件:
cd catkin_ws/src/
catkin_create_pkg slam_pkg roscpp rospy std_msgs

打开vscode,在上述slam_pkg文件中创建launch文件夹
在launch文件夹中新建一个文件:hector.launch
将下列指令按照.launch文件的语法写入hector.launch
roslaunch wpr_simulation wpb_stage_slam.launch
rosrun hector_mapping hector_mapping
rosrun rviz rviz
rosrun rqt_robot_steering rqt_robot_steering

这里可以使用rospack指令获取软件包的完整路径

<launch>

    <include file="$(find wpr_simulation)/launch/wpb_stage_slam.launch"/>
    <node pkg="hector_mapping" type="hector_mapping" name="hector_mapping"/>
    <node pkg="rviz" type="rviz" name="rviz"/>
    <node pkg="rqt_robot_steering" type="rqt_robot_steering" name="rqt_robot_steering"/>
    
</launch>

(编译后)启用上述节点
roslaunch slam_pkg hector.launch

rviz配置的保存与调用

rivz每次配置都比较麻烦,可以将rviz的显示设置保存为文件;
点击左上角的File-Save Config As
将配置文件保存到上述新建的slam_pkg里(单独新建一个rviz文件存放配置)
文件名称取:slam.rviz
在这里插入图片描述检查配置文件是否正确
关闭rviz,输入指令
rosrun rviz rviz -d /home/robot/catkin_ws/src/slam_pkg/rviz/slam.rviz

将配置文件写入launch文件中

<launch>

    <include file="$(find wpr_simulation)/launch/wpb_stage_slam.launch"/>
    <node pkg="hector_mapping" type="hector_mapping" name="hector_mapping"/>
    <node pkg="rviz" type="rviz" name="rviz" args="-d $(find slam_pkg)/rviz/slam.rviz"/>
    <node pkg="rqt_robot_steering" type="rqt_robot_steering" name="rqt_robot_steering"/>

</launch>

运行
roslaunch slam_pkg hector.launch
发现配置成功倒入进来了
在这里插入图片描述
如果是在实体机器人上运行Hector_Mapping,只需要将

<include file="$(find wpr_simulation)/launch/wpb_stage_slam.launch"/>

其中的wpb_stage_slam替换成启动实体机器人激光雷达和底盘控制的launch文件即可;
或者只启动激光雷达推动机器人建图;


总结

简单介绍了栅格地图,发布了简单的栅格地图,简单体验了SLAM的建图功能。

猜你喜欢

转载自blog.csdn.net/weixin_46187287/article/details/143353134