robotiq_control.launch.py brings up exactly one gripper, and several things in it are hardcoded in ways that collide if a second one is brought up beside it. An integrator running two arms, each with its own gripper, needs all of them parameterised. This issue collects the whole surface so the work can be done in one pass rather than discovered piecemeal.
What is hardcoded today
The launch expands robotiq_2f_85_gripper.urdf.xacro, which includes robotiq_2f_gripper.urdf.xacro. That file declares <link name="world" /> and instantiates the macro with prefix="", parent="world" and name="RobotiqGripperHardwareInterface".
- No namespace argument. Two copies collide on node names, on
/controller_manager and on every topic and service.
- No prefix argument.
robotiq_2f_85_macro.urdf.xacro and 2f_85.ros2_control.xacro already thread ${prefix} through every link and joint, but the top-level file passes the empty string, so both grippers publish robotiq_85_base_link and TF collides whatever the namespace is.
- The controller config is selected, not passed.
controllers_file_for_distro() picks one of four shipped files. A prefixed gripper needs its own, because the config names the joint and the set_gripper_max_* interfaces.
- The spawners name
/controller_manager absolutely. The spawner's own default is the relative controller_manager, resolved against the spawner's namespace, which is what makes a namespace work at all.
- The
ros2_control component name is fixed at RobotiqGripperHardwareInterface, so two components in one description would collide on it.
- The reactivation GPIO is declared unprefixed as
reactivate_gripper in both model xacros, and RobotiqActivationController claims that literal name. Two grippers in one description declare the same GPIO twice, which ros2_control rejects. This one blocks a single description carrying two grippers even after the launch arguments exist.
Two arrangements, and they need different things
A namespace per gripper, each with its own ros2_control_node. Needs the namespace, prefix, config and relative-controller-manager items. The component name and the GPIO are fine, because each namespace has its own controller manager and its own description.
One controller manager carrying both. Needs the component name and the GPIO prefixed as well, and GripperStatusBroadcaster would need an optional joint parameter: it binds to whichever joint exports object_status first, which is unambiguous for one gripper and arbitrary for two. RobotiqActivationController would need the same.
The first is the usual ROS arrangement and the one to aim at.
A caveat on the entry point
This launch is a standalone bring-up: it owns the world link and spawns its own robot_state_publisher. Including it twice gives two world links and two state publishers even once every argument above exists. The arguments are worth adding regardless, but a two-arm system will more likely include the description and ros2_control macros directly, once per gripper, from a top-level launch of its own. Worth deciding which of the two this issue is committing to before writing the code.
Note
Defaults must not change behaviour: empty prefix, no namespace, and the existing per-distro selection as the config argument's default. Humble has no parallel_gripper_action_controller, so a single static default would break that distro.
robotiq_control.launch.pybrings up exactly one gripper, and several things in it are hardcoded in ways that collide if a second one is brought up beside it. An integrator running two arms, each with its own gripper, needs all of them parameterised. This issue collects the whole surface so the work can be done in one pass rather than discovered piecemeal.What is hardcoded today
The launch expands
robotiq_2f_85_gripper.urdf.xacro, which includesrobotiq_2f_gripper.urdf.xacro. That file declares<link name="world" />and instantiates the macro withprefix="",parent="world"andname="RobotiqGripperHardwareInterface"./controller_managerand on every topic and service.robotiq_2f_85_macro.urdf.xacroand2f_85.ros2_control.xacroalready thread${prefix}through every link and joint, but the top-level file passes the empty string, so both grippers publishrobotiq_85_base_linkand TF collides whatever the namespace is.controllers_file_for_distro()picks one of four shipped files. A prefixed gripper needs its own, because the config names the joint and theset_gripper_max_*interfaces./controller_managerabsolutely. The spawner's own default is the relativecontroller_manager, resolved against the spawner's namespace, which is what makes a namespace work at all.ros2_controlcomponent name is fixed atRobotiqGripperHardwareInterface, so two components in one description would collide on it.reactivate_gripperin both model xacros, andRobotiqActivationControllerclaims that literal name. Two grippers in one description declare the same GPIO twice, which ros2_control rejects. This one blocks a single description carrying two grippers even after the launch arguments exist.Two arrangements, and they need different things
A namespace per gripper, each with its own
ros2_control_node. Needs the namespace, prefix, config and relative-controller-manager items. The component name and the GPIO are fine, because each namespace has its own controller manager and its own description.One controller manager carrying both. Needs the component name and the GPIO prefixed as well, and
GripperStatusBroadcasterwould need an optionaljointparameter: it binds to whichever joint exportsobject_statusfirst, which is unambiguous for one gripper and arbitrary for two.RobotiqActivationControllerwould need the same.The first is the usual ROS arrangement and the one to aim at.
A caveat on the entry point
This launch is a standalone bring-up: it owns the
worldlink and spawns its ownrobot_state_publisher. Including it twice gives two world links and two state publishers even once every argument above exists. The arguments are worth adding regardless, but a two-arm system will more likely include the description andros2_controlmacros directly, once per gripper, from a top-level launch of its own. Worth deciding which of the two this issue is committing to before writing the code.Note
Defaults must not change behaviour: empty prefix, no namespace, and the existing per-distro selection as the config argument's default. Humble has no
parallel_gripper_action_controller, so a single static default would break that distro.