ROS探索总结(六十六)—— 古月私房课 | MoveIt!中不得不说的“潜规则”

  • 内容
  • 评论
  • 相关

~欢迎关注~

微信公众号:古月居

新浪微博:古月春旭

知乎专栏:古月居

原文链接:古月私房课 | MoveIt!中不得不说的“潜规则”

 

古月居联合深蓝学院推出的“古月私房课”第一弹——《ROS机械臂开发:从入门到实战》已经上线啦,欢迎各位小伙伴前来围观,以下是第七讲《MoveIt!中不得不说的“潜规则”》的内容精要。

大家好,这里是《ROS机械臂开发:从入门到实战》的第七讲——MoveIt!中不得不说的“潜规则”,我是主讲人胡春旭。

幻灯片1

今天我们来揭秘MoveIt!使用过程中的一些潜规则,也是大家经常会有疑惑的地方,很多在MoveIt!教程中并没有说明,而是古月君在研究过程中结合API文档发现的,也给大家分享一下。

幻灯片2

首先我们来看圆弧轨迹的规划。

幻灯片3

很多同学会有这样一个疑问,MoveIt!可以规划笛卡尔直线运动,那能不能规划圆弧运动,甚至任意曲线轨迹的运动呢?MoveIt!中没有直接的API接口,但是下边这张图应该可以给大家灵感:通过直线逼近的方式,就可以实现啦!

幻灯片4

按照这样的思路,我们来看MoveIt!下实现的圆弧轨迹规划例程,演示中我们可以看到机械臂的终端走出了一个完整的圆形轨迹。

幻灯片5

该例程实现的流程:首先通过圆的轨迹方程,计算得到一系列圆上的路径点,然后使用computeCartesianPath函数完成所有路径点之间的直线轨迹规划,最后execute执行运动。

幻灯片6

很多情况下,我们对MoveIt!规划的轨迹并不满意,那这条轨迹能不能修改呢?当然是可以的。

课件_ROS机械臂开发_7. MoveIt!中不得不说的“潜规则”

运行例程,我们可以看到机器人会完成两次相同的运动,但是速度有明显的差异,这就是因为我们对MoveIt!规划的轨迹做了人为的修改。

幻灯片8

该例程实现的流程:首先使用plan正常完成规划,然后遍历规划得到的轨迹数据,里边的位置、速度、加速度、时间想怎么改就怎么改了,最后execute执行修改之后的轨迹即可。

幻灯片9

到现在为止,例程中机械臂每次运动的速度变化都是从0到0的,在连续运动中会出现频繁的停顿,如何减少甚至去掉中间的停顿呢?古月君结合自己对API的研究,给大家介绍一种方法。

幻灯片10

运行多轨迹连续运动的例程,机械臂会一次完成两条轨迹的运动,中间并不会出现停顿的问题。

幻灯片11

该例程的实现相对复杂一些,用到了很多MoveIt!深层的API。主要流程如下:首先规划多条需要连续运动的轨迹,但是此时机器人并没有真实运动,所以需要注意后续轨迹规划的起点应该是前一条轨迹的终点。

幻灯片12

然后创建一个新的轨迹对象,把以上规划好的轨迹全部push进去,再调用IPTP时间最优算法的接口,重新规划这条新轨迹的速度、加速度、时间等信息,规划完成后就可以调用execute连续运动啦。

幻灯片13

最后一个部分我们来介绍如何更换MoveIt!中的运动学插件。

课件_ROS机械臂开发_7. MoveIt!中不得不说的“潜规则”

在之前的课程中,我们介绍过MoveIt!三大核心功能之一就是运动学,那什么是运动学?大家可以参考《机器人学导论》中的理论介绍,以一个两自由度的机械臂为例,已知关节角度推算终端XY坐标的过程就是正运动学,相反就是逆运动学。

幻灯片15

MoveIt!默认使用的运动学插件是KDL,但是该算法是基于迭代的数值解,求解速度慢,失败率高,并不是开发的首选。

幻灯片16

TRAC-IK虽然也是数值解,但是算法上做了很多优化,速度和成功率都有了很大程度的提升。

幻灯片17

TRAC-IK的使用方法也很简单,安装后修改配置文件就可以启用了。

幻灯片18

另外一个运动学插件是基于解析解的IKFAST,可以根据模型生成专属的运动学算法插件,求解速度快,成功率高,不过配置过程着实有点复杂,有兴趣的小伙伴可以参考古月君的配置:

