Creating custom message for ros1_bridge, #include <my_msgs/MyCustom.h> fails

asked 2018-07-27 15:52:15 -0600

Rob V gravatar image

updated 2018-07-30 04:20:23 -0600

Tom Moore gravatar image

ROS: Kinetic, ROS2: Ardent, OS: Ubuntu 16.04

Hello! This question acts as somewhat of a continuation of my previous question. I'm trying to build a custom message to use with ros1_bridge, and in the generated file <path_to_folder>/ros2_ws/build/ros1_bridge/generated/my_msgs_factories.hpp, the line #include <my_msgs/MyCustom.h> is failing while trying to build ros1_bridge. The error message is as follows:

In file included from <path_to_folder>/ros2_ws/build/ros1_bridge/generated/get_factory.cpp:25:0:
<path_to_folder>/ros2_ws/build/ros1_bridge/generated/my_msgs_factories.hpp:6:31: fatal error: my_msgs/MyCustom.h: No such file or directory
compilation terminated.
CMakeFiles/ros1_bridge.dir/build.make:156: recipe for target 'CMakeFiles/ros1_bridge.dir/generated/get_factory.cpp.o' failed

As a sanity check, in /opt/ros/kinetic/include, I created a folder called my_msgs and placed MyCustom.h in it, and then it successfully built. Only at this point is my_msgs seen in the output of ros2 run ros1_bridge dynamic_bridge --print-pairs. However, when I run dynamic_bridge after this (using MyCustom), I get the following output:

Failed to find library 'my_msgs__rosidl_typesupport_introspection_cpp'
failed to create 1to2 bridge for topic '/test_chatter' with ROS 1 type 'my_msgs/MyCustom' and ROS 2 type 'my_msgs/MyCustom': could not create publisher: type support not from this implementation, at <path_to_folder>/ros2_ws/src/ros2/rmw_fastrtps/rmw_fastrtps_cpp/src/rmw_publisher.cpp:75, at <path_to_folder>/ros2_ws/src/ros2/rcl/rcl/src/rcl/publisher.c:151

The contents of <path_to_folder>/ros2_ws/build/ros1_bridge/generated/my_msgs_factories.hpp and .cpp are as follows:

//CONTENTS OF my_msgs_factories.hpp
// generated from ros1_bridge/resource/pkg_factories.hpp.em

#include <ros1_bridge/factory.hpp>

// include ROS 1 messages
#include <my_msgs/MyCustom.h>

// include ROS 2 messages
#include <my_msgs/msg/my_custom.hpp>

namespace ros1_bridge
{

std::shared_ptr<FactoryInterface>
get_factory_my_msgs(const std::string & ros1_type_name, const std::string & ros2_type_name);
std::unique_ptr<ServiceFactoryInterface>
get_service_factory_my_msgs(const std::string & ros_id, const std::string & package_name, const std::string & service_name);
// conversion functions for available interfaces

template<>
void
Factory<
  my_msgs::MyCustom,
  my_msgs::msg::MyCustom
>::convert_1_to_2(
  const my_msgs::MyCustom & ros1_msg,
  my_msgs::msg::MyCustom & ros2_msg);

template<>
void
Factory<
  my_msgs::MyCustom,
  my_msgs::msg::MyCustom
>::convert_2_to_1(
  const my_msgs::msg::MyCustom & ros2_msg,
  my_msgs::MyCustom & ros1_msg);

}  // namespace ros1_bridge

And .cpp:

// CONTENTS OF my_msgs_factories.cpp
// generated from ros1_bridge/resource/pkg_factories.cpp.em
#include "rclcpp/rclcpp.hpp"
#include "my_msgs_factories.hpp"

// include builtin interfaces
#include <ros1_bridge/convert_builtin_interfaces.hpp>
// include ROS 1 services

// include ROS 2 services

namespace ros1_bridge
{

std::shared_ptr<FactoryInterface>
get_factory_my_msgs(const std::string & ros1_type_name, const std::string & ros2_type_name)
{
  // mapping from string to specialized template
  if (
    (ros1_type_name == my_"msgs/MyCustom" ||
     ros1_type_name == "") &&
    ros2_type_name == "my_msgs/MyCustom")
  {
    return std::make_shared<
      Factory<
        my_msgs::MyCustom,
        my_msgs::msg::MyCustom
      >
    >("my_msgs/MyCustom", ros2_type_name);
  }
  return std::shared_ptr<FactoryInterface>();
}
// conversion functions for available interfaces

template<>
void
Factory<
  my_msgs::MyCustom,
  my_msgs::msg::MyCustom
>::convert_1_to_2(
  const my_msgs::MyCustom & ros1_msg,
  my_msgs::msg::MyCustom & ros2_msg)
{
  // convert array field
  // ensure array size
  // dynamic arrays must be resized
  ros2_msg.positions.resize(ros1_msg.positions.size());
  // convert primitive array elements
  std::copy(
    ros1_msg.positions.begin(),
    ros1_msg.positions.end(),
    ros2_msg.positions.begin());
  // convert array field
  // ensure array size
  // dynamic arrays must be resized
  ros2_msg.velocities.resize(ros1_msg.velocities.size());
  // convert primitive ...
(more)
edit retag flag offensive close merge delete

Comments

Did you source your ROS 1 workspace after building it? Please try to include the exact steps you did with which you can reproduce the problem.

Dirk Thomas gravatar imageDirk Thomas ( 2018-07-27 16:20:20 -0600 )edit

See my above edit... Thanks for helping out again!!

Rob V gravatar imageRob V ( 2018-07-27 17:00:13 -0600 )edit

Your original post mentioned that the include failed. So you shouldn't be able to build successfully. You might want to revert your manual changes to /opt/ros/kinetic to reproduce the original problem.

Dirk Thomas gravatar imageDirk Thomas ( 2018-07-27 17:03:58 -0600 )edit

You should only need to source a single ws per ROS version. In ROS 1 your overlay workspace will automatically source the underlay which was used to build that ws. In ROS 2 that works the same when you source the setup.* instead of the local_setup.*.

Dirk Thomas gravatar imageDirk Thomas ( 2018-07-27 17:05:15 -0600 )edit

Good point... However, when I revert it back, that's the same procedure I follow too. See the above minor edit at EDIT #2. Also, didn't know about that setup functionality. Good to know.

Rob V gravatar imageRob V ( 2018-07-27 17:08:45 -0600 )edit