[Humble] No conversion from `rcl_interfaces/msg/Log` and `rosgraph_msgs/Log`
Timple opened this issue ยท 21 comments
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)
PS. Also seems to be the case for rolling.
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
But that would mean I would need to configure all nodes to run without /rosout
right?
Hi! Were you able to resolve the issue? I am also experiencing the same error.
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.
@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.
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?
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.
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.
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.
You are pointing to a commit that modified a typo in a readme. I guess you meant another commit?
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?
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 ๐
Thanks for the follow up. I modified https://github.com/contradict/ros-humble-ros1-bridge/blob/main/Dockerfile to checkout the commit.
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
but my listener is not outputting anything.
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
Not to my knowledge.
But if you go bug-hunting: might as well try the master ๐
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/
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.
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.
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.
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.