MoveIt!由ROS中一系列移动操作的功能包组成,包含运动规划,操作控制,3D感知,运动学,碰撞检测等等,而且提供友好的GUI。官方网站:http://moveit.ros.org/,上边有MoveIt!的教程和API说明。
一、架构
下图是MoveIt的总体框架:
move_group是MoveIt的核心部分,可以综合机器人的各独立组件,为用户提供一系列需要的动作指令和服务。从架构图中我们可以看到,move_group类似于一个积分器,本身并不具备丰富的功能,主要做各功能包、插件的集成。它通过消息或服务的形式接收机器人上传的点云信息、joints的状态消息,还有机器人的tf tree,另外还需要ROS的参数服务器提供机器人的运动学参数,这些参数会在使用setup assistant的过程中根据机器人的URDF模型文件,创建生成(SRDF和配置文件)。
官网的说明:http://moveit.ros.org/documentation/concepts/
二、安装
MoveIt的安装很简单,使用下边的命令即可:
sudo apt-get install ros-indigo-moveit-full
下边会使用《master ros for robotics programming》里的案例进行学习,在工作空间里git下来源码:
git clone https://github.com/qboticslabs/mastering_ros.git
三、setup配置
使用MoveIt!的第一步是要使用 Setup Assistant工具完成一些配置工作。Setup Assistant会根据用户导入的机器人的urdf模型,生成SRDF( Semantic Robot Description Format)文件,从而生成一个MoveIt!的功能包,来完成机器人的互动、可视化和仿真。
首先,来运行setup assistant:
rosrun moveit_setup_assistant moveit_setup_assistant
在出现的界面左侧,可以看到我们接下来需要配置的步骤。
3.1 加载URDF
这里有两个选择,一个是新建一个配置功能包,一个是使用已有的配置功能包,我们选择新建,在源码中找到urdf文件。如果已有配置功能包,那么新建后会覆盖原有的文件。
从右边的窗口我们看到导入的机器人模型。
3.2 Self-Collision
然后点击左侧的第二项配置步骤,配置自碰撞矩阵,MoveIt!可以让我们设置一定数量的随机采样点,根据这些点生成配装参数,可想而知,过多的点会造成运算速度慢,过少的点会导致参数不完善,默认的采样点数量是10000个,官方称经过实践,要获得不错的效果,10000是最低要求,我们就按照这个默认值生成碰撞矩阵。
3.3 Virtual Joints
虚拟关节主要是用来描述机器人在world坐标系下的位置,如果机器人是移动的,虚拟关节可以与移动基座关联,不过一般的机械臂都是固定不动的,所以也可以不需要虚拟关节。
3.4 Planning Groups
这一步可以将机器人的多个组成部分(links,joints)集成到一个组当中,运动规划会针对一组links或joints完成运动规划,在配置个过程中还可以选择运动学解析器( kinematic solver)。这里创建两个组,一个是机械臂部分,一个是夹具部分。
3.5 Robot Poses
这里可以设置一些固定的位置,比如说机器人的零点位置、初始位置等等,当然这些位置是用户根据场景自定义的,不一定要和机器人本身的零点位置、初始位置相同。这样做的好处就是我们使用MoveIt!的API编程时,可以直接调用这些位置。
3.6 End-Effectors
机械臂在一些实用场景下,会安装夹具等终端结构,可以在这一步中添加。
3.7 Passive Joints
机器人上的某些关节,可能在规划、控制过程中使用不到,可以先声明出来,这里没有就不用管了。
3.8 Configuration Files
最后一步,生成配置文件。一般会取名 robot_name_moveit_config。这里,会提示覆盖已有的配置文件。
OK,现在已经完成配置了,可以退出 Setup Assistant,运行demo看看:
这个界面是在rviz的基础上加入了MoveIt!插件,通过左下角的插件,我们可以选择机械臂的目标位置,进行运动规划。
拖动机械臂的前端,可以改变机械臂的姿态,在planning页面,点击“Plan and Execute”,MoveIt!开始规划路径,并且可以看到机械臂开始向目标位置移动了!
四、运动规划
看过直观效果之后,我们来分析一下运作的机理。
假设我们已知机器人的初始姿态和目标姿态,以及机器人和环境的模型参数,那么我们就可以通过一定的算法,在躲避环境障碍物和放置自身碰撞的同时,找到一条到达目标姿态的较优路径,这种算法就称为机器人的运动规划。机器人和环境的模型静态参数由URDF文件提供,在默写场景下还需要加入3D摄像头、激光雷达来动态检测环境变化,避免与动态障碍物发生碰撞。
4.1 motion_planner
在MoveIt中,运动规划算法由运动规划器完成,当然,运动规划算法有很多,每一个运动规划器都是MoveIt的一个插件,可以根据需求选用不同的规划算法。,move_group 默认使用的是OMPL算法(http://ompl.kavrakilab.org/ )。
运动规划的流程如上图所示,首先我们需要发送一个运动规划的请求(比如说一个新的终端位置)给运动规划器,当然,运动规划也不能随意计算,我们可以根据实际情况,设置一些约束条件:
l 位置约束:约束link的位置
l 方向约束:约束link的运动方向
l 可见性约束:约束link上的某点在某区域的可见性(通过视觉传感器)
l joint约束:约束joint的运动范围
l 用户定义约束:用户通过回调函数自定义一些需要的约束条件。
根据这些约束条件和用户的规划请求,运动规划器通过算法计算求出一条合适的运动轨迹,并回复给机器人控制器。
上图的运功规划器两侧,还分别有一个planning request adapters,这个东东是干什么的呢?从名称上我们大概可以猜出来,planning request adapters作为一个适配器接口,主要功能是预处理运功规划请求和响应的数据,使之满足规划和使用的需求。adapters带有一个s,可见适配器的种类还不只一种,以下是MoveIt!默认使用的一些适配器:
l FixStartStateBounds:如果一个joint的状态稍微超出了joint的极限,这个adapter可以修复joint的初始极限。
l FixWorkspaceBounds:这个adapter可以设置一个10m*10m*10m的规划运动空间。
l FixStartStateCollision:如果已有的joint配置文件会导致碰撞,这个adapter可以采样新的碰撞配置文件,并且根据一个 jiggle_factor因子修改已有的配置文件。
l FixStartStatePathConstraints:如果机器人的初始姿态不满足路径约束,这个adapter可以找到附近满足约束的姿态作为机器人的初始姿态。
l AddTimeParameterization:运动规划器规划得出的轨迹只是一条空间路径,这个adapter可以为这条空间轨迹进行速度、加速度约束,我们可以通过rostopic echo查看规划的路径数据,这个adapter其实就是把空间路径按照距离等分,然后在每个点加入速度、加速度、时间等参数。
4.2 Planning Scene
planning scene可以为机器人创建一个具体的工作环境,加入一些障碍物。
这一功能主要由move group节点中的planning scene monitor来实现,主要监听:
l State Information: joint_states topic
l Sensor Information: the world geometry monitor,视觉传感器采集周围环境数据
l World geometry information: planning_scene topic
4.3 Kinematics
运动学算法是机械臂各种算法中的核心,尤其是反向运动学算法( inverse kinematics, IK)。MoveIt!使用插件的形式可以让用户灵活的选择需要使用的反向运动学算法,也可以选择自己的算法。
MoveIt!中默认的IK算法是 numerical jacobian-based算法。关于算法,可以参考:
l http://roswiki.com/read.php?tid=402
l http://roswiki.com/read.php?tid=535&fid=9
4.4 Collision Checking
MoveIt使用 CollisionWorld 对象进行碰撞检测,采用FCL( Flexible Collision Library,http://gamma.cs.unc.edu/FCL/fcl_docs/webpage/generated/index.html)功能包。碰撞检测是运动规划中最耗时的运算,往往会占用90%左右的时间,为了减少计算量,可以通过设置ACM( Allowed Collision Matrix )来进行优化,如果两个bodys之间的ACM设置为1,则意味着这两个bodys永远不会发生碰撞,不需要碰撞检测。