前言
上几篇博客完成了这个基于旭日X3作为主控的两轮差速车的里程计,上位机底层文件的编写等等,是为了最终实现这个导航做的基础准备,完成了之前的步骤,便可以正式进入建图和导航了。如图可以见到该车主控为旭日X3,且连接到了32单片机进行通信,不过还没有完全组装好,会显得有点简陋哈哈。
正文
关于ROS的建图和导航详细描述和介绍,大家可以 ROS WIKI中详细了解和学习,这里就不过多的进行介绍了。
流程实现
在跑功能包之前,我们需要配置一下主从机,因为小车载着旭日X3跑时,我们想要可视化,或者发一些话题、命令,是无法直接控制终端的,这时要想实现上述功能就需要进行主从机配置,这样小车的主控作为主机,我们的电脑作为从机,可以实现从机向主机发送命令,远程可视化等等。
我这里由于是远程调试,所以先在从机用ssh连接到了主机,即旭日X3
使用ssh需要获取旭日X3的IP地址,使用ifconfig便可查看
然后使用ssh进行远程连接,命令是ssh+主机名@主机IP地址
那这里由于是旭日X3派,所以主机名为sunrise,IP为192.168.1.110。
然后在该终端打开主机bashrc文件
sudo vi ~/.bashrc
sudo vi ~/.bashrc
然后在末尾添加:
export ROS_HOSTNAME=主机HOSTNAME
export ROS_MASTER_URI=http://主机IP:11311
export ROS_IP=主机IP
export ROS_HOSTNAME=主机HOSTNAME export ROS_MASTER_URI=http://主机IP:11311 export ROS_IP=主机IP
然后新建终端打开从机bashrc文件
export ROS_HOSTNAME=从机HOSTNAME
export ROS_MASTER_URI=http://主机IP:11311
export ROS_IP=主机IP
export ROS_HOSTNAME=从机HOSTNAME export ROS_MASTER_URI=http://主机IP:11311 export ROS_IP=主机IP
然后修改/etc/hosts文件
主机添加:
从机IP 从机hostname
从机IP 从机hostname
从机添加:
主机IP 主机hostname
主机IP 主机hostname
完成之后便可以远程调用啦。
建图和导航实现
1.由于我这里是差速车,所以我在旭日X3派创建了一个名为diff_car_ws的工作空间,编译一下
mkdir -p diff_car_ws/src
cd diff_car_ws/
catkin_make
mkdir -p diff_car_ws/src cd diff_car_ws/ catkin_make
mkdir -p diff_car_ws/src cd diff_car_ws/ catkin_make
mkdir -p diff_car_ws/src cd diff_car_ws/ catkin_make
复制
mkdir -p diff_car_ws/src cd diff_car_ws/ catkin_make
mkdir -p diff_car_ws/src cd diff_car_ws/ catkin_make
mkdir -p diff_car_ws/src cd diff_car_ws/ catkin_make
2.创建小车底层功能包car_base和建图功能包car_mapping,再编译一下确保没有问题。
cd src
catkin_create_pkg car_base std_msgs roscpp tf geometry_msgs nav_msgs
catkin_create_pkg car_mapping std_msgs roscpp tf geometry_msgs nav_msgs
cd ..
catkin_make
cd src catkin_create_pkg car_base std_msgs roscpp tf geometry_msgs nav_msgs catkin_create_pkg car_mapping std_msgs roscpp tf geometry_msgs nav_msgs cd .. catkin_make
cd src catkin_create_pkg car_base std_msgs roscpp tf geometry_msgs nav_msgs catkin_create_pkg car_mapping std_msgs roscpp tf geometry_msgs nav_msgs cd .. catkin_make
cd src catkin_create_pkg car_base std_msgs roscpp tf geometry_msgs nav_msgs catkin_create_pkg car_mapping std_msgs roscpp tf geometry_msgs nav_msgs cd .. catkin_make
复制
cd src catkin_create_pkg car_base std_msgs roscpp tf geometry_msgs nav_msgs catkin_create_pkg car_mapping std_msgs roscpp tf geometry_msgs nav_msgs cd .. catkin_make
cd src catkin_create_pkg car_base std_msgs roscpp tf geometry_msgs nav_msgs catkin_create_pkg car_mapping std_msgs roscpp tf geometry_msgs nav_msgs cd .. catkin_make
3.使用hector建图算法进行建图
在用hector之前需要提前进行安装:
sudo apt install ros-noetic-hector-*
sudo apt install ros-noetic-hector-*
sudo apt install ros-noetic-hector-*
sudo apt install ros-noetic-hector-*
复制
sudo apt install ros-noetic-hector-*
sudo apt install ros-noetic-hector-*
然后将上篇博客所提到的小车底层文件放在car_base功能包下,再新建几个launch文件用于启动和配置建图相关包,按照如下目录树配置就可以了:
此外该工作空间还有一个雷达功能包,这里就按所使用的公司的雷达所提供的包直接调用就可以了。
我这里hector.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_footprint" />
<param name="odom_frame" value="odom" />
<!-- 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="2048"/>
<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" />
<!-- 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>
</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_footprint" /> <param name="odom_frame" value="odom" /> <!-- 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="2048"/> <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" /> <!-- 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> </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_footprint" /> <param name="odom_frame" value="odom" /> <!-- 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="2048"/> <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" /> <!-- 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> </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_footprint" /> <param name="odom_frame" value="odom" /> <!-- 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="2048"/> <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" /> <!-- 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> </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_footprint" /> <param name="odom_frame" value="odom" /> <!-- 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="2048"/> <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" /> <!-- 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> </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_footprint" /> <param name="odom_frame" value="odom" /> <!-- 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="2048"/> <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" /> <!-- 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> </launch>
3.进行建图
开启一个终端,远程连接到旭日X3派,在工作空间下执行命令启动底层节点和雷达节点。
roslaunch car_base car_base.launch
roslaunch car_base car_base.launch
roslaunch car_base car_base.launch
roslaunch car_base car_base.launch
复制
roslaunch car_base car_base.launch
roslaunch car_base car_base.launch
再新建一个终端,远程连接到旭日X3派,在工作空间下执行下面命令启动建图文件开始建图。
roslaunch car_mapping hector.launch
roslaunch car_mapping hector.launch
roslaunch car_mapping hector.launch
roslaunch car_mapping hector.launch
复制
roslaunch car_mapping hector.launch
roslaunch car_mapping hector.launch
在从机打开rviz,使用手柄控制车沿着地图移动和探索,进行建图,建图过程截图如下:
探索地图完毕之后,终端不要关,再新建一个终端使用map_server进行地图的保存,这里我暂时保存在了主目录
rosrun map_server map_saver -f car_map
rosrun map_server map_saver -f car_map
rosrun map_server map_saver -f car_map
rosrun map_server map_saver -f car_map
复制
rosrun map_server map_saver -f car_map
如果上述命令找不到,那就是没有安装map_server,使用下面命令进行安装
sudo apt install ros-noetic-map-server
sudo apt install ros-noetic-map-server
sudo apt install ros-noetic-map-server
sudo apt install ros-noetic-map-server
复制
sudo apt install ros-noetic-map-server
没有报错的话就成功的完成了地图的构建,保存的地图car_map,包含着地图和起点信息。
3.导航实现
我这里使用的是teb局部路径规划,再安装过导航功能包的基础上还需要额外安装teb功能包:
sudo apt install ros-noetic-teb-local-planner
sudo apt install ros-noetic-teb-local-planner
sudo apt install ros-noetic-teb-local-planner
sudo apt install ros-noetic-teb-local-planner
复制
sudo apt install ros-noetic-teb-local-planner
然后像上文操作一样,首先需要新建一个导航功能包
cd diff_car_ws/src
catkin_create_pkg car_nav std_msgs roscpp tf geometry_msgs nav_msgs
cd ..
catkin_make
cd diff_car_ws/src catkin_create_pkg car_nav std_msgs roscpp tf geometry_msgs nav_msgs cd .. catkin_make
cd diff_car_ws/src catkin_create_pkg car_nav std_msgs roscpp tf geometry_msgs nav_msgs cd .. catkin_make
cd diff_car_ws/src catkin_create_pkg car_nav std_msgs roscpp tf geometry_msgs nav_msgs cd .. catkin_make
复制
cd diff_car_ws/src catkin_create_pkg car_nav std_msgs roscpp tf geometry_msgs nav_msgs cd .. catkin_make
按如下目录树进行文件的配置即可:
其中config中存放的是amcl和move_base的一些参数,map中存放的是刚刚保存的地图,把它拖到map文件夹下。
move_base提供了许多参数,可以用于调整机器人导航的性能和行为。move_base的参数通常存储在一个YAML格式的文件中,该文件可以通过ROS参数服务器进行加载和修改。具体如何修改在roswiki中有较为详细的说明,链接如下:ROS WIKI
这里navi_demo_teb.launch主要部分如下:
<!-- 运行地图服务器,并且加载设置的地图-->
<node name="map_server" pkg="map_server" type="map_server" args="$(find gazebo_nav)/map/car_map.yaml" output="screen">
<param name="frame_id" value="map" />
</node>
<!-- 启动AMCL节点 -->
<include file="$(find gazebo_nav)/config/amcl/amcl_omni.launch" > </include>
<!-- 运行move_base节点 -->
<node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen" clear_params="true">
<param name="base_local_planner" value="teb_local_planner/TebLocalPlannerROS" />
<rosparam file="$(find gazebo_nav)/config/move_base/costmap_common_params.yaml" command="load" ns="global_costmap" />
<rosparam file="$(find gazebo_nav)/config/move_base/costmap_common_params.yaml" command="load" ns="local_costmap" />
<rosparam file="$(find gazebo_nav)/config/move_base/local_costmap_params.yaml" command="load" />
<rosparam file="$(find gazebo_nav)/config/move_base/global_costmap_params.yaml" command="load" />
<rosparam file="$(find gazebo_nav)/config/move_base/move_base_params.yaml" command="load" />
<rosparam file="$(find gazebo_nav)/config/move_base/base_global_planner_params.yaml" command="load" />
<rosparam file="$(find gazebo_nav)/config/move_base/teb_local_planner_params.yaml" command="load" />
</node>
<!-- 运行地图服务器,并且加载设置的地图--> <node name="map_server" pkg="map_server" type="map_server" args="$(find gazebo_nav)/map/car_map.yaml" output="screen"> <param name="frame_id" value="map" /> </node> <!-- 启动AMCL节点 --> <include file="$(find gazebo_nav)/config/amcl/amcl_omni.launch" > </include> <!-- 运行move_base节点 --> <node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen" clear_params="true"> <param name="base_local_planner" value="teb_local_planner/TebLocalPlannerROS" /> <rosparam file="$(find gazebo_nav)/config/move_base/costmap_common_params.yaml" command="load" ns="global_costmap" /> <rosparam file="$(find gazebo_nav)/config/move_base/costmap_common_params.yaml" command="load" ns="local_costmap" /> <rosparam file="$(find gazebo_nav)/config/move_base/local_costmap_params.yaml" command="load" /> <rosparam file="$(find gazebo_nav)/config/move_base/global_costmap_params.yaml" command="load" /> <rosparam file="$(find gazebo_nav)/config/move_base/move_base_params.yaml" command="load" /> <rosparam file="$(find gazebo_nav)/config/move_base/base_global_planner_params.yaml" command="load" /> <rosparam file="$(find gazebo_nav)/config/move_base/teb_local_planner_params.yaml" command="load" /> </node>
<!-- 运行地图服务器,并且加载设置的地图--> <node name="map_server" pkg="map_server" type="map_server" args="$(find gazebo_nav)/map/car_map.yaml" output="screen"> <param name="frame_id" value="map" /> </node> <!-- 启动AMCL节点 --> <include file="$(find gazebo_nav)/config/amcl/amcl_omni.launch" > </include> <!-- 运行move_base节点 --> <node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen" clear_params="true"> <param name="base_local_planner" value="teb_local_planner/TebLocalPlannerROS" /> <rosparam file="$(find gazebo_nav)/config/move_base/costmap_common_params.yaml" command="load" ns="global_costmap" /> <rosparam file="$(find gazebo_nav)/config/move_base/costmap_common_params.yaml" command="load" ns="local_costmap" /> <rosparam file="$(find gazebo_nav)/config/move_base/local_costmap_params.yaml" command="load" /> <rosparam file="$(find gazebo_nav)/config/move_base/global_costmap_params.yaml" command="load" /> <rosparam file="$(find gazebo_nav)/config/move_base/move_base_params.yaml" command="load" /> <rosparam file="$(find gazebo_nav)/config/move_base/base_global_planner_params.yaml" command="load" /> <rosparam file="$(find gazebo_nav)/config/move_base/teb_local_planner_params.yaml" command="load" /> </node>
<!-- 运行地图服务器,并且加载设置的地图--> <node name="map_server" pkg="map_server" type="map_server" args="$(find gazebo_nav)/map/car_map.yaml" output="screen"> <param name="frame_id" value="map" /> </node> <!-- 启动AMCL节点 --> <include file="$(find gazebo_nav)/config/amcl/amcl_omni.launch" > </include> <!-- 运行move_base节点 --> <node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen" clear_params="true"> <param name="base_local_planner" value="teb_local_planner/TebLocalPlannerROS" /> <rosparam file="$(find gazebo_nav)/config/move_base/costmap_common_params.yaml" command="load" ns="global_costmap" /> <rosparam file="$(find gazebo_nav)/config/move_base/costmap_common_params.yaml" command="load" ns="local_costmap" /> <rosparam file="$(find gazebo_nav)/config/move_base/local_costmap_params.yaml" command="load" /> <rosparam file="$(find gazebo_nav)/config/move_base/global_costmap_params.yaml" command="load" /> <rosparam file="$(find gazebo_nav)/config/move_base/move_base_params.yaml" command="load" /> <rosparam file="$(find gazebo_nav)/config/move_base/base_global_planner_params.yaml" command="load" /> <rosparam file="$(find gazebo_nav)/config/move_base/teb_local_planner_params.yaml" command="load" /> </node>
复制
<!-- 运行地图服务器,并且加载设置的地图--> <node name="map_server" pkg="map_server" type="map_server" args="$(find gazebo_nav)/map/car_map.yaml" output="screen"> <param name="frame_id" value="map" /> </node> <!-- 启动AMCL节点 --> <include file="$(find gazebo_nav)/config/amcl/amcl_omni.launch" > </include> <!-- 运行move_base节点 --> <node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen" clear_params="true"> <param name="base_local_planner" value="teb_local_planner/TebLocalPlannerROS" /> <rosparam file="$(find gazebo_nav)/config/move_base/costmap_common_params.yaml" command="load" ns="global_costmap" /> <rosparam file="$(find gazebo_nav)/config/move_base/costmap_common_params.yaml" command="load" ns="local_costmap" /> <rosparam file="$(find gazebo_nav)/config/move_base/local_costmap_params.yaml" command="load" /> <rosparam file="$(find gazebo_nav)/config/move_base/global_costmap_params.yaml" command="load" /> <rosparam file="$(find gazebo_nav)/config/move_base/move_base_params.yaml" command="load" /> <rosparam file="$(find gazebo_nav)/config/move_base/base_global_planner_params.yaml" command="load" /> <rosparam file="$(find gazebo_nav)/config/move_base/teb_local_planner_params.yaml" command="load" /> </node>
配置完成过后,开启一个终端,远程连接到旭日X3派,在工作空间下执行启动底层节点和雷达节点的命令。
roslaunch car_base car_base.launch
roslaunch car_base car_base.launch
roslaunch car_base car_base.launch
roslaunch car_base car_base.launch
复制
roslaunch car_base car_base.launch
再新建一个终端,远程连接到旭日X3派,在工作空间下启动导航节点:
roslaunch car_nav navi_demo_teb.launch
roslaunch car_nav navi_demo_teb.launch
roslaunch car_nav navi_demo_teb.launch
roslaunch car_nav navi_demo_teb.launch
复制
roslaunch car_nav navi_demo_teb.launch
然后发布目标点,实现导航。
在从机调用的rviz进行可视化如下:
到这里就完成了ROS智能车中的建图与导航实现啦。
评论(0)
您还未登录,请登录后发表或查看评论