本制作采用了:上位机----tx2(ubuntu16.04)
下位机----Arduino 2560
传感器-----思岚rplidar A2
代码见:https://github.com/crjxixixi/cleaner_robot1.git
现在主要对自己的上位机代码进行一些解释:
一、建图
建立地图的方式有两种:gmapping算法与 hector算法
区别:Gmapping 算法在建立地图时需要机器人雷达的扫描信息与里程计信息
Hector 算法只需要机器人的雷达扫描信息
本实验采取的是hector进行建图:
(1)准备工作:安装hector_slam库
sudo apt-get install ros-kinetic-hector-slam
(2) 创建 hector.launch(本代码在/src/mrobot_navigation/launch)
<launch>
<node pkg="hector_mapping" type="hector_mapping" name="hector_mapping" output="screen">
<!-- Frame names -->
<param name="pub_map_odom_transform" value="true"/>
<param name="map_frame" value="map" />
<param name="base_frame" value="base_link" />
<param name="odom_frame" value="base_link" />
<!-- Tf use -->
<param name="use_tf_scan_transformation" value="true"/>
<param name="use_tf_pose_start_estimate" value="false"/>
<!-- Map size / start point -->
<param name="map_resolution" value="0.05"/>
<param name="map_size" value="512"/>
<param name="map_start_x" value="0.5"/>
<param name="map_start_y" value="0.5" />
<param name="laser_z_min_value" value = "-1.0" />
<param name="laser_z_max_value" value = "1.0" />
<param name="map_multi_res_levels" value="2" />
<param name="map_pub_period" value="2" />
<param name="laser_min_dist" value="0.4" />
<param name="laser_max_dist" value="5.5" />
<param name="output_timing" value="false" />
<param name="pub_map_scanmatch_transform" value="true" />
<!--<param name="tf_map_scanmatch_transform_frame_name" value="scanmatcher_frame" />-->
<!-- Map update parameters -->
<param name="update_factor_free" value="0.4"/>
<param name="update_factor_occupied" value="0.7" />
<param name="map_update_distance_thresh" value="0.2"/>
<param name="map_update_angle_thresh" value="0.06" />
<!-- Advertising config -->
<param name="advertise_map_service" value="true"/>
<param name="scan_subscriber_queue_size" value="5"/>
<param name="scan_topic" value="scan"/>
</node>
<node pkg="tf" type="static_transform_publisher" name="base_to_laser_broadcaster" args="0 0 0 0 0 0 /base_link /laser 100"/>
<node pkg="rviz" type="rviz" name="rviz"
args="-d $(find hector_slam_launch)/rviz_cfg/mapping_demo.rviz"/>
</launch>
若遇到有不能启动则根据提示安装相应的包就可运行,随着机器人的移动可以在rviz可视化界面中看到你的栅格地图构建的情况。
(3)地图保存
在地图保存之前,需要安装map_server包,在终端中输入:
sudo apt-get install ros-kinetic-map-server
然后,保存图形:
rosrun map_server map_saver -f ~/my_map
~处可以修改为你要存放的地址,本操作将地址保存在根目录下。
二、导航
由于每个人的机器人外形都不相同,大家可以自己去编写适合自己机器人的urdf,大家可以参考 urdf古月居
在本实验中,由于下位机是采取的Arduino,则在开发时可以将Arduino定义为一个结点来收发话题,从而方便开发(若使用的是stm32进行开发的则需要自己编写串口通信)
1.准备工作
(1)若想要学习如何将Arduino定义为一个结点的大家可以到创客智造中找到相应的教程:
https://www.ncnynl.com/archives/201701/1215.html
(2)Arduino IDE的安装
可以参考教程:https://jingyan.baidu.com/article/219f4bf7e45df3de442d388e.html
(3)ROS相应的导航包安装
2.编写相应的launch文件(可见代码/src/mrobot_navigation/mrobot_nav.launch)
<launch>
<param name="use_sim_time" value="false" />
<arg name="use_map_topic" default="false"/>
<arg name="scan_topic" default="scan"/>
<!-- 配置雷达 -->
<node name="rplidarNode" pkg="rplidar_ros" type="rplidarNode" output="screen">
<param name="serial_port" type="string" value="/dev/ttyUSB0"/>
<param name="serial_baudrate" type="int" value="115200"/>
<param name="frame_id" type="string" value="laser"/>
<param name="inverted" type="bool" value="false"/>
<param name="angle_compensate" type="bool" value="true"/>
</node>
<!--地图信息-->
<arg name="map_file" default="/home/xt/my_map.yaml"/>
<node name="map_server" pkg="map_server" type="map_server" args="$(arg map_file)" />
<!--机器人 move_base -->
<node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen" clear_params="false">
<rosparam file="$(find mrobot_navigation)/config/mrobot1/costmap_common_params.yaml" command="load" ns="global_costmap" />
<rosparam file="$(find mrobot_navigation)/config/mrobot1/costmap_common_params.yaml" command="load" ns="local_costmap" />
<rosparam file="$(find mrobot_navigation)/config/mrobot1/local_costmap_params.yaml" command="load" />
<rosparam file="$(find mrobot_navigation)/config/mrobot1/global_costmap_params.yaml" command="load" />
<rosparam file="$(find mrobot_navigation)/config/mrobot1/base_local_planner_params.yaml" command="load" />
</node>
<include file="$(find mrobot_navigation)/launch/amcl.launch" />
<!-- 设置坐标-->
<node pkg="tf" type="static_transform_publisher" name="base_link_to_laser" args="0.0 0.0 0.0 0.0 0.0 0.0 /base_link /laser 40" />
<!-- 运行rviz -->
<node pkg="rviz" type="rviz" name="rviz" args="-d $(find mrobot_navigation)/rviz/nav.rviz"/>
</launch>
根据自己的传感器进行相应的配置,本实验中用的是思岚的rplidar A2雷达,所以该launch文件首先对雷达进行了配置
< laser >
<node name="rplidarNode" pkg="rplidar_ros" type="rplidarNode" output="screen">
<param name="serial_port" type="string" value="/dev/ttyUSB0"/>
<param name="serial_baudrate" type="int" value="115200"/>
<param name="frame_id" type="string" value="laser"/>
<param name="inverted" type="bool" value="false"/>
<param name="angle_compensate" type="bool" value="true"/>
设置雷达的串口号、波特率等一些参数,在使用雷达的时候需要给串口权限(根据自己的串口号),本实验中用的是ttyUSB0则给权限如下:
sudo chmod 777 /dev/ttyUSB0
接着加载你刚建好的地图信息:
< map >
<arg name="map_file" default="/home/xt/my_map.yaml"/>
<node name="map_server" pkg="map_server" type="map_server" args="$(arg map_file)" />
将default后面的参数为你地图所在的路径
< move_base > 主要配置机器人的移动时的一些参数(如速度、避障、地图膨胀、路径规划算法)等
<node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen" clear_params="false">
<rosparam file="$(find mrobot_navigation)/config/mrobot1/costmap_common_params.yaml" command="load" ns="global_costmap" />
<rosparam file="$(find mrobot_navigation)/config/mrobot1/costmap_common_params.yaml" command="load" ns="local_costmap" />
<rosparam file="$(find mrobot_navigation)/config/mrobot1/local_costmap_params.yaml" command="load" />
<rosparam file="$(find mrobot_navigation)/config/mrobot1/global_costmap_params.yaml" command="load" />
<rosparam file="$(find mrobot_navigation)/config/mrobot1/base_local_planner_params.yaml" command="load" />
</node>
</node>
其中base_local_planner_params.yaml、costmap_common_params.yaml、global_costmap_params.yaml、local_costmap_params.yaml文件各参数的配置及其各参数的含义可以看此教程https://www.guyuehome.com/28164
< amcl >
<node pkg="amcl" type="amcl" name="amcl" clear_params="true">
<param name="use_map_topic" value="$(arg use_map_topic)"/>
<!-- translation std dev, m -->
<param name="global_frame_id" value="/map" />
<param name="initial_pose_x" value="0.0"/>
<param name="initial_pose_y" value="0.0"/>
<param name="initial_pose_a" value="0.0"/>
<param name="initial_cov_xx" value="0.5*0.5"/>
<param name="initial_cov_yy" value="0.5*0.5"/>
<param name="initial_cov_aa" value="(π/12)*(π/12)"/>
<param name="odom_alpha3" value="0.2"/>
<param name="odom_alpha4" value="0.2"/>
<param name="laser_z_hit" value="0.5"/>
<param name="laser_z_short" value="0.05"/>
<param name="laser_z_max" value="0.05"/>
<param name="laser_z_rand" value="0.5"/>
<param name="laser_sigma_hit" value="0.2"/>
<param name="laser_lambda_short" value="0.1"/>
<param name="laser_model_type" value="likelihood_field"/>
<param name="initial_pose_x" value="0.0"/>
<param name="odom_model_type" value="diff"/>
<param name="odom_alpha5" value="0.1"/>
<param name="gui_publish_rate" value="10.0"/>
<param name="laser_max_beams" value="60"/>
<param name="laser_max_range" value="12.0"/>
<param name="min_particles" value="500"/>
<param name="max_particles" value="2000"/>
<param name="kld_err" value="0.05"/>
<param name="kld_z" value="0.99"/>
<param name="odom_alpha1" value="0.2"/>
<param name="odom_alpha2" value="0.2"/>
<!-- <param name="laser_model_type" value="beam"/> -->
<param name="laser_likelihood_max_dist" value="2.0"/>
<param name="update_min_d" value="0.25"/>
<param name="update_min_a" value="0.2"/>
<param name="odom_frame_id" value="odom"/>
<param name="base_frame_id" value="base_link"/>
<param name="resample_interval" value="1"/>
<!-- Increase tolerance because the computer can get quite busy -->
<param name="transform_tolerance" value="1.0"/>
<param name="recovery_alpha_slow" value="1.0"/>
<param name="recovery_alpha_fast" value="0.0"/>
<remap from="scan" to="$(arg scan_topic)"/>
</node>
此结点是用于发布机器人的定位信息的功能,详细情况可以参考:http://wiki.ros.org/amcl,大致来说,amcl需要订阅机器人的消息有 1.传感器的信息 2.tf变换 3.地图信息 4.机器人的初始位置,从而通过这些信息来发布 1.机器人的位姿 2.粒子云 3./tf变换(/map–>/odom),这样机器人就能实时的掌握自己所处的位置,并通过mover_base来进行导航。
< rviz >
<node pkg="rviz" type="rviz" name="rviz" args="-d $(find mrobot_navigation)/rviz/nav.rviz"/>
打开rviz可视化工具可以看到机器人在地图上的位置,与导航算法所规划出来的路径。
2.导航操作
导航前需要使用2D Post estimate对机器人位姿进行初始化,使得机器人雷达扫描点与之前所建地图尽可能重合。初始点的好坏对机器人导航效果有着一定的影响。
使用2D NAV Goal点击地图即可为机器人设置导航目标点,机器人会自动规划出行进路线,机器人会循着路径到达设置的地点。