ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
4

multiple robots and ros_control

asked 2015-02-08 08:48:35 -0500

gpldecha gravatar image

updated 2015-02-10 07:52:13 -0500

I am trying to spawn two different robot models, one is a robotic arm (lwr kuka) and the other is a robotic hand manipulator (allegro hand), with their own controllers. I can load and control both robots independently from one another at the moment. See the figure bellow for an idea of the setup. My goal is to be able to control these two connected robots with their own separate controllers.

image description

I have seen the discussion regarding spawning multiple turtle-bots, but my situation is different. I want the two robots (arm and hand) to be connect by a link (from arm eof to hand base) but controlled separately. Here is the description of my launch file robots.lauch:

<launch>
<!-- LWR KUKA ROBOT -->
<group ns="lwr">
    <param name="robot_description"                                                                   command="$(find xacro)/xacro.py $(find pkg)/urdf/kuka_init.xacro" />
    <include file="$(find pkg)/launch/launch/lwr_kuka.launch" >
        <arg name="init_pose" value="-x 0 -y 0 -z 0" />
        <arg name="robot_name"  value="lwr" />
    </include>
</group>

<!-- ALLEGRO HAND ROBOT-->  
<group ns="ahand">
    <param name="robot_description"                                                                   command="$(find xacro)/xacro.py $(find pkg)/urdf/ahand_init.xacro" />
    <include file="$(find pkg)/launch/launch/ahand.launch" >
            <arg name="init_pose" value="-x 0 -y 0 -z 0.2" />
            <arg name="robot_name"  value="ahand" />
        </include>
</group>
</launch>

Here are two launch files of the independent robots lwr_kuka.lauch

<launch>
    <arg name="robot_name" default="lwr"/>
    <arg name="init_pose"/>
    <arg name="use_joint_state_publisher" default="true"/>

    <node name="spawn_kuka_model" pkg="gazebo_ros" type="spawn_model"
     args="$(arg init_pose) -urdf -param /lwr/robot_description -model $(arg robot_name)"
     respawn="false" output="screen" />
</launch>

and ahand.launch

<launch>
    <arg name="robot_name" default="ahand"/>
    <arg name="init_pose"/>

    <node name="spawn_ahand_model" pkg="gazebo_ros" type="spawn_model"
     args="$(arg init_pose) -urdf -param /ahand/robot_description -model $(arg robot_name)"
     respawn="false" output="screen" />
</launch>

To connect both of them I tried to change the parent link in my ahand_init.xacro to be the last link of the robot arm.

<robot name="ahand" xmlns:xacro="http://www.ros.org/wiki/xacro">
<xacro:include filename="$(find allegro_hand_description)/urdf/hand.xacro"/>
<link name="lwr_7_link"/>
<xacro:ahand prefix="ahand" parent_link="lwr_7_link" xyz="0.0 0 0.2" rpy="0 0 0" left="1"/>
</robot>

This not a workable solution. It seems that the full description of the robot (both arm and hand) have be defined in a single .xacro file and cannot be combine in a roslaunch file. Is this an accurate observation ? It would be great if a robot could be assembled in the roslaunch file, especially when considering multiple possible end-effectors.

Since this did not work, the back up solution is to have a kuka_ahand.xacro file which combines the two models. The problem is then shifted in how to important two controllers for one urdf robot description. I would appreciate suggestions on how to do this. I would like to have two separate .yaml files and controllers which get loaded in the launch file. Is this possible ?

Proposed solution 1) connect ahand_base_link and lwr_link with a static tf broadcaster. (Edit: only works (possibly) when consider ... (more)

edit retag flag offensive close merge delete

5 Answers

Sort by ยป oldest newest most voted
5

answered 2015-02-10 07:50:51 -0500

gpldecha gravatar image

I have managed to make it working following Stefan's and Adolfo's suggestions. I will summarise two important points for anybody in the future who would like to combine two robots together which have separate controllers.

  • Both robot description files have to be combined into a single URDF (lwr_ahand_init.xacro in my case which combines the lwr kuka and allegro hand) before being called in a launch file.
  • Take care of namespaces which are defined in .yaml control config files, when you spawn a controller manager it will take a default namespace which was specified at the top of your .yaml file.

In Stephan's solution the description of the robot components are in a single .yaml file. We can however keep the description of both robots in two separate catkin projects and combine them in a third project. My robots.launch file changed as follows (see the original problem description for the previous form):

<launch>
    <!-- LWR KUKA & HAND ROBOT -->
    <group ns="lwr">
        <param name="robot_description"                                                                   command="$(find xacro)/xacro.py $(find table_world)/urdf/lwr_ahand_init.xacro" />
            <include file="$(find table_world)/launch/launch/lwr_ahand.launch" >
                <arg name="init_pose" value="-x 0 -y 0 -z 0" />
                <arg name="robot_name"  value="lwr" />
            </include>
    </group>
</launch>

This is the first part. The second involves loading the two .yaml control files of each respective robot and spawn them in control manager.

<launch>
<rosparam ns="lwr" file="$(find lwr_control)/config/lwr_control.yaml" command="load"/>
<rosparam ns="lwr" file="$(find ahand_control)/config/ahand_control.yaml" command="load"/>

<node ns="lwr" name="controller_spawner" pkg="controller_manager" type="spawner"             
          output="screen" 
          args="lwr/joint_state_controller lwr/OneTaskInverseKinematics 
               ahand/TaskInverseKinematics" /> 

<node  name="controller_spawner_stopped" pkg="controller_manager" type="spawner" 
        output="screen"  args="--stopped $(arg stopped_controllers)"/> 

</launch>

I loaded the two config files into there own namespace /lwr and /ahand respectively. I tried to have a different namespace for the controller_spawner but nothing else than lwr seems to work. In this setting I can control both the hand and the robot with their own controllers and I don't need to merge the .yaml files. The control topics (rostopic list) are now:

  • /lwr/lwr/OneTaskInverseKinematics
  • /lwr/ahand/TaskInverseKinematics
edit flag offensive delete link more
4

answered 2015-02-08 13:20:28 -0500

You can load different controller that actuate the different joints on your robot (for instance one joint_trajectory_controller for the arm and one custom hand controller for the hand).

Example:

Note that separate joint trajectoy controllers are loaded for arms, legs and torso. This situation should be comparable to your case (with arm and hand playing the role of the separate entities).

edit flag offensive delete link more

Comments

Thanks for your replay. So basically I have to have one urdf for the complete robot (hand + arm) and one .yaml file for all the joints (hand + arm). However I can load the controllers as separate entities. This is a workable solution.

gpldecha gravatar image gpldecha  ( 2015-02-08 13:37:03 -0500 )edit

It is a shame I cannot load both robots separately and join them there after. I will try out your suggestion tomorrow. Thanks.

gpldecha gravatar image gpldecha  ( 2015-02-08 13:38:43 -0500 )edit
2

answered 2015-02-09 02:28:35 -0500

Adolfo Rodriguez T gravatar image

updated 2015-02-09 09:52:20 -0500

You can load the arm and hand separately, as in separate URDFs and controller_managers. To rigidly couple the hand to the arm using roslaunch, you can spawn a static tf publisher that broadcasts the transform between lwr_7_link and ahand_base_link.

Edit: I realize after your tests that this trick is useful to couple links together on the ROS side of things. If you were using actual hardware that _is_ coupled together, then it would work. However, as long as you're not doing anything else on the Gazebo side of things, the hand will remain disconnected from the arm. You're missing a mechanism to tell Gazebo that there's a fixed joint between your two models.

The least-resistance solution right now seems to be what Stefan suggests in his answer. To create a single URDF containing the arm-hand system. If you leverage xacro, you can still have two separate models, one for the arm and one for the hand, and combine them in a very brief URDF.

edit flag offensive delete link more

Comments

I have tried your proposed approach (I have detailed it in the question section above). I have checked the tf frames and it shows a connection between the two. However when I run the simulation the hand just falls off. The link does not seem to be rigid. I must be doing something wrong ?

gpldecha gravatar image gpldecha  ( 2015-02-09 06:11:48 -0500 )edit
0

answered 2015-02-16 05:00:01 -0500

carlosjoserg gravatar image

I'm aware of the issue since I have a similar setup, only that twice. I solved it in a more natural and easy way, and you don't loose the coupling of the hand and arm in gazebo, which otherwise would be bad for dynamics, since the arm wouldn't account for the hand weight and inertia. However it requires (not so complicated and not conflicting) changes in the gazebo_ros_control plugin and in the transmission_interface package.

Take a look at this issue, where I propose the answer.

edit flag offensive delete link more

Comments

carlosjoserg gravatar image carlosjoserg  ( 2015-02-16 05:01:39 -0500 )edit

Hi carlosjoserg, I will have a look at your setup. Looks like you guys are actively using KUKA. I will be trying your package out on the real KUKA.

gpldecha gravatar image gpldecha  ( 2015-02-16 08:27:27 -0500 )edit

Yes, indeed. All hardware (except the head) packages you see in the robot follow this diagram, and on top, MoveIt! is already configured to make the most of the controllers.

carlosjoserg gravatar image carlosjoserg  ( 2015-02-16 08:57:11 -0500 )edit
0

answered 2015-11-27 04:05:55 -0500

J_Schaefer gravatar image

I now face a similar kind of problem as you did, @gpldecha. I'm trying to create a simulation for an UR5 with Robotiq_85_C2_Gripper.

First I tried to reference the Gripper inside the xacro-File of the UR5. It partly worked, but the Gripper didn't spawn fully.

Now I want to create a new xacro-File in which I combine both xacro's of the robot and gripper and call this file with a launch-file.

My code is (ur5_robotiq.xacro):

<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="ur5_robotiq_model">
<property name="pi" value="3.1415"/>
<xacro:include filename="$(find ur_description)/urdf/ur5_robot.urdf.xacro"/>
<xacro:include filename="$(find robotiq_c2_model_visualization)/urdf/robotiq_c2_model.xacro"/>

<link name="world" />

<joint name="world_joint" type="fixed">
    <parent link="world" />
    <child link = "base_foot" />
    <origin xyz="0.0 0.0 0.026" rpy="0.0 0.0 0.0" />
</joint>

<joint name="Gripper_Adapter_Fix" type="fixed">
    <parent link="fts_toolside" />
    <child link="robotiq_85_adapter_link" />
    <origin xyz="0.0 0.0 -0.0125" rpy="0.0 ${- pi / 2} 0.0" />
</joint>

</robot>

This file is loaded by (ur5_robotiq.launch):

<?xml version="1.0"?>
<launch>
<arg name="limited" default="false"/>

<param name="robot_description" command="$(find xacro)/xacro.py '$(find myrobot_description)/urdf/ur5_robotiq.xacro'" />

</launch>

The highest launch-file is:

<?xml version="1.0"?>
<launch>

<arg name="limited" default="false"/>
<arg name="paused" default="false"/>
<arg name="gui" default="true"/>



<include file="$(find gazebo_ros)/launch/empty_world.launch">
    <arg name="world_name" value="$(find myrobot_gazebo)/worlds/myworld.world"/>
    <arg name="paused" value="$(arg paused)"/>
    <arg name="gui" value="$(arg gui)"/>
</include>

      <!-- UR5 & Robotiq Gripper -->
      <!-- load ur5 into sim -->
     <!-- send robot urdf to param server -->

     <include file="$(find myrobot_description)/launch/ur5_robotiq.launch">
        <arg name="limited" value="$(arg limited)"/>
     </include>

     <!-- push robot_description to factory and spawn robot in gazebo -->
     <node name="spawn_gazebo_model" pkg="gazebo_ros" type="spawn_model"
         args="-urdf -param robot_description
         -model robot
         -z 0.0"
         respawn="false" output="screen" />

</launch>

I'm new to ROS and Gazebo. First I just want to spawn both Models in my world. The controllers are less important at the moment. When I launch the highest launch file with roslaunch, then Gazebo starts with myworld but without the models:

...
[INFO] [WallTime: 1448618278.209298] [0.245000] Calling service /gazebo/spawn_urdf_model                                                      
Error [Param.cc:181] Unable to set value [1,0471975511965976] for key[horizontal_fov]                                                         
Error [Param.cc:181] Unable to set value [0,100000001] for key[near]                                                                          
Error:   Failed to build tree: parent link [fts_toolside] of joint [Gripper_Adapter_Fix] not found.  This is not valid according to the URDF spec. Every link you refer to from a joint needs to be explicitly defined in the robot description. To fix this problem you can either remove this joint [Gripper_Adapter_Fix] from your urdf file, or add "<link name="fts_toolside" />" to your urdf file.                                 
     at line 226 in /build/buildd/urdfdom-0.2.10+dfsg/urdf_parser/src/model.cpp                                                           
Error [parser_urdf.cc:2608] Unable to call parseURDF on robot model                                                                           
Error [parser.cc:299] parse as old deprecated model file failed.                                                                              
Error [World.cc:1527] Unable ...
(more)
edit flag offensive delete link more

Comments

I might be late, but the problem is, that the URDF you have for the gripper only has visuals and collision attributes. Gazebo requires inertial. And I think you need transmissions too for Gazebo (in the URDF).

That URDF (and the whole gripper you linked from github) wasn't made for Gazebo

TredBobek gravatar image TredBobek  ( 2016-07-21 08:52:24 -0500 )edit

Question Tools

5 followers

Stats

Asked: 2015-02-08 08:48:35 -0500

Seen: 6,402 times

Last updated: Feb 16 '15