ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
0

Linker error for geometry_msgs

asked 2021-04-05 01:31:57 -0500

clepz gravatar image

Hi,

I explore ros2 recently. Differences with ros, creating custom messages, pub sub examples for c++ etc.

I just wanted to demonstrate that another package can be used in a custom message.

I generated a message for simple pub-sub example. Message and its CMakefile in autodrive_msgs package :

AccelCommand.msg

float32 accel
geometry_msgs/Vector3 v

CMakefile:

cmake_minimum_required(VERSION 3.5)
project(autodrive_msgs)

# Default to C99
if(NOT CMAKE_C_STANDARD)
  set(CMAKE_C_STANDARD 99)
endif()

# Default to C++14
if(NOT CMAKE_CXX_STANDARD)
  set(CMAKE_CXX_STANDARD 14)
endif()

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp)
find_package(autodrive_msgs)
find_package(rosidl_default_generators REQUIRED)
rosidl_generate_interfaces(${PROJECT_NAME}
  "msg/AccelCommand.msg"
 )
# uncomment the following section in order to fill in
# further dependencies manually.
# find_package(<dependency> REQUIRED)

if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  # the following line skips the linter which checks for copyrights
  # uncomment the line when a copyright and license is not present in all source files
  #set(ament_cmake_copyright_FOUND TRUE)
  # the following line skips cpplint (only works in a git repo)
  # uncomment the line when this package is not in a git repo
  #set(ament_cmake_cpplint_FOUND TRUE)
  ament_lint_auto_find_test_dependencies()
endif()

ament_package()

I can generate the message. However It gives me a linker error when I want to use the message. Codes and CMakefile in pub_sub package:

pub.cpp:

#include <chrono>
#include <memory>

#include "rclcpp/rclcpp.hpp"
#include "autodrive_msgs/msg/accel_command.hpp"     // CHANGE

using namespace std::chrono_literals;

class MinimalPublisher : public rclcpp::Node
{
public:
  MinimalPublisher()
  : Node("minimal_publisher"), count_(0)
  {
    publisher_ = this->create_publisher<autodrive_msgs::msg::AccelCommand>("topic", 10);    // CHANGE
    timer_ = this->create_wall_timer(
      500ms, std::bind(&MinimalPublisher::timer_callback, this));
  }

private:
  void timer_callback()
  {
    auto message = autodrive_msgs::msg::AccelCommand();                               // CHANGE
    message.accel = this->count_++;                                        // CHANGE
    RCLCPP_INFO(this->get_logger(), "Publishing: '%d'", message.accel);    // CHANGE
    publisher_->publish(message);
  }
  rclcpp::TimerBase::SharedPtr timer_;
  rclcpp::Publisher<autodrive_msgs::msg::AccelCommand>::SharedPtr publisher_;         // CHANGE
  size_t count_;
};

int main(int argc, char * argv[])
{
  rclcpp::init(argc, argv);
  rclcpp::spin(std::make_shared<MinimalPublisher>());
  rclcpp::shutdown();
  return 0;
}

sub.cpp:

#include <memory>

#include "rclcpp/rclcpp.hpp"
#include "autodrive_msgs/msg/accel_command.hpp"     // CHANGE
using std::placeholders::_1;

class MinimalSubscriber : public rclcpp::Node
{
public:
  MinimalSubscriber()
  : Node("minimal_subscriber")
  { 
    subscription_ = this->create_subscription<autodrive_msgs::msg::AccelCommand>(          // CHANGE
      "topic", 10, std::bind(&MinimalSubscriber::topic_callback, this, _1));
  }

private:
  void topic_callback(const autodrive_msgs::msg::AccelCommand::SharedPtr msg) const       // CHANGE
  {
    RCLCPP_INFO(this->get_logger(), "I heard: '%d'", msg->accel);              // CHANGE
  }
  rclcpp::Subscription<autodrive_msgs::msg::AccelCommand>::SharedPtr subscription_;       // CHANGE
};

int main(int argc, char * argv[])
{
  rclcpp::init(argc, argv);
  rclcpp::spin(std::make_shared<MinimalSubscriber>());
  rclcpp::shutdown();
  return 0;
}

CMakefile:

cmake_minimum_required(VERSION 3.5)
project(pub_sub)

# Default to C99
if(NOT CMAKE_C_STANDARD)
  set(CMAKE_C_STANDARD 99)
endif()

# Default to C++14
if(NOT CMAKE_CXX_STANDARD)
  set(CMAKE_CXX_STANDARD 14)
endif()

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp)
find_package(autodrive_msgs)
find_package(geometry_msgs)
# uncomment the following section in order to fill in
# further dependencies manually.
# find_package(<dependency> REQUIRED)


add_executable(talker src/pub.cpp)
ament_target_dependencies(talker rclcpp autodrive_msgs geometry_msgs)         # CHANGE

add_executable(listener src/sub.cpp)
ament_target_dependencies(listener rclcpp autodrive_msgs geometry_msgs)     # CHANGE

install(TARGETS
  talker
  listener
  DESTINATION lib/${PROJECT_NAME})

if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  # the following line skips the linter which ...
(more)
edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
1

answered 2021-04-05 04:40:02 -0500

sgvandijk gravatar image

I copied your code to give it a try and it did compile for me. I however then get the following error when trying to run a node:

$ ros2 run pubsub talker 
/home/sander/install/pubsub/lib/pubsub/talker: symbol lookup error: /home/sander/install/autodrive_msgs/lib/libautodrive_msgs__rosidl_typesupport_fastrtps_cpp.so: undefined symbol: _ZN13geometry_msgs3msg24typesupport_fastrtps_cpp27max_serialized_size_Vector3ERbm

I could get it working with the following pointers:

  • Have you sourced the whole of the ROS 2 environment? If perhaps you only do source install/local_setup.bash, only packages in your local workspace will be available, but not the base ROS 2 packages. So autodrive_msgs can be found, but geometry_msgs not, which looks like what you get. If this is the case, you need to either source install/setup.bash, or source the base environment first. See also: https://answers.ros.org/question/2925...
  • Your autodrive_msgs package is the one with the direct dependency on geometry_msgs, so you should specify that in that package. I am slightly surprised the autodrive_msgs package built without doing so and thought that that was your issue, but I guess the generation process doesn't actually need to work with the base messages. You should still specify the dependency though to enable easier use of your msgs package. For this, you should add this to auodrive_msgs/CMakeLists.txt:

    find_package(geometry_msgs)
    

    And then specify the dependency in the rosidl_generate_interface call:

    rosidl_generate_interfaces(${PROJECT_NAME}
      "msg/AccelCommand.msg"
      DEPENDENCIES geometry_msgs
     )
    

    Finally you should also have a <depend>geometry_msgs</depend> in autodrive_msgs/package.xml. This way any package that depends on your autodrive_msgs package will know it transitively depends on geometry_msgs and you don't have specify that in puch_sub/CMakeLists.txt

  • You have find_package(autodrive_msgs) in autodrive_msgs/CMakeLists.txt, implying the package depends on itself, which can't be (you should get a warning about that when building the package), so that line can/should go.
edit flag offensive delete link more

Comments

Thank you a lot. It builds now. I get this warning:

WARNING:colcon.colcon_ros.prefix_path.ament:The path '/home/clepz/workspace/autodrivemessages_ros2/install/pub_sub' in the environment variable AMENT_PREFIX_PATH doesn't exist

Should I ignore that?

clepz gravatar image clepz  ( 2021-04-05 05:50:51 -0500 )edit

Good to hear you got it building! The warning you get usually indicates you removed a previously built package from the install directory or maybe renamed and rebuilt the package, after you had sourced [local_]setup.bash, causing the old path still to be in the AMENT_PREFIX_PATH environment variable even though it is not there on disk any more. You can indeed ignore it. Opening a new terminal and sourcing the workspace again may resolve it, or else a completely fresh start by doing rm -r install build and build again. In general it is advisable not to source install/[local_]setup.bash in the same terminal where you run Colcon (but to just source the base ROS 2 installation), to prevent this kind of issue and hidden issues with how dependencies are specified in your packages.

sgvandijk gravatar image sgvandijk  ( 2021-04-05 12:06:36 -0500 )edit

Question Tools

1 follower

Stats

Asked: 2021-04-05 01:31:57 -0500

Seen: 1,796 times

Last updated: Apr 05 '21