所需硬件
- RGBD摄像头(Kinet或Xtion)/激光雷达
- 里程计,即编码器,或者叫码盘
- 上位机,装ubuntu ROS
- 下位机,给轮子发速度,返回码盘数据给上位机
速度接口
总的来说,上位机发布topic “cmd_vel”,将速度平滑等处理后发送给下位机,然后下位机底盘解算将速度发给每个轮子。
上位机发送速度的接口
输出都是一个topic “cmd_vel”
里面的数据类型为 geometry_msgs/Twist 这个数据类型表示的是3d空间中的速度,2d的移动机器人只会用到三个值:linear.x,linear.y与angular.z,分别表示水平分速度,垂直分速度,与角速度。
‘[2.0, 0.0, 0.0]’’[0.0,0.0,1.8]’表示:以2.0大小的线速度和1.8大小的角速度开始移动。
下位机底盘运动学解算
将一个描述一个平面刚体的三个分速度映射成驱动部分的速度
分为:差动底盘(turtlebot那种两轮差速来实现转弯)和全向底盘这两种
曾经实现过的三轮解算为全向轮,四轮解算为麦伦
下位机发送速度给轮子
- 发送频率:看板子性能
- 速度平滑:过大的加速减速,不定的发送频率会导致运动的不理想,解决办法:上位机在速度接口这边执行一个平滑的过程,turtlebot中给出了一个非常好的速度插值的包。
里程计接口
总的来说,下位机发送topic “odom”
里面的数据类型为 nav_msgs/Odometry
Header header
string child_frame_id
geometry_msgs/PoseWithCovariance pose
geometry_msgs/TwistWithCovariance twist
下位机采集里程计数据,发送里程计接口给上位机
下位机得到各个里程计的位移,然后逆运动学解算,得到机器人中心相对坐标“原点”的坐标,发送当前位姿geometry_msgs/Pose和速度geometry_msgs/Twist给上位机
教程在这儿,http://wiki.ros.org/navigation/Tutorials/RobotSetup/Odom
上位机接收里程计接口
上位机从里程计接口得到机器人当前的位姿和速度
图像接口
一般rgbd-camera与激光雷达都有相应的sensor driver 提供,roslaunch相应文件就可以了。
传感器一般在消息的 header中都需要相应的传感器采集坐标系,对于固定的传感器使用 http://wiki.ros.org/tf#static_transform_publisher tf中的static_transform_publisher 给定传感器与机器人中心相对位姿就可以了。
SLAM及navigaion ROS 工具
OpenSLAM上面有几乎所有主流slam方法的C++/C实现,ROS的gmapping就是调用的这个上面的代码。不管是视觉还是激光雷达算法都非常丰富。
路径规划:move_base:,作为navigation的逻辑核心。它实现了一个供上层节点调用的action 接口(通过actionlib 实现),即给定坐标信息与相应坐标位置,执行相应的安全导航动作。对于下层控制器,之前说过了输出为cmd_vel 2d速度。 它规定了这个navigation的行为。
建图:gmapping/hector_slam,从激光扫描数据建图
定位:amcl,利用map和激光数据进行定位
导航规划
navigation metapackage:一般输入为激光雷达(使用rgbd-camera 效果不佳)与里程计数据,输出为cmd_vel 机器人在2d平面上的速度。与之类似的是hector_navigation。这一部分主要解决安全路径的规划问题。
costmap_2d :这一部分可看作为navigation的输入处理器。不同的传感器输入的数据差异很大(激光雷达 & RGBD-camera)通过costmap_2d , 不同的数据被处理成统一的格式:栅格地图,权值用经过概率方法处理过的,表示空间中障碍物,未知与安全区域。生成出来的costmap则是planner的输入。
global_planner:为navigation的全局规划器,接受costmap生成的 global costmap规划出从起始点到目标点的路径,为local_planner 作出参考。
local_planner:为navigation的局部规划器,接受costmap 生成的local costmap 规划出速度。
recovery_behavior : 规定move_base 行为集合中处理异常情况的行为
nav_core: 这个包里面就包含了global_planner,local_planner 与 recovery_behavior的基类的头文件。但是极其重要。
在ROS navigation中,move_base提供的是框架,在move_base 中是通过nav_core中规定的planner与recovery_behavior 的基类的接口进行调用。与具体的实现方法隔离开来。而具体采用的方法由pluginlib根据不同参数导入。这样的实现方法使得navigation的可定制性大大增加。像base_local_planner 中就实现了两种局部路径规划方法,global_planner 实现了A* 与Dijkstra两种方法,在navigation_experimental 中还有更多这样的实现。这赋予了这个框架很大的灵活性。通过不同的配置方法可以让navigation适应很多不同的任务。
定位部分
定位模块作为规划层的输入与参考数据所存在。而对于ROS navigation 体系而言,因为它先天的模块间通讯方式实现了模块间的完全解耦,所以对于导航规划层而言(具体就是move_base 这个node),什么定位方法,静态还是动态的地图,对于导航层内部几乎没有区别。
navigation metapackage中就有了为仿真器环境下的定位工具包fake_localization:用于把仿真器中的位姿(就是直接把odom 变换成map)估计直接变换成关于全局地图的定位,简化定位部分;
amcl:适应性蒙特卡洛定位方法,在base_scan的topic上利用激光数据来定位