45 ros的导航算法(全局路径规划算法与局部路径规划算法)
(1) 全局路径规划算法(Dijkstra算法和A*算法) 
{ 绿色:起点 红色:终点   黑色:障碍物    白色:路径    黄色:已处理的节点 }
(1_1) Dijkstra 算.法(没有使用启发式信息)

ros python发布导航点 ros导航算法_iot

  (1_2) A* 算.法(使用了启发式信息:到目标的距离)

ros python发布导航点 ros导航算法_ros python发布导航点_02

        香侬告诉我们,信息可以消除不确定性。其实,信息还可以提高算法的效率。因为我们都有这样的经验:信息越充分,决策越容易成功。A* 算法仅仅将非常简单的启发式信息引入了Dijkstra 算法,就能大幅降低待处理节点的数量,从而极大的提高了效率。

(2) 局部路径规划算法(DWA算法)
        DWA由两个主要部分组成,一是利用速度矢量空间为移动机器人生成有效的搜索空间,Fox等人将搜索空间仅限于安全的圆形区域或扇形区域,然后在短时间内达到并且没有碰撞。二是在搜索空间中选择最佳解决方案。设计评价函数对速度矢量空间中轨迹进行评价,选择出一条当前最优轨迹,使机器人与任何障碍物保持最大间隙。具体的算法步骤如下:
(2_1)离散采样移动机器人的运行状态(dx,dy,θ),即多组速度对(v,w);
(2_2)对获得的每一组采样速度进行模拟,以预测这些速度集在短时间内的运动轨迹;
(2_3)使用到障碍物的距离,到目标的距离,速度等标准来评估每个获得的轨迹,并从集合中删除与障碍物碰撞的轨迹;
(2_4)选择最佳轨迹并在机器人模型中配置合适的设定速度;
(2_5)执行选定的轨迹并重复,直到机器人到达目标点。

ros python发布导航点 ros导航算法_ros python发布导航点_03

(3)AMCL算法

ros python发布导航点 ros导航算法_移动机器人_04

44 优化AMCL,我们目前简单的做法就是调整AMCL节点的参数。复杂的做法就是我们需要自己来修改AMCL的源码了,或者实现自己的定位算法。在真实的机器人开发中,我们除了使用AMCL来进行定位外。还可以使用室内UWB定位技术。

43 当使用某个功能不知道坐标系的名称时,可以通过 rosrun tf view_frames 查看。坐标系一般直接就是名字,话题等一般前面有"/"符号。

42 ros中通过catkin_make 编译完代码后,需要使用source ~/catkin_ws/devel/setup.bash才可以发现先编译的包

41 TF变换为了方便可以理解为一些功能节点订阅一些相关话题,输入相应的TF变换,比如amcl节点通过订阅地图以及激光信息等输出map到odom的TF变化,robot_pose_ekf节点通过订阅陀螺仪数据以及odom数据,发布odom到base_footprint的TF变换,这样就形成了一个树。

40 ros中地图原点一般位于地图中心位置,map.ymal中origin属性中可以查看地图中心指定,ros中地图数据的存储方式按照从左到右从下到上的顺序依次排列。

ros python发布导航点 ros导航算法_移动机器人_05

rostopic echo //map查看地图数据信息, 
rostopic echo //map_metadata查看地图大小,分辨率以及坐标原点等信息。

 39 ros中同名包解决方法,删除src目录下的同名包名,以及删除build、devel目录下的所有文件重新编译即可。

38 包是模块的集合,在ros中,如果使用相应的包,C++可以通过include,python可以通过import导入相应的功能包。

37 ros开机运行launch文件

//(1)安装package

sudo apt-get install ros-kinetic-robot-upstart

//(2)执行install命令,在/etc/ros/kinetic目录下生成响应的脚本文件

rosrun robot_upstart install package_name/launch/start.launch

//(3)添加开机启动选项

sudo systemctl daemonreload && sudo systemctl start stdr

