【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

        关于ros导航的部分,网上的大部分内容要么过于理论,要么直接讲代码实现,门槛有点高。但是怎么让ros navigation用起来,或者说怎么让初学者看到ros导航的效果,这方面的文章很少。最近自己正好学习ros,并且结合视频网站上的一些介绍,学会了怎么使用ros navigation,正好可以写一篇文章简单介绍下。

        要实现ros导航,最主要的是分成两个部分,第一就是建图;第二就是使用ros下面的导航栈软件,即move_base来实现robot自主导航。

1、下载wpb_home

        之前我们进行ros仿真的时候,只下载了wpr_simulation,这一次还要下载wpb_home。如果用git不太好下载,可以直接下载对应的压缩包文件,

https://github.com/6-robot/wpb_home/tree/master

2、解压wpb_home,同时执行./install_for_noetic.sh

        下载好wpb_home之后,需要把文件解压到 catkin_ws的./src目录下面。接着,cd到wpb_home_bringup/scripts下面,继续执行./install_for_noetic.sh脚本,不然后面执行catkin_make的时候会有一部分代码无法编译通过。

3、catkin_make编译

        编译就比较简单了,直接在workspace顶层输入catkin_make即可。

4、绘制地图

        绘制地图的部分,主要有两个。第一,利用roslaunch wpr_simulation wpb_gmapping.launch命令把仿真和gmapping启动起来;第二,利用rosrun wpr_simulation keyboard_vel_ctrl命令控制好小车。为了绘制地图,有必要利用keyboard_vel_ctrl让小车走到场景下的每个角落,这样就可以把地图完整地绘制出来。

5、保存地图

        保存地图的动作不复杂,之前也提及过。就是输入rosrun map_server map_saver。这样就会在当前目录下看到map.yaml和map.pgm两个文件。

6、拷贝地图

        为了move_base使用方便,需要把map_server生成的地图文件拷贝到wpr_simulation的map目录下。

7、开启导航

        开启导航的动作其实很简单。直接在catkin_ws目录下输入roslaunch wpr_simulation wpb_navigation.launch命令即可。因为一开始robot位置不对,所以需要在rivz下面用“2D Pose Estimate”设置一下robot的初始位姿,保证当前lidar的扫描线和外部环境的轮廓基本重合。注意,如果需要不停调整robot位姿的话,需要每次单击一下“2D Pose Estimate”按钮。

        给robot设置好位置之后,接下来就是利用“2D Nav Goal”按钮给小车一个目标点。设置完毕之后,小车就会规划出一条曲线,然后按着设计好的曲线走过去。

8、关于move_base

        前面我们使用wpb_navigation.launch实现robot的自主导航。这个时候,可以看下launch文件下面关于move_base这部分是如何进行配置的,也有利于后面的进一步学习和理解。

  <!--- Run move base -->
  <node pkg="move_base" type="move_base" respawn="false" name="move_base"  output="screen">
    <rosparam file="$(find wpb_home_tutorials)/nav_lidar/costmap_common_params.yaml" command="load" ns="global_costmap" />
    <rosparam file="$(find wpb_home_tutorials)/nav_lidar/costmap_common_params.yaml" command="load" ns="local_costmap" />
    <rosparam file="$(find wpb_home_tutorials)/nav_lidar/local_costmap_params.yaml" command="load" />
    <rosparam file="$(find wpb_home_tutorials)/nav_lidar/global_costmap_params.yaml" command="load" />
    <rosparam file="$(find wpb_home_tutorials)/nav_lidar/local_planner_params.yaml" command="load" />
    <param name="base_global_planner" value="global_planner/GlobalPlanner" /> 
    <param name="use_dijkstra" value="true"/>
    <param name="base_local_planner" value="wpbh_local_planner/WpbhLocalPlanner" />
    <param name= "controller_frequency" value="10" type="double"/>
  </node>

        而对amcl的配置是这样的,

  <!--- Run AMCL -->
  <include file="$(find wpb_home_tutorials)/nav_lidar/amcl_omni.launch" />

        进一步找到amcl_omni.launch文件,

<launch>
<node pkg="amcl" type="amcl" name="amcl" output="screen">
  <!-- Publish scans from best pose at a max of 10 Hz -->
  <param name="odom_model_type" value="omni"/>
  <param name="odom_alpha5" value="0.1"/>
  <param name="transform_tolerance" value="0.2" />
  <param name="gui_publish_rate" value="10.0"/>
  <param name="laser_max_beams" value="30"/>
  <param name="min_particles" value="100"/>
  <param name="max_particles" value="1000"/>
  <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"/>
  <!-- translation std dev, m -->
  <param name="odom_alpha3" value="0.8"/>
  <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_lambda_short" value="0.1"/>
  <param name="laser_model_type" value="likelihood_field"/>
  <!-- <param name="laser_model_type" value="beam"/> -->
  <param name="laser_likelihood_max_dist" value="2.0"/>
  <param name="update_min_d" value="0.2"/>
  <param name="update_min_a" value="0.5"/>
  <param name="odom_frame_id" value="odom"/>
  <param name="resample_interval" value="1"/>
  <param name="transform_tolerance" value="0.1"/>
  <param name="recovery_alpha_slow" value="0.0"/>
  <param name="recovery_alpha_fast" value="0.0"/>
</node>
</launch>

        参数比较多,只能等到amcl单步调试的时候,再来学习效果才会比较好一点。

9、利用代码发送目标

        上面我们测试的时候是直接手动标点的行驶发送目标。实际运行中,我们可以通过编写代码发送目标。比如有这样一个simple_goal.cpp文件,


#include <ros/ros.h>
#include <move_base_msgs/MoveBaseAction.h>
#include <actionlib/client/simple_action_client.h>

typedef actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction> MoveBaseClient;

int main(int argc, char* argv[])
{
	ros::init(argc, argv, "simple_goal");
	MoveBaseClient ac("move_base", true);

	while(!ac.waitForServer(ros::Duration(5.0)))
	{
		ROS_INFO("Waiting for the move_base action serveer to come up");
	}

	move_base_msgs::MoveBaseGoal goal;
	goal.target_pose.header.frame_id = "map";
	goal.target_pose.header.stamp = ros::Time::now();

	goal.target_pose.pose.position.x = -3.0;
	goal.target_pose.pose.position.y = 2.0;
	goal.target_pose.pose.orientation.w = 1.0;

	ROS_INFO("Sending goal");
	ac.sendGoal(goal);

	ac.waitForResult();
	if(ac.getState() == actionlib::SimpleClientGoalState::SUCCEEDED)
	{
		ROS_INFO("Mission complete");
	}
	else
	{
		ROS_INFO("Mission failed ...");
	}

	return 0;
}

        上面这段代码中最重要的函数就是sendGoal & waitForResult。要想编译的话,两个地方需要修改,一个是添加依赖包,

find_package(catkin REQUIRED COMPONENTS message_generation roscpp rospy std_msgs genmsg tf cv_bridge pcl_ros actionlib move_base_msgs)

        一个是添加编译规则,

add_executable(simple_goal src/simple_goal.cpp)
target_link_libraries(simple_goal ${catkin_LIBRARIES})
add_dependencies(simple_goal beginner_tutorials_generate_messages_cpp)

        利用catkin_make编译完成后,就可以在roslaunch wpr_simulation wpb_navigation.launch之后,用rosrun beginner_tutorials simple goal进行测试。重点看小车的路径是否生成,并且小车是否会按照指定的曲线走过去。

Logo

更多推荐