ROS技术点滴 —— MoveIt!中的运动学插件

幻灯片19

以上就是本讲的内容精要,详细讲解过程和仿真/真机演示过程请见具体课程。

幻灯片25

更多精彩,欢迎大家关注“古月居”。

幻灯片28

 

更多内容欢迎关注:

微信公众号:古月居 (guyue_home)

新浪微博:古月春旭

知乎专栏:古月居

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

评论

38条评论
  1. Gravatar 头像

    湖大小王 回复

    古老师,你好!我最近在一个程序里使用了关节角的运动规划和笛卡尔computeCartesianPath()规划,通过setMaxAccelerationScalingFator()和setMaxVelocityScalingFactor()对速度和加速度进行限制,结果发现在目标是关节角的规划运动速度很慢,而computeCartesianPath()规划出来后,机械臂运行很快,感觉速度没有收到限制。请问该怎么对computeCartesianPath()规划进行速度限制呢?

    • 古月

      古月 回复

      @湖大小王 setMaxAccelerationScalingFator()和setMaxVelocityScalingFactor()对computeCartesianPath()不起作用

      • Gravatar 头像

        湖大小王 回复

        @古月 古老师,那么这种笛卡尔空间的运动规划怎么对速度进行限制呢?我现在规划出来了一些列路点,想控制机械臂按照路点运动,你有什么建议吗?

  2. Gravatar 头像

    唐同学 回复

    古老师,那如果是这种情况呢?要怎么处理才好
    dreamer@ubuntu:~/test/src/three_moveit_config/launch$ roslaunch demo.launch
    ... logging to /home/dreamer/.ros/log/97c8385e-82d2-11e9-b9e9-000c2919e353/roslaunch-ubuntu-22346.log
    Checking log directory for disk usage. This may take awhile.
    Press Ctrl-C to interrupt
    Done checking log file disk usage. Usage is <1GB.

    Traceback (most recent call last):
    File "/opt/ros/kinetic/lib/python2.7/dist-packages/roslaunch/__init__.py", line 306, in main
    p.start()
    File "/opt/ros/kinetic/lib/python2.7/dist-packages/roslaunch/parent.py", line 268, in start
    self._start_infrastructure()
    File "/opt/ros/kinetic/lib/python2.7/dist-packages/roslaunch/parent.py", line 217, in _start_infrastructure
    self._load_config()
    File "/opt/ros/kinetic/lib/python2.7/dist-packages/roslaunch/parent.py", line 132, in _load_config
    roslaunch_strs=self.roslaunch_strs, verbose=self.verbose)
    File "/opt/ros/kinetic/lib/python2.7/dist-packages/roslaunch/config.py", line 451, in load_config_default
    loader.load(f, config, verbose=verbose)
    File "/opt/ros/kinetic/lib/python2.7/dist-packages/roslaunch/xmlloader.py", line 749, in load
    self._load_launch(launch, ros_config, is_core=core, filename=filename, argv=argv, verbose=verbose)
    File "/opt/ros/kinetic/lib/python2.7/dist-packages/roslaunch/xmlloader.py", line 721, in _load_launch
    self._recurse_load(ros_config, launch.childNodes, self.root_context, None, is_core, verbose)
    File "/opt/ros/kinetic/lib/python2.7/dist-packages/roslaunch/xmlloader.py", line 685, in _recurse_load
    val = self._include_tag(tag, context, ros_config, default_machine, is_core, verbose)
    File "/opt/ros/kinetic/lib/python2.7/dist-packages/roslaunch/xmlloader.py", line 95, in call
    return f(*args, **kwds)
    File "/opt/ros/kinetic/lib/python2.7/dist-packages/roslaunch/xmlloader.py", line 627, in _include_tag
    default_machine, is_core, verbose)
    File "/opt/ros/kinetic/lib/python2.7/dist-packages/roslaunch/xmlloader.py", line 655, in _recurse_load
    default_machine, is_core, verbose)
    File "/opt/ros/kinetic/lib/python2.7/dist-packages/roslaunch/xmlloader.py", line 681, in _recurse_load
    self._rosparam_tag(tag, context, ros_config, verbose=verbose)
    File "/opt/ros/kinetic/lib/python2.7/dist-packages/roslaunch/xmlloader.py", line 95, in call
    return f(*args, **kwds)
    File "/opt/ros/kinetic/lib/python2.7/dist-packages/roslaunch/xmlloader.py", line 239, in _rosparam_tag
    self.load_rosparam(context, ros_config, cmd, param, file, value, verbose=verbose, subst_function=subst_function)
    File "/opt/ros/kinetic/lib/python2.7/dist-packages/roslaunch/loader.py", line 430, in load_rosparam
    self.add_param(ros_config, full_param, data, verbose=verbose)
    File "/opt/ros/kinetic/lib/python2.7/dist-packages/roslaunch/loader.py", line 357, in add_param
    self.add_param(ros_config, ns_join(param_name, k), v, verbose=verbose)
    File "/opt/ros/kinetic/lib/python2.7/dist-packages/roslaunch/loader.py", line 357, in add_param
    self.add_param(ros_config, ns_join(param_name, k), v, verbose=verbose)
    File "/opt/ros/kinetic/lib/python2.7/dist-packages/rosgraph/names.py", line 172, in ns_join
    if is_private(name) or is_global(name):
    File "/opt/ros/kinetic/lib/python2.7/dist-packages/rosgraph/names.py", line 133, in is_private
    return name and name[0] == PRIV_NAME
    TypeError: 'int' object has no attribute '__getitem__'
    谢谢老师的指点

    • Gravatar 头像

      唐同学 回复

      @唐同学 我也是从solidwork里面导出了urdf文件 ,并且在movit里面配置了文件,并且通过catkin_make编译过工作空间了,显示成功导出了包,但是当我运行demo.launch的时候出现了报错

      • 古月

        古月 回复

        @唐同学 solidworks默认导出的包有bug的,检查下模型urdf文件和launch中的路径

  3. Gravatar 头像

    刘宇程 回复

    老师您好,我的模型是六轴加一个打磨头,在书上10.9.2做工作空间规划时,我按照书中步骤,运行时出现这样的问题:
    Could not find the planner configuration 'None' on the param server

    [ERROR] [1557493702.607948236]: RRTConnect: Unable to sample any valid states for goal tree
    [ INFO] [1557493702.608001018]: RRTConnect: Created 1 states (1 start + 0 goal)
    [ INFO] [1557493702.608022100]: No solution found after 5.006618 seconds
    [ INFO] [1557493702.632580424]: Unable to solve the planning problem
    [ INFO] [1557493702.633094763]: Execution request received
    [ INFO] [1557493702.988561284]: Completed trajectory execution with status SUCCEEDED ...
    这样的类似错误有好几个

    导致Fail: ABORTED: No motion plan found. No execution attempted.
    我做的改动是在rosbot.srdf中增加了如下内容:

    ,Link 7就是我的打磨头。谢谢老师

      • Gravatar 头像

        刘宇程 回复

        @古月 老师您好,上面没显示,我在srdf加的是

        我应该在URDF中有link7的定义,我还应该加什么

        • Gravatar 头像

          刘宇程 回复

          @刘宇程 内容加的end_effector name="polisher" parent_link="Link7" group="arm"
          group name="polish"
          link name="Link7"
          joint name="joint7"
          /group

          • 古月

            古月 回复

            @刘宇程 你得按照moveit setup assistant做urdf的配置,不能直接修改srdf,还有很多其他参数文件需要配套生成

            • Gravatar 头像

              刘宇程 回复

              @古月 谢谢老师指点。因为出现[ WARN] [1557884400.180857309]: Could not identify parent group for end-effector 'polisher',Could not find the planner configuration 'None' on the param server,请您看下我的规划存在哪些问题:我的轴有dummy,base_link,link1,...,link6,link7(打磨头),polish_frame(打磨头圆盘上建的参考坐标),关节:dummy_joint,joint1,...,joint6(1到6都为旋转关节),joint7,polish_frame_joint(这两个为固定关节),规划组有:arm:chain:base_link->link6。polish:joint:join7,polish_frame_joint.link:,link7,polish_frame。
              end_effector name="polisher" parent_link="polish_frame" group="polish"。万分感谢

  4. Gravatar 头像

    烟消云散 回复

    古月老师你好,在微信群里有问题想问你可是你一直都比较忙有的时候没空看,所以来这里留个言.
    听说你做机械臂开发,不知道这个问题你知不知道:假设我要在ROS下自己规划一条轨迹然后发送给joint_trajectory,那么首先我就得先定义一个joint_trajectory,这个Joint_trajectory是空的,然后我添加机械臂的名字joint_nams时直接push_back就添加成功了,但是我想要把自己规划的轨迹的Points添加到这个Joint_trajectory里面,却怎么也加不进去,是不是要自己先写一个跟joint_trajectory格式的机械臂的points的结构体才能添加?

    • 古月

      古月 回复

      @烟消云散 思路是没问题的,Joint_trajectory就是一个数据结构,往里放数据就行了,具体可以看下文档里的定义,points是一个vector

  5. Gravatar 头像

    xarthurx 回复

    這個velocity_scaling的方法非常簡單粗暴,點個贊!
    測試了好多種Cartesian Path的調節速度的方法,終於找到一個能用的了~

  6. Gravatar 头像

    何绪晖 回复

    胡老师,您好,学生有几个问题想向您请教,我从solidwork里面导出了urdf文件 ,并且在movit里面配置了文件,并且通过catkin_make编译过工作空间了,显示成功导出了包,但是当我运行demo.launch的时候出现了以下报错
    roslaunch robot_config demo.launch
    INFO: cannot create a symlink to latest log directory: [Errno 13] Permission denied: '/home/simon/.ros/log/latest'
    WARNING: unable to configure logging. No log files will be generated
    Checking log directory for disk usage. This may take awhile.
    Press Ctrl-C to interrupt
    Done checking log file disk usage. Usage is <1GB.

    Traceback (most recent call last):
    File "/opt/ros/melodic/lib/python2.7/dist-packages/roslaunch/__init__.py", line 322, in main
    p.start()
    File "/opt/ros/melodic/lib/python2.7/dist-packages/roslaunch/parent.py", line 277, in start
    self._start_infrastructure()
    File "/opt/ros/melodic/lib/python2.7/dist-packages/roslaunch/parent.py", line 226, in _start_infrastructure
    self._load_config()
    File "/opt/ros/melodic/lib/python2.7/dist-packages/roslaunch/parent.py", line 138, in _load_config
    roslaunch_strs=self.roslaunch_strs, verbose=self.verbose)
    File "/opt/ros/melodic/lib/python2.7/dist-packages/roslaunch/config.py", line 457, in load_config_default
    loader.load(f, config, argv=args, verbose=verbose)
    File "/opt/ros/melodic/lib/python2.7/dist-packages/roslaunch/xmlloader.py", line 751, in load
    self._load_launch(launch, ros_config, is_core=core, filename=filename, argv=argv, verbose=verbose)
    File "/opt/ros/melodic/lib/python2.7/dist-packages/roslaunch/xmlloader.py", line 723, in _load_launch
    self._recurse_load(ros_config, launch.childNodes, self.root_context, None, is_core, verbose)
    File "/opt/ros/melodic/lib/python2.7/dist-packages/roslaunch/xmlloader.py", line 687, in _recurse_load
    val = self._include_tag(tag, context, ros_config, default_machine, is_core, verbose)
    File "/opt/ros/melodic/lib/python2.7/dist-packages/roslaunch/xmlloader.py", line 95, in call
    return f(*args, **kwds)
    File "/opt/ros/melodic/lib/python2.7/dist-packages/roslaunch/xmlloader.py", line 629, in _include_tag
    default_machine, is_core, verbose)
    File "/opt/ros/melodic/lib/python2.7/dist-packages/roslaunch/xmlloader.py", line 657, in _recurse_load
    default_machine, is_core, verbose)
    File "/opt/ros/melodic/lib/python2.7/dist-packages/roslaunch/xmlloader.py", line 683, in _recurse_load
    self._rosparam_tag(tag, context, ros_config, verbose=verbose)
    File "/opt/ros/melodic/lib/python2.7/dist-packages/roslaunch/xmlloader.py", line 95, in call
    return f(*args, **kwds)
    File "/opt/ros/melodic/lib/python2.7/dist-packages/roslaunch/xmlloader.py", line 241, in _rosparam_tag
    self.load_rosparam(context, ros_config, cmd, param, file, value, verbose=verbose, subst_function=subst_function)
    File "/opt/ros/melodic/lib/python2.7/dist-packages/roslaunch/loader.py", line 433, in load_rosparam
    self.add_param(ros_config, full_param, data, verbose=verbose)
    File "/opt/ros/melodic/lib/python2.7/dist-packages/roslaunch/loader.py", line 364, in add_param
    self.add_param(ros_config, ns_join(param_name, k), v, verbose=verbose)
    File "/opt/ros/melodic/lib/python2.7/dist-packages/roslaunch/loader.py", line 364, in add_param
    self.add_param(ros_config, ns_join(param_name, k), v, verbose=verbose)
    File "/opt/ros/melodic/lib/python2.7/dist-packages/rosgraph/names.py", line 172, in ns_join
    if is_private(name) or is_global(name):
    File "/opt/ros/melodic/lib/python2.7/dist-packages/rosgraph/names.py", line 133, in is_private
    return name and name[0] == PRIV_NAME
    TypeError: 'int' object has no attribute '__getitem__'
    我已经重装过ros 重装过ubuntu 了 可是仍旧出现这个错 清老师给我分析分析

    • 古月

      古月 回复

      @何绪晖 INFO: cannot create a symlink to latest log directory: [Errno 13] Permission denied: '/home/simon/.ros/log/latest'
      有一句这个错误,应该是文件的权限不够,提升下权限

  7. Gravatar 头像

    小张 回复

    月哥哥,通过moveit控制gazebo中的机械臂的时候,出现了这个问题,您遇见过吗?
    Dropping first 1 trajectory point(s) out of 27, as they occur before the current time.
    First valid point will be reached in 0.239s.
    gazebo中的机械臂会动,rviz中会停在开始的地方。

  8. Gravatar 头像

    牛大 回复

    胡老师好!我在你的ros机器人开发实践这本书的10.7,添加arbotix关节控制器这一章节中,尝试着跑下你的教程,控制一个六轴的机械臂运动,配置文件,py源码都是按照你书上的来写的,只是换了一个模型,但是运行的时候臂架在rviz中根本不动,提示:[INFO] [1555923605.106513]: left_controller: Action goal recieved.
    [INFO] [1555923605.107088]: Executing trajectory
    [INFO] [1555923608.109254]: left_controller: Done.
    [WARN] [1555923608.141007]: Inbound TCP/IP connection failed: connection from sender terminated before handshake header received. 0 bytes were received. Please check sender for additional details.
    这是什么问题导致的机械臂不动啊

    • Gravatar 头像

      牛大 回复

      @牛大 这个问题已经解决了,不过我在运行10.9的关节空间规划时,会提示错误
      [ INFO] [1556090360.227002187]: RRTConnect: Created 5 states (3 start + 2 goal)
      [ INFO] [1556090360.227065154]: Solution found in 0.023067 seconds
      [ INFO] [1556090360.240247522]: SimpleSetup: Path simplification took 0.012945 seconds and changed from 4 to 2 states
      [ERROR] [1556090360.241767347]: Unable to identify any set of controllers that can actuate the specified joints: [ j1 j2 j3 j4 j5 j6 j7 j8 ]
      [ERROR] [1556090360.241801231]: Known controllers and their joints:
      [ERROR] [1556090360.241841205]: Apparently trajectory initialization failed
      我有8个关节,请问下这是出什么问题了

    • 古月

      古月 回复

      @牛大 应该是模型和控制器中间的某些参数没配置好,检查下各种命名

  9. Gravatar 头像

    小李 回复

    [ERROR] [1555400928.114091131]: Validation failed: Trajectory doesn't start at current position.这个错误怎么解决??

      • Gravatar 头像

        小李 回复

        @古月 古老师,这个问题该如何解决?

        • 古月

          古月 回复

          @小李 程序里加一句设置当前位置为起始位置

          • Gravatar 头像

            小李 回复

            @古月 group.set_start_state_to_current_state(),这个我已经加进去了,但是错误还是会发生 。这又是为什么?

  10. Gravatar 头像

    刘凌峰 回复

    古老师,我的机器人结构中有一两个关节是移动关节,但是moveit教程中使用的控制器是Arbotix,好像针对的是旋转关节,请问有什么关节控制器的推荐或者案例教程吗

    • 古月

      古月 回复

      @刘凌峰 Arbotix应该可以设置平移关节的,或者用ros_controller里边的位置控制器

      • Gravatar 头像

        刘凌峰 回复

        @古月 那么Arbotix的配置文件应该怎么写啊,应该把max_angle改成什么了

  11. Gravatar 头像

    小昌同学 回复

    古老师,我在用cartographer跑自己的bag,可是一直有问题,我是参考cartographer的文档修改的,请问配置需要注意些什么呢?

  12. Gravatar 头像

    小张 回复

    月哥哥,这一课的代码在哪能找到呀?我想学习学习 😛 ,还是 要花钱买呀

烟消云散进行回复 取消回复

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

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据