//(4)取消开机启动选项

36 twist.linear.y = 0 是在move_base的配置文件base_local_planner_params.yaml中有明确指定,所以不需关注linear.y的转换:

35 ROS多线程订阅消息

34 ROS使用多个工作空间容易出现BUG,所以尽量所有的程序放在同一个工作空间,同一个工作空间禁止出现同名的包,可以通过查看rospackage list指令查看起作用的ros包。通过echo $ROS_PACKAGE_PATH 查看搜索路径

33 rospack:查找和检索有关软件包的信息

32 部分函数

(1)rospy.Rate(hz)
        rospy provides a rospy.Rate convenience class which makes a best effort at maintaining a particular rate for a loop.

r = rospy.Rate(10) # 10hz 
while not rospy.is_shutdown(): 
    pub.publish("hello") 
    r.sleep()

(2)rospy.Timer(period, callback, oneshot=False)
        rospy provides a rospy.Timer convenience class which periodically calls a callback. Timer is similar to roscpp's Timer class. The arguments to the constructor are:

def my_callback(event): 
    print 'Timer called at ' + str(event.current_real) 

rospy.Timer(rospy.Duration(2), 
my_callback)

31 ROS中的CMakeLists.txt

  

30 map_update_thread_ = new boost::thread(boost::bind(&Costmap2DROS::mapUpdateLoop, this, map_update_frequency));

29 使用ROS出现找不到package的情况或者找不到excute文件的情况,在~/目录下修改.bashrc文件添加:

source ~/catkin_ws/devel/setup.bash

28 navication 参数设置

27 在仿真过程中,可以使用rqt_reconfigure在不重新启动仿真的情况下对参数值进行修改,使用以下指令:

ros python发布导航点 ros导航算法_iot_06

rosrun rqt_reconfigure rqt_reconfigure

26 移动机器人导航仿真(3)——定位(amcl)和路径规划(move_base)

25 costmap
        ros利用插件机制实现了分层的costmap,每一层保存一张由该层对应的数据源生成的costmap,由各自的数据源实时更新,最后,各层的数据上下叠加在一起,就生成了最终的costmap。每一层的costmap为Costmap2D类型,最后叠加在一起的为LayeredCostmap类型,LayeredCostmap类里包含一个Costmap2D类型的成员变量。

ros python发布导航点 ros导航算法_人工智能_07

22 tf变换

rosrun tf tf_echo word turtle1 //查看turtle1 相对于世界坐标系的TF变换 
rosrun tf tf_echo turtle1 turtle2//查看turtle2 相对于turtle1的TF变换 
rosrun tf view_frames 查看tf树

21 节点中订阅的话题可以通过remap更换名字。

<node pkg="robot_pose_ekf" type="robot_pose_ekf" name="robot_pose_ekf">
<param name="output_frame" value="odom"/> 
<param name="base_footprint_frame" value="base_footprint"/> 
<param name="freq" value="30.0"/> 
<param name="sensor_timeout" value="1.0"/> 
<param name="odom_used" value="true"/> 
<param name="imu_used" value="true"/> 
<param name="vo_used" value="false"/> 
<remap from="imu_data" to="imu/data"/> 
<remap from="odom" to="base_footprint"/> 
<remap from="robot_pose_ekf/odom_combined" to="imu/data_ekf"/> 
</node>

     remap这个标签是用于将此节点的topic的名称进行重映射, from中填入原来的topic名称,to中填入新的topic名称。<remap>标签根据放置在launch文件的层级不同,在相应的层级起作用。      robot_pose_ekf将订阅imu_data以及odom话题,发布话题robot_pose_ekf/odom_combined,可以通过remap这个标签更改订阅以及发布话题的名称。

20 ros 生成的地图,坐标原点都是固定位于图片的中心,跟什么时候开启gmapping无关。如果开启gmapping前机器人有移动(odom),则机器人(图中灰白位置的地图)就回偏离图片中心点位置。如果开启gmapping的时候,机器人没有移动,则开启gmapping的时候机器人就位于图片中心位置。

