ros2 / ros1_bridge

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

Failed to build ros1_bridge from source when a custom srv includes a custom msg in the same package #348

Closed nqduy35 closed 2 years ago

nqduy35 commented 2 years ago

Trying to build a two very basic examples of using ros1_bridge: test_one and test_two, with custom message and service. The content of the two examples are almost the same except that a custom srv file of the second example includes the type of another custom msg in the same package. I can build the ros1_bridge from souce in the first example, but not in the second example. Following is the detail:

In test_one, there are two msg and one srv: msg/Data.msg:

int32 a

msg/Info.msg:

Data data

srv/Print.srv:

int32 input — — — string output

I can build ros1_bridge and everything works fine. Exacly the same as the above, the only difference of the test_two is the srv's content:

srv/Print.srv:

Data input — — — string output

The error appears. Check the error in Section "Actual Error". I also tried to change the first line of the srv file as following, but the error is still.

test_two/Data input

However, if the package test_two uses the Data.msg of the package test_one, everything works fine. In detail, when I change the first line of Print.srv into

test_one/Data input

and declare the dependency of test_two on test_one in its CMakeLists.txt and package.xml, then I can build ros1_bridge without fault.

Bug report

Steps to reproduce issue

$ source /opt/ros/noetic/setup.bash $ source /opt/ros/foxy/setup.bash $ source ~/catkin_ws/devel/setup.bash $ source ~/ament_ws/install/local_setup.bash $ colcon build --packages-select ros1_bridge --cmake-force-configure

Actual Error

--- stderr: ros1_bridge
/usr/bin/ld: libros1_bridge.so: undefined reference to ros1_bridge::Factory<test_two::Data_<std::allocator<void> >, test_two::msg::Data_<std::allocator<void> > >::convert_1_to_2(test_two::Data_<std::allocator<void> > const&, test_two::msg::Data_<std::allocator<void> >&)' /usr/bin/ld: libros1_bridge.so: undefined reference toros1_bridge::Factory<testtwo::Data<std::allocator >, testtwo::msg::Data<std::allocator > >::convert_2_to_1(testtwo::msg::Data<std::allocator > const&, testtwo::Data<std::allocator >&)' collect2: error: ld returned 1 exit status make[2]: [CMakeFiles/static_bridge.dir/build.make:368: static_bridge] Error 1 make[1]: [CMakeFiles/Makefile2:233: CMakeFiles/static_bridge.dir/all] Error 2 make[1]: Waiting for unfinished jobs.... /usr/bin/ld: libros1_bridge.so: undefined reference to ros1_bridge::Factory<test_two::Data_<std::allocator<void> >, test_two::msg::Data_<std::allocator<void> > >::convert_1_to_2(test_two::Data_<std::allocator<void> > const&, test_two::msg::Data_<std::allocator<void> >&)' /usr/bin/ld: libros1_bridge.so: undefined reference toros1_bridge::Factory<testtwo::Data<std::allocator >, testtwo::msg::Data<std::allocator > >::convert_2_to_1(testtwo::msg::Data<std::allocator > const&, testtwo::Data<std::allocator >&)' collect2: error: ld returned 1 exit status make[2]: [CMakeFiles/parameter_bridge.dir/build.make:368: parameter_bridge] Error 1 make[1]: [CMakeFiles/Makefile2:314: CMakeFiles/parameter_bridge.dir/all] Error 2 /usr/bin/ld: libros1_bridge.so: undefined reference to ros1_bridge::Factory<test_two::Data_<std::allocator<void> >, test_two::msg::Data_<std::allocator<void> > >::convert_1_to_2(test_two::Data_<std::allocator<void> > const&, test_two::msg::Data_<std::allocator<void> >&)' /usr/bin/ld: libros1_bridge.so: undefined reference toros1_bridge::Factory<testtwo::Data<std::allocator >, testtwo::msg::Data<std::allocator > >::convert_2_to_1(testtwo::msg::Data<std::allocator > const&, testtwo::Data<std::allocator >&)' collect2: error: ld returned 1 exit status make[2]: [CMakeFiles/dynamic_bridge.dir/build.make:368: dynamic_bridge] Error 1 make[1]: [CMakeFiles/Makefile2:341: CMakeFiles/dynamic_bridge.dir/all] Error 2 make: [Makefile:141: all] Error 2 — — — Failed <<< ros1_bridge [4min 26s, exited with code 2]

gbiggs commented 2 years ago

Can you please provide a repository or tarball containing the working and failing cases that I can use to reproduce the error?

nqduy35 commented 2 years ago

The code is available in here github.com:nqduy35/ros1_bridge_348. Thank you.

amilcarlucas commented 2 years ago

I get similar linking errors when using rmw_fastrtps_cpp on galactic.

I get no linking errors when not using rmw_fastrtps_cpp .

@pablogs9 do I need to install fastrtpsgen or something like that?

ROS1 messages build fine:

root@Amilcar-HP-ZBook:/ernteroboter_ws/ros1_ws# rosmsg list | grep emily
emily_uc_msgs/BatteryStatus
emily_uc_msgs/ButtonsStatus
root@Amilcar-HP-ZBook:/ernteroboter_ws/ros1_ws# rossrv list | grep emily
emily_uc_msgs/Gripper
emily_uc_msgs/LoadCell
emily_uc_msgs/SemaphoreLights

ROS2 messages build fine:

root@Amilcar-HP-ZBook:/ernteroboter_ws/ros2_ws# ros2 interface list | grep emily
    emily_uc_msgs/msg/BatteryStatus
    emily_uc_msgs/msg/ButtonsStatus
    emily_uc_msgs/srv/Gripper
    emily_uc_msgs/srv/LoadCell
    emily_uc_msgs/srv/SemaphoreLights

Then I do:

export CHOOSE_ROS1_DISTRO=noetic &&
export CHOOSE_ROS2_DISTRO=galactic &&
source /opt/ros/${CHOOSE_ROS1_DISTRO}/setup.bash &&
export RMW_IMPLEMENTATION=rmw_fastrtps_cpp &&
source /opt/ros/${CHOOSE_ROS2_DISTRO}/setup.bash &&
source ../ros1_ws/install_isolated/setup.bash &&
source ../ros2_ws/install/local_setup.bash &&
colcon build --packages-select ros1_bridge --cmake-force-configure --cmake-args -DBUILD_TESTING=FALSE --cmake-args -DCMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES=/ernteroboter_ws/ros2_ws/install/emily_uc_msgs/include/

and it compiles fine but gives linking errors.

amilcarlucas commented 2 years ago

I seam to have fixed the linking error by installing ros-galactic-rmw-fastrtps-dynamic-cpp

@pablogs9 you might what to add that to the documentation.

nqduy35 commented 2 years ago

Literally, the problem I raised is not the same to the problem of @amilcarlucas. The issue I raised is illustrated by a very basic example at github.com:nqduy35/ros1_bridge_348. @gbiggs Please tell me if you need other information. Thank you.

gbiggs commented 2 years ago

Not as yet. I will take a look at your example and try to replicate the problem. If I can replicate it, then we will work on fixing it.

nqduy35 commented 2 years ago

@gbiggs Sorry if I disturb you too much. I just wanted to know if you have already tried to reproduce the error? By the way, I have added two new images at github.com:nqduy35/ros1_bridge_348 so you can check the problem easier. Thank you again.

amilcarlucas commented 2 years ago

I have two messages and three services on the same package. And I got it to run now, after updating to the latest micro_ros_arduino version. This version uses the latest rmw version.

nqduy35 commented 2 years ago

@amilcarlucas Could you run my example to check ? Thank you. P.s. It is just a very basic example with basic ROS and ROS2 with no fancy things.

gbiggs commented 2 years ago

@nqduy35 I've been able to reproduce the error. I'll start figuring out the cause and a fix.

gbiggs commented 2 years ago

@nqduy35 Just to let you know I'm still working on this, but have not made progress in identifying the error yet.

gbiggs commented 2 years ago

I found some more time to work on this, and managed to identify the source of your problem.

In ROS 2, interface definitions (messages, services and actions) are, by convention, stored in their own package that has _interfaces (new) or _msgs as the suffix of its name. This is only a convention: in general things will work just fine if you don't do this. However the ros1_bridge has this convention hard-coded in when it searches for matching interface definitions between ROS 1 and ROS 2. If you rename your test_two package to test_two_interfaces, the bridge will compile.

nqduy35 commented 2 years ago

@gbiggs Thank you very much for your time and effort.