ROS探索总结(二十五)——MoveIt基础

  • 内容
  • 评论
  • 相关

MoveIt!由ROS中一系列移动操作的功能包组成,包含运动规划,操作控制,3D感知,运动学,碰撞检测等等,而且提供友好的GUI。官方网站:http://moveit.ros.org/,上边有MoveIt!的教程和API说明。

一、架构

下图是MoveIt的总体框架:

clip_image002

 

move_groupMoveIt的核心部分,可以综合机器人的各独立组件,为用户提供一系列需要的动作指令和服务。从架构图中我们可以看到,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

在出现的界面左侧,可以看到我们接下来需要配置的步骤。

clip_image004

3.1 加载URDF

这里有两个选择,一个是新建一个配置功能包,一个是使用已有的配置功能包,我们选择新建,在源码中找到urdf文件。如果已有配置功能包,那么新建后会覆盖原有的文件。

clip_image006

从右边的窗口我们看到导入的机器人模型。

3.2 Self-Collision

    然后点击左侧的第二项配置步骤,配置自碰撞矩阵,MoveIt!可以让我们设置一定数量的随机采样点,根据这些点生成配装参数,可想而知,过多的点会造成运算速度慢,过少的点会导致参数不完善,默认的采样点数量是10000个,官方称经过实践,要获得不错的效果,10000是最低要求,我们就按照这个默认值生成碰撞矩阵。

clip_image008

3.3 Virtual Joints

     虚拟关节主要是用来描述机器人在world坐标系下的位置,如果机器人是移动的,虚拟关节可以与移动基座关联,不过一般的机械臂都是固定不动的,所以也可以不需要虚拟关节。

3.4 Planning Groups

这一步可以将机器人的多个组成部分(linksjoints)集成到一个组当中,运动规划会针对一组linksjoints完成运动规划,在配置个过程中还可以选择运动学解析器( kinematic solver)。这里创建两个组,一个是机械臂部分,一个是夹具部分。

clip_image010

 

clip_image012

3.5 Robot Poses

     这里可以设置一些固定的位置,比如说机器人的零点位置、初始位置等等,当然这些位置是用户根据场景自定义的,不一定要和机器人本身的零点位置、初始位置相同。这样做的好处就是我们使用MoveIt!的API编程时,可以直接调用这些位置。

clip_image014

3.6 End-Effectors

机械臂在一些实用场景下,会安装夹具等终端结构,可以在这一步中添加。

clip_image016

3.7 Passive Joints

机器人上的某些关节,可能在规划、控制过程中使用不到,可以先声明出来,这里没有就不用管了。

3.8 Configuration Files

最后一步,生成配置文件。一般会取名 robot_name_moveit_config。这里,会提示覆盖已有的配置文件。

clip_image018

OK,现在已经完成配置了,可以退出 Setup Assistant运行demo看看:

clip_image020

这个界面是在rviz的基础上加入了MoveIt!插件,通过左下角的插件,我们可以选择机械臂的目标位置,进行运动规划。

拖动机械臂的前端,可以改变机械臂的姿态,在planning页面,点击“Plan and Execute”MoveIt!开始规划路径,并且可以看到机械臂开始向目标位置移动了!

clip_image022

四、运动规划

     看过直观效果之后,我们来分析一下运作的机理。

     假设我们已知机器人的初始姿态和目标姿态,以及机器人和环境的模型参数,那么我们就可以通过一定的算法,在躲避环境障碍物和放置自身碰撞的同时,找到一条到达目标姿态的较优路径,这种算法就称为机器人的运动规划。机器人和环境的模型静态参数由URDF文件提供,在默写场景下还需要加入3D摄像头、激光雷达来动态检测环境变化,避免与动态障碍物发生碰撞。

