在前面的三篇中,对ros_control也有个大致了解了。这篇就是将之前学到的用于我们实验室的平台KUKA youBot上。在此之前,其实网上已经有关于youBot在Gazebo下的仿真视频了。
另外说个题外话,用Gazebo和Riz都可以做仿真,Gazebo最强大的是拥有物理引擎,有物理渲染,有碰撞效果、重力等等。
这里参考的package主要是:
- https://github.com/micpalmia/youbot_ros_tools
- https://github.com/pschillinger/youbot_integration
- https://github.com/mas-group/youbot_simulation 这个Mas-group很有来头,德国Bonn-Rhei-Sieg大学,youBot的驱动就是KUKA和他们搞的,15年[email protected]的第三名b-it-bots就是他们,现在youBot的软件维护主要就是他们在做。
建议大家直接照着第二个来,很快就可以用起来,它主要是启动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
这里主要的问题有两个:
- navigation的时候,rviz中的模型可以动,但是Gazebo中的却没有运动。
- 我的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并没有加载起来,只加载了下图最下面的三个,也就是目前只能控制手臂