在前面的三篇中,对ros_control也有个大致了解了。这篇就是将之前学到的用于我们实验室的平台KUKA youBot上。在此之前,其实网上已经有关于youBot在Gazebo下的仿真视频了。

另外说个题外话,用Gazebo和Rviz都可以做仿真,Gazebo最强大的是拥有物理引擎,有物理渲染,有碰撞效果、重力等等。

这里参考的package主要是:

建议大家直接照着第二个来,很快就可以用起来,它主要是启动gazebo仿真环境,加载模型。也即上面文章的第二、三个阶段,加载完仿真的控制器后就可以对它进行控制了。它的节点图如下所示,已经暴露出来了控制手臂和夹子的action接口,同时还接受cmd_vel这个topic,发布odom。

1. Topic直接控制

这个action接口与实际机器人的是一样的,直接拿一个以前action教程的程序,跑一跑。发现Gazebo中的机器人也动起来了。

2. Moveit轨迹规划输出到Gazebo中的youBot上

同上一篇文章一样,我们也可以利用Moveit来生成控制轨迹输出控制youBot。视频如下:

http://v.youku.com/v_show/id_XMTU4MTYxNjA2MA==.html

这里主要的问题有两个:

  1. navigation的时候,rviz中的模型可以动,但是Gazebo中的却没有运动。
  2. 我的fixed 坐标用的是odom,相对于它,坐标在用nav的时候场景也跟着旋转了(机器人相对于场景并没有变化),而实际上在ros_control(2)中,那个差速驱动的小车并不是这样,这里的运动很有问题。

这是我们系统上的所有的controller,可以看到里面有我们下文将会提到的SteeredWheelBaseController,在倒数第二个。

我们利用上面的package加载的controller可以用命令查看,如下:

3. 改动官方的youbot description自己添加控制接口

要学到东西,最好的办法就是自己做一遍,确实我遇到了很多问题,但是发现慢慢思路也明朗不少。

最开始,我的youbot description是官方的,后来同学介绍,发现一个模型还不错的包,最主要的区别就是轮子不再是四个球了,更真实一些。也即上面的第一个链接里的description。

第二个我做了修改的地方是,夹子之间加了一个坐标系,同时加入了xtion深度相机。

1. 第一步还是从urdf.xacro开始

这里涉及文件较多,请掏出A4纸,自己对着文件一个个做好笔记。

youbot官方其实已经将xacro中包含了一些gazebo的transmission以及interface,也即lib*.so文件。特别要注意的是urdf/youbot_base/base.gazebo.xacro这个文件,这个文件包含的是libgazebo_ros_planar_move.so它的作用就是将输入的cmd_vel(底座的线速度和角速度)转化为odom topic(包含机器人自己的位置、姿态以及线速度和角速度)。后来在搜索的过程中,发现另一种写法SteeredWheelBaseController。这里埋下伏笔,主要是在odom,底座移动的时候才会做修改,如果只是控制手臂,先不用改。

有了这个之后第二步就是将模型加载到Gazebo。

2. 将模型加载到Gazebo

加载的时候是起名为youbot_world.launch

<launch>
 
  <arg name="paused" default="false"/>
  <arg name="use_sim_time" default="true"/>
  <arg name="gui" default="true"/>
  <arg name="headless" default="false"/>
  <arg name="debug" default="false"/>
 
  <arg name="init_pos_x" default="0.0"/>
  <arg name="init_pos_y" default="0.0"/>
  <arg name="init_pos_z" default="0.1"/>
 
    <include file="$(find gazebo_ros)/launch/empty_world.launch">
<!--	<arg name="world_name" value="$(find youbot_gazebo)/worlds/laser_box.world"/>-->
    <arg name="debug" value="$(arg debug)" />
    <arg name="gui" value="$(arg gui)" />
    <arg name="paused" value="$(arg paused)"/>
    <arg name="use_sim_time" value="$(arg use_sim_time)"/>
    <arg name="headless" value="$(arg headless)"/>
  </include>
 
  <param name="robot_description"
	 command="$(find xacro)/xacro.py '$(find youbot_description)/robots/youbot.urdf.xacro'" />
 
  <!-- Run a python script to the send a service call to gazebo_ros to spawn a URDF robot -->
  <node name="urdf_spawner" pkg="gazebo_ros" type="spawn_model" respawn="false" output="screen"
	args="-urdf
	      -model youbot
	      -param robot_description
	      -x $(arg init_pos_x)
           -y $(arg init_pos_y)
           -z $(arg init_pos_z)
	      "/>
 
  <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" output="screen" respawn="false">
    <param name="publish_frequency" type="double" value="50.0" />
  </node>
</launch>
3. 配置控制接口

我的文件总的如下,是将它依据不同的controller分散到三个不同的文件中,因为为了与实际的topic对上,arm跟gripper是有arm_1这个命名空间的,所以它们两个放在一个文件里,然后base_controller和joint_state_controller单独作为一个。

joint_state_controller:
    type: joint_state_controller/JointStateController
    publish_rate: 100
