frankaemika / franka_ros

ROS integration for Franka research robots
https://frankaemika.github.io
Apache License 2.0
351 stars 308 forks source link

How to change nameing of services to switch between robot and simulation #245

Closed peetCreative closed 2 years ago

peetCreative commented 2 years ago

Hello, I want to call some services provided by franka_control e.g. set_EE_frame For demonstration I exended the cartesian_impedance_example_controller here. So I want to run the controller in the simulation as well as on the robot.

However running on the robot (roslaunch franka_example_controllers cartesian_impedance_example_controller.launch ...), the node franka_control provides the service of course to /franka_control/set_EE_frame. Running the gazebo simulation (roslaunch franka_gazebo panda.launch ...), franka_hw_sim provides the service on /set_EE_frame.

So the standard way to face this issue in ROS is to use the remap-tag in the roslaunch file to redirect the services. However I did not find a way for to pass this to controller_manager/spawner.

My workaround currently is to define a param called operation_type I read from the controller, and depending on it I call either the one or the other service name. I think, that's a bad solution as the controller should not care about it is simulated or not. This is connected to #241, where it is also recomended to call either the one or the other.

gollth commented 2 years ago

Sure you can. Have you tried using a namespace?

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

  <include file="$(find gazebo_ros)/launch/empty_world.launch"/>

  <group ns="franka_control">
    <include file="$(find franka_gazebo)/launch/panda.launch">
      <arg name="gazebo" value="false" />
      <!-- all other your args you want to set here -->
    </include>
  </group>

</launch>

Then you should see every topic, service & action within that namespace similar to the real robot:

$ rosservice list /franka_control | grep -E "set_(EE|K|load)"
/franka_control/set_EE_frame
/franka_control/set_K_frame
/franka_control/set_load

Does this help you?

peetCreative commented 2 years ago

Hey, thanks for the quick help, it actually changes the name. However this seems to break some things in the panda.launch file. I will try to find a way..

gollth commented 2 years ago

What exactly breaks?

peetCreative commented 2 years ago

However gazebo is not working and the controller as well, there is no obvious errormessages in the log, but I guess some services and topics are now on the wrong namespace. Best hint is: Controller Spawner couldn't find the expected controller_manager ROS interface. So the controller_manager does not find the services controller_manager/load_controller, unload_controller, ... because they are now under /franka_control

I also pushed your suggestion to my previous branch so you could checkout here. Screenshot_20220422_160721

I think, we need to put the name into the urdf. But maybe also have a look, how the setups with two robots solve this problem. Because there you want the services advertise for each robot.

peetCreative commented 2 years ago

It's a general thing also on how does naming works in the ROS world. So should these services live in: /<robot_arm_name>/franka_control/set_load or rather directly in /<robot_arm_name>/set_load In contrast the examples here with two arms are that there is one controller and one combined_ros_control node. However what if I want to have two seperate ros_control_node nodes running and two times the same controller on them. How's the naming than, and best would consistent between simulation and the real robot.

gollth commented 2 years ago

Yes you are on a good track I think. The problem with the namespace is that the model spawner must find the spawn_urdf_model service of Gazebo and the controller spawner must find the controller_manager/load_controller service of the controller manager. Unfortunately for your use case both nodes are started from the same panda.launch file, which works fine if everything is top-level.

So I think you have two options:

  1. Let Gazebo top-level (i.e. /gazebo) and pass the namespace of the robot into the model spawner:
    
    diff --git a/franka_gazebo/launch/panda.launch b/franka_gazebo/launch/panda.launch
    index a15c27e..69ba397 100644
    --- a/franka_gazebo/launch/panda.launch
    +++ b/franka_gazebo/launch/panda.launch
    @@ -57,7 +57,7 @@
    <node name="$(arg arm_id)_model_spawner"
         pkg="gazebo_ros"
         type="spawn_model"
    -        args="-param robot_description -urdf -model $(arg arm_id) $(arg unpause)
    +        args="-param robot_description -urdf -model $(arg arm_id) $(arg unpause) -robot_namespace /franka_control
               $(arg initial_joint_positions)
               "/>
2. or move Gazebo into the robot's namespace and remap the gazebo namespace of the model spawner:
```diff
diff --git a/franka_gazebo/launch/panda.launch b/franka_gazebo/launch/panda.launch
index a15c27e..e5fa512 100644
--- a/franka_gazebo/launch/panda.launch
+++ b/franka_gazebo/launch/panda.launch
@@ -57,7 +57,7 @@
   <node name="$(arg arm_id)_model_spawner"
         pkg="gazebo_ros"
         type="spawn_model"
-        args="-param robot_description -urdf -model $(arg arm_id) $(arg unpause)
+        args="-param robot_description -urdf -model $(arg arm_id) $(arg unpause) -gazebo_namespace /franka_control/gazebo
               $(arg initial_joint_positions)
               "/>

Please try if this helps your use case as intermediate solution. Of course hardcoding the namespace into the panda.launch is not a resilient solution, so we have to discuss a bit internally about how to make this proper. Maybe a(nother) arg to panda.launch?

Let me know if any of this helps you in the process

gollth commented 2 years ago

Note for solution 1. you would probably want <arg name="gazebo" value="true" /> and for 2. <arg name="gazebo" value="false" /> (and the empty_world.launch outside of the <group>) in your outer launch file

peetCreative commented 2 years ago

That definitly helps.

For perspective: From what I think, and know about ROS and nameing it would be good to have a scheme, which is interchangeable between simulation and "reality". So as a proposal for a naming scheme for a single robot arm.

/<arm_id>/franka_control
/<arm_id>/controller_manager
/<arm_id>/controller_spawner
/<arm_id>/joint_state_publisher
/<arm_id>/robot_state_publisher
/<arm_id>/<controller_name>

However for that we would need to tinker also around with the examples in franka_example_controllers. I'm about to commit a proposal. But didn't got it quite right jet.

peetCreative commented 2 years ago

Also I often find in launch files $(arg arm_id)_more_naming. I'm not a big expert with ROS, but I thought this is supposed to be solved using namespaces. So $(arg arm_id)/more_naming or probably put the corresponding node to the corresponding namespace.

gollth commented 2 years ago

Hi @peetCreative,

you definitely have a point regarding our naming and namespaces in general. However this is a relatively breaking change for users which we have to discuss internally. Your original problem how to match simulation & real robot naming is solved, right? Can we close this issue then?

gollth commented 2 years ago

For reference, the service names were adjusted within franka_gazebo so they better match now with franka_control. See 54ab726ba2eea4 for details