4.1 motion_planner

     MoveIt中,运动规划算法由运动规划器完成,当然,运动规划算法有很多,每一个运动规划器都是MoveIt的一个插件,可以根据需求选用不同的规划算法。,move_group 默认使用的是OMPL算法(http://ompl.kavrakilab.org/ )。

clip_image024

     运动规划的流程如上图所示,首先我们需要发送一个运动规划的请求(比如说一个新的终端位置)给运动规划器,当然,运动规划也不能随意计算,我们可以根据实际情况,设置一些约束条件:

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

clip_image026

planning scene可以为机器人创建一个具体的工作环境,加入一些障碍物。

clip_image028

这一功能主要由move group节点中的planning scene monitor来实现,主要监听:

l  State Information joint_states topic

l  Sensor Information the world geometry monitor,视觉传感器采集周围环境数据

clip_image030

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 Libraryhttp://gamma.cs.unc.edu/FCL/fcl_docs/webpage/generated/index.html)功能包。碰撞检测是运动规划中最耗时的运算,往往会占用90%左右的时间,为了减少计算量,可以通过设置ACM( Allowed Collision Matrix )来进行优化,如果两个bodys之间的ACM设置为1,则意味着这两个bodys永远不会发生碰撞,不需要碰撞检测。


原创文章,转载请注明: 转载自古月居

本文链接地址: ROS探索总结(二十五)——MoveIt基础

微信 OR 支付宝 扫描二维码
为本文作者 打个赏
pay_weixinpay_weixin

评论

16条评论
  1. Gravatar 头像

    Y-liberal 回复

    古月老师,你好。我目前也在学习ROS,但是我发现里面的函数实在是太多了,不知道怎样才能找到所需要的函数。我不知道学习编程语言的时候应该是什么套路,我的理解是先看懂代码,然后在模仿写代码,但是目前我连ROS的代码都看不懂,在找相关函数的结构都找不到,现在已经到了困境了,不知道该如何脱离,恳请指教。

    • 古月

      古月 回复

      @Y-liberal 如果你是ROS初学者,建议先了解ROS的框架、基础概念、编程方法。ROS是一个非常大的社区,有很多功能包,首先需要找到你需要的功能包,大部分功能包的使用不需要去看实现代码,只需要关注topic、service、parameter等接口即可使用,如果涉及到代码级的API使用,就需要去看代码的接口函数了,分成两种情况:一种是使用ROS自身的API,比如说moveit、tf、move_base,这些功能包的API使用wiki上可以找到手册,也可以看其他其他机器人的使用例程;另外一种就是他人分享的功能包,不会有完整的手册,就需要去看代码了。总体来讲,如果不涉及到功能包源码级的修改,基本不用看ROS的C++代码,会使用接口即可。

    • 古月

      古月 回复

      @Y-liberal 如果你指的是节点创建、话题创建等函数的使用,可以看现有的ROS书籍和书籍配套的源码,讲解更详细

      • Gravatar 头像

        Y-liberal 回复

        @古月 古月老师,你好,可能我的问题描述的不是很清楚。我想用moveit控制串联机械臂,没有实体,只是用urdf文件进行仿真而已,想做到的程度就是能够进行运动学正解和逆解,然后再做一下轨迹规划,至于后面的运动控制问题,会放着慢慢解决。但现在遇到的主要困难有以下几个:
        1.看moveit官网上的教程,然后自己学习,发现用它的repository可以实现运动,但是仿照它的代码编写的程序总是出现各种各样的编译错误,刚解决完一个,又出现好几个,晕头转向。我用的Ubuntu的16.04kinetic ROS系统
        2.看到官网的程序,知道是这么写的,但是当换了本体,换了需求的时候需要用新的函数,这个时候就不知道该选用什么样的函数了。
        3.我的C++语言基础很薄弱,对于官网中的程序,有的时候看不懂它用的什么语法,然后在网上找相关内容,发现虽然看起来用的一样,但其实它们是有区别的,分辨不清楚到底函数该怎么用。
        4.公司项目催的紧,需要的时间只有三个月,目前快过去一半了。我每天加班加点的学,但感觉像无头苍蝇一样乱飞,不知道哪里才是入口。所以特别希望古月老师能够指导一下,并推荐一些好的学习moveit的教材,或者你当时用来学习的教材。现在真的是深陷苦海,无法出逃。
        5.希望能联系到古月老师,向您学习一下,自学东西真的是太难了。我的微信号是410396405,希望能得到您的帮助。
        对我而言那些节点的创建和话题的创建不是太难但是

        • 古月

          古月 回复

          @Y-liberal 推荐你一本书:mastering ros for robotics programming,里边有从模型到控制的详细讲解,源码也可以直接复用,应该可以满足你目前的需求,另外还有一本ros by example vol 2 可以作为参考。至于代码,主要是MoveIt中API的使用,仿照书中的例程来用,也可以参考MoveIt的wiki。编程语言就是基础了,本身和ROS没什么关系,还是得多看多写。
          建议先把书里的代码跑通了,再看代码,可以直接在源码的基础上改成自己的。

          • Gravatar 头像

            Y-liberal 回复

            @古月 嗯,好的,谢谢古月老师,还有一个问题,就是用moveit的话,C++需要学到什么程度?

            • 古月

              古月 回复

              @Y-liberal 这个看你的项目需求了,没有一个固定的标准,如果不去看moveit内部实现代码的话,不需要很多C++的高级内容。重点还是一边看一边学,浏览一下C++的基础内容,然后在开发过程中遇到不明白的就去学习相关的内容,没必要花很长时间专门学C++。

              • Gravatar 头像

                Y-liberal 回复

                @古月 好的,谢谢古月老师。

  2. Gravatar 头像

    李锐 回复

    大神你好,我用的UR5 package,准备在gazebo里进行真实仿真。能在rviz里进行plan & execute。但是gazebo里的ur模型并不会更新状态也不会移动,请问我是漏了什么关键步骤吗?我是按照wiki里面一步一步来的。http://wiki.ros.org/ur_gazebo?distro=kinetic

    • 古月

      古月 回复

      @李锐 你好,我按照wiki试了一下,是没问题的,这个是官方的包,只要安装了所有需要的功能包,不应该有问题。你先检查一下有没有报错的地方,再用rqt_graph命令看一下节点图,从move_group到gazebo应该有一个/joint_states话题,从gazebo到robot_state_publisher也应该有一个/joint_states话题

      • Gravatar 头像

        李锐 回复

        @古月 居然回复我了,这个问题已经解决了。问题好像出在主机与机械臂之间的无线网络连接不稳定。当我用有线网路的时候这个问题就没有了。目前我用moveit的API控制ur5做正运动学规划,存在一个执行时间的限制。set target & go的时候如果速度比较低,机械臂将会在中途停下来。我想问一下这个时间限制是写到hardware_interface里了吗?还有moveit里面是否可以对关节角速度和角加速度进行控制。

        • Gravatar 头像

          李锐 回复

          @李锐 我已经找到控制速度和加速度的函数了。目前存在一个问题,我把代码贴上来
          moveit_commander.roscpp_initialize(sys.argv)

          arm=moveit_commander.MoveGroupCommander('manipulator')

          end_effector_link=arm.get_end_effector_link()
          reference_frame='base_link'
          arm.set_pose_reference_frame(reference_frame)

          arm.allow_replanning(True)
          arm.set_goal_position_tolerance(0.01)
          arm.set_goal_orientation_tolerance(0.1)
          arm.set_max_velocity_scaling_factor(0.2)
          arm.set_max_acceleration_scaling_factor(0.02)
          arm.set_named_target("reset")
          arm.go()
          rospy.sleep(2)

          target_pose=PoseStamped()
          target_pose.header.stamp=rospy.Time.now()
          target_pose.pose.position.x=-0.62
          target_pose.pose.position.y=-0.35
          target_pose.pose.position.z=0.20
          target_pose.pose.orientation.x=0
          target_pose.pose.orientation.y=0
          target_pose.pose.orientation.z=0
          target_pose.pose.orientation.w=1.0

          arm.set_pose_target(target_pose,end_effector_link)
          arm.set_start_state_to_current_state()

          traj=arm.plan()
          arm.execute(traj)
          rospy.sleep(2)

          saved_target_pose=arm.get_current_pose(end_effector_link)
          arm.set_named_target("reset")
          arm.go()
          rospy.sleep(1)

          arm.set_pose_target(saved_target_pose,end_effector_link)
          arm.go()
          rospy.sleep(1)
          我设定了TCP的位姿,但是每次执行相同的代码时机械臂就会到达一个随机的位姿。很奇怪

          • 古月

            古月 回复

            @李锐 在设置target_pose的时候加上:
            target_pose.header.frame_id = reference_frame
            试试行不行

  3. Gravatar 头像

    moveit!新手 回复

    古月大神,您好。
    请问一下,在RVIZ里面显示了机械臂的初始和目标状态,而且可以更新
    但是plan and execute 总是显示failed 怎么解决呀?
    谢谢~
    以下是报错
    [ WARN] [1493106880.035669047]: The root link base_link has an inertia specified in the URDF, but KDL does not support a root link with an inertia. As a workaround, you can add an extra dummy link to your URDF.

    [ WARN] [1493106895.866520376]: Unable to find a random collision free configuration after 100 attempts

    Unable to find a valid state nearby the start state (using jiggle fraction of 0.050000 and 100 sampling attempts). Passing the original planning request to the planner.

    [ WARN] [1493106905.152040983]: RRTConnect: Skipping invalid start state (invalid state)
    [ERROR] [1493106905.154846833]: RRTConnect: Motion planning start tree could not be initialized!

  4. Gravatar 头像

    JF 回复

    古月,您好,不知道怎么能联系上您,所以只能给您留言了,我是上海哲谦应用科技的,说大了就是看你的文章在学习,直接点就是想找您合作,方便的话,您能把你的联系方式发到我的邮箱吗?zzhang0617@163.com 希望您能看到我的这条留言,也希望您能给我发个联系邮件,我们具体谈,谢谢!

发表评论

电子邮件地址不会被公开。 必填项已用*标注