Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Humble] No conversion from rcl_interfaces/msg/Log and rosgraph_msgs/Log #391

Open
Timple opened this issue Jan 12, 2023 · 21 comments
Open

Comments

@Timple
Copy link
Contributor

Timple commented Jan 12, 2023

Bug report

Required Info:

  • Operating System:
    • Docker (ubuntu:jammy)
  • Installation type:
    • ROS1 from ubuntu binaries
    • ROS2 from source (because of catkin conflict)
    • ros_bridge from source
  • Version or commit hash:
    • master
  • DDS implementation:
    • Fast-RTPS
  • Client library (if applicable):

Steps to reproduce issue

git clone https://github.com/contradict/ros-humble-ros1-bridge.git
cd ros-humble-ros1-bridge
docker build . -t bridge

Then run with this docker-compose file:

version: "2.1"
services:
  roscore:
    image: "ros:noetic"
    network_mode: host
    command: roscore
  ros1-bridge:
    image: bridge
    network_mode: host
    command: ros2 run ros1_bridge dynamic_bridge

Expected behavior

Bridging /rosout

Actual behavior

Not bridging /rosout

Additional information

Seems like the mapping is not found: https://github.com/ros2/rcl_interfaces/blob/humble/rcl_interfaces/mapping_rules.yaml

Relevant other issues:

#159 Was fixed, is broken again for humble
contradict/ros-humble-ros1-bridge#2 (Not the fault of the dockerfile I think)

@Timple
Copy link
Contributor Author

Timple commented Jan 12, 2023

PS. Also seems to be the case for rolling.

@brow1633
Copy link

brow1633 commented Feb 2, 2023

Not a fix, but a workaround to enable the use of ROS1 bridge with the above Dockerfile (without logging):

Instead of roscore run rosmaster --core

@Timple
Copy link
Contributor Author

Timple commented Feb 18, 2023

But that would mean I would need to configure all nodes to run without /rosout right?

@faraz7321
Copy link

Hi! Were you able to resolve the issue? I am also experiencing the same error.

@brow1633
Copy link

brow1633 commented Mar 6, 2023

I did something similar here, but with the addition of rosbridge_suite: https://github.com/brow1633/ros_docker/blob/main/ros-humble-bridge

I'm not sure about configuring other nodes. I haven't run into issues, but haven't run this extensively to be honest.

@Timple
Copy link
Contributor Author

Timple commented Mar 14, 2023

@brow1633 because you are using rosmaster --core instead of roscore.
Therefore you simply skip logging and there is no issue with converting the logging message.

@Timple
Copy link
Contributor Author

Timple commented Mar 16, 2023

So this #393 (comment) led me to investigate the history.

The last working commit for Log messages was 81f8b08. Since 2381bf4 it's broken (PR #382).

@LoyVanBeek did you ever run in to problems with Log messages?

@LoyVanBeek
Copy link
Contributor

LoyVanBeek commented Mar 17, 2023

Hey Tim

Nope, have never tried bridging those until now.
We only use the parameter_bridge. When I configure it to bridge /rosout and type rcl_interfaces/msg/Log with this config:

topics:
  - topic: /rosout
    type: rcl_interfaces/msg/Log
    queue_size: 1

I get:

failed to create bidirectional bridge for topic '/rosout' with ROS 2 type 'rcl_interfaces/msg/Log': No template specialization for the pair

We're still on Foxy + Noetic btw.

Even with the mapping rules in https://github.com/ros2/rcl_interfaces/blob/humble/rcl_interfaces/mapping_rules.yaml, the 'enum' for error levels also doesn't yet line up. And the ROS1 field topics[] is also missing from the ROS 2 variant.
But I'd expect that to be fine:
2381bf4#diff-addbc08357f431e24b7c461dce9513f7aa52338c08319c8929b17e213a9e4037R808-R822

    ros1_field_missing_in_ros2 = any(ros1_fields_not_mapped)

    if ros1_field_missing_in_ros2:
        # if some fields exist in ROS 1 but not in ROS 2
        # check that no fields exist in ROS 2 but not in ROS 1
        # since then it might be the case that those have been renamed and should be mapped
        for ros2_member in ros2_spec.structure.members:
            for ros1_field in ros1_spec.parsed_fields():
                if ros1_field.name.lower() == ros2_member.name:
                    break
            else:
                # if fields from both sides are not mappable the whole message is not mappable
                return None
return mapping

So I'm not sure what the problem is. I have a branch on my fork https://github.com/LoyVanBeek/ros1_bridge/tree/debug/mapping_uuids that adds a whole bunch of logging to pinpoint this. All I have to offer at the moment.

@kennyS99
Copy link

kennyS99 commented Oct 7, 2023

Yes, i found the same issue for rolling ros2 version. i installed the ros noetic version in my ubuntu22 docker container built from source. and when I print out the pairs, there is no output like this:
" - 'rcl_interfaces/msg/Log' (ROS 2) <=> 'rosgraph_msgs/Log' (ROS 1)"

I have tried many methods to solve this problem, but it does not work. i would appreciate that If anybody could provide a solution to it.

@kennyS99
Copy link

kennyS99 commented Oct 8, 2023

Yes, i found the same issue for rolling ros2 version. i installed the ros noetic version in my ubuntu22 docker container built from source. and when I print out the pairs, there is no output like this: " - 'rcl_interfaces/msg/Log' (ROS 2) <=> 'rosgraph_msgs/Log' (ROS 1)"

I have tried many methods to solve this problem, but it does not work. i would appreciate that If anybody could provide a solution to it.

Hi guys, I have solved this problem with this commit b9f1739.
My work env is (ubuntu 22 jammy + build from source ros noetic + ros2 rolling) docker container.

@Timple
Copy link
Contributor Author

Timple commented Oct 8, 2023

You are pointing to a commit that modified a typo in a readme. I guess you meant another commit?

@kennyS99
Copy link

kennyS99 commented Oct 8, 2023

This commit 81f8b08 is still stuck on the same issue that /rosout topics cannot be mapped.
Nope, this commit solved my problem. b9f1739

@limshoonkit
Copy link

limshoonkit commented Nov 14, 2023

is there a solution to this problem?
failed to create 2to1 bridge for topic '/rosout' with ROS 2 type 'rcl_interfaces/msg/Log' and ROS 1 type 'rosgraph_msgs/Log': No template specialization for the pair

do we just checkout the code at this point of commit b9f1739?

@Timple
Copy link
Contributor Author

Timple commented Nov 14, 2023

We do.
But it's a shame we miss all the new features and improvements that are being implemented.

But that's how it goes: workaround is in place, so the issue plunges down the backlog 🙁

@limshoonkit
Copy link

limshoonkit commented Nov 14, 2023

@Timple,

Thanks for the follow up. I modified https://github.com/contradict/ros-humble-ros1-bridge/blob/main/Dockerfile to checkout the commit.
Screenshot from 2023-11-14 17-05-29

Afterwards, I tried running the examples.
I have the following docker containers running with -net=host option.

ros-humble-ros1-bridge running ros1-bridge
osrf/ros:noetic-desktop-full running roscore
osrf/ros:noetic-desktop-full for running ros1 talker
osrf/ros:humble-desktop-full for running ros2 listener

i can see that the bridge is connected
Screenshot from 2023-11-14 17-13-44

but my listener is not outputting anything.
Screenshot from 2023-11-14 17-14-39

is there another bug i am unaware of?

update

I run the commnad
ros2 topic info /chatter --verbose
Type: std_msgs/msg/String

Publisher count: 1

Node name: NODE_NAME_UNKNOWN
Node namespace: NODE_NAMESPACE_UNKNOWN
Topic type: std_msgs/msg/String
Endpoint type: PUBLISHER
GID: 01.0f.0c.f2.55.00.80.68.01.00.00.00.00.00.12.03.00.00.00.00.00.00.00.00
QoS profile:
Reliability: RELIABLE
History (Depth): UNKNOWN
Durability: VOLATILE
Lifespan: Infinite
Deadline: Infinite
Liveliness: AUTOMATIC
Liveliness lease duration: Infinite

Subscription count: 1

Node name: NODE_NAME_UNKNOWN
Node namespace: NODE_NAMESPACE_UNKNOWN
Topic type: std_msgs/msg/String
Endpoint type: SUBSCRIPTION
GID: 01.0f.0c.f2.55.00.80.68.01.00.00.00.00.00.13.04.00.00.00.00.00.00.00.00
QoS profile:
Reliability: BEST_EFFORT
History (Depth): UNKNOWN
Durability: VOLATILE
Lifespan: Infinite
Deadline: Infinite
Liveliness: AUTOMATIC
Liveliness lease duration: Infinite

and apparently the Node name for the ros1_bridge package in my ros2 humble docker is not defined. NODE_NAME_UNKNOWN
i am expecting the node to be ros1_bridge as i can see it in my ros1 noetic docker with rosnode list.

issue resolved

problem was my docker network configuration and host firewall settings, the ros1_bridge works fine.
recommend to disable firewall with
sudo ufw disable

@Timple
Copy link
Contributor Author

Timple commented Nov 14, 2023

Not to my knowledge.

But if you go bug-hunting: might as well try the master 😉

@TommyChangUMD
Copy link

Hi. This thread helped me a lot in getting the ros1-bridge to work on my ROS2 Humble + ROS Noetic setup. I've created a Docker image that can build the ros-humble-ros1-bridge package in 10 minutes -- no need to compile ROS2 Humble from the source. You can find my setup here:
https://github.com/TommyChangUMD/ros-humble-ros1-bridge-builder/

@KKSTB
Copy link

KKSTB commented Dec 22, 2023

Hi @TommyChangUMD

Nice work. I actually made it to work on ROS2 Iron + ROS Noetic. Also the bridge works by copying the build output into my ROS2 install folder which is very neat and clean.

@smith-doug
Copy link

I'm running a horrible amalgamation of master + action support + some cherry picked fixes. I had to create custom convert_2_to_1 template specializations to convert the severity levels between ros1/ros2. The dynamic bridge needed an extra check to set the QoS for /rosout as well. The other nodes might need that too, but I haven't looked at them.

I'm not sure if this repo is still alive, or will accept changes for humble.

@maum-meliora
Copy link

maum-meliora commented Sep 22, 2024

I think the issue is with the is_package_mapping() method in this code snippet from __init__.py:

def determine_package_pairs(ros1_msgs, ros2_msgs, mapping_rules):
    pairs = []
    # determine package names considered equal between ROS 1 and ROS 2
    ros1_suffix = '_msgs'
    ros2_suffixes = ['_msgs', '_interfaces']
    ros1_package_names = {m.package_name for m in ros1_msgs}
    ros2_package_names = {m.package_name for m in ros2_msgs}
    for ros1_package_name in ros1_package_names:
        if not ros1_package_name.endswith(ros1_suffix):
            continue
        ros1_package_basename = ros1_package_name[:-len(ros1_suffix)]
        for ros2_package_name in ros2_package_names:
            for ros2_suffix in ros2_suffixes:
                if ros2_package_name.endswith(ros2_suffix):
                    break
            else:
                continue
            ros2_package_basename = ros2_package_name[:-len(ros2_suffix)]
            if ros1_package_basename != ros2_package_basename:
                continue
            pairs.append((ros1_package_name, ros2_package_name))
    # add manual package mapping rules
    for rule in mapping_rules:
        if not rule.is_package_mapping():
            continue
        if rule.ros1_package_name not in ros1_package_names:
            continue
        if rule.ros2_package_name not in ros2_package_names:
            continue
        pair = (rule.ros1_package_name, rule.ros2_package_name)
        if pair not in pairs:
            pairs.append(pair)
    return pairs

In the last loop, the code is maybe trying to add mapping rules that don't share the same package names for ROS 1 and ROS 2, like rosgraph_msgs and rcl_interfaces. However, since rule.is_package_mapping() returns false for these cases, it skips adding that pair to pairs, which is later used for mapping messages.

The is_package_mapping(), which comes from the MappingRule class (the parent of MessageMappingRule), checks this condition:

    len(data) == (2 + int('enable_foreign_mappings' in data))

and the data looks like this:

{
	'ros1_package_name': 'rosgraph_msgs',
	'ros1_message_name': 'Log',
	'ros2_package_name': 'rcl_interfaces',
	'ros2_message_name': 'Log',
	'fields_1_to_2': {'header.stamp': 'stamp', 'level': 'level', 'name': 'name', 'msg': 'msg', 'file': 'file', 'function': 'function', 'line': 'line'}
}

In this case, len(data) equals 5 and int('enable_foreign_mappings' in data) is 0, so the condition if not rule.is_package_mapping() evaluates to true, which leads the code to exit the loop without adding the pair to pairs.

I'm not quite sure about the purpose of the check len(data) == (2 + int('enable_foreign_mappings' in data)), so I'm uncertain about how to fix this code.

This might be related to #367, which introduced the enable_foreign_mappings flag around 2 years ago. The mapping file for the rcl_interfaces package was added about 5 years ago, so it doesn't set that flag.

@hoffmann-stefan
Copy link

from @Timple #391 (comment) :

The last working commit for Log messages was 81f8b08. Since 2381bf4 it's broken (PR #382).

This change has triggered the check in determine_field_mapping if fields are missing on both sides. Before this commit from @LoyVanBeek the early return skipped this check.

From @maum-meliora #391 (comment)

I think the issue is with the is_package_mapping() method in this code snippet from init.py:

This seems the be unrelated to #367. It was broken before that PR as well for custom mappings that also specify message names or fields mappings.
The check for the len(data) was to strict for is_package_mapping. Custom mappings that included message name or fields mapping keys where ignored. This lead to the Log message not being found as mapping pair.

I have a open WorkInProgress PR on our ros1_bridge fork that fixes both issues: mojin-robotics#21

What is missing is that the level constant values differ between ROS1 and ROS2, so at least rqt crashes if it sees an unknown (to ROS1) level value. But foxglove/lichtblick can handle this.

So we need custom mapping code like for std_msgs/Duration and std_msgs/Time in convert_builtin_interfaces.cpp to get this to work proper.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests