0
$\begingroup$

Rosanswers logo

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 non physics-simulated robots)

I have added the following to my file robots.launch

<node pkg="tf" type="static_transform_publisher" name="link1_broadcaster" args="0 0 0.02 0 0 0 lwr_7_link ahand_palm_link 100" />

When I check the output of rosrun tf view_frames and everything seems fine here is a section of the output:

image description

However this seems to have no effect at all, Two problems, 1) the specified transformation between the two links are not respected and 2) when I run the simulator the hand just falls to the floor. It seems that there is an initialisation problem with the static link.


Originally posted by gpldecha on ROS Answers with karma: 285 on 2015-02-08

Post score: 4

$\endgroup$

3 Answers 3

0
$\begingroup$

Rosanswers logo

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).


Originally posted by Stefan Kohlbrecher with karma: 24361 on 2015-02-08

This answer was NOT ACCEPTED on the original site

Post score: 4


Original comments

Comment by gpldecha on 2015-02-08:
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.

Comment by gpldecha on 2015-02-08:
It is a shame I cannot load both robots separately and join them there after. I will try out your suggestion tomorrow. Thanks.

$\endgroup$
0
$\begingroup$

Rosanswers logo

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.


Originally posted by Adolfo Rodriguez T with karma: 3907 on 2015-02-09

This answer was NOT ACCEPTED on the original site

Post score: 2


Original comments

Comment by gpldecha on 2015-02-09:
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 ?

$\endgroup$
0
$\begingroup$

Rosanswers logo

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

Originally posted by gpldecha with karma: 285 on 2015-02-10

This answer was ACCEPTED on the original site

Post score: 5

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.