ros python发布导航点 ros导航算法_ros python发布导航点_08

 19 ros摄像头标定棋盘格

18 os::spin()和ros::spinOnce()函数
        如果你的程序写了相关的消息订阅函数,那么程序在执行过程中,除了主程序以外,ROS还会自动在后台按照你规定的格式,接受订阅的消息,但是所接到的消息并不是立刻就被处理,而是必须要等到ros::spin()或ros::spinOnce()执行的时候才被调用,这就是消息回到函数的原理。
        如果仅仅只是响应topic,就用ros::spin()。当程序中除了响应回调函数还有其他重复性工作的时候,那就在循环中做那些工作,然后调用ros::spinOnce()。

17 对姿态的描述,最直观的便是欧拉角了。实际上一个动图便能十分直观的解释清楚了最直观的感受就是分别绕三个轴进行旋转便是了。

ros python发布导航点 ros导航算法_移动机器人_09

 16 GMapping虽然没有优化,但依靠粒子的多样性,在回环时仍能消除累计误差。但需要注意的是,要尽量走小回环,回环越大,粒子耗尽的可能性就越高,越难在回环时修正回来。所以规划建图路径时,应先走一个小回环,当回环成功后,可以再多走几圈,消除粒子在这个回环的多样性。接下来走下一个回环,直到把整个地图连通成一个大的回环。

15 粒子滤波(Particle Filter)的通俗解释

14 学习costmap代价地图

13 ros增加安装包搜索路径,需要在~/.bashrc文件中增加以下语句

source ~/catkin_ws/devel/setup.bash

12 ubuntu通过apt-get安装软件失败,一般是软件源设置不对,软件源一般设置为国内常用的软件源。国外的软件源下载常常会出现问题,设置完软件源之后,通过apt-get update更新软件列表,就可以安装该软件源的所有程序(提示安装)。
        注:由于不同的linux版本对应的ROS版本不一样,所以当你需要安装ROS的依赖包时,需要使用sudo apt-get install ros-kinetic-PACKAGE命令

11 ROS无法定位软件包解决方法

        Ubuntu 和 ROS 都是存在不同的版本,而且ROS各个版本之间互不兼容,所以每一个 ROS 版本都对应着一个或两个对应的 Ubuntu 版本。 如果系统版本和ROS版本不对应,就可能遇到无法定位软件包的问题。

ros python发布导航点 ros导航算法_ros python发布导航点_10

10 ROS坐标系

如图红色为x轴,绿色为y轴,蓝色为z轴。

ros python发布导航点 ros导航算法_iot_11

注:link与joint中origin使用:

<link name="dsad"> 
    <visual> 
        <origin xyz="a b c" rpy="d e f"/> 
    </visual> 
</link> 
<joint name="" type=""> 
    <origin xyz="a b c" rpy="d e f"/> 
</joint>

        link中origin:xyz是指以父节点的坐标系为参考系(若没有父节点则以世界坐标系为参考系),该link分别向xyz方向移动a b c的距离,但是该link本身的坐标系不移动(该link的默认坐标系与起父节点相同);rpy是指以父节点的坐标系为参考系,分别以xyz轴为旋转轴,旋转d e f的弧度,但是该link本身的坐标系不旋转。并且先执行旋转rpy,再执行移动xyz,link本身的坐标系始终不动。
        而joint中origin与link的区别是,link移动和旋转时,该link本身的坐标系随该link一同移动,即他本身的坐标系是在变化的。并且先执行xyz移动,再执行rpy旋转。

9 ROS安装 

kinetic/Installation/Ubuntu - ROS Wikihttp://wiki.ros.org/kinetic/Installation/Ubuntu

如果ros功能包下载失败,注意更换软件源 kinetic/Installation/Ubuntu - ROS Wikihttp://wiki.ros.org/kinetic/Installation/Ubuntu

8 ROS相关的环境变量可以使用echo显示,ROS相关环境变量一般以ROS开头,可以键入$ROS后通过tab键查看所有相关的环境变量
显示包搜索路径echo $ROS_PACKAGE_PATH
显示主机地址 echo $ROS_MASTER_URI

6 ros常用坐标系(map,odom,base_link,base_laser)
(1) map:地图坐标系,顾名思义,一般设该坐标系为固定坐标系(fixed frame),一般与机器人所在的世界坐标系一致。
(2) odom:里程计坐标系,这里要区分开odom topic,这是两个概念,一个是坐标系,一个是根据编码器(或者视觉等)计算的里程计。但是两者也有关系,odom topic 转化得位姿矩阵是odom-->base_link的tf关系。这时可有会有疑问,odom和map坐标系是不是重合的?(这也是我写这个博客解决的主要问题)可以很肯定的告诉你,机器人运动开始是重合的。但是,随着时间的推移是不重合的,而出现的偏差就是里程计的累积误差。那map-->odom的tf怎么得到?就是在一些校正传感器合作校正的package比如amcl会给出一个位置估计(localization),这可以得到map-->base_link的tf,所以估计位置和里程计位置的偏差也就是odom与map的坐标系偏差。所以,如果你的odom计算没有错误,那么map-->odom的tf就是0.
(3) base_link:机器人本体坐标系,与机器人中心重合,当然有些机器人(PR 2)是base_footprint,其实是一个意思。
(4) base_laser:激光雷达的坐标系,与激光雷达的安装点有关,其与base_link的tf为固定的

5 hawkbot运行建图与导航时的tf tree

注意:运行导航时,会开启amcl节点,此节点会发布map到odom的tf变换。

ros python发布导航点 ros导航算法_iot_12

 4 ros 常用指令

(1) rostopic //ros话题相关指令
//发送话题消息 rostopic pub /turtle1/cmd_vel geometry_msgs/Twist "linear: x: 0.0 y: 0.0 z: 0.0 angular: x: 0.0 y: 0.0 z: 0.0" -r 1 //订阅话题消息并显示 rostopic echo /turtle1/cmd_vel
(2) rosservice //ros服务
//请求服务(通过以下指令生成一个小海龟) rosservice call /spawn "x: 0.0 theta: 0.0 name: ''"
(3) rosparam//ros参数
rosparam set rosparam get
(4) rosmsg//ros消息信息
(5) rossrv//ros服务信息
(6) rosnode//ros节点
(7) rosbag//ros日志信息
(8) catkin_make//编译
(9) catkin_create_pkg//创建包

3 需要配置运行roscore的主机地址,如果不设置默认是本机地址
ROS_MASTER_URI=http://10.42.0.73:11311

2 相关文档
(11) 差速驱动机器人的里程计信息计算

(10) cmd_vel转化为电机控制指令

(9) 编码器转化为odom

(8) ros by example教材学习

(7) 使用dynamic_reconfigure实现节点参数动态更新

(6) 在STDR中配置planner路径规划器参数

(3) slam博客


(1) ROS C++程序编译流程图

1 执行rosrun指令时传递给应用程序的参数

#include "ros/ros.h" 
#include "std_msgs/String.h" 
int main(int argc, char *argv[]) 
{ /* code for main function */ 
    int value; char i=0; 
    ros::init(argc, argv, "param_test");             
    ros::NodeHandle n; 
    for(i=0;i<argc;i++) 
    { 
        ROS_INFO("para%d=%s",i,argv[i]); 
    } 
    ros::Rate loop_rate(1); 
    while (ros::ok()) 
    { 
        ros::spinOnce(); 
        loop_rate.sleep(); 
    } 
    return 0; 
} 
//执行 rosrun hello param_test param1 param2 //传递给main函数中的第一个参数为包含完整路径的可执行程序名 第二个参数为param1 //para0=/home/hawkbot/work/package/devel/lib/hello/param_test //para1=param1 //para2=param2