arm_controller:
  type: effort_controllers/JointTrajectoryController
  joints:
    - arm_joint_1
    - arm_joint_2
    - arm_joint_3
    - arm_joint_4
    - arm_joint_5
  gains:
    arm_joint_1: {p: 1000.0, i: 0.01, d: 0.1}
    arm_joint_2: {p: 1000.0, i: 0.01, d: 0.1}
    arm_joint_3: {p: 1000.0, i: 0.01, d: 0.1}
    arm_joint_4: {p: 1000.0, i: 0.01, d: 0.1}
    arm_joint_5: {p: 1000.0, i: 0.01, d: 0.1}
gripper_controller:
  type: effort_controllers/JointTrajectoryController
  joints:
    - gripper_finger_joint_l
    - gripper_finger_joint_r
  gains:
    gripper_finger_joint_l: {p: 1000.0, d: 1.0}
    gripper_finger_joint_r: {p: 1000.0, d: 1.0}
base_controller:
  pid_gains:
    wheel_joint_fl: {p: 100.0, i: 0.0, d: 1.0}
    caster_joint_fl: {p: 100.0, i: 0.0, d: 1.0}
    wheel_joint_fr: {p: 100.0, i: 0.0, d: 1.0}
    caster_joint_fr: {p: 100.0, i: 0.0, d: 1.0}
    wheel_joint_bl: {p: 100.0, i: 0.0, d: 1.0}
    caster_joint_bl: {p: 100.0, i: 0.0, d: 1.0}
    wheel_joint_br: {p: 100.0, i: 0.0, d: 1.0}
    caster_joint_br: {p: 100.0, i: 0.0, d: 1.0}

  type: steered_wheel_base_controller/SteeredWheelBaseController

  base_frame: base_footprint

  linear_speed_limit: 1.5
  linear_acceleration_limit: 2.5
  linear_deceleration_limit: 2.5

  yaw_speed_limit: 3.0
  yaw_acceleration_limit: 3.2
  yaw_deceleration_limit: 3.2

  cmd_vel_timeout: 0.0  # disabled, as it is on the real platform

  wheels:
    - steering_joint: caster_joint_fl
      axle_joint: wheel_joint_fl
      diameter: 0.095
    - steering_joint: caster_joint_fr
      axle_joint: wheel_joint_fr
      diameter: 0.095
    - steering_joint: caster_joint_bl
      axle_joint: wheel_joint_bl
      diameter: 0.095
    - steering_joint: caster_joint_br
      axle_joint: wheel_joint_br
      diameter: 0.095
特别注意base_controller的type,比较特别,又遇见新的一种它叫做 SteeredWheelBaseController,这个的写法是参照mas_group的youbot_simulation改的。它的 base_gazebo.xacro的写法也很特别,它也做了修改需要注意

controller.yaml写完之后,照例还是写launch文件加载它,因为有不同的yaml和namespace,而配置文件只有一个名字,一次写三个肯定有冲突,所以,首先在三个不同的launch文件中调用controller_spawner,然后再在一个launch中包含它们三个。

arm_controller.launch它包含了namespace:arm_1

<?xml version="1.0"?>
<launch>
 
  <arg name="arm_name" default="arm_1"/>
 
  <!-- upload arm and gripper controller parameters -->
  <rosparam file="$(find youbot_control)/config/only/arm_controller.yaml" command="load" ns="$(arg arm_name)"/>
 
  <!-- spawn arm controller -->
  <node pkg="controller_manager" type="spawner" name="arm_1_arm_controller_spawner"  
        args="$(arg arm_name)/arm_controller" respawn="false" output="screen" />
 
  <!-- spawn gripper controller -->
  <node pkg="controller_manager" type="spawner" name="arm_1_gripper_controller_spawner"  
        args="$(arg arm_name)/gripper_controller" respawn="false" output="screen" />
 
</launch>
包含三个launch的文件youbot_all_inone.launch
<?xml version="1.0"?>
<launch>
 
  <include file="$(find youbot_control)/launch/joint_state_controller.launch" />
 
  <include file="$(find youbot_control)/launch/base_controller.launch" />
 
  <include file="$(find youbot_control)/launch/arm_controller.launch" />
 
</launch>
4. 配置moveit

这里我在配置7自由度机械臂的时候提过,它们都有一个共同的夹子间的坐标系。

因此这里就没有参考youbot_integration中的moveit的配置,我的主要配置如下

groups

end effector

生成好了以后,照例配置controllers.yaml以及controller_manager.launch.xml

5.实验

视频:

http://v.youku.com/v_show/id_XMTU4MTcyNjMxMg==.html

节点关系图:

问题:

因为youBot的底座是全向轮,默认的是 libgazebo_ros_planar_move.so。关于它这里也有个讨论 https://github.com/micpalmia/youbot_ros_tools/issues/5根据youtube上面的一个视频,这个使用起来转弯的时候会飘

ROS Planar Move vs Gazebo on the youBot: turn https://www.youtube.com/watch?v=oHlSGvBii2Q。修改的这个是用的SteeredWheelBaseController,和youbot_simulation的一样,最开始的问题是找不到,后来解决是因为发现base_gazebo.xacro做过非常大的修改,参考mars group的youbot_simulation解决掉了。然后的问题是如下图这样:发现它的base_controller并没有加载起来,只加载了下图最下面的三个,也就是目前只能控制手臂

附加资料:

=============================================================

youbot底座移动导航仿真:点击打开链接

模拟激光雷达建图:点击打开链接