From 27bc4d30d1bca4fe0a514f80abcdef043d1ab6d0 Mon Sep 17 00:00:00 2001 From: Rebecca Butler Date: Mon, 28 Jun 2021 15:11:01 -0400 Subject: [PATCH 01/13] Create image_transport_tutorial package Signed-off-by: Rebecca Butler --- image_transport_tutorial/CMakeLists.txt | 91 +++++++++++++++++++ .../resized_publisher.hpp | 19 ++++ .../resized_subscriber.hpp | 21 +++++ image_transport_tutorial/msg/ResizedImage.msg | 3 + image_transport_tutorial/package.xml | 36 ++++++++ image_transport_tutorial/resized_plugins.xml | 13 +++ image_transport_tutorial/src/manifest.cpp | 6 ++ image_transport_tutorial/src/my_publisher.cpp | 26 ++++++ .../src/my_subscriber.cpp | 35 +++++++ .../src/resized_publisher.cpp | 37 ++++++++ .../src/resized_publisher.hpp | 18 ++++ .../src/resized_subscriber.cpp | 18 ++++ .../src/resized_subscriber.hpp | 21 +++++ 13 files changed, 344 insertions(+) create mode 100644 image_transport_tutorial/CMakeLists.txt create mode 100644 image_transport_tutorial/include/image_transport_tutorial/image_transport_tutorial/resized_publisher.hpp create mode 100644 image_transport_tutorial/include/image_transport_tutorial/image_transport_tutorial/resized_subscriber.hpp create mode 100644 image_transport_tutorial/msg/ResizedImage.msg create mode 100644 image_transport_tutorial/package.xml create mode 100644 image_transport_tutorial/resized_plugins.xml create mode 100644 image_transport_tutorial/src/manifest.cpp create mode 100644 image_transport_tutorial/src/my_publisher.cpp create mode 100644 image_transport_tutorial/src/my_subscriber.cpp create mode 100644 image_transport_tutorial/src/resized_publisher.cpp create mode 100644 image_transport_tutorial/src/resized_publisher.hpp create mode 100644 image_transport_tutorial/src/resized_subscriber.cpp create mode 100644 image_transport_tutorial/src/resized_subscriber.hpp diff --git a/image_transport_tutorial/CMakeLists.txt b/image_transport_tutorial/CMakeLists.txt new file mode 100644 index 00000000..8b9c2c25 --- /dev/null +++ b/image_transport_tutorial/CMakeLists.txt @@ -0,0 +1,91 @@ +cmake_minimum_required(VERSION 3.8) +project(image_transport_tutorial) + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +find_package(ament_cmake REQUIRED) +find_package(rclcpp REQUIRED) +find_package(std_msgs REQUIRED) +find_package(sensor_msgs REQUIRED) +find_package(cv_bridge REQUIRED) +find_package(image_transport REQUIRED) + +# add the resized image message +set(msg_files + "msg/ResizedImage.msg" +) +rosidl_generate_interfaces(${PROJECT_NAME}_interface + ${msg_files} + DEPENDENCIES builtin_interfaces +) + +include_directories(include) + +add_library(${PROJECT_NAME} + src/manifest.cpp + src/my_publisher.cpp + src/my_subscriber.cpp + src/resized_publisher.cpp + src/resized_subscriber.cpp +) + +ament_target_dependencies( + ${PROJECT_NAME} + rclcpp + std_msgs + sensor_msgs + cv_bridge + image_transport +) + +target_compile_definitions(${PROJECT_NAME} PUBLIC "PLUGINLIB__DISABLE_BOOST_FUNCTIONS") +target_compile_definitions(${PROJECT_NAME} PRIVATE "IMAGE_TRANSPORT_BUILDING_DLL") + +# Build image_transport_plugins library (raw) +add_library(${PROJECT_NAME}_plugins + src/manifest.cpp +) +target_link_libraries(${PROJECT_NAME}_plugins ${PROJECT_NAME}) + +# add the publisher example +add_executable(my_publisher src/my_publisher.cpp) +target_link_libraries(my_publisher ${PROJECT_NAME}) + +# add the subscriber example +add_executable(my_subscriber src/my_subscriber.cpp) +target_link_libraries(my_subscriber ${PROJECT_NAME}) + +# Install plugin descriptions +#pluginlib_export_plugin_description_file(image_transport default_plugins.xml) + +# add the plugin example +add_library(resized_publisher src/manifest.cpp src/resized_publisher.cpp src/resized_subscriber.cpp) +target_link_libraries(resized_publisher ${PROJECT_NAME}) + +# Install libraries +install( + TARGETS ${PROJECT_NAME} ${PROJECT_NAME}_plugins + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin +) + +# Install executables +install( + TARGETS my_publisher my_subscriber resized_publisher + RUNTIME DESTINATION lib/${PROJECT_NAME} +) + +# Install include directories +install( + DIRECTORY include/ + DESTINATION include +) + +ament_export_include_directories(include) +ament_export_libraries(${PROJECT_NAME}) +ament_export_dependencies(rclcpp std_msgs sensor_msgs cvbridge image_transport) + +ament_package() \ No newline at end of file diff --git a/image_transport_tutorial/include/image_transport_tutorial/image_transport_tutorial/resized_publisher.hpp b/image_transport_tutorial/include/image_transport_tutorial/image_transport_tutorial/resized_publisher.hpp new file mode 100644 index 00000000..d47552a8 --- /dev/null +++ b/image_transport_tutorial/include/image_transport_tutorial/image_transport_tutorial/resized_publisher.hpp @@ -0,0 +1,19 @@ +#include +//#include +#include "image_transport_tutorial/msg/resized_image.hpp" + +IMAGE_TRANSPORT_PUBLIC +class ResizedPublisher : public image_transport::SimplePublisherPlugin +{ +public: + IMAGE_TRANSPORT_PUBLIC + virtual std::string getTransportName() const + { + return "resized"; + } + +protected: + IMAGE_TRANSPORT_PUBLIC + virtual void publish(const sensor_msgs::Image& message, + const PublishFn& publish_fn) const; +}; diff --git a/image_transport_tutorial/include/image_transport_tutorial/image_transport_tutorial/resized_subscriber.hpp b/image_transport_tutorial/include/image_transport_tutorial/image_transport_tutorial/resized_subscriber.hpp new file mode 100644 index 00000000..452d5212 --- /dev/null +++ b/image_transport_tutorial/include/image_transport_tutorial/image_transport_tutorial/resized_subscriber.hpp @@ -0,0 +1,21 @@ +#include +#include "image_transport_tutorial/msg/resized_image.hpp" + +IMAGE_TRANSPORT_PUBLIC +class ResizedSubscriber : public image_transport::SimpleSubscriberPlugin +{ +public: + IMAGE_TRANSPORT_PUBLIC + virtual ~ResizedSubscriber() {} + + IMAGE_TRANSPORT_PUBLIC + virtual std::string getTransportName() const + { + return "resized"; + } + +protected: + IMAGE_TRANSPORT_PUBLIC + virtual void internalCallback(const typename image_transport_tutorial::ResizedImage::ConstPtr& message, + const Callback& user_cb); +}; diff --git a/image_transport_tutorial/msg/ResizedImage.msg b/image_transport_tutorial/msg/ResizedImage.msg new file mode 100644 index 00000000..d8c8fadb --- /dev/null +++ b/image_transport_tutorial/msg/ResizedImage.msg @@ -0,0 +1,3 @@ +uint32 original_height +uint32 original_width +sensor_msgs/Image image diff --git a/image_transport_tutorial/package.xml b/image_transport_tutorial/package.xml new file mode 100644 index 00000000..96f86854 --- /dev/null +++ b/image_transport_tutorial/package.xml @@ -0,0 +1,36 @@ + + image_transport_tutorial + 0.0.0 + Tutorial for image_transport. + Vincent Rabaud + Vincent Rabaud + Apache 2.0 + + ament_cmake + rosidl_default_generators + + builtin_interfaces + cv_bridge + image_transport + message_generation + opencv2 + sensor_msgs + + builtin_interfaces + rosidl_default_runtime + cv_bridge + image_transport + message_runtime + opencv2 + sensor_msgs + + ament_lint_auto + ament_lint_common + + rosidl_interface_packages + + + ament_cmake + + + diff --git a/image_transport_tutorial/resized_plugins.xml b/image_transport_tutorial/resized_plugins.xml new file mode 100644 index 00000000..bd2dff1a --- /dev/null +++ b/image_transport_tutorial/resized_plugins.xml @@ -0,0 +1,13 @@ + + + + This plugin publishes a decimated version of the image. + + + + + + This plugin rescales a decimated image to its original size. + + + diff --git a/image_transport_tutorial/src/manifest.cpp b/image_transport_tutorial/src/manifest.cpp new file mode 100644 index 00000000..e03a5909 --- /dev/null +++ b/image_transport_tutorial/src/manifest.cpp @@ -0,0 +1,6 @@ +#include +#include + +PLUGINLIB_EXPORT_CLASS(ResizedPublisher, image_transport::PublisherPlugin) + +PLUGINLIB_EXPORT_CLASS(ResizedSubscriber, image_transport::SubscriberPlugin) diff --git a/image_transport_tutorial/src/my_publisher.cpp b/image_transport_tutorial/src/my_publisher.cpp new file mode 100644 index 00000000..a5bfa159 --- /dev/null +++ b/image_transport_tutorial/src/my_publisher.cpp @@ -0,0 +1,26 @@ +#include +#include +#include +#include + +int main(int argc, char** argv) +{ + rclcpp::init(argc, argv); + rclcpp::NodeOptions options; + rclcpp::Node::SharedPtr node = rclcpp::Node::make_shared("image_publisher", options); + image_transport::ImageTransport it(node); + image_transport::Publisher pub = it.advertise("camera/image", 1); + + cv::Mat image = cv::imread(argv[1], cv::IMREAD_COLOR); + std_msgs::msg::Header hdr; + sensor_msgs::msg::Image::SharedPtr msg; + msg = cv_bridge::CvImage(hdr, "bgr8", image).toImageMsg(); + + rclcpp::WallRate loop_rate(5); + while (rclcpp::ok()) { + pub.publish(msg); + rclcpp::spin_some(node); + loop_rate.sleep(); + } +} + diff --git a/image_transport_tutorial/src/my_subscriber.cpp b/image_transport_tutorial/src/my_subscriber.cpp new file mode 100644 index 00000000..5009beb4 --- /dev/null +++ b/image_transport_tutorial/src/my_subscriber.cpp @@ -0,0 +1,35 @@ +#include +#include +#include +#include + +#include "rclcpp/logging.hpp" + +void imageCallback(const sensor_msgs::msg::Image::ConstSharedPtr& msg) +{ + try + { + cv::imshow("view", cv_bridge::toCvShare(msg, "bgr8")->image); + cv::waitKey(10); + } + catch (cv_bridge::Exception& e) + { + auto logger = rclcpp::get_logger("camera_calibration_parsers.convert"); + RCLCPP_ERROR(logger, "Could not convert from '%s' to 'bgr8'.", msg->encoding.c_str()); + } +} + +//image_transport::Subscriber::Callback &callback = std::function imageCallback; + +int main(int argc, char **argv) +{ + rclcpp::init(argc, argv); + rclcpp::NodeOptions options; + rclcpp::Node::SharedPtr node = rclcpp::Node::make_shared("image_listener", options); + cv::namedWindow("view"); + cv::startWindowThread(); + image_transport::ImageTransport it(node); + image_transport::Subscriber sub = it.subscribe("camera/image", 1, imageCallback); + rclcpp::spin_some(node); + cv::destroyWindow("view"); +} diff --git a/image_transport_tutorial/src/resized_publisher.cpp b/image_transport_tutorial/src/resized_publisher.cpp new file mode 100644 index 00000000..6fd2fa4a --- /dev/null +++ b/image_transport_tutorial/src/resized_publisher.cpp @@ -0,0 +1,37 @@ +#include +#include +#include + +void ResizedPublisher::publish(const sensor_msgs::Image& message, + const PublishFn& publish_fn) const +{ + cv::Mat cv_image; + boost::shared_ptr tracked_object; + try + { + cv_image = cv_bridge::toCvShare(message, tracked_object, message.encoding)->image; + } + catch (cv::Exception &e) + { + ROS_ERROR("Could not convert from '%s' to '%s'.", message.encoding.c_str(), message.encoding.c_str()); + return; + } + + // Retrieve subsampling factor from the parameter server + double subsampling_factor; + std::string param_name; + nh().param("resized_image_transport_subsampling_factor", subsampling_factor, 2.0); + + // Rescale image + int new_width = cv_image.cols / subsampling_factor + 0.5; + int new_height = cv_image.rows / subsampling_factor + 0.5; + cv::Mat buffer; + cv::resize(cv_image, buffer, cv::Size(new_width, new_height)); + + // Set up ResizedImage and publish + image_transport_tutorial::ResizedImage resized_image; + resized_image.original_height = cv_image.rows; + resized_image.original_width = cv_image.cols; + resized_image.image = *(cv_bridge::CvImage(message.header, "bgr8", cv_image).toImageMsg()); + publish_fn(resized_image); +} diff --git a/image_transport_tutorial/src/resized_publisher.hpp b/image_transport_tutorial/src/resized_publisher.hpp new file mode 100644 index 00000000..c1e2fafe --- /dev/null +++ b/image_transport_tutorial/src/resized_publisher.hpp @@ -0,0 +1,18 @@ +#include +#include "image_transport_tutorial/msg/resized_image.hpp" + +IMAGE_TRANSPORT_PUBLIC +class ResizedPublisher : public image_transport::SimplePublisherPlugin +{ +public: + IMAGE_TRANSPORT_PUBLIC + virtual std::string getTransportName() const + { + return "resized"; + } + +protected: + IMAGE_TRANSPORT_PUBLIC + virtual void publish(const sensor_msgs::Image& message, + const PublishFn& publish_fn) const; +}; diff --git a/image_transport_tutorial/src/resized_subscriber.cpp b/image_transport_tutorial/src/resized_subscriber.cpp new file mode 100644 index 00000000..982985e4 --- /dev/null +++ b/image_transport_tutorial/src/resized_subscriber.cpp @@ -0,0 +1,18 @@ +#include +#include +#include + +void ResizedSubscriber::internalCallback(const image_transport_tutorial::ResizedImage::ConstPtr& msg, + const Callback& user_cb) +{ + // This is only for optimization, not to copy the image + boost::shared_ptr tracked_object_tmp; + cv::Mat img_rsz = cv_bridge::toCvShare(msg->image, tracked_object_tmp)->image; + // Resize the image to its original size + cv::Mat img_restored; + cv::resize(img_rsz, img_restored, cv::Size(msg->original_width, msg->original_height)); + + // Call the user callback with the restored image + cv_bridge::CvImage cv_img(msg->image.header, msg->image.encoding, img_restored); + user_cb(cv_img.toImageMsg()); +}; diff --git a/image_transport_tutorial/src/resized_subscriber.hpp b/image_transport_tutorial/src/resized_subscriber.hpp new file mode 100644 index 00000000..452d5212 --- /dev/null +++ b/image_transport_tutorial/src/resized_subscriber.hpp @@ -0,0 +1,21 @@ +#include +#include "image_transport_tutorial/msg/resized_image.hpp" + +IMAGE_TRANSPORT_PUBLIC +class ResizedSubscriber : public image_transport::SimpleSubscriberPlugin +{ +public: + IMAGE_TRANSPORT_PUBLIC + virtual ~ResizedSubscriber() {} + + IMAGE_TRANSPORT_PUBLIC + virtual std::string getTransportName() const + { + return "resized"; + } + +protected: + IMAGE_TRANSPORT_PUBLIC + virtual void internalCallback(const typename image_transport_tutorial::ResizedImage::ConstPtr& message, + const Callback& user_cb); +}; From 3743e6967c5e0bac48723c8e21307ad6b35e94c3 Mon Sep 17 00:00:00 2001 From: Rebecca Butler Date: Tue, 29 Jun 2021 10:25:18 -0400 Subject: [PATCH 02/13] Rewrote CMakeLists.txt Signed-off-by: Rebecca Butler --- image_transport_tutorial/CMakeLists.txt | 70 +++++++++---------- .../resized_publisher.hpp | 19 ----- .../resized_publisher.hpp | 3 - .../resized_subscriber.hpp | 4 -- image_transport_tutorial/package.xml | 2 +- image_transport_tutorial/src/manifest.cpp | 4 +- .../src/resized_publisher.cpp | 6 +- .../src/resized_subscriber.cpp | 2 +- .../src/resized_subscriber.hpp | 21 ------ 9 files changed, 42 insertions(+), 89 deletions(-) delete mode 100644 image_transport_tutorial/include/image_transport_tutorial/image_transport_tutorial/resized_publisher.hpp rename image_transport_tutorial/{src => include/image_transport_tutorial}/resized_publisher.hpp (85%) rename image_transport_tutorial/include/image_transport_tutorial/{image_transport_tutorial => }/resized_subscriber.hpp (84%) delete mode 100644 image_transport_tutorial/src/resized_subscriber.hpp diff --git a/image_transport_tutorial/CMakeLists.txt b/image_transport_tutorial/CMakeLists.txt index 8b9c2c25..3546d721 100644 --- a/image_transport_tutorial/CMakeLists.txt +++ b/image_transport_tutorial/CMakeLists.txt @@ -6,67 +6,66 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") endif() find_package(ament_cmake REQUIRED) +find_package(message_filters REQUIRED) +find_package(pluginlib REQUIRED) +find_package(rosidl_default_generators REQUIRED) find_package(rclcpp REQUIRED) find_package(std_msgs REQUIRED) find_package(sensor_msgs REQUIRED) find_package(cv_bridge REQUIRED) find_package(image_transport REQUIRED) +include_directories(include ${OpenCV_INCLUDE_DIRS}) + # add the resized image message set(msg_files "msg/ResizedImage.msg" ) -rosidl_generate_interfaces(${PROJECT_NAME}_interface +rosidl_generate_interfaces(${PROJECT_NAME} ${msg_files} - DEPENDENCIES builtin_interfaces -) - -include_directories(include) - -add_library(${PROJECT_NAME} - src/manifest.cpp - src/my_publisher.cpp - src/my_subscriber.cpp - src/resized_publisher.cpp - src/resized_subscriber.cpp -) - -ament_target_dependencies( - ${PROJECT_NAME} - rclcpp - std_msgs - sensor_msgs - cv_bridge - image_transport + DEPENDENCIES sensor_msgs ) -target_compile_definitions(${PROJECT_NAME} PUBLIC "PLUGINLIB__DISABLE_BOOST_FUNCTIONS") -target_compile_definitions(${PROJECT_NAME} PRIVATE "IMAGE_TRANSPORT_BUILDING_DLL") - # Build image_transport_plugins library (raw) -add_library(${PROJECT_NAME}_plugins +add_library(${PROJECT_NAME}_plugins SHARED src/manifest.cpp ) -target_link_libraries(${PROJECT_NAME}_plugins ${PROJECT_NAME}) +target_link_libraries(${PROJECT_NAME}_plugins ${rclcpp_LIBRARIES} ${OpenCV_LIBRARIES}) # add the publisher example add_executable(my_publisher src/my_publisher.cpp) -target_link_libraries(my_publisher ${PROJECT_NAME}) +ament_target_dependencies(my_publisher + "cv_bridge" + "image_transport") +target_link_libraries(my_publisher ${rclcpp_LIBRARIES} ${OpenCV_LIBRARIES}) -# add the subscriber example +# # add the subscriber example add_executable(my_subscriber src/my_subscriber.cpp) -target_link_libraries(my_subscriber ${PROJECT_NAME}) +ament_target_dependencies(my_subscriber + "cv_bridge" + "image_transport") +target_link_libraries(my_subscriber ${rclcpp_LIBRARIES} ${OpenCV_LIBRARIES}) -# Install plugin descriptions -#pluginlib_export_plugin_description_file(image_transport default_plugins.xml) +# # Install plugin descriptions +pluginlib_export_plugin_description_file(${PROJECT_NAME} resized_plugins.xml) # add the plugin example add_library(resized_publisher src/manifest.cpp src/resized_publisher.cpp src/resized_subscriber.cpp) -target_link_libraries(resized_publisher ${PROJECT_NAME}) +target_link_libraries(resized_publisher ${rclcpp_LIBRARIES} ${OpenCV_LIBRARIES}) + +### link ### +rosidl_target_interfaces(my_publisher + ${PROJECT_NAME} "rosidl_typesupport_cpp") + +rosidl_target_interfaces(my_subscriber + ${PROJECT_NAME} "rosidl_typesupport_cpp") + +rosidl_target_interfaces(resized_publisher + ${PROJECT_NAME} "rosidl_typesupport_cpp") # Install libraries install( - TARGETS ${PROJECT_NAME} ${PROJECT_NAME}_plugins + TARGETS ${PROJECT_NAME}_plugins ARCHIVE DESTINATION lib LIBRARY DESTINATION lib RUNTIME DESTINATION bin @@ -85,7 +84,8 @@ install( ) ament_export_include_directories(include) -ament_export_libraries(${PROJECT_NAME}) -ament_export_dependencies(rclcpp std_msgs sensor_msgs cvbridge image_transport) +ament_export_libraries(${PROJECT_NAME}_plugins) + +ament_export_dependencies(rclcpp std_msgs sensor_msgs cvbridge image_transport pluginlib message_filters rosidl_default_runtime) ament_package() \ No newline at end of file diff --git a/image_transport_tutorial/include/image_transport_tutorial/image_transport_tutorial/resized_publisher.hpp b/image_transport_tutorial/include/image_transport_tutorial/image_transport_tutorial/resized_publisher.hpp deleted file mode 100644 index d47552a8..00000000 --- a/image_transport_tutorial/include/image_transport_tutorial/image_transport_tutorial/resized_publisher.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#include -//#include -#include "image_transport_tutorial/msg/resized_image.hpp" - -IMAGE_TRANSPORT_PUBLIC -class ResizedPublisher : public image_transport::SimplePublisherPlugin -{ -public: - IMAGE_TRANSPORT_PUBLIC - virtual std::string getTransportName() const - { - return "resized"; - } - -protected: - IMAGE_TRANSPORT_PUBLIC - virtual void publish(const sensor_msgs::Image& message, - const PublishFn& publish_fn) const; -}; diff --git a/image_transport_tutorial/src/resized_publisher.hpp b/image_transport_tutorial/include/image_transport_tutorial/resized_publisher.hpp similarity index 85% rename from image_transport_tutorial/src/resized_publisher.hpp rename to image_transport_tutorial/include/image_transport_tutorial/resized_publisher.hpp index c1e2fafe..e2bfa9d7 100644 --- a/image_transport_tutorial/src/resized_publisher.hpp +++ b/image_transport_tutorial/include/image_transport_tutorial/resized_publisher.hpp @@ -1,18 +1,15 @@ #include #include "image_transport_tutorial/msg/resized_image.hpp" -IMAGE_TRANSPORT_PUBLIC class ResizedPublisher : public image_transport::SimplePublisherPlugin { public: - IMAGE_TRANSPORT_PUBLIC virtual std::string getTransportName() const { return "resized"; } protected: - IMAGE_TRANSPORT_PUBLIC virtual void publish(const sensor_msgs::Image& message, const PublishFn& publish_fn) const; }; diff --git a/image_transport_tutorial/include/image_transport_tutorial/image_transport_tutorial/resized_subscriber.hpp b/image_transport_tutorial/include/image_transport_tutorial/resized_subscriber.hpp similarity index 84% rename from image_transport_tutorial/include/image_transport_tutorial/image_transport_tutorial/resized_subscriber.hpp rename to image_transport_tutorial/include/image_transport_tutorial/resized_subscriber.hpp index 452d5212..c6189ecc 100644 --- a/image_transport_tutorial/include/image_transport_tutorial/image_transport_tutorial/resized_subscriber.hpp +++ b/image_transport_tutorial/include/image_transport_tutorial/resized_subscriber.hpp @@ -1,21 +1,17 @@ #include #include "image_transport_tutorial/msg/resized_image.hpp" -IMAGE_TRANSPORT_PUBLIC class ResizedSubscriber : public image_transport::SimpleSubscriberPlugin { public: - IMAGE_TRANSPORT_PUBLIC virtual ~ResizedSubscriber() {} - IMAGE_TRANSPORT_PUBLIC virtual std::string getTransportName() const { return "resized"; } protected: - IMAGE_TRANSPORT_PUBLIC virtual void internalCallback(const typename image_transport_tutorial::ResizedImage::ConstPtr& message, const Callback& user_cb); }; diff --git a/image_transport_tutorial/package.xml b/image_transport_tutorial/package.xml index 96f86854..cc319d17 100644 --- a/image_transport_tutorial/package.xml +++ b/image_transport_tutorial/package.xml @@ -6,7 +6,7 @@ Vincent Rabaud Apache 2.0 - ament_cmake + ament_cmake_ros rosidl_default_generators builtin_interfaces diff --git a/image_transport_tutorial/src/manifest.cpp b/image_transport_tutorial/src/manifest.cpp index e03a5909..45226991 100644 --- a/image_transport_tutorial/src/manifest.cpp +++ b/image_transport_tutorial/src/manifest.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "image_transport_tutorial/resized_publisher.hpp" +#include "image_transport_tutorial/resized_subscriber.hpp" PLUGINLIB_EXPORT_CLASS(ResizedPublisher, image_transport::PublisherPlugin) diff --git a/image_transport_tutorial/src/resized_publisher.cpp b/image_transport_tutorial/src/resized_publisher.cpp index 6fd2fa4a..b0d65a25 100644 --- a/image_transport_tutorial/src/resized_publisher.cpp +++ b/image_transport_tutorial/src/resized_publisher.cpp @@ -1,8 +1,8 @@ -#include +#include "image_transport_tutorial/resized_publisher.hpp" #include #include -void ResizedPublisher::publish(const sensor_msgs::Image& message, +/*void ResizedPublisher::publish(const sensor_msgs::Image& message, const PublishFn& publish_fn) const { cv::Mat cv_image; @@ -34,4 +34,4 @@ void ResizedPublisher::publish(const sensor_msgs::Image& message, resized_image.original_width = cv_image.cols; resized_image.image = *(cv_bridge::CvImage(message.header, "bgr8", cv_image).toImageMsg()); publish_fn(resized_image); -} +}*/ diff --git a/image_transport_tutorial/src/resized_subscriber.cpp b/image_transport_tutorial/src/resized_subscriber.cpp index 982985e4..685dfad6 100644 --- a/image_transport_tutorial/src/resized_subscriber.cpp +++ b/image_transport_tutorial/src/resized_subscriber.cpp @@ -1,4 +1,4 @@ -#include +#include "image_transport_tutorial/resized_subscriber.hpp" #include #include diff --git a/image_transport_tutorial/src/resized_subscriber.hpp b/image_transport_tutorial/src/resized_subscriber.hpp deleted file mode 100644 index 452d5212..00000000 --- a/image_transport_tutorial/src/resized_subscriber.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include "image_transport_tutorial/msg/resized_image.hpp" - -IMAGE_TRANSPORT_PUBLIC -class ResizedSubscriber : public image_transport::SimpleSubscriberPlugin -{ -public: - IMAGE_TRANSPORT_PUBLIC - virtual ~ResizedSubscriber() {} - - IMAGE_TRANSPORT_PUBLIC - virtual std::string getTransportName() const - { - return "resized"; - } - -protected: - IMAGE_TRANSPORT_PUBLIC - virtual void internalCallback(const typename image_transport_tutorial::ResizedImage::ConstPtr& message, - const Callback& user_cb); -}; From 74f30e3e08483abb64fe93cb08e88b545f83c2b5 Mon Sep 17 00:00:00 2001 From: Rebecca Butler Date: Tue, 29 Jun 2021 11:05:27 -0400 Subject: [PATCH 03/13] Port resized pub/sub to ROS2 Signed-off-by: Rebecca Butler --- image_transport_tutorial/CMakeLists.txt | 5 +++++ .../resized_publisher.hpp | 6 +++--- .../resized_subscriber.hpp | 6 +++--- image_transport_tutorial/src/manifest.cpp | 4 ++-- .../src/my_subscriber.cpp | 4 +--- .../src/resized_publisher.cpp | 21 +++++++++---------- .../src/resized_subscriber.cpp | 9 ++++---- 7 files changed, 29 insertions(+), 26 deletions(-) diff --git a/image_transport_tutorial/CMakeLists.txt b/image_transport_tutorial/CMakeLists.txt index 3546d721..24b936b2 100644 --- a/image_transport_tutorial/CMakeLists.txt +++ b/image_transport_tutorial/CMakeLists.txt @@ -1,6 +1,11 @@ cmake_minimum_required(VERSION 3.8) project(image_transport_tutorial) +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() + if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wall -Wextra -Wpedantic) endif() diff --git a/image_transport_tutorial/include/image_transport_tutorial/resized_publisher.hpp b/image_transport_tutorial/include/image_transport_tutorial/resized_publisher.hpp index e2bfa9d7..4e1a1844 100644 --- a/image_transport_tutorial/include/image_transport_tutorial/resized_publisher.hpp +++ b/image_transport_tutorial/include/image_transport_tutorial/resized_publisher.hpp @@ -1,7 +1,7 @@ #include -#include "image_transport_tutorial/msg/resized_image.hpp" +#include -class ResizedPublisher : public image_transport::SimplePublisherPlugin +class ResizedPublisher : public image_transport::SimplePublisherPlugin { public: virtual std::string getTransportName() const @@ -10,6 +10,6 @@ class ResizedPublisher : public image_transport::SimplePublisherPlugin -#include "image_transport_tutorial/msg/resized_image.hpp" +#include -class ResizedSubscriber : public image_transport::SimpleSubscriberPlugin +class ResizedSubscriber : public image_transport::SimpleSubscriberPlugin { public: virtual ~ResizedSubscriber() {} @@ -12,6 +12,6 @@ class ResizedSubscriber : public image_transport::SimpleSubscriberPluginencoding.c_str()); } } -//image_transport::Subscriber::Callback &callback = std::function imageCallback; - int main(int argc, char **argv) { rclcpp::init(argc, argv); diff --git a/image_transport_tutorial/src/resized_publisher.cpp b/image_transport_tutorial/src/resized_publisher.cpp index b0d65a25..6a36c0ad 100644 --- a/image_transport_tutorial/src/resized_publisher.cpp +++ b/image_transport_tutorial/src/resized_publisher.cpp @@ -1,37 +1,36 @@ -#include "image_transport_tutorial/resized_publisher.hpp" #include #include -/*void ResizedPublisher::publish(const sensor_msgs::Image& message, +#include "image_transport_tutorial/resized_publisher.hpp" +#include "rclcpp/logging.hpp" + +void ResizedPublisher::publish(const sensor_msgs::msg::Image& message, const PublishFn& publish_fn) const { cv::Mat cv_image; - boost::shared_ptr tracked_object; + std::shared_ptr tracked_object; try { cv_image = cv_bridge::toCvShare(message, tracked_object, message.encoding)->image; } catch (cv::Exception &e) { - ROS_ERROR("Could not convert from '%s' to '%s'.", message.encoding.c_str(), message.encoding.c_str()); + auto logger = rclcpp::get_logger("resized_publisher"); + RCLCPP_ERROR(logger, "Could not convert from '%s' to '%s'.", message.encoding.c_str(), message.encoding.c_str()); return; } - // Retrieve subsampling factor from the parameter server - double subsampling_factor; - std::string param_name; - nh().param("resized_image_transport_subsampling_factor", subsampling_factor, 2.0); - // Rescale image + double subsampling_factor = 2.0; int new_width = cv_image.cols / subsampling_factor + 0.5; int new_height = cv_image.rows / subsampling_factor + 0.5; cv::Mat buffer; cv::resize(cv_image, buffer, cv::Size(new_width, new_height)); // Set up ResizedImage and publish - image_transport_tutorial::ResizedImage resized_image; + image_transport_tutorial::msg::ResizedImage resized_image; resized_image.original_height = cv_image.rows; resized_image.original_width = cv_image.cols; resized_image.image = *(cv_bridge::CvImage(message.header, "bgr8", cv_image).toImageMsg()); publish_fn(resized_image); -}*/ +} diff --git a/image_transport_tutorial/src/resized_subscriber.cpp b/image_transport_tutorial/src/resized_subscriber.cpp index 685dfad6..0a2e25bc 100644 --- a/image_transport_tutorial/src/resized_subscriber.cpp +++ b/image_transport_tutorial/src/resized_subscriber.cpp @@ -1,12 +1,13 @@ -#include "image_transport_tutorial/resized_subscriber.hpp" #include #include -void ResizedSubscriber::internalCallback(const image_transport_tutorial::ResizedImage::ConstPtr& msg, +#include "image_transport_tutorial/resized_subscriber.hpp" + +void ResizedSubscriber::internalCallback(const image_transport_tutorial::msg::ResizedImage::ConstSharedPtr& msg, const Callback& user_cb) { // This is only for optimization, not to copy the image - boost::shared_ptr tracked_object_tmp; + std::shared_ptr tracked_object_tmp; cv::Mat img_rsz = cv_bridge::toCvShare(msg->image, tracked_object_tmp)->image; // Resize the image to its original size cv::Mat img_restored; @@ -15,4 +16,4 @@ void ResizedSubscriber::internalCallback(const image_transport_tutorial::Resized // Call the user callback with the restored image cv_bridge::CvImage cv_img(msg->image.header, msg->image.encoding, img_restored); user_cb(cv_img.toImageMsg()); -}; +} From 606b65552f6a22ce269240d5b2eb22562378b23e Mon Sep 17 00:00:00 2001 From: Rebecca Butler Date: Tue, 29 Jun 2021 11:26:56 -0400 Subject: [PATCH 04/13] Fix error in manifest.cpp Signed-off-by: Rebecca Butler --- image_transport_tutorial/CMakeLists.txt | 18 ++---------------- image_transport_tutorial/src/manifest.cpp | 7 ++++--- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/image_transport_tutorial/CMakeLists.txt b/image_transport_tutorial/CMakeLists.txt index 24b936b2..feb93425 100644 --- a/image_transport_tutorial/CMakeLists.txt +++ b/image_transport_tutorial/CMakeLists.txt @@ -31,12 +31,6 @@ rosidl_generate_interfaces(${PROJECT_NAME} DEPENDENCIES sensor_msgs ) -# Build image_transport_plugins library (raw) -add_library(${PROJECT_NAME}_plugins SHARED - src/manifest.cpp -) -target_link_libraries(${PROJECT_NAME}_plugins ${rclcpp_LIBRARIES} ${OpenCV_LIBRARIES}) - # add the publisher example add_executable(my_publisher src/my_publisher.cpp) ament_target_dependencies(my_publisher @@ -56,6 +50,8 @@ pluginlib_export_plugin_description_file(${PROJECT_NAME} resized_plugins.xml) # add the plugin example add_library(resized_publisher src/manifest.cpp src/resized_publisher.cpp src/resized_subscriber.cpp) +ament_target_dependencies(resized_publisher + "pluginlib") target_link_libraries(resized_publisher ${rclcpp_LIBRARIES} ${OpenCV_LIBRARIES}) ### link ### @@ -68,14 +64,6 @@ rosidl_target_interfaces(my_subscriber rosidl_target_interfaces(resized_publisher ${PROJECT_NAME} "rosidl_typesupport_cpp") -# Install libraries -install( - TARGETS ${PROJECT_NAME}_plugins - ARCHIVE DESTINATION lib - LIBRARY DESTINATION lib - RUNTIME DESTINATION bin -) - # Install executables install( TARGETS my_publisher my_subscriber resized_publisher @@ -89,8 +77,6 @@ install( ) ament_export_include_directories(include) -ament_export_libraries(${PROJECT_NAME}_plugins) - ament_export_dependencies(rclcpp std_msgs sensor_msgs cvbridge image_transport pluginlib message_filters rosidl_default_runtime) ament_package() \ No newline at end of file diff --git a/image_transport_tutorial/src/manifest.cpp b/image_transport_tutorial/src/manifest.cpp index 9c1d013f..4945aae2 100644 --- a/image_transport_tutorial/src/manifest.cpp +++ b/image_transport_tutorial/src/manifest.cpp @@ -1,6 +1,7 @@ -/*#include "image_transport_tutorial/resized_publisher.hpp" +#include + +#include "image_transport_tutorial/resized_publisher.hpp" #include "image_transport_tutorial/resized_subscriber.hpp" PLUGINLIB_EXPORT_CLASS(ResizedPublisher, image_transport::PublisherPlugin) - -PLUGINLIB_EXPORT_CLASS(ResizedSubscriber, image_transport::SubscriberPlugin)*/ +PLUGINLIB_EXPORT_CLASS(ResizedSubscriber, image_transport::SubscriberPlugin) From f81dcd9eea4d6b769af7104a0e187d2d6e015b75 Mon Sep 17 00:00:00 2001 From: Rebecca Butler Date: Tue, 29 Jun 2021 12:16:22 -0400 Subject: [PATCH 05/13] Lint Signed-off-by: Rebecca Butler --- image_transport_tutorial/CMakeLists.txt | 37 ++++++++----------- .../resized_publisher.hpp | 29 +++++++++++++-- .../resized_subscriber.hpp | 29 +++++++++++++-- image_transport_tutorial/package.xml | 2 - image_transport_tutorial/src/manifest.cpp | 14 +++++++ image_transport_tutorial/src/my_publisher.cpp | 17 ++++++++- .../src/my_subscriber.cpp | 25 +++++++++---- .../src/resized_publisher.cpp | 34 ++++++++++++----- .../src/resized_subscriber.cpp | 21 ++++++++++- 9 files changed, 159 insertions(+), 49 deletions(-) diff --git a/image_transport_tutorial/CMakeLists.txt b/image_transport_tutorial/CMakeLists.txt index feb93425..66f31bb8 100644 --- a/image_transport_tutorial/CMakeLists.txt +++ b/image_transport_tutorial/CMakeLists.txt @@ -11,24 +11,22 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") endif() find_package(ament_cmake REQUIRED) -find_package(message_filters REQUIRED) +find_package(cv_bridge REQUIRED) +find_package(image_transport REQUIRED) find_package(pluginlib REQUIRED) -find_package(rosidl_default_generators REQUIRED) find_package(rclcpp REQUIRED) -find_package(std_msgs REQUIRED) +find_package(rosidl_default_generators REQUIRED) find_package(sensor_msgs REQUIRED) -find_package(cv_bridge REQUIRED) -find_package(image_transport REQUIRED) include_directories(include ${OpenCV_INCLUDE_DIRS}) # add the resized image message set(msg_files - "msg/ResizedImage.msg" + "msg/ResizedImage.msg" ) rosidl_generate_interfaces(${PROJECT_NAME} - ${msg_files} - DEPENDENCIES sensor_msgs + ${msg_files} + DEPENDENCIES sensor_msgs ) # add the publisher example @@ -38,29 +36,21 @@ ament_target_dependencies(my_publisher "image_transport") target_link_libraries(my_publisher ${rclcpp_LIBRARIES} ${OpenCV_LIBRARIES}) -# # add the subscriber example +# add the subscriber example add_executable(my_subscriber src/my_subscriber.cpp) ament_target_dependencies(my_subscriber "cv_bridge" "image_transport") target_link_libraries(my_subscriber ${rclcpp_LIBRARIES} ${OpenCV_LIBRARIES}) -# # Install plugin descriptions -pluginlib_export_plugin_description_file(${PROJECT_NAME} resized_plugins.xml) - # add the plugin example add_library(resized_publisher src/manifest.cpp src/resized_publisher.cpp src/resized_subscriber.cpp) -ament_target_dependencies(resized_publisher - "pluginlib") target_link_libraries(resized_publisher ${rclcpp_LIBRARIES} ${OpenCV_LIBRARIES}) -### link ### -rosidl_target_interfaces(my_publisher - ${PROJECT_NAME} "rosidl_typesupport_cpp") - -rosidl_target_interfaces(my_subscriber - ${PROJECT_NAME} "rosidl_typesupport_cpp") +# Install plugin descriptions +pluginlib_export_plugin_description_file(${PROJECT_NAME} resized_plugins.xml) +# Link interface rosidl_target_interfaces(resized_publisher ${PROJECT_NAME} "rosidl_typesupport_cpp") @@ -77,6 +67,11 @@ install( ) ament_export_include_directories(include) -ament_export_dependencies(rclcpp std_msgs sensor_msgs cvbridge image_transport pluginlib message_filters rosidl_default_runtime) +ament_export_dependencies(cv_bridge image_transport pluginlib rosidl_default_runtime rclcpp sensor_msgs) + +if(BUILD_TESTING) + find_package(ament_lint_auto REQUIRED) + ament_lint_auto_find_test_dependencies() +endif() ament_package() \ No newline at end of file diff --git a/image_transport_tutorial/include/image_transport_tutorial/resized_publisher.hpp b/image_transport_tutorial/include/image_transport_tutorial/resized_publisher.hpp index 4e1a1844..39c3ef10 100644 --- a/image_transport_tutorial/include/image_transport_tutorial/resized_publisher.hpp +++ b/image_transport_tutorial/include/image_transport_tutorial/resized_publisher.hpp @@ -1,7 +1,27 @@ +// Copyright 2021, Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef IMAGE_TRANSPORT_TUTORIAL__RESIZED_PUBLISHER_HPP_ +#define IMAGE_TRANSPORT_TUTORIAL__RESIZED_PUBLISHER_HPP_ + #include #include -class ResizedPublisher : public image_transport::SimplePublisherPlugin +#include + +class ResizedPublisher : public image_transport::SimplePublisherPlugin + { public: virtual std::string getTransportName() const @@ -10,6 +30,9 @@ class ResizedPublisher : public image_transport::SimplePublisherPlugin #include -class ResizedSubscriber : public image_transport::SimpleSubscriberPlugin +#include + +class ResizedSubscriber : public image_transport::SimpleSubscriberPlugin + { public: virtual ~ResizedSubscriber() {} @@ -12,6 +32,9 @@ class ResizedSubscriber : public image_transport::SimpleSubscriberPluginament_cmake_ros rosidl_default_generators - builtin_interfaces cv_bridge image_transport message_generation opencv2 sensor_msgs - builtin_interfaces rosidl_default_runtime cv_bridge image_transport diff --git a/image_transport_tutorial/src/manifest.cpp b/image_transport_tutorial/src/manifest.cpp index 4945aae2..0fa48fc1 100644 --- a/image_transport_tutorial/src/manifest.cpp +++ b/image_transport_tutorial/src/manifest.cpp @@ -1,3 +1,17 @@ +// Copyright 2021, Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + #include #include "image_transport_tutorial/resized_publisher.hpp" diff --git a/image_transport_tutorial/src/my_publisher.cpp b/image_transport_tutorial/src/my_publisher.cpp index a5bfa159..8e2a30bb 100644 --- a/image_transport_tutorial/src/my_publisher.cpp +++ b/image_transport_tutorial/src/my_publisher.cpp @@ -1,9 +1,23 @@ +// Copyright 2021, Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + #include #include #include #include -int main(int argc, char** argv) +int main(int argc, char ** argv) { rclcpp::init(argc, argv); rclcpp::NodeOptions options; @@ -23,4 +37,3 @@ int main(int argc, char** argv) loop_rate.sleep(); } } - diff --git a/image_transport_tutorial/src/my_subscriber.cpp b/image_transport_tutorial/src/my_subscriber.cpp index 3f75e7ca..5c33dd31 100644 --- a/image_transport_tutorial/src/my_subscriber.cpp +++ b/image_transport_tutorial/src/my_subscriber.cpp @@ -1,3 +1,17 @@ +// Copyright 2021, Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + #include #include #include @@ -5,21 +19,18 @@ #include "rclcpp/logging.hpp" -void imageCallback(const sensor_msgs::msg::Image::ConstSharedPtr& msg) +void imageCallback(const sensor_msgs::msg::Image::ConstSharedPtr & msg) { - try - { + try { cv::imshow("view", cv_bridge::toCvShare(msg, "bgr8")->image); cv::waitKey(10); - } - catch (cv_bridge::Exception& e) - { + } catch (cv_bridge::Exception & e) { auto logger = rclcpp::get_logger("my_subscriber"); RCLCPP_ERROR(logger, "Could not convert from '%s' to 'bgr8'.", msg->encoding.c_str()); } } -int main(int argc, char **argv) +int main(int argc, char ** argv) { rclcpp::init(argc, argv); rclcpp::NodeOptions options; diff --git a/image_transport_tutorial/src/resized_publisher.cpp b/image_transport_tutorial/src/resized_publisher.cpp index 6a36c0ad..4b61c82e 100644 --- a/image_transport_tutorial/src/resized_publisher.cpp +++ b/image_transport_tutorial/src/resized_publisher.cpp @@ -1,22 +1,38 @@ -#include +// Copyright 2021, Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + #include +#include + +#include #include "image_transport_tutorial/resized_publisher.hpp" #include "rclcpp/logging.hpp" -void ResizedPublisher::publish(const sensor_msgs::msg::Image& message, - const PublishFn& publish_fn) const +void ResizedPublisher::publish( + const sensor_msgs::msg::Image & message, + const PublishFn & publish_fn) const { cv::Mat cv_image; std::shared_ptr tracked_object; - try - { + try { cv_image = cv_bridge::toCvShare(message, tracked_object, message.encoding)->image; - } - catch (cv::Exception &e) - { + } catch (cv::Exception & e) { auto logger = rclcpp::get_logger("resized_publisher"); - RCLCPP_ERROR(logger, "Could not convert from '%s' to '%s'.", message.encoding.c_str(), message.encoding.c_str()); + RCLCPP_ERROR( + logger, "Could not convert from '%s' to '%s'.", + message.encoding.c_str(), message.encoding.c_str()); return; } diff --git a/image_transport_tutorial/src/resized_subscriber.cpp b/image_transport_tutorial/src/resized_subscriber.cpp index 0a2e25bc..a073ad01 100644 --- a/image_transport_tutorial/src/resized_subscriber.cpp +++ b/image_transport_tutorial/src/resized_subscriber.cpp @@ -1,10 +1,27 @@ +// Copyright 2021, Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + #include #include +#include + #include "image_transport_tutorial/resized_subscriber.hpp" -void ResizedSubscriber::internalCallback(const image_transport_tutorial::msg::ResizedImage::ConstSharedPtr& msg, - const Callback& user_cb) +void ResizedSubscriber::internalCallback( + const image_transport_tutorial::msg::ResizedImage::ConstSharedPtr & msg, + const Callback & user_cb) { // This is only for optimization, not to copy the image std::shared_ptr tracked_object_tmp; From 3b40285e53722e8791eb8b177433e3efeb16524d Mon Sep 17 00:00:00 2001 From: Rebecca Butler Date: Thu, 1 Jul 2021 11:10:33 -0400 Subject: [PATCH 06/13] Deleted image_transport/tutorial folder Signed-off-by: Rebecca Butler --- image_transport/tutorial/CMakeLists.txt | 43 ------------------- .../resized_publisher.hpp | 15 ------- .../resized_subscriber.hpp | 17 -------- image_transport/tutorial/msg/ResizedImage.msg | 3 -- image_transport/tutorial/package.xml | 26 ----------- image_transport/tutorial/resized_plugins.xml | 13 ------ image_transport/tutorial/src/manifest.cpp | 7 --- image_transport/tutorial/src/my_publisher.cpp | 23 ---------- .../tutorial/src/my_subscriber.cpp | 29 ------------- .../tutorial/src/resized_publisher.cpp | 37 ---------------- .../tutorial/src/resized_subscriber.cpp | 18 -------- 11 files changed, 231 deletions(-) delete mode 100644 image_transport/tutorial/CMakeLists.txt delete mode 100644 image_transport/tutorial/include/image_transport_tutorial/resized_publisher.hpp delete mode 100644 image_transport/tutorial/include/image_transport_tutorial/resized_subscriber.hpp delete mode 100644 image_transport/tutorial/msg/ResizedImage.msg delete mode 100644 image_transport/tutorial/package.xml delete mode 100644 image_transport/tutorial/resized_plugins.xml delete mode 100644 image_transport/tutorial/src/manifest.cpp delete mode 100644 image_transport/tutorial/src/my_publisher.cpp delete mode 100644 image_transport/tutorial/src/my_subscriber.cpp delete mode 100644 image_transport/tutorial/src/resized_publisher.cpp delete mode 100644 image_transport/tutorial/src/resized_subscriber.cpp diff --git a/image_transport/tutorial/CMakeLists.txt b/image_transport/tutorial/CMakeLists.txt deleted file mode 100644 index ed5f28fe..00000000 --- a/image_transport/tutorial/CMakeLists.txt +++ /dev/null @@ -1,43 +0,0 @@ -cmake_minimum_required(VERSION 2.8) -project(image_transport_tutorial) - -find_package(catkin REQUIRED COMPONENTS cv_bridge image_transport message_generation sensor_msgs) - -# add the resized image message -add_message_files(DIRECTORY msg - FILES ResizedImage.msg -) -generate_messages(DEPENDENCIES sensor_msgs) - -catkin_package(CATKIN_DEPENDS cv_bridge image_transport message_runtime sensor_msgs) - -find_package(OpenCV) - -include_directories(include ${catkin_INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS}) - -# add the publisher example -add_executable(my_publisher src/my_publisher.cpp) -add_dependencies(my_publisher ${catkin_EXPORTED_TARGETS} ${${PROJECT_NAME}_EXPORTED_TARGETS}) -target_link_libraries(my_publisher ${catkin_LIBRARIES} ${OpenCV_LIBRARIES}) - -# add the subscriber example -add_executable(my_subscriber src/my_subscriber.cpp) -add_dependencies(my_subscriber ${catkin_EXPORTED_TARGETS} ${${PROJECT_NAME}_EXPORTED_TARGETS}) -target_link_libraries(my_subscriber ${catkin_LIBRARIES} ${OpenCV_LIBRARIES}) - -# add the plugin example -add_library(resized_publisher src/manifest.cpp src/resized_publisher.cpp src/resized_subscriber.cpp) -add_dependencies(resized_publisher ${catkin_EXPORTED_TARGETS} ${${PROJECT_NAME}_EXPORTED_TARGETS}) -target_link_libraries(resized_publisher ${catkin_LIBRARIES} ${OpenCV_LIBRARIES}) - - -# Mark executables and/or libraries for installation -install(TARGETS my_publisher my_subscriber resized_publisher - ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} - LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} - RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -) - -install(FILES resized_plugins.xml - DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -) diff --git a/image_transport/tutorial/include/image_transport_tutorial/resized_publisher.hpp b/image_transport/tutorial/include/image_transport_tutorial/resized_publisher.hpp deleted file mode 100644 index 9a37de54..00000000 --- a/image_transport/tutorial/include/image_transport_tutorial/resized_publisher.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include - -class ResizedPublisher : public image_transport::SimplePublisherPlugin -{ -public: - virtual std::string getTransportName() const - { - return "resized"; - } - -protected: - virtual void publish(const sensor_msgs::Image& message, - const PublishFn& publish_fn) const; -}; diff --git a/image_transport/tutorial/include/image_transport_tutorial/resized_subscriber.hpp b/image_transport/tutorial/include/image_transport_tutorial/resized_subscriber.hpp deleted file mode 100644 index 0a5cbe3b..00000000 --- a/image_transport/tutorial/include/image_transport_tutorial/resized_subscriber.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include - -class ResizedSubscriber : public image_transport::SimpleSubscriberPlugin -{ -public: - virtual ~ResizedSubscriber() {} - - virtual std::string getTransportName() const - { - return "resized"; - } - -protected: - virtual void internalCallback(const typename image_transport_tutorial::ResizedImage::ConstPtr& message, - const Callback& user_cb); -}; diff --git a/image_transport/tutorial/msg/ResizedImage.msg b/image_transport/tutorial/msg/ResizedImage.msg deleted file mode 100644 index d8c8fadb..00000000 --- a/image_transport/tutorial/msg/ResizedImage.msg +++ /dev/null @@ -1,3 +0,0 @@ -uint32 original_height -uint32 original_width -sensor_msgs/Image image diff --git a/image_transport/tutorial/package.xml b/image_transport/tutorial/package.xml deleted file mode 100644 index 668cd0ac..00000000 --- a/image_transport/tutorial/package.xml +++ /dev/null @@ -1,26 +0,0 @@ - - image_transport_tutorial - 0.0.0 - Tutorial for image_transport. This is useful for the tutorials at http://wiki.ros.org/image_transport/Tutorials/ - Vincent Rabaud - Vincent Rabaud - Apache 2.0 - - cv_bridge - image_transport - message_generation - opencv2 - sensor_msgs - - cv_bridge - image_transport - message_runtime - opencv2 - sensor_msgs - - catkin - - - - - diff --git a/image_transport/tutorial/resized_plugins.xml b/image_transport/tutorial/resized_plugins.xml deleted file mode 100644 index bd2dff1a..00000000 --- a/image_transport/tutorial/resized_plugins.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - This plugin publishes a decimated version of the image. - - - - - - This plugin rescales a decimated image to its original size. - - - diff --git a/image_transport/tutorial/src/manifest.cpp b/image_transport/tutorial/src/manifest.cpp deleted file mode 100644 index ab208194..00000000 --- a/image_transport/tutorial/src/manifest.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include -#include -#include - -PLUGINLIB_EXPORT_CLASS(ResizedPublisher, image_transport::PublisherPlugin) - -PLUGINLIB_EXPORT_CLASS(ResizedSubscriber, image_transport::SubscriberPlugin) diff --git a/image_transport/tutorial/src/my_publisher.cpp b/image_transport/tutorial/src/my_publisher.cpp deleted file mode 100644 index 458a5893..00000000 --- a/image_transport/tutorial/src/my_publisher.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include -#include -#include -#include - -int main(int argc, char** argv) -{ - ros::init(argc, argv, "image_publisher"); - ros::NodeHandle nh; - image_transport::ImageTransport it(nh); - image_transport::Publisher pub = it.advertise("camera/image", 1); - - cv::Mat image = cv::imread(argv[1], CV_LOAD_IMAGE_COLOR); - sensor_msgs::ImagePtr msg = cv_bridge::CvImage(std_msgs::Header(), "bgr8", image).toImageMsg(); - - ros::Rate loop_rate(5); - while (nh.ok()) { - pub.publish(msg); - ros::spinOnce(); - loop_rate.sleep(); - } -} - diff --git a/image_transport/tutorial/src/my_subscriber.cpp b/image_transport/tutorial/src/my_subscriber.cpp deleted file mode 100644 index 63544a36..00000000 --- a/image_transport/tutorial/src/my_subscriber.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include -#include -#include - -void imageCallback(const sensor_msgs::ImageConstPtr& msg) -{ - try - { - cv::imshow("view", cv_bridge::toCvShare(msg, "bgr8")->image); - cv::waitKey(10); - } - catch (cv_bridge::Exception& e) - { - ROS_ERROR("Could not convert from '%s' to 'bgr8'.", msg->encoding.c_str()); - } -} - -int main(int argc, char **argv) -{ - ros::init(argc, argv, "image_listener"); - ros::NodeHandle nh; - cv::namedWindow("view"); - cv::startWindowThread(); - image_transport::ImageTransport it(nh); - image_transport::Subscriber sub = it.subscribe("camera/image", 1, imageCallback); - ros::spin(); - cv::destroyWindow("view"); -} diff --git a/image_transport/tutorial/src/resized_publisher.cpp b/image_transport/tutorial/src/resized_publisher.cpp deleted file mode 100644 index 178f4821..00000000 --- a/image_transport/tutorial/src/resized_publisher.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include -#include -#include - -void ResizedPublisher::publish(const sensor_msgs::Image& message, - const PublishFn& publish_fn) const -{ - cv::Mat cv_image; - boost::shared_ptr tracked_object; - try - { - cv_image = cv_bridge::toCvShare(message, tracked_object, message.encoding)->image; - } - catch (cv::Exception &e) - { - ROS_ERROR("Could not convert from '%s' to '%s'.", message.encoding.c_str(), message.encoding.c_str()); - return; - } - - // Retrieve subsampling factor from the parameter server - double subsampling_factor; - std::string param_name; - nh().param("resized_image_transport_subsampling_factor", subsampling_factor, 2.0); - - // Rescale image - int new_width = cv_image.cols / subsampling_factor + 0.5; - int new_height = cv_image.rows / subsampling_factor + 0.5; - cv::Mat buffer; - cv::resize(cv_image, buffer, cv::Size(new_width, new_height)); - - // Set up ResizedImage and publish - image_transport_tutorial::ResizedImage resized_image; - resized_image.original_height = cv_image.rows; - resized_image.original_width = cv_image.cols; - resized_image.image = *(cv_bridge::CvImage(message.header, "bgr8", cv_image).toImageMsg()); - publish_fn(resized_image); -} diff --git a/image_transport/tutorial/src/resized_subscriber.cpp b/image_transport/tutorial/src/resized_subscriber.cpp deleted file mode 100644 index 299dc83d..00000000 --- a/image_transport/tutorial/src/resized_subscriber.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include -#include -#include - -void ResizedSubscriber::internalCallback(const image_transport_tutorial::ResizedImage::ConstPtr& msg, - const Callback& user_cb) -{ - // This is only for optimization, not to copy the image - boost::shared_ptr tracked_object_tmp; - cv::Mat img_rsz = cv_bridge::toCvShare(msg->image, tracked_object_tmp)->image; - // Resize the image to its original size - cv::Mat img_restored; - cv::resize(img_rsz, img_restored, cv::Size(msg->original_width, msg->original_height)); - - // Call the user callback with the restored image - cv_bridge::CvImage cv_img(msg->image.header, msg->image.encoding, img_restored); - user_cb(cv_img.toImageMsg()); -}; From 23c965754c8f98f8b88c969391d7b33a25ce6f9f Mon Sep 17 00:00:00 2001 From: Rebecca Butler Date: Thu, 1 Jul 2021 11:11:36 -0400 Subject: [PATCH 07/13] Add publisher_from_video Signed-off-by: Rebecca Butler --- image_transport_tutorial/CMakeLists.txt | 9 ++- image_transport_tutorial/package.xml | 4 -- .../src/my_subscriber.cpp | 2 +- .../src/publisher_from_video.cpp | 59 +++++++++++++++++++ 4 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 image_transport_tutorial/src/publisher_from_video.cpp diff --git a/image_transport_tutorial/CMakeLists.txt b/image_transport_tutorial/CMakeLists.txt index 66f31bb8..9d9df3ae 100644 --- a/image_transport_tutorial/CMakeLists.txt +++ b/image_transport_tutorial/CMakeLists.txt @@ -47,6 +47,13 @@ target_link_libraries(my_subscriber ${rclcpp_LIBRARIES} ${OpenCV_LIBRARIES}) add_library(resized_publisher src/manifest.cpp src/resized_publisher.cpp src/resized_subscriber.cpp) target_link_libraries(resized_publisher ${rclcpp_LIBRARIES} ${OpenCV_LIBRARIES}) +# add the publisher from video example +add_executable(publisher_from_video src/publisher_from_video.cpp) +ament_target_dependencies(publisher_from_video + "cv_bridge" + "image_transport") +target_link_libraries(publisher_from_video ${rclcpp_LIBRARIES} ${OpenCV_LIBRARIES}) + # Install plugin descriptions pluginlib_export_plugin_description_file(${PROJECT_NAME} resized_plugins.xml) @@ -56,7 +63,7 @@ rosidl_target_interfaces(resized_publisher # Install executables install( - TARGETS my_publisher my_subscriber resized_publisher + TARGETS my_publisher my_subscriber resized_publisher publisher_from_video RUNTIME DESTINATION lib/${PROJECT_NAME} ) diff --git a/image_transport_tutorial/package.xml b/image_transport_tutorial/package.xml index c68fb539..40f7910c 100644 --- a/image_transport_tutorial/package.xml +++ b/image_transport_tutorial/package.xml @@ -11,15 +11,11 @@ cv_bridge image_transport - message_generation - opencv2 sensor_msgs rosidl_default_runtime cv_bridge image_transport - message_runtime - opencv2 sensor_msgs ament_lint_auto diff --git a/image_transport_tutorial/src/my_subscriber.cpp b/image_transport_tutorial/src/my_subscriber.cpp index 5c33dd31..6f79e698 100644 --- a/image_transport_tutorial/src/my_subscriber.cpp +++ b/image_transport_tutorial/src/my_subscriber.cpp @@ -39,6 +39,6 @@ int main(int argc, char ** argv) cv::startWindowThread(); image_transport::ImageTransport it(node); image_transport::Subscriber sub = it.subscribe("camera/image", 1, imageCallback); - rclcpp::spin_some(node); + rclcpp::spin(node); cv::destroyWindow("view"); } diff --git a/image_transport_tutorial/src/publisher_from_video.cpp b/image_transport_tutorial/src/publisher_from_video.cpp new file mode 100644 index 00000000..58c15061 --- /dev/null +++ b/image_transport_tutorial/src/publisher_from_video.cpp @@ -0,0 +1,59 @@ +// Copyright 2021, Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include + +int main(int argc, char ** argv) +{ + // Check if video source has been passed as a parameter + if (argv[1] == NULL) {return 1;} + + rclcpp::init(argc, argv); + rclcpp::NodeOptions options; + rclcpp::Node::SharedPtr node = rclcpp::Node::make_shared("image_publisher", options); + image_transport::ImageTransport it(node); + image_transport::Publisher pub = it.advertise("camera/image", 1); + + // Convert the command line parameter index for the video device to an integer + std::istringstream video_sourceCmd(argv[1]); + int video_source; + + // Check if it is indeed a number + if (!(video_sourceCmd >> video_source)) {return 1;} + + cv::VideoCapture cap(video_source); + // Check if video device can be opened with the given index + if (!cap.isOpened()) {return 1;} + cv::Mat frame; + std_msgs::msg::Header hdr; + sensor_msgs::msg::Image::SharedPtr msg; + + rclcpp::WallRate loop_rate(5); + while (rclcpp::ok()) { + cap >> frame; + // Check if grabbed frame is actually full with some content + if (!frame.empty()) { + msg = cv_bridge::CvImage(hdr, "bgr8", frame).toImageMsg(); + pub.publish(msg); + cv::waitKey(1); + } + + rclcpp::spin_some(node); + loop_rate.sleep(); + } +} From acccfe9365bbbab0d7e00756e423982339800a35 Mon Sep 17 00:00:00 2001 From: Rebecca Butler Date: Thu, 1 Jul 2021 11:26:13 -0400 Subject: [PATCH 08/13] Add tutorial instructions to README.md Signed-off-by: Rebecca Butler --- image_transport_tutorial/README.md | 256 +++++++++++++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 image_transport_tutorial/README.md diff --git a/image_transport_tutorial/README.md b/image_transport_tutorial/README.md new file mode 100644 index 00000000..6fecbdb5 --- /dev/null +++ b/image_transport_tutorial/README.md @@ -0,0 +1,256 @@ +# image_transport_tutorial + +Before starting any of the tutorials below, create a workspace and clone the `image_common` repository so you can inspect and manipulate the code: + +``` +$ mkdir -p ~/image_transport_ws/src +$ cd ~/image_transport_ws/src +$ git clone --branch ros2 https://github.com/ros-perception/image_common.git +``` + +Install needed dependencies: + +``` +$ cd ~/image_transport_ws/ +$ source /opt/ros/galactic/setup.bash +$ rosdep install -i --from-path src --rosdistro galactic -y +$ colcon build +``` + +Make sure to include the correct setup file (in the above example it is for Galactic on Ubuntu and for bash). + +## Writing a Simple Image Publisher (C++) +Description: This tutorial shows how to create a publisher node that will continually publish an image. + +Tutorial Level: Beginner + +Take a look at [my_publisher.cpp](src/my_publisher.cpp). + +### The code explained +Now, let's break down the code piece by piece. For lines not explained here, review [Writing a Simple Publisher and Subscriber (C++)](https://docs.ros.org/en/galactic/Tutorials/Writing-A-Simple-Cpp-Publisher-And-Subscriber.html). + +``` +#include +#include +#include +#include +``` + +These headers will allow us to load an image using OpenCV, convert it to the ROS message format, and publish it. + +``` +rclcpp::Node::SharedPtr node = rclcpp::Node::make_shared("image_publisher", options); +image_transport::ImageTransport it(node); +``` + +We create an `ImageTransport` instance, initializing it with our node. +We use methods of `ImageTransport` to create image publishers and subscribers, much as we use methods of `Node` to create generic ROS publishers and subscribers. + +``` +image_transport::Publisher pub = it.advertise("camera/image", 1); +``` + +Advertise that we are going to be publishing images on the base topic `camera/image`. Depending on whether more plugins are built, additional (per-plugin) topics derived from the base topic may also be advertised. The second argument is the size of our publishing queue. + +`advertise()` returns an `image_transport::Publisher` object, which serves two purposes: +1. It contains a `publish()` method that lets you publish images onto the base topic it was created with +2. When it goes out of scope, it will automatically unadvertise + +``` +cv::Mat image = cv::imread(argv[1], cv::IMREAD_COLOR); +std_msgs::msg::Header hdr; +sensor_msgs::msg::Image::SharedPtr msg; +msg = cv_bridge::CvImage(hdr, "bgr8", image).toImageMsg(); +``` + +We load a user-specified (on the command line) color image from disk using OpenCV, then convert it to the ROS type `sensor_msgs/Image`. + +``` +rclcpp::WallRate loop_rate(5); +while (rclcpp::ok()) { + pub.publish(msg); + rclcpp::spin_some(node); + loop_rate.sleep(); +} +``` + +We broadcast the image to anyone connected to one of our topics, exactly as we would have using an `rclrcpp::Publisher`. + +### Adding video stream from a webcam +The example above requires a path to an image file to be added as a command line parameter. This image will be converted and sent as a message to an image subscriber. In most cases, however, this is not a very practical example as you are often required to handle streaming data. (For example: multiple webcams mounted on a robot record the scene around it and you have to pass the image data to some other node for further analysis). + +The publisher example can be modified quite easily to make it work with a video device supported by `cv::VideoCapture` (in case it is not, you have to handle it accordingly). Take a look at [publisher_from_video.cpp](src/publisher_from_video.cpp) to see how a video device can be passed in as a command line argument and used as the image source. + +If you have a single device, you do not need to do the whole routine with passing a command line argument. In this case, you can hard-code the index/address of the device and directly pass it to the video capturing structure in OpenCV (example: `cv::VideoCapture(0)` if `/dev/video0` is used). Multiple checks are also included here to make sure that the publisher does not break if the camera is shut down. If the retrieved frame from the video device is not empty, it will then be converted to a ROS message which will be published by the publisher. + +## Writing a Simple Image Subscriber (C++) +Description: This tutorial shows how to create a subscriber node that will display an image on the screen. By using the `image_transport` subscriber to subscribe to images, any image transport can be used at runtime. To learn how to actually use a specific image transport, see the next tutorial. + +Tutorial Level: Beginner + +Take a look at [my_subscriber.cpp](src/my_subscriber.cpp). + +### The code explained +Now, let's break down the code piece by piece. + +``` +#include +#include +#include +#include + +#include "rclcpp/logging.hpp" +``` + +These headers will allow us to subscribe to image messages, display images using OpenCV's simple GUI capabilities, and log errors. + +``` +void imageCallback(const sensor_msgs::msg::Image::ConstSharedPtr & msg) +``` + +This is the callback function that will be called when a new image has arrived on the `camera/image` topic. Although the image may have been sent in some arbitrary transport-specific message type, notice that the callback need only handle the normal `sensor_msgs/Image` type. All image encoding/decoding is handled automatically for you. + +``` +try { + cv::imshow("view", cv_bridge::toCvShare(msg, "bgr8")->image); + cv::waitKey(10); +} catch (cv_bridge::Exception & e) { + auto logger = rclcpp::get_logger("my_subscriber"); + RCLCPP_ERROR(logger, "Could not convert from '%s' to 'bgr8'.", msg->encoding.c_str()); +``` + +The body of the callback. We convert the ROS image message into an OpenCV image with BGR pixel encoding, then show it in a display window. + + +``` +rclcpp::Node::SharedPtr node = rclcpp::Node::make_shared("image_listener", options); +image_transport::ImageTransport it(node); +``` + +We create an `ImageTransport` instance, initializing it with our node. + +``` +image_transport::Subscriber sub = it.subscribe("camera/image", 1, imageCallback); +``` + +Subscribe to the `camera/image` base topic. The actual ROS topic subscribed to depends on which transport is used. In the default case, "raw" transport, the topic is `camera/image` with type `sensor_msgs/Image`. ROS will call the `imageCallback` function whenever a new image arrives. The 2nd argument is the queue size. + +`subscribe()` returns an `image_transport::Subscriber` object that you must hold on to until you want to unsubscribe. When the Subscriber object is destructed, it will automatically unsubscribe from the `camera/image` base topic. + +In just a few lines of code, we have written a ROS image viewer that can handle images in both raw and a variety of compressed forms. + +## Running the Simple Image Publisher and Subscriber with Different Transports +Description: This tutorial discusses running the simple image publisher and subscriber using multiple transports. + +Tutorial Level: Beginner + +### Running the publisher +In a previous tutorial we made a publisher node called `my_publisher`. Now run the node with an image file as the command-line argument: + +``` +$ ros2 run image_transport_tutorial my_publisher path/to/some/image.jpg +``` + +To check that your node is running properly, list the topics being published: + +``` +$ ros2 topic list +``` + +You should see `/camera/image` in the output. You can also get more information about the topic: + +``` +$ ros2 topic info /camera/image +``` + +The output should be: + +``` +Type: sensor_msgs/msg/Image +Publisher count: 1 +Subscription count: 0 +``` + +### Running the subscriber +In the last tutorial, we made a subscriber node called `my_subscriber`. Now run it: + +``` +$ ros2 run image_transport_tutorial my_subscriber +``` + +You should see a window pop up with the image you gave to the publisher. + +### Finding available transports +`image_transport` searches your ROS installation for transport plugins at runtime and dynamically loads all that are built. This affords you great flexibility in adding additional transports, but makes it unclear which are available on your system. `image_transport` provides a `list_transports` executable for this purpose: + +``` +$ ros2 run image_transport list_transports +``` + +Which should show: + +``` +Declared transports: +image_transport/raw + +Details: +---------- +"image_transport/raw" + - Provided by package: image_transport + - Publisher: + This is the default publisher. It publishes the Image as-is on the base topic. + + - Subscriber: + This is the default pass-through subscriber for topics of type sensor_msgs/Image. +``` + +This the expected output for an otherwise new ROS installation after completing the previous tutorials. Depending on your setup, you may already have "theora" or other transports available. + +### Adding new transports +Our nodes are currently communicating raw `sensor_msgs/Image` messages, so we are not gaining anything over using `rclcpp::Publisher` and `rclcpp::Subscriber`. Let's change that by introducing a new transport. + +The `compressed_image_transport` package provides plugins for the "compressed" transport, which sends images over the wire in either JPEG- or PNG-compressed form. Notice that `compressed_image_transport` is not a dependency of your package; `image_transport` will automatically discover all transport plugins built in your ROS system. + +The easiest way to add the "compressed" transport is to install the package: + +``` +$ sudo apt-get install ros-galactic-compressed-image-transport +``` + +Or install all the transport plugins at once: + +``` +$ sudo apt-get install ros-galactic-image-transport-plugins +``` + +But you can also build from source. + +### Changing the transport used +Now let's start up a new subscriber, this one using compressed transport. The key is that `image_transport` subscribers check the parameter `_image_transport` for the name of a transport to use in place of "raw". Let's set this parameter and start a subscriber node with name "compressed_listener": + +``` +$ ros2 run image_transport_tutorial my_subscriber --ros-args --remap __name:=compressed_listener -p _image_transport:=compressed +``` + +You should see an identical image window pop up. + +`compressed_listener` is listening to a separate topic carrying JPEG-compressed versions of the same images published on `/camera/image`. + +### Changing transport-specific behavior +For a particular transport, we may want to tweak settings such as compression level, bit rate, etc. Transport plugins can expose such settings through `rqt_reconfigure`. For example, `/camera/image/compressed` allows you to change the compression format and quality on the fly; see the package documentation for full details. + +For now let's adjust the JPEG quality. By default, the "compressed" transport uses JPEG compression at 80% quality. Let's change it to 15%: + +``` +$ ros2 run rqt_reconfigure rqt_reconfigure +``` + +Now pick `/image_publisher` in the drop-down menu and move the `jpeg_quality` slider down to 15%. Do you see the compression artifacts in your second view window? + +Dynamic Reconfigure has updated the dynamically reconfigurable parameter `/image_publisher/jpeg_quality`. You can verify this by running: + +``` +$ ros2 param get /image_publisher jpeg_quality +``` + +This should display 15. From fae90bc9bdbcb039d82486e2acfb3bc124a824f4 Mon Sep 17 00:00:00 2001 From: Rebecca Butler Date: Thu, 1 Jul 2021 11:34:57 -0400 Subject: [PATCH 09/13] Add newline Signed-off-by: Rebecca Butler --- image_transport_tutorial/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/image_transport_tutorial/CMakeLists.txt b/image_transport_tutorial/CMakeLists.txt index 9d9df3ae..ede14f38 100644 --- a/image_transport_tutorial/CMakeLists.txt +++ b/image_transport_tutorial/CMakeLists.txt @@ -81,4 +81,4 @@ if(BUILD_TESTING) ament_lint_auto_find_test_dependencies() endif() -ament_package() \ No newline at end of file +ament_package() From 68f1a14503694eb5728b906259b0e7106b82662c Mon Sep 17 00:00:00 2001 From: Rebecca Butler Date: Thu, 1 Jul 2021 15:38:44 -0400 Subject: [PATCH 10/13] Fix build error caused by missing dependency Signed-off-by: Rebecca Butler --- image_transport_tutorial/CMakeLists.txt | 2 ++ .../include/image_transport_tutorial/resized_subscriber.hpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/image_transport_tutorial/CMakeLists.txt b/image_transport_tutorial/CMakeLists.txt index ede14f38..b0e57e3b 100644 --- a/image_transport_tutorial/CMakeLists.txt +++ b/image_transport_tutorial/CMakeLists.txt @@ -45,6 +45,8 @@ target_link_libraries(my_subscriber ${rclcpp_LIBRARIES} ${OpenCV_LIBRARIES}) # add the plugin example add_library(resized_publisher src/manifest.cpp src/resized_publisher.cpp src/resized_subscriber.cpp) +ament_target_dependencies(resized_publisher + "image_transport") target_link_libraries(resized_publisher ${rclcpp_LIBRARIES} ${OpenCV_LIBRARIES}) # add the publisher from video example diff --git a/image_transport_tutorial/include/image_transport_tutorial/resized_subscriber.hpp b/image_transport_tutorial/include/image_transport_tutorial/resized_subscriber.hpp index f6cbad54..c8a8babd 100644 --- a/image_transport_tutorial/include/image_transport_tutorial/resized_subscriber.hpp +++ b/image_transport_tutorial/include/image_transport_tutorial/resized_subscriber.hpp @@ -31,6 +31,7 @@ class ResizedSubscriber : public image_transport::SimpleSubscriberPlugin return "resized"; } +protected: void subscribeImpl( rclcpp::Node * node, const std::string & base_topic, @@ -41,7 +42,6 @@ class ResizedSubscriber : public image_transport::SimpleSubscriberPlugin this->subscribeImplWithOptions(node, base_topic, callback, custom_qos, options); } -protected: virtual void internalCallback( const typename image_transport_tutorial::msg::ResizedImage::ConstSharedPtr & message, const Callback & user_cb); From e19703f9f85be039dd22b2afd0b2966eab923e4f Mon Sep 17 00:00:00 2001 From: Rebecca Butler Date: Thu, 8 Jul 2021 10:32:35 -0400 Subject: [PATCH 11/13] Edit README to have one sentence per line Signed-off-by: Rebecca Butler --- image_transport_tutorial/README.md | 79 +++++++++++++++++++++--------- 1 file changed, 57 insertions(+), 22 deletions(-) diff --git a/image_transport_tutorial/README.md b/image_transport_tutorial/README.md index 6fecbdb5..21adfb02 100644 --- a/image_transport_tutorial/README.md +++ b/image_transport_tutorial/README.md @@ -27,7 +27,8 @@ Tutorial Level: Beginner Take a look at [my_publisher.cpp](src/my_publisher.cpp). ### The code explained -Now, let's break down the code piece by piece. For lines not explained here, review [Writing a Simple Publisher and Subscriber (C++)](https://docs.ros.org/en/galactic/Tutorials/Writing-A-Simple-Cpp-Publisher-And-Subscriber.html). +Now, let's break down the code piece by piece. +For lines not explained here, review [Writing a Simple Publisher and Subscriber (C++)](https://docs.ros.org/en/galactic/Tutorials/Writing-A-Simple-Cpp-Publisher-And-Subscriber.html). ``` #include @@ -50,7 +51,9 @@ We use methods of `ImageTransport` to create image publishers and subscribers, m image_transport::Publisher pub = it.advertise("camera/image", 1); ``` -Advertise that we are going to be publishing images on the base topic `camera/image`. Depending on whether more plugins are built, additional (per-plugin) topics derived from the base topic may also be advertised. The second argument is the size of our publishing queue. +Advertise that we are going to be publishing images on the base topic `camera/image`. +Depending on whether more plugins are built, additional (per-plugin) topics derived from the base topic may also be advertised. +The second argument is the size of our publishing queue. `advertise()` returns an `image_transport::Publisher` object, which serves two purposes: 1. It contains a `publish()` method that lets you publish images onto the base topic it was created with @@ -74,17 +77,26 @@ while (rclcpp::ok()) { } ``` -We broadcast the image to anyone connected to one of our topics, exactly as we would have using an `rclrcpp::Publisher`. +We broadcast the image to anyone connected to one of our topics, exactly as we would have using an `rclcpp::Publisher`. ### Adding video stream from a webcam -The example above requires a path to an image file to be added as a command line parameter. This image will be converted and sent as a message to an image subscriber. In most cases, however, this is not a very practical example as you are often required to handle streaming data. (For example: multiple webcams mounted on a robot record the scene around it and you have to pass the image data to some other node for further analysis). +The example above requires a path to an image file to be added as a command line parameter. +This image will be converted and sent as a message to an image subscriber. +In most cases, however, this is not a very practical example as you are often required to handle streaming data. +(For example: multiple webcams mounted on a robot record the scene around it and you have to pass the image data to some other node for further analysis). -The publisher example can be modified quite easily to make it work with a video device supported by `cv::VideoCapture` (in case it is not, you have to handle it accordingly). Take a look at [publisher_from_video.cpp](src/publisher_from_video.cpp) to see how a video device can be passed in as a command line argument and used as the image source. +The publisher example can be modified quite easily to make it work with a video device supported by `cv::VideoCapture` (in case it is not, you have to handle it accordingly). +Take a look at [publisher_from_video.cpp](src/publisher_from_video.cpp) to see how a video device can be passed in as a command line argument and used as the image source. -If you have a single device, you do not need to do the whole routine with passing a command line argument. In this case, you can hard-code the index/address of the device and directly pass it to the video capturing structure in OpenCV (example: `cv::VideoCapture(0)` if `/dev/video0` is used). Multiple checks are also included here to make sure that the publisher does not break if the camera is shut down. If the retrieved frame from the video device is not empty, it will then be converted to a ROS message which will be published by the publisher. +If you have a single device, you do not need to do the whole routine with passing a command line argument. +In this case, you can hard-code the index/address of the device and directly pass it to the video capturing structure in OpenCV (example: `cv::VideoCapture(0)` if `/dev/video0` is used). +Multiple checks are also included here to make sure that the publisher does not break if the camera is shut down. +If the retrieved frame from the video device is not empty, it will then be converted to a ROS message which will be published by the publisher. ## Writing a Simple Image Subscriber (C++) -Description: This tutorial shows how to create a subscriber node that will display an image on the screen. By using the `image_transport` subscriber to subscribe to images, any image transport can be used at runtime. To learn how to actually use a specific image transport, see the next tutorial. +Description: This tutorial shows how to create a subscriber node that will display an image on the screen. +By using the `image_transport` subscriber to subscribe to images, any image transport can be used at runtime. +To learn how to actually use a specific image transport, see the next tutorial. Tutorial Level: Beginner @@ -108,7 +120,9 @@ These headers will allow us to subscribe to image messages, display images using void imageCallback(const sensor_msgs::msg::Image::ConstSharedPtr & msg) ``` -This is the callback function that will be called when a new image has arrived on the `camera/image` topic. Although the image may have been sent in some arbitrary transport-specific message type, notice that the callback need only handle the normal `sensor_msgs/Image` type. All image encoding/decoding is handled automatically for you. +This is the callback function that will be called when a new image has arrived on the `camera/image` topic. +Although the image may have been sent in some arbitrary transport-specific message type, notice that the callback need only handle the normal `sensor_msgs/Image` type. +All image encoding/decoding is handled automatically for you. ``` try { @@ -119,7 +133,8 @@ try { RCLCPP_ERROR(logger, "Could not convert from '%s' to 'bgr8'.", msg->encoding.c_str()); ``` -The body of the callback. We convert the ROS image message into an OpenCV image with BGR pixel encoding, then show it in a display window. +The body of the callback. +We convert the ROS image message into an OpenCV image with BGR pixel encoding, then show it in a display window. ``` @@ -133,9 +148,14 @@ We create an `ImageTransport` instance, initializing it with our node. image_transport::Subscriber sub = it.subscribe("camera/image", 1, imageCallback); ``` -Subscribe to the `camera/image` base topic. The actual ROS topic subscribed to depends on which transport is used. In the default case, "raw" transport, the topic is `camera/image` with type `sensor_msgs/Image`. ROS will call the `imageCallback` function whenever a new image arrives. The 2nd argument is the queue size. +Subscribe to the `camera/image` base topic. +The actual ROS topic subscribed to depends on which transport is used. +In the default case, "raw" transport, the topic is `camera/image` with type `sensor_msgs/Image`. +ROS will call the `imageCallback` function whenever a new image arrives. +The 2nd argument is the queue size. -`subscribe()` returns an `image_transport::Subscriber` object that you must hold on to until you want to unsubscribe. When the Subscriber object is destructed, it will automatically unsubscribe from the `camera/image` base topic. +`subscribe()` returns an `image_transport::Subscriber` object that you must hold on to until you want to unsubscribe. +When the Subscriber object is destructed, it will automatically unsubscribe from the `camera/image` base topic. In just a few lines of code, we have written a ROS image viewer that can handle images in both raw and a variety of compressed forms. @@ -145,7 +165,8 @@ Description: This tutorial discusses running the simple image publisher and subs Tutorial Level: Beginner ### Running the publisher -In a previous tutorial we made a publisher node called `my_publisher`. Now run the node with an image file as the command-line argument: +In a previous tutorial we made a publisher node called `my_publisher`. +Now run the node with an image file as the command-line argument: ``` $ ros2 run image_transport_tutorial my_publisher path/to/some/image.jpg @@ -157,7 +178,8 @@ To check that your node is running properly, list the topics being published: $ ros2 topic list ``` -You should see `/camera/image` in the output. You can also get more information about the topic: +You should see `/camera/image` in the output. +You can also get more information about the topic: ``` $ ros2 topic info /camera/image @@ -181,7 +203,9 @@ $ ros2 run image_transport_tutorial my_subscriber You should see a window pop up with the image you gave to the publisher. ### Finding available transports -`image_transport` searches your ROS installation for transport plugins at runtime and dynamically loads all that are built. This affords you great flexibility in adding additional transports, but makes it unclear which are available on your system. `image_transport` provides a `list_transports` executable for this purpose: +`image_transport` searches your ROS installation for transport plugins at runtime and dynamically loads all that are built. +This affords you great flexibility in adding additional transports, but makes it unclear which are available on your system. +`image_transport` provides a `list_transports` executable for this purpose: ``` $ ros2 run image_transport list_transports @@ -204,12 +228,15 @@ Details: This is the default pass-through subscriber for topics of type sensor_msgs/Image. ``` -This the expected output for an otherwise new ROS installation after completing the previous tutorials. Depending on your setup, you may already have "theora" or other transports available. +This the expected output for an otherwise new ROS installation after completing the previous tutorials. +Depending on your setup, you may already have "theora" or other transports available. ### Adding new transports -Our nodes are currently communicating raw `sensor_msgs/Image` messages, so we are not gaining anything over using `rclcpp::Publisher` and `rclcpp::Subscriber`. Let's change that by introducing a new transport. +Our nodes are currently communicating raw `sensor_msgs/Image` messages, so we are not gaining anything over using `rclcpp::Publisher` and `rclcpp::Subscriber`. +Let's change that by introducing a new transport. -The `compressed_image_transport` package provides plugins for the "compressed" transport, which sends images over the wire in either JPEG- or PNG-compressed form. Notice that `compressed_image_transport` is not a dependency of your package; `image_transport` will automatically discover all transport plugins built in your ROS system. +The `compressed_image_transport` package provides plugins for the "compressed" transport, which sends images over the wire in either JPEG- or PNG-compressed form. +Notice that `compressed_image_transport` is not a dependency of your package; `image_transport` will automatically discover all transport plugins built in your ROS system. The easiest way to add the "compressed" transport is to install the package: @@ -226,7 +253,9 @@ $ sudo apt-get install ros-galactic-image-transport-plugins But you can also build from source. ### Changing the transport used -Now let's start up a new subscriber, this one using compressed transport. The key is that `image_transport` subscribers check the parameter `_image_transport` for the name of a transport to use in place of "raw". Let's set this parameter and start a subscriber node with name "compressed_listener": +Now let's start up a new subscriber, this one using compressed transport. +The key is that `image_transport` subscribers check the parameter `_image_transport` for the name of a transport to use in place of "raw". +Let's set this parameter and start a subscriber node with name "compressed_listener": ``` $ ros2 run image_transport_tutorial my_subscriber --ros-args --remap __name:=compressed_listener -p _image_transport:=compressed @@ -237,17 +266,23 @@ You should see an identical image window pop up. `compressed_listener` is listening to a separate topic carrying JPEG-compressed versions of the same images published on `/camera/image`. ### Changing transport-specific behavior -For a particular transport, we may want to tweak settings such as compression level, bit rate, etc. Transport plugins can expose such settings through `rqt_reconfigure`. For example, `/camera/image/compressed` allows you to change the compression format and quality on the fly; see the package documentation for full details. +For a particular transport, we may want to tweak settings such as compression level, bit rate, etc. +Transport plugins can expose such settings through `rqt_reconfigure`. +For example, `/camera/image/compressed` allows you to change the compression format and quality on the fly; see the package documentation for full details. -For now let's adjust the JPEG quality. By default, the "compressed" transport uses JPEG compression at 80% quality. Let's change it to 15%: +For now let's adjust the JPEG quality. +By default, the "compressed" transport uses JPEG compression at 80% quality. +Let's change it to 15%: ``` $ ros2 run rqt_reconfigure rqt_reconfigure ``` -Now pick `/image_publisher` in the drop-down menu and move the `jpeg_quality` slider down to 15%. Do you see the compression artifacts in your second view window? +Now pick `/image_publisher` in the drop-down menu and move the `jpeg_quality` slider down to 15%. +Do you see the compression artifacts in your second view window? -Dynamic Reconfigure has updated the dynamically reconfigurable parameter `/image_publisher/jpeg_quality`. You can verify this by running: +Dynamic Reconfigure has updated the dynamically reconfigurable parameter `/image_publisher/jpeg_quality`. +You can verify this by running: ``` $ ros2 param get /image_publisher jpeg_quality From d4dc59340f2c6b0c9a05ef8fb8c41d657abf2c75 Mon Sep 17 00:00:00 2001 From: Rebecca Butler Date: Thu, 8 Jul 2021 10:39:52 -0400 Subject: [PATCH 12/13] Fix errors in README Signed-off-by: Rebecca Butler --- image_transport_tutorial/README.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/image_transport_tutorial/README.md b/image_transport_tutorial/README.md index 21adfb02..43538720 100644 --- a/image_transport_tutorial/README.md +++ b/image_transport_tutorial/README.md @@ -66,7 +66,7 @@ sensor_msgs::msg::Image::SharedPtr msg; msg = cv_bridge::CvImage(hdr, "bgr8", image).toImageMsg(); ``` -We load a user-specified (on the command line) color image from disk using OpenCV, then convert it to the ROS type `sensor_msgs/Image`. +We load a user-specified (on the command line) color image from disk using OpenCV, then convert it to the ROS type `sensor_msgs/msg/Image`. ``` rclcpp::WallRate loop_rate(5); @@ -121,7 +121,7 @@ void imageCallback(const sensor_msgs::msg::Image::ConstSharedPtr & msg) ``` This is the callback function that will be called when a new image has arrived on the `camera/image` topic. -Although the image may have been sent in some arbitrary transport-specific message type, notice that the callback need only handle the normal `sensor_msgs/Image` type. +Although the image may have been sent in some arbitrary transport-specific message type, notice that the callback need only handle the normal `sensor_msgs/msg/Image` type. All image encoding/decoding is handled automatically for you. ``` @@ -150,7 +150,7 @@ image_transport::Subscriber sub = it.subscribe("camera/image", 1, imageCallback) Subscribe to the `camera/image` base topic. The actual ROS topic subscribed to depends on which transport is used. -In the default case, "raw" transport, the topic is `camera/image` with type `sensor_msgs/Image`. +In the default case, "raw" transport, the topic is `camera/image` with type `sensor_msgs/msg/Image`. ROS will call the `imageCallback` function whenever a new image arrives. The 2nd argument is the queue size. @@ -232,7 +232,7 @@ This the expected output for an otherwise new ROS installation after completing Depending on your setup, you may already have "theora" or other transports available. ### Adding new transports -Our nodes are currently communicating raw `sensor_msgs/Image` messages, so we are not gaining anything over using `rclcpp::Publisher` and `rclcpp::Subscriber`. +Our nodes are currently communicating raw `sensor_msgs/msg/Image` messages, so we are not gaining anything over using `rclcpp::Publisher` and `rclcpp::Subscriber`. Let's change that by introducing a new transport. The `compressed_image_transport` package provides plugins for the "compressed" transport, which sends images over the wire in either JPEG- or PNG-compressed form. @@ -267,12 +267,13 @@ You should see an identical image window pop up. ### Changing transport-specific behavior For a particular transport, we may want to tweak settings such as compression level, bit rate, etc. -Transport plugins can expose such settings through `rqt_reconfigure`. +Transport plugins can expose such settings through ROS parameters. For example, `/camera/image/compressed` allows you to change the compression format and quality on the fly; see the package documentation for full details. For now let's adjust the JPEG quality. By default, the "compressed" transport uses JPEG compression at 80% quality. -Let's change it to 15%: +Let's change it to 15%. +We can use the GUI, `rqt_reconfigure`, to change the quality: ``` $ ros2 run rqt_reconfigure rqt_reconfigure @@ -281,7 +282,7 @@ $ ros2 run rqt_reconfigure rqt_reconfigure Now pick `/image_publisher` in the drop-down menu and move the `jpeg_quality` slider down to 15%. Do you see the compression artifacts in your second view window? -Dynamic Reconfigure has updated the dynamically reconfigurable parameter `/image_publisher/jpeg_quality`. +The `rqt_reconfigure` GUI has updated the ROS parameter `/image_publisher/jpeg_quality`. You can verify this by running: ``` From e6ae21150766d5a020cffff2d3d90418febee938 Mon Sep 17 00:00:00 2001 From: Rebecca Butler Date: Thu, 8 Jul 2021 10:58:29 -0400 Subject: [PATCH 13/13] Fix errors in CMakeLists.txt and package.xml Signed-off-by: Rebecca Butler --- image_transport_tutorial/CMakeLists.txt | 30 ++++++++++++++----------- image_transport_tutorial/package.xml | 6 +++-- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/image_transport_tutorial/CMakeLists.txt b/image_transport_tutorial/CMakeLists.txt index b0e57e3b..c88520a2 100644 --- a/image_transport_tutorial/CMakeLists.txt +++ b/image_transport_tutorial/CMakeLists.txt @@ -13,12 +13,13 @@ endif() find_package(ament_cmake REQUIRED) find_package(cv_bridge REQUIRED) find_package(image_transport REQUIRED) +find_package(OpenCV REQUIRED) find_package(pluginlib REQUIRED) find_package(rclcpp REQUIRED) find_package(rosidl_default_generators REQUIRED) find_package(sensor_msgs REQUIRED) -include_directories(include ${OpenCV_INCLUDE_DIRS}) +include_directories(include) # add the resized image message set(msg_files @@ -33,39 +34,42 @@ rosidl_generate_interfaces(${PROJECT_NAME} add_executable(my_publisher src/my_publisher.cpp) ament_target_dependencies(my_publisher "cv_bridge" - "image_transport") -target_link_libraries(my_publisher ${rclcpp_LIBRARIES} ${OpenCV_LIBRARIES}) + "image_transport" + "OpenCV" + "rclcpp") # add the subscriber example add_executable(my_subscriber src/my_subscriber.cpp) ament_target_dependencies(my_subscriber "cv_bridge" - "image_transport") -target_link_libraries(my_subscriber ${rclcpp_LIBRARIES} ${OpenCV_LIBRARIES}) + "image_transport" + "OpenCV" + "rclcpp") # add the plugin example -add_library(resized_publisher src/manifest.cpp src/resized_publisher.cpp src/resized_subscriber.cpp) -ament_target_dependencies(resized_publisher - "image_transport") -target_link_libraries(resized_publisher ${rclcpp_LIBRARIES} ${OpenCV_LIBRARIES}) +add_library(resized_plugins src/manifest.cpp src/resized_publisher.cpp src/resized_subscriber.cpp) +ament_target_dependencies(resized_plugins + "image_transport" + "OpenCV") # add the publisher from video example add_executable(publisher_from_video src/publisher_from_video.cpp) ament_target_dependencies(publisher_from_video "cv_bridge" - "image_transport") -target_link_libraries(publisher_from_video ${rclcpp_LIBRARIES} ${OpenCV_LIBRARIES}) + "image_transport" + "OpenCV" + "rclcpp") # Install plugin descriptions pluginlib_export_plugin_description_file(${PROJECT_NAME} resized_plugins.xml) # Link interface -rosidl_target_interfaces(resized_publisher +rosidl_target_interfaces(resized_plugins ${PROJECT_NAME} "rosidl_typesupport_cpp") # Install executables install( - TARGETS my_publisher my_subscriber resized_publisher publisher_from_video + TARGETS my_publisher my_subscriber resized_plugins publisher_from_video RUNTIME DESTINATION lib/${PROJECT_NAME} ) diff --git a/image_transport_tutorial/package.xml b/image_transport_tutorial/package.xml index 40f7910c..c75e7003 100644 --- a/image_transport_tutorial/package.xml +++ b/image_transport_tutorial/package.xml @@ -1,9 +1,9 @@ image_transport_tutorial - 0.0.0 + 3.1.0 Tutorial for image_transport. Vincent Rabaud - Vincent Rabaud + Michael Carroll Apache 2.0 ament_cmake_ros @@ -11,11 +11,13 @@ cv_bridge image_transport + libopencv-dev sensor_msgs rosidl_default_runtime cv_bridge image_transport + libopencv-dev sensor_msgs ament_lint_auto