1
$\begingroup$

Rosanswers logo

I'm having trouble understanding how to publish a cv::Mat image in C++, and I can find very little documentation about this.

Here's my publish code. I based it on this tutorial: https://docs.ros.org/en/galactic/Tutorials/Writing-A-Simple-Cpp-Publisher-And-Subscriber.html

#include <chrono>
#include <memory>

#include "cv_bridge/cv_bridge.h"
#include "rclcpp/rclcpp.hpp"
#include "sensor_msgs/msg/image.hpp"
#include "std_msgs/msg/header.hpp"
#include <opencv2/opencv.hpp>
#include <stdio.h>

// for Size
#include <opencv2/core/types.hpp>
// for CV_8UC3
#include <opencv2/core/hal/interface.h>
// for compressing the image
#include <image_transport/image_transport.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace std::chrono_literals;

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

  private:
    void timer_callback() {
        cv_bridge::CvImagePtr cv_ptr;

        cv::Mat img(cv::Size(1280, 720), CV_8UC3);
        cv::randu(img, cv::Scalar(0, 0, 0), cv::Scalar(255, 255, 255));

        sensor_msgs::msg::Image::SharedPtr msg =
            cv_bridge::CvImage(std_msgs::msg::Header(), "bgr8", img)
                .toImageMsg();

        publisher_->publish(msg);
        std::cout << "Published!" << std::endl;
    }

    rclcpp::TimerBase::SharedPtr timer_;

    rclcpp::Publisher<sensor_msgs::msg::Image>::SharedPtr publisher_;

    size_t count_;
};

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

The publisher_->publish(msg) line throws the following error:

Starting >>> cpp_pubsub
--- stderr: cpp_pubsub                               
/app/tests/ros2_cpp_test/src/cpp_pubsub/src/publisher_member_function.cpp: In member function ‘void MinimalPublisher::timer_callback()’:
/app/tests/ros2_cpp_test/src/cpp_pubsub/src/publisher_member_function.cpp:67:26: error: no matching function for call to ‘rclcpp::Publisher<sensor_msgs::msg::Image_<std::allocator<void> > >::publish(sensor_msgs::msg::Image_<std::allocator<void> >::SharedPtr&)’
   publisher_->publish(msg);
                          ^
In file included from /opt/ros/galactic/install/include/rclcpp/topic_statistics/subscription_topic_statistics.hpp:31:0,
                 from /opt/ros/galactic/install/include/rclcpp/subscription.hpp:50,
                 from /opt/ros/galactic/install/include/rclcpp/any_executable.hpp:25,
                 from /opt/ros/galactic/install/include/rclcpp/memory_strategy.hpp:25,
                 from /opt/ros/galactic/install/include/rclcpp/memory_strategies.hpp:18,
                 from /opt/ros/galactic/install/include/rclcpp/executor_options.hpp:20,
                 from /opt/ros/galactic/install/include/rclcpp/executor.hpp:36,
                 from /opt/ros/galactic/install/include/rclcpp/executors/multi_threaded_executor.hpp:26,
                 from /opt/ros/galactic/install/include/rclcpp/executors.hpp:21,
                 from /opt/ros/galactic/install/include/rclcpp/rclcpp.hpp:156,
                 from /app/tests/ros2_cpp_test/src/cpp_pubsub/src/publisher_member_function.cpp:19:
/opt/ros/galactic/install/include/rclcpp/publisher.hpp:187:3: note: candidate: void rclcpp::Publisher<MessageT, AllocatorT>::publish(std::unique_ptr<MessageT, typename std::conditional<std::is_same<typename std::allocator_traits<typename std::allocator_traits<_Alloc>::rebind_traits<MessageT>::allocator_type>::rebind_alloc<MessageT>, typename std::allocator<void>::rebind<_Tp1>::other>::value, std::default_delete<_Tp>, rclcpp::allocator::AllocatorDeleter<typename std::allocator_traits<_Alloc>::rebind_traits<MessageT>::allocator_type> >::type>) [with MessageT = sensor_msgs::msg::Image_<std::allocator<void> >; AllocatorT = std::allocator<void>; typename std::conditional<std::is_same<typename std::allocator_traits<typename std::allocator_traits<_Alloc>::rebind_traits<MessageT>::allocator_type>::rebind_alloc<MessageT>, typename std::allocator<void>::rebind<_Tp1>::other>::value, std::default_delete<_Tp>, rclcpp::allocator::AllocatorDeleter<typename std::allocator_traits<_Alloc>::rebind_traits<MessageT>::allocator_type> >::type = std::default_delete<sensor_msgs::msg::Image_<std::allocator<void> > >]
   publish(std::unique_ptr<MessageT, MessageDeleter> msg)
   ^~~~~~~
/opt/ros/galactic/install/include/rclcpp/publisher.hpp:187:3: note:   no known conversion for argument 1 from ‘sensor_msgs::msg::Image_<std::allocator<void> >::SharedPtr {aka std::shared_ptr<sensor_msgs::msg::Image_<std::allocator<void> > >}’ to ‘std::unique_ptr<sensor_msgs::msg::Image_<std::allocator<void> >, std::default_delete<sensor_msgs::msg::Image_<std::allocator<void> > > >’
/opt/ros/galactic/install/include/rclcpp/publisher.hpp:211:3: note: candidate: void rclcpp::Publisher<MessageT, AllocatorT>::publish(const MessageT&) [with MessageT = sensor_msgs::msg::Image_<std::allocator<void> >; AllocatorT = std::allocator<void>]
   publish(const MessageT & msg)
   ^~~~~~~
/opt/ros/galactic/install/include/rclcpp/publisher.hpp:211:3: note:   no known conversion for argument 1 from ‘sensor_msgs::msg::Image_<std::allocator<void> >::SharedPtr {aka std::shared_ptr<sensor_msgs::msg::Image_<std::allocator<void> > >}’ to ‘const sensor_msgs::msg::Image_<std::allocator<void> >&’
/opt/ros/galactic/install/include/rclcpp/publisher.hpp:228:3: note: candidate: void rclcpp::Publisher<MessageT, AllocatorT>::publish(const rcl_serialized_message_t&) [with MessageT = sensor_msgs::msg::Image_<std::allocator<void> >; AllocatorT = std::allocator<void>; rcl_serialized_message_t = rcutils_uint8_array_t]
   publish(const rcl_serialized_message_t & serialized_msg)
   ^~~~~~~
/opt/ros/galactic/install/include/rclcpp/publisher.hpp:228:3: note:   no known conversion for argument 1 from ‘sensor_msgs::msg::Image_<std::allocator<void> >::SharedPtr {aka std::shared_ptr<sensor_msgs::msg::Image_<std::allocator<void> > >}’ to ‘const rcl_serialized_message_t& {aka const rcutils_uint8_array_t&}’
/opt/ros/galactic/install/include/rclcpp/publisher.hpp:234:3: note: candidate: void rclcpp::Publisher<MessageT, AllocatorT>::publish(const rclcpp::SerializedMessage&) [with MessageT = sensor_msgs::msg::Image_<std::allocator<void> >; AllocatorT = std::allocator<void>]
   publish(const SerializedMessage & serialized_msg)
   ^~~~~~~
/opt/ros/galactic/install/include/rclcpp/publisher.hpp:234:3: note:   no known conversion for argument 1 from ‘sensor_msgs::msg::Image_<std::allocator<void> >::SharedPtr {aka std::shared_ptr<sensor_msgs::msg::Image_<std::allocator<void> > >}’ to ‘const rclcpp::SerializedMessage&’
/opt/ros/galactic/install/include/rclcpp/publisher.hpp:248:3: note: candidate: void rclcpp::Publisher<MessageT, AllocatorT>::publish(rclcpp::LoanedMessage<MessageT, AllocatorT>&&) [with MessageT = sensor_msgs::msg::Image_<std::allocator<void> >; AllocatorT = std::allocator<void>]
   publish(rclcpp::LoanedMessage<MessageT, AllocatorT> && loaned_msg)
   ^~~~~~~
/opt/ros/galactic/install/include/rclcpp/publisher.hpp:248:3: note:   no known conversion for argument 1 from ‘sensor_msgs::msg::Image_<std::allocator<void> >::SharedPtr {aka std::shared_ptr<sensor_msgs::msg::Image_<std::allocator<void> > >}’ to ‘rclcpp::LoanedMessage<sensor_msgs::msg::Image_<std::allocator<void> >, std::allocator<void> >&&’
make[2]: *** [CMakeFiles/talker.dir/src/publisher_member_function.cpp.o] Error 1
make[1]: *** [CMakeFiles/talker.dir/all] Error 2
make: *** [all] Error 2
---
Failed   <<< cpp_pubsub [22.8s, exited with code 2]

Summary: 0 packages finished [23.8s]
  1 package failed: cpp_pubsub
  1 package had stderr output: cpp_pubsub

Originally posted by zjeffer on ROS Answers with karma: 46 on 2022-03-07

Post score: 1

$\endgroup$

1 Answer 1

0
$\begingroup$

Rosanswers logo

I fixed it by changing the publisher line to:

publisher_->publish(*msg.get());


Originally posted by zjeffer with karma: 46 on 2022-03-07

This answer was ACCEPTED on the original site

Post score: 2

$\endgroup$

Your Answer

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