ROS探索总结(三十一)——ros_control

  • 内容
  • 评论
  • 相关

ROS中提供了丰富的机器人应用:SLAM、导航、MoveIt......但是你可能一直有一个疑问,这些功能包到底应该怎么样用到我们的机器人上,也就是说在应用和实际机器人或者机器人仿真器之间,缺少一个连接两者的东西。

clip_image002

ros_control就是ROS为用户提供的应用与机器人之间的中间件,包含一系列控制器接口、传动装置接口、硬件接口、控制器工具箱等等,可以帮助机器人应用快速落地,提高开发效率。

 

一、总体框架

clip_image004

上图是ros_control的总体框架,可以看到正对不同类型的控制器(底盘、机械臂等),ros_control可以提供多种类型的控制器,但是这些控制器的接口各不相同,为了提高代码的复用率,ros_control还提供一个硬件的抽象层。

clip_image006

硬件抽象层负责机器人硬件资源的管理,而controller从抽象层请求资源即可,并不直接接触硬件。

clip_image008

上图是ros_control的数据流图,可以更加清晰的看到每个层次包含的功能:

  1. Controller Manager:每个机器人可能有多个controller,所以这里有一个控制器管理器的概念,提供一种通用的接口来管理不同的controllercontroller manager的输入就是ROS上层应用的输出。
  2. Controllercontroller可以完成每个joint的控制,请求下层的硬件资源,并且提供了PID控制器,读取硬件资源接口中的状态,在发布控制命令。
  3. Hardware Rescource:为上下两层提供硬件资源的接口。
  4. RobotHW:硬件抽象层和硬件直接打交道,通过writeread方法来完成硬件的操作,这一层也包含关节限位、力矩转换、状态转换等功能。
  5. Real Robot:实际的机器人上也需要有自己的嵌入式控制器,接收到命令后需要反映到执行器上,比如接收到位置1的命令后,那就需要让执行器快速、稳定的到达位置1

 

二、Controllers

ros_controllers这个功能包提供了已有的一些controllers

clip_image010

当然,我们也可以根据自己的需求,创建需要的controller,然后通过controller来管理自己创建的controller,可以参考https://github.com/ros-controls/ros_control/wiki/controller_interface

clip_image012

 

 

三、Hardware Interface

Hardware InterfacecontrollerRobotHw沟通的接口,基本上和controllers的种类是对应的,同样可以自己创建需要的接口,可以参考:https://github.com/ros-controls/ros_control/wiki/hardware_interface

clip_image014clip_image015

 

 

四、Transmissions

Transmissions就是机器人的传动系统,机器人每个需要运动的关节都需要配置相应的Transmission

可以通过代码完成https://github.com/ros-controls/ros_control/wiki/transmission_interface,但大部分情况下,都会在URDF文件中直接添加(http://ros.org/wiki/urdf/XML/Transmission):

  1. <transmission name="simple_trans">
  2.      <type>transmission_interface/SimpleTransmission</type>
  3.      <joint name="foo_joint">
  4.           <hardwareInterface>EffortJointInterface</hardwareInterface>
  5.      </joint>
  6.      <actuator name="foo_motor">
  7.           <mechanicalReduction>50</mechanicalReduction>
  8.           <hardwareInterface>EffortJointInterface</hardwareInterface>
  9.      </actuator>
  10. </transmission>

 

五、Joint Limits

Joint Limits是硬件抽象层中的一块,维护一个关节限位的数据结构,这些限位数据可以从机器人的URDF文件中加载,也可以ROS的参数服务器上加载(先用YAML配置文件导入ROS parameter server),这些限位数据不仅包含关节速度、位置、加速度、加加速度、力矩等方面的限位,还包含安全作用的位置软限位、速度边界(k_v位置边界(k_p等等。

我们来看一个URDF中设置Joint Limits的例子:

  1. <joint name="$foo_joint" type="revolute">
  2.   <!-- other joint description elements -->
  3.  
  4.   <!-- Joint limits -->
  5.   <limit lower="0.0"
  6.          upper="1.0"
  7.          effort="10.0"
  8.          velocity="5.0" />
  9.  
  10.   <!-- Soft limits -->
  11.   <safety_controller k_position="100"
  12.                      k_velocity="10"
  13.                      soft_lower_limit="0.1"
  14.                      soft_upper_limit="0.9" /> 
  15. </joint>

还有一些参数需要通过YAML配置文件先加载到参数服务器中,YAML文件的格式如下:

  1. joint_limits:
  2.   foo_joint:
  3.     has_position_limits: true
  4.     min_position: 0.0
  5.     max_position: 1.0
  6.     has_velocity_limits: true
  7.     max_velocity: 2.0
  8.     has_acceleration_limits: true
  9.     max_acceleration: 5.0
  10.     has_jerk_limits: true
  11.     max_jerk: 100.0
  12.     has_effort_limits: true
  13.     max_effort: 5.0
  14.   bar_joint:
  15.     has_position_limits: false # Continuous joint
  16.     has_velocity_limits: true
  17.     max_velocity: 4.0

另外,我们还可以在代码中使用joint_limits_interface来加载和设置关节的限位参数,可以参考:joint_limits_interface

 

六、controller manager

controller_manager提供了一种多controller控制的机制,可以加载、开始运行、停止运行、卸载不同的controller,并且提供了多种工具来完成这些操作。

 

clip_image017

 

1.命令行工具

命令行的格式为:

  1. $ rosrun controller_manager controller_manager <command> <controller_name>

支持的<command>

  • load: load a controller (construct and initialize)
  • unload: unload a controller (destruct)
  • start: start a controller
  • stop: stop a controller
  • spawn: load and start a controller
  • kill: stop and unload a controller

如果想要查看某个controller的状态,可以使用下边的命令:

  1. $ rosrun controller_manager controller_manager <command>

支持的<command>

  • list: list all the controllers in the order they are executed, and give the state of each controller
  • list-types: list all the controller types the controller manager knows about. If your controller is not in this list, you won't be able to spawn it.
  • reload-libraries: Reloads all the controller libraries that are available as plugins. This is convenient when you are developing a controller and you want to test your new controller code, without restarting the robot every time. This does not restart controllers which were running before.
  • reload-libraries --restore: Reloads all the controller libraries that are available as plugins and restores all controllers to their original state.

但是很多时候我们需要控制的controller有很多,比如六轴机器人,至少有六个controller,这时也可以使用“spawner ”这个命令来一次控制多个controller

  1. rosrun controller_manager spawner [--stopped] name1 name2 name3

上边的命令可以自动加载、启动controller,如果加上--stopped参数,那么contrller则只会被加载,但是并不会开始运行。如果想要停止一系列controller,但是不需要卸载,还需要运行的话,可以使用下边的命令:

  1.  $ rosrun controller_manager unspawner name1 name2 name3

 

2.launch工具

launch文件中,同样可以通过运行controller_manager包的命令,来加载和启动一系列controller

  1.  <launch>
  2.    <node pkg="controller_manager"
  3.          type="spawner"
  4.          args="controller_name1 controller_name2" /> 
  5.  </launch>

上边的launch文件会加载并启动controllers,如果只需要加载:

  1. <launch>
  2.   <node pkg="controller_manager"
  3.     type="spawner"
  4.     args="--stopped controller_name1 controller_name2" />
  5. </launch>

 

3.可视化工具rqt_controller_manager

controller_manager还提供了可视化工具rqt_controller_manager,安装rosrun rqt_controller_manager rqt_controller_manager,直接使用下边的命令打开:

  1. rosrun rqt_controller_manager rqt_controller_manager

不过目前我用的indigo ros版本里边,这个工具貌似有问题,找不到executable

 

七、案例分析

OK,前边学习了这么多新的概念,我们还是找一个实际的案例来分析一下。gazebotutorials里边提供了gazebo_ros_control的教程,用到一个两个关节的机械臂作为案例,我们就来分析一下这个案例中都是怎样落实上边这些概念的。源码可以在这里找到。

clip_image019

首先来看一张gazebo结合ros_control的架构图,其实和上边的数据流图差别不大。

 

1.Transmissions

rrbot有两个关节,每个关节都有一个传动装置,所以应该有两个Transmissions,在rrbotURDF文件rrbot.xacro文件中,我们可以找到这两个Transmissions

  1.   <transmission name="tran1">
  2.     <type>transmission_interface/SimpleTransmission</type>
  3.     <joint name="joint1">
  4.       <hardwareInterface>EffortJointInterface</hardwareInterface>
  5.     </joint>
  6.     <actuator name="motor1">
  7.       <hardwareInterface>EffortJointInterface</hardwareInterface>
  8.       <mechanicalReduction>1</mechanicalReduction>
  9.     </actuator>
  10.   </transmission>
  11.  
  12.   <transmission name="tran2">
  13.     <type>transmission_interface/SimpleTransmission</type>
  14.     <joint name="joint2">
  15.       <hardwareInterface>EffortJointInterface</hardwareInterface>
  16.     </joint>
  17.     <actuator name="motor2">
  18.       <hardwareInterface>EffortJointInterface</hardwareInterface>
  19.       <mechanicalReduction>1</mechanicalReduction>
  20.     </actuator>
  21.  
  22.   </transmission>

同时,为了让Gazebo可以识别<transmission>标签,还需要家在一个gazeboros_control插件:

  1. <gazebo>
  2.   <plugin name="gazebo_ros_control" filename="libgazebo_ros_control.so">
  3.     <robotNamespace>/rrbot</robotNamespace>
  4.   </plugin>
  5. </gazebo>

2.controllercontroller_manager

首先通过一个YAML文件rrbot_control.yaml来声明我们所需要的controller,以及对应的参数:

  1. rrbot:
  2.   # Publish all joint states -----------------------------------
  3.   joint_state_controller:
  4.     type: joint_state_controller/JointStateController
  5.     publish_rate: 50 
  6.  
  7.   # Position Controllers ---------------------------------------
  8.   joint1_position_controller:
  9.     type: effort_controllers/JointPositionController
  10.     joint: joint1
  11.     pid: {p: 100.0, i: 0.01, d: 10.0}
  12.   joint2_position_controller:
  13.     type: effort_controllers/JointPositionController
  14.     joint: joint2
  15.  
  16.     pid: {p: 100.0, i: 0.01, d: 10.0}

其中还需要包含一个joint_state_controller,来控制发布每个关节的实时状态。

然后使用launch文件rrbot_control.launch,运行controller_manager中的spawner,加载并运行这些上边这些controller

  1. <launch>
  2.  
  3.   <!-- Load joint controller configurations from YAML file to parameter server -->
  4.   <rosparam file="$(find rrbot_control)/config/rrbot_control.yaml" command="load"/>
  5.  
  6.   <!-- load the controllers -->
  7.   <node name="controller_spawner" pkg="controller_manager" type="spawner" respawn="false"
  8.     output="screen" ns="/rrbot" args="joint1_position_controller joint2_position_controller joint_state_controller"/>
  9.  
  10.   <!-- convert joint states to TF transforms for rviz, etc -->
  11.   <node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher"
  12.     respawn="false" output="screen">
  13.     <remap from="/joint_states" to="/rrbot/joint_states" />
  14.   </node>
  15.  
  16. </launch>

这个例程没有涉及到Joint Limits。通过下边命令就可以在gazebo中启动rrbot并且开始控制:

  1. roslaunch rrbot_gazebo rrbot_world.launch
  2. roslaunch rrbot_control rrbot_control.launch

clip_image021

也可以手动调用完成controller的加载:

  1. rosservice call /rrbot/controller_manager/load_controller "name: 'joint1_position_controller'"
  2. rosservice call /rrbot/controller_manager/load_controller "name: 'joint2_position_controller'"

启动controller

  1. rosservice call /rrbot/controller_manager/switch_controller "{start_controllers: ['joint1_position_controller','joint2_position_controller'], stop_controllers: [], strictness: 2}"

停止controller

  1. rosservice call /rrbot/controller_manager/switch_controller "{start_controllers: [], stop_controllers: ['joint1_position_controller','joint2_position_controller'], strictness: 2}"

使用下边的命令就可以让机器人动起来:

  1. rostopic pub -1 /rrbot/joint1_position_controller/command std_msgs/Float64 "data: 1.5"
  2. rostopic pub -1 /rrbot/joint2_position_controller/command std_msgs/Float64 "data: 1.0"

 

 


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

本文链接地址: ROS探索总结(三十一)——ros_control

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

评论

41条评论
  1. Gravatar 头像

    镇华 回复

    您好,古月大神,请问我在运行时候出现了这个错误应该怎么解决
    [urdf_spawner-4] process has died [pid 3582, exit code 1, cmd /home/rzh/catkin_ws/src/gazebo_ros_pkgs/gazebo_ros/scripts/spawn_model -urdf -model rrbot -param robot_description __name:=urdf_spawner __log:=/home/rzh/.ros/log/27ce05ca-b21c-11e7-b98c-3497f62b4981/urdf_spawner-4.log].
    log file: /home/rzh/.ros/log/27ce05ca-b21c-11e7-b98c-3497f62b4981/urdf_spawner-4*.log

  2. Gravatar 头像

    罗西 回复

    您好,我自己的模型在gazebo中打开,好像事碰撞属性有点问题,没法调到正好轮子接触地面,一打开就是翻着的,请问应该怎么样解决?

    • 古月

      古月 回复

      @罗西 如果模型是用三维软件设计的,一般可以在设计软件中计算得到惯性矩阵;如果是简单的URDF模型,可以参考Mastering ROS for Robotics Programming里边两轮小车的设置方法,给一个固定值;还有一种方法是通过公式计算惯性矩阵,可以上网找到规则物体的(长方体,圆柱,球)惯性矩阵计算公式。

      • Gravatar 头像

        罗西 回复

        @古月 我的时用三维软件设计的,在gazebo中打开后发现碰撞属性有问题,我直接在xacro文件中改了mass 和 inertia的值,再打开gazebo发现模型全散了 然后没了,不能直接在里面改是吗? 如果我需要改 应该怎么样做

        • 古月

          古月 回复

          @罗西 gazebo是读取的xacro文件中的配置,可以直接在xacro文件中修改。参数设置可能还是有问题,建议先在rviz中看一下机器人的模型,可以控制每个关节运动,测试模型的关节配置是否有问题;如果没有问题的话,再修改物理参数。

          • Gravatar 头像

            罗西 回复

            @古月 您好,我在rviz中打开模型文件报错,报错信息为Fixed Frame
            Fixed Frame [map] does not exist 想请问一下是什么原因?

              • Gravatar 头像

                罗西 回复

                @古月 谢谢,已经解决 但是现在我用 roslaunch xxx display。launch 运行时,模型加载不出来? 还有,我用roscontrol 已经实现单独给每个轮子速度,但是是以命令行的形式发布的,我想把它写成脚本文件来运行,应该参照什么教程呢?

                • 古月

                  古月 回复

                  @罗西 加载的时候看下有没有报错信息;可以参考《Mastering ROS for Robotics Programming》这本书

                  • Gravatar 头像

                    罗西 回复

                    @古月 加载的时候报错信息 [ERROR] [1505985603.016950115, 1.242000000]: Character [.] at element [19] is not valid in Graph Resource Name [joint_limits/joint1.1]. Valid characters are a-z, A-Z, 0-9, / and _.
                    Error [World.cc:1666] Loading model from factory message failed 请问是什么原因导致的?

                    • 古月

                      古月

                      @罗西 好好检查代码,有非法字符

    • Gravatar 头像

      罗西 回复

      @罗西 月哥,你好,因为现在在学习ros,现在学习速度太慢,学着学着不知道该怎么样进行下去,遇到很多问题,想问问最近哪里有没有针对ROS初阶和中阶的培训项目,最好是那种针对具体项目的培训,我想去参加培训,不知道月哥有没有一些好的建议?

      • 古月

        古月 回复

        @罗西 你好,你可以关注一些ros星火计划,会有公开课和进阶课,主要针对ROS实践方面的培训。
        另外建议多看目前已有的英文书籍,先把书中的例程和源码看明白,然后再复用到自己的项目中。

  3. Gravatar 头像

    罗西 回复

    我想问一下,我把这个源文件包直接拷贝到我的 catkin_ws/src文件夹下面,直接运行,报错,我重新编译catkin_make 他也报错,想问一下可能是什么原因 ?

      • Gravatar 头像

        罗西 回复

        @古月 CMake Error at /opt/ros/indigo/share/catkin/cmake/catkinConfig.cmake:75 (find_package):
        Could not find a package configuration file provided by "ros_control" with
        any of the following names:

        ros_controlConfig.cmake
        ros_control-config.cmake

        Add the installation prefix of "ros_control" to CMAKE_PREFIX_PATH or set
        "ros_control_DIR" to a directory containing one of the above files. If
        "ros_control" provides a separate development package or SDK, be sure it
        has been installed.
        Call Stack (most recent call first):
        crobot/crobot_control/CMakeLists.txt:7 (find_package)

        -- Configuring incomplete, errors occurred!
        See also "/home/exbot/catkin_ws/build/CMakeFiles/CMakeOutput.log".
        See also "/home/exbot/catkin_ws/build/CMakeFiles/CMakeError.log".
        make: *** [cmake_check_build_system] Error 1
        Invoking "make cmake_check_build_system" failed
        大概是这样

        • Gravatar 头像

          罗西 回复

          @罗西 大概意思是差东西或者有东西没有添加,因为不能放截图,所以就知粘贴了部分报错信息

          • 古月

            古月 回复

            @罗西 ros_control功能包没有安装,使用以下命令安装:
            sudo apt-get install ros-indigo-ros-control

            • Gravatar 头像

              罗西 回复

              @古月 之前安装过的呀,我再安装是这样
              exbot@ubuntu:~$ sudo apt-get install ros-indigo-ros-control
              [sudo] password for exbot:
              正在读取软件包列表... 完成
              正在分析软件包的依赖关系树
              正在读取状态信息... 完成
              ros-indigo-ros-control is already the newest version.
              升级了 0 个软件包,新安装了 0 个软件包,要卸载 0 个软件包,有 1096 个软件包未被升级。
              N: Ignoring file 'gazebo' in directory '/etc/apt/sources.list.d/' as it has no filename extension
              N: Ignoring file 'gazebo' in directory '/etc/apt/sources.list.d/' as it has no filename extension

              • 古月

                古月 回复

                @罗西 那可能就是环境变量的问题了,编译报错是找不到这个包

                • Gravatar 头像

                  罗西 回复

                  @古月 您好,我把文中rrbot文件下载后运行 rostopic pub -1 /rrbot/joint2_position_controller/command std_msgs/Float64 "data: 1.0" 该命令运行完后,机械臂没动 exbot@ubuntu:~$ rostopic pub -1 /rrbot/joint2_position_controller/command std_msgs/Float64 "data: 1.0"
                  publishing and latching message for 3.0 seconds
                  想问一下是什么原因。

                  • Gravatar 头像

                    罗西 回复

                    @罗西 刚看了一下没有错误 是对的 我想问一下他那个最后一个参数1.0 是表示什么 想让他一直动应该怎么用?

                    • 古月

                      古月

                      @罗西 -1代表只发送一次,如果要一直发送,需要加-r 10,10代表10hz,可以根据需要设置

                    • Gravatar 头像

                      罗西

                      @罗西 想让机械臂一直动,rostopic 应该怎么样加在上面,我试着改了一下,发现不对?

          • Gravatar 头像

            罗西 回复

            @罗西 rostopic pub -r 10 /rrbot/joint2_position_controller/command std_msgs/Float64 "data: 3.0"

            我发布这个rostopic 界面就停住了 也不知道啥情况,请问是什么原因?

            • 古月

              古月 回复

              @罗西 这个topic是让机械臂的joint2运动到3的位置,运动到后就会停止

                  • Gravatar 头像

                    罗西 回复

                    @古月 不好意思 我打错了,我是想问,想让机械臂不停的运动(一直运动),这个rostopic 应该怎么样发布?

                    • 古月

                      古月

                      @罗西 这个命令没办法让机械臂一直运动,机械臂运动到设定的位置就停止了,要一直运动需要写个节点,到达设定目标后发送下一个目标位置

                    • Gravatar 头像

                      罗西

                      @罗西 非常感谢您的解答 如果采用速度控制模式的话,给关节速度,应该就可以一直动了吧

    • 古月

      古月 回复

      @罗西 使用速度控制可以让机器人以指定速度运动,到达限位或者接到停止命令时才停止

  4. Gravatar 头像

    海漩涡 回复

    请问下,能实现给关节发送速度吗,因为这个例子是发送位置的。

  5. Gravatar 头像

    云天 回复

    有点疑问, 硬件的read, write 接口在哪实现呢? 谢谢解答

    • 古月

      古月 回复

      @云天 接口定义在:https://github.com/ros-controls/ros_control/blob/kinetic-devel/hardware_interface/include/hardware_interface/robot_hw.h
      根据自己使用的机器人,需要继承这个类自己实现相应的write和read

      • Gravatar 头像

        云天 回复

        @古月 谢谢! 另外还有一个疑问, 假设机器上是有3个joint,但两个是主动节点, 另一个是被动结点, 也就是它的角度是由前面两个决定的(机械限制), 那么在joint_state_controller是发布三个结点的状态还是两个主动的结点? 还有就是被动结点和主动节点的关系在哪里体现呢?也就是C=A+B, 这个在哪里实现?

        • 古月

          古月 回复

          @云天 这种结构我没试过,不是很清楚,应该是发布两个节点,主动和被动需要在URDF中设置

  6. Gravatar 头像

    海漩涡 回复

    月哥又出新文章了
    而且正是我现在需要弄明白的,好好学习下
    thank

发表评论

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