ros2 / ros1_bridge

ROS 2 package that provides bidirectional communication between ROS 1 and ROS 2
Apache License 2.0
436 stars 283 forks source link

Unable to remap Parameter Bridge namespace #316

Open robin-read opened 3 years ago

robin-read commented 3 years ago

Bug report

Required Info:

Steps to reproduce issue

The ultimate goal is to be able to start multiple bridges that have different names, bridge different topics/services and each run on a different computer.

To reproduce, attempt to start a parameter_bridge node and remap the node namespace from the command line.

ros2 run ros1_bridge parameter_bridge --ros-args -r __ns:=bridge_1

Expected behavior

Bridge starts with a different name and can be inspected via ROS 1 and ROS2:

ros2 node list
ros2 node info /bridge_1/ros_bridge
rosnode list
rosnode info /bridge_1/ros_bridge

Actual behavior

Node crashes with the following error message:

terminate called after throwing an instance of 'rclcpp::exceptions::RCLInvalidROSArgsError'
  what():  failed to initialize rcl: Couldn't parse trailing -r flag. No remap rule found., at /tmp/binarydeb/ros-foxy-rcl-1.1.11/src/rcl/arguments.c:357
iuhilnehc-ynos commented 3 years ago

Supporting: Change the Default Namespace

The replacement side must have a FQN with no special operators.

Even if we use a FQN for ros2 namespace, there still exists an error. Because ros::init, which update the arg(c|v) if := exists, is called before rclcpp::init.

Solution:

  1. Move rclcpp::init(argc, argv); before ros::init(argc, argv, "ros_bridge");, and then rebuild ros1_bridge
  2. Use ros2 run ros1_bridge parameter_bridge --ros-args -r __ns:=/bridge_1
Dave-van-der-Meer commented 2 years ago

What is the current status of this issue?

I try to rename the node with a namespace and I receive the following terminal output when it fails:

dave@adminuser-Precision-5560:~/ros2_ws/src/src-ros2-leo/leorover_ros1_bridge$ ros2 run ros1_bridge parameter_bridge --ros-args -r __ns:=/dave 
[ERROR] [1661346159.242514740] [rcl]: Failed to parse global arguments
terminate called after throwing an instance of 'rclcpp::exceptions::RCLInvalidROSArgsError'
  what():  failed to initialize rcl: Couldn't parse trailing -r flag. No remap rule found., at /tmp/binarydeb/ros-foxy-rcl-1.1.13/src/rcl/arguments.c:357

And when I try to rename it, it will show the following:

dave@adminuser-Precision-5560:~/ros2_ws/src/src-ros2-leo/leorover_ros1_bridge$ ros2 run ros1_bridge parameter_bridge --ros-args -r __node:=dave 
[ERROR] [1661347969.014888544] [rcl]: Failed to parse global arguments
terminate called after throwing an instance of 'rclcpp::exceptions::RCLInvalidROSArgsError'
  what():  failed to initialize rcl: Couldn't parse trailing -r flag. No remap rule found., at /tmp/binarydeb/ros-foxy-rcl-1.1.13/src/rcl/arguments.c:357

I did not apply the proposed solution as I was hoping there would be an update that would make this solution obsolete. Also, this issue is still marked as open.

Gabryss commented 2 years ago

I have the same issue as Dave has. The only difference is that I used already available binaries from the apt repo.

Dave-van-der-Meer commented 2 years ago

In the end, I did change the following code in the parameter_bridge.cpp file from:


  // ROS 1 node
  ros::init(argc, argv, "ros_bridge");
  ros::NodeHandle ros1_node;

  // ROS 2 node
  rclcpp::init(argc, argv);
  auto ros2_node = rclcpp::Node::make_shared("ros_bridge");

To the following (switching the order of the two init functions):

  // ROS 2 node
  rclcpp::init(argc, argv);
  auto ros2_node = rclcpp::Node::make_shared("ros_bridge");

  // ROS 1 node
  ros::init(argc, argv, "ros_bridge");
  ros::NodeHandle ros1_node;

Now, I am able to give the node a name inside a namespace. I would consider this should have been solved in the foxy branch already unless there is a specific reason to not change the order of the init functions.

gbiggs commented 1 year ago

This error appears to be caused by a clash in the argument processing between ROS 1 and ROS 2. ROS 2 requires the node name remap to be provided after a -r flag. ROS 1 does not. Because ROS 1 gets to process argv first, it probably processes and removes the __ns:=bridge_1 argument but not the -r flag. Then ROS 2 sees a -r flag without a following argument, and throws an exception.

Reversing the order of argument processing does work, but I'm not sure it's a universally acceptable solution.

Dave-van-der-Meer commented 1 year ago

Reversing the order of argument processing does work, but I'm not sure it's a universally acceptable solution.

I guess this is why it is still in the same order as it is now. For my specific use case, it seems to work, but more out of luck rather than as a universal solution.

I just wonder how people implement it to have several robots where each of them has its own ros1_bridge for bridging its own topics. Or am I doing something totally strange here?

I have multiple robots each in a namespace, but I cannot run the ros1_bidge parameter_bridge in the same namespace unless I reverse the order of the inits.

gbiggs commented 1 year ago

I just wonder how people implement it to have several robots where each of them has its own ros1_bridge for bridging its own topics. Or am I doing something totally strange here?

I guess that people generally don't do that. The ros1_bridge is designed to cover the general use case, but I think it falls over pretty quickly when it's used in complex ways, such as the way you are doing it. It might be easier to just use a single bridge for all the robots. Is that possible for you?

130s commented 1 year ago

Far from being an expert, just trying to give more data points.

I get the error in this ticket when executing parameter_bridge via a .launch.py, like so:

def generate_launch_description():
        Node(
            package='ros1_bridge',
            executable='parameter_bridge',
            namespace="bridge_param",
            arguments=["__name:=parameter_bridge"],
       ),
    ])

But, exec-ing from CLI hasn't caused the same error so far.

source /opt/ros/noetic/setup.bash && source /opt/ros/foxy/setup.bash
ros2 run ros1_bridge parameter_bridge __name:=parameter_bridge
Dave-van-der-Meer commented 1 year ago

@gbiggs No, I am afraid this was not possible for us since we needed to have 3 robots that were fully independent and we could not afford that when they lose connection to a central ROS master also containing the bridge.

We modified the code to switch the inits and we were able to apply a namespace.

@130s Interesting. I do not remember if we tried this. By now, we migrated the entire robot to ROS 2 so we do not need the ros1_bridge anymore.

carvee1 commented 1 year ago

I have a similar problem, I already switched the init commands, but unfortunately, although I tried to use ros2 run ros1_bridge dynamic_bridge --bridge-all-topics --ros-args -remap __ns:=/my_namespace and --ros-args -r __ns:=/my_namespace`, the output is always exactly the same topic as on the ros 1 side. Is there anything else I could try? Or is my only hope to try and hardcode the namespace in the dynamic bridge?