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"

 



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM