0
$\begingroup$

Rosanswers logo

Hi there. Recently, I'm trying to combine two string messages and use message_filters::TimeSynchronizer to synchronize the two message. I have written the minimal code as follows:

The talker1:

#include <chrono>
#include <functional>
#include <memory>
#include <string>

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"

using namespace std::chrono_literals;

/* This example creates a subclass of Node and uses std::bind() to register a
 * member function as a callback from the timer. */

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

private:
  void timer_callback()
  {
    auto message = std_msgs::msg::String();
    message.data = "Hello, world! " + std::to_string(count_++);
    RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str());
    publisher_->publish(message);
  }

  rclcpp::TimerBase::SharedPtr timer_;
  rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
  size_t count_;
};

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

The talker2:

#include <chrono>
#include <functional>
#include <memory>
#include <string>

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"

using namespace std::chrono_literals;

/* This example creates a subclass of Node and uses std::bind() to register a
 * member function as a callback from the timer. */

class MinimalPublisher : public rclcpp::Node
{
public:
  MinimalPublisher()
  : Node("minimal_publisher"), count_(0)
  {
    publisher_ = this->create_publisher<std_msgs::msg::String>("topic2", 10);
    timer_ = this->create_wall_timer(
      1000ms, std::bind(&MinimalPublisher::timer_callback, this));
  }

private:
  void timer_callback()
  {
    auto message = std_msgs::msg::String();
    message.data = "Hello, world! " + std::to_string(count_++);
    RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str());
    publisher_->publish(message);
  }
  rclcpp::TimerBase::SharedPtr timer_;
  rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
  size_t count_;
};

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

The listener:

#include <functional>
#include <memory>

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
#include "message_filters/subscriber.h"
#include "message_filters/time_synchronizer.h"

using std::placeholders::_1;
using std::placeholders::_2;

class MinimalSubscriber : public rclcpp::Node
{
public:
  MinimalSubscriber()
  : Node("minimal_sync_subscriber")
  {
    sub1_.subscribe(this, "topic1");
    sub2_.subscribe(this, "topic2");
    sync_ = std::make_shared<
        message_filters::TimeSynchronizer<std_msgs::msg::String, std_msgs::msg::String>>(
          sub1_, sub2_, 10
        );
    sync_->registerCallback(std::bind(&MinimalSubscriber::topic_callback, this, _1, _2));
  }

private:
  void topic_callback(const std_msgs::msg::String::ConstSharedPtr &msg1, 
                      const std_msgs::msg::String::ConstSharedPtr &msg2) const
  {
    RCLCPP_INFO(this->get_logger(), "I heard: '%s'", msg1->data.c_str());
    RCLCPP_INFO(this->get_logger(), "I heard: '%s'", msg2->data.c_str());
  }
  message_filters::Subscriber<std_msgs::msg::String> sub1_;
  message_filters::Subscriber<std_msgs::msg::String> sub2_;
  std::shared_ptr<message_filters::TimeSynchronizer<std_msgs::msg::String, std_msgs::msg::String>> sync_;
};

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

Basically, for these three nodes, I would expect that the listener can print some info. The compilation process is OK. No error happens after I typed colcon build in the workspace directory. However, a strange error occurred at runtime. Here's the error message when I try to run the listener node: /home/baozhe/dev_ws/install/cpp_pubsub/lib/cpp_pubsub/listener: symbol lookup error: /home/baozhe/dev_ws/install/cpp_pubsub/lib/cpp_pubsub/listener: undefined symbol: _ZN15message_filters10ConnectionC1ERKSt8functionIFvvEE

I used c++filt and found the symbol above is message_filters::Connection::Connection(std::function<void ()> const&), but I don't know why this happened. The CMakeLists.txt is shown below:

make_minimum_required(VERSION 3.8)
project(cpp_pubsub)

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 REQUIRED)
find_package(std_msgs REQUIRED)
find_package(message_filters REQUIRED)
# uncomment the following section in order to fill in
# further dependencies manually.
# find_package(<dependency> REQUIRED)

add_executable(talker1 src/publisher_member_function.cpp)
ament_target_dependencies(talker1 rclcpp std_msgs)
add_executable(talker2 src/publisher_member_function_slow.cpp)
ament_target_dependencies(talker2 rclcpp std_msgs)

add_executable(listener src/subscriber_member_function.cpp)
ament_target_dependencies(listener rclcpp std_msgs message_filters)

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

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()

One website mentioned that this may be related to ROS versions. My computer has noetic and galactic installed.


Originally posted by Baozhe Zhang on ROS Answers with karma: 16 on 2022-06-17

Post score: 0

$\endgroup$

1 Answer 1

0
$\begingroup$

Rosanswers logo

This is indeed a ROS-version problem. I tried deploy my code in a docker container and it turned out that the code can run successfully.


Originally posted by Baozhe Zhang with karma: 16 on 2022-06-17

This answer was ACCEPTED on the original site

Post score: 0

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.