From 9d7a4c6b3f1c2afc2ea4f7f6070db00c0f174078 Mon Sep 17 00:00:00 2001 From: Alejandro Hernandez Cordero Date: Fri, 17 Apr 2026 10:08:38 +0200 Subject: [PATCH] Added rosdoc2 documentation to image_transport Signed-off-by: Alejandro Hernandez Cordero --- image_transport/doc/camera_api.rst | 85 ++++++++++ image_transport/doc/conf.py | 43 +++++ image_transport/doc/filter_api.rst | 63 ++++++++ image_transport/doc/overview.rst | 106 +++++++++++++ image_transport/doc/plugin_api.rst | 150 ++++++++++++++++++ image_transport/doc/user_api.rst | 105 ++++++++++++ .../include/image_transport/camera_common.hpp | 28 ++-- .../image_transport/camera_publisher.hpp | 17 ++ .../image_transport/camera_subscriber.hpp | 23 ++- .../include/image_transport/exception.hpp | 9 ++ .../image_transport/image_transport.hpp | 17 ++ .../include/image_transport/publisher.hpp | 21 +++ .../image_transport/publisher_plugin.hpp | 4 +- .../image_transport/raw_subscriber.hpp | 5 + .../include/image_transport/republish.hpp | 18 +++ .../simple_publisher_plugin.hpp | 21 +++ .../simple_subscriber_plugin.hpp | 20 +++ .../single_subscriber_publisher.hpp | 14 ++ .../include/image_transport/subscriber.hpp | 26 +++ .../image_transport/subscriber_filter.hpp | 30 +++- .../image_transport/subscriber_plugin.hpp | 22 ++- .../image_transport/transport_hints.hpp | 14 +- image_transport/package.xml | 9 +- image_transport/rosdoc2.yaml | 32 ++++ 24 files changed, 845 insertions(+), 37 deletions(-) create mode 100644 image_transport/doc/camera_api.rst create mode 100644 image_transport/doc/conf.py create mode 100644 image_transport/doc/filter_api.rst create mode 100644 image_transport/doc/overview.rst create mode 100644 image_transport/doc/plugin_api.rst create mode 100644 image_transport/doc/user_api.rst create mode 100644 image_transport/rosdoc2.yaml diff --git a/image_transport/doc/camera_api.rst b/image_transport/doc/camera_api.rst new file mode 100644 index 00000000..be31ca58 --- /dev/null +++ b/image_transport/doc/camera_api.rst @@ -0,0 +1,85 @@ +Camera API +========== + +Camera drivers typically publish both an ``Image`` and a ``CameraInfo`` topic. +``image_transport`` provides helper classes that publish and subscribe to these +two topics together, keeping them synchronised. + +CameraPublisher +--------------- + +:cpp:class:`image_transport::CameraPublisher` publishes ``Image`` and +``CameraInfo`` on a pair of synchronised topics derived from a single base +topic name. + +See the full :ref:`exhale_class_classimage__transport_1_1CameraPublisher` API reference. + +CameraSubscriber +---------------- + +:cpp:class:`image_transport::CameraSubscriber` subscribes to both the +``Image`` and ``CameraInfo`` topics and delivers them via a single callback. + +See the full :ref:`exhale_class_classimage__transport_1_1CameraSubscriber` API reference. + +Topic Naming Convention +----------------------- + +Given a base topic name (e.g. ``/camera/image_raw``), ``CameraPublisher`` +automatically creates the matching camera info topic by appending +``/../camera_info``: + +.. code-block:: text + + /camera/image_raw ← image topic + /camera/camera_info ← camera info topic (sibling) + +The sibling topic name is computed by +:cpp:func:`image_transport::getCameraInfoTopic`. + +Usage Example +------------- + +**Publisher side (camera driver)** + +.. code-block:: cpp + + #include + #include + #include + + class CameraDriver : public rclcpp::Node + { + public: + CameraDriver() : Node("camera_driver") + { + it_ = std::make_shared( + shared_from_this()); + cam_pub_ = it_->advertiseCamera("camera/image_raw", 1); + } + + void publishFrame( + sensor_msgs::msg::Image::SharedPtr image, + sensor_msgs::msg::CameraInfo::SharedPtr info) + { + cam_pub_.publish(image, info); + } + + private: + std::shared_ptr it_; + image_transport::CameraPublisher cam_pub_; + }; + +**Subscriber side** + +.. code-block:: cpp + + it_ = std::make_shared(shared_from_this()); + cam_sub_ = it_->subscribeCamera( + "camera/image_raw", 1, + [this]( + const sensor_msgs::msg::Image::ConstSharedPtr & img, + const sensor_msgs::msg::CameraInfo::ConstSharedPtr & info) + { + RCLCPP_INFO(get_logger(), "fx = %f", info->k[0]); + }); diff --git a/image_transport/doc/conf.py b/image_transport/doc/conf.py new file mode 100644 index 00000000..3252237e --- /dev/null +++ b/image_transport/doc/conf.py @@ -0,0 +1,43 @@ +import os +import sys + +# Allow Sphinx extensions to find local modules +sys.path.insert(0, os.path.abspath('.')) + +# -- Project information (overridden by rosdoc2 from package.xml) ---------- +project = 'image_transport' +copyright = '2024, Open Robotics' +author = 'Alejandro Hernandez Cordero, Geoffrey Biggs' + +# -- General configuration ------------------------------------------------- +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.intersphinx', + 'breathe', + 'myst_parser', +] + +# breathe_projects and breathe_default_project are overridden by rosdoc2 at build time. +breathe_default_project = 'image_transport Doxygen Project' +breathe_default_members = ('members', 'undoc-members') + +# myst_parser — allow .md files in toctrees +source_suffix = { + '.rst': 'restructuredtext', + '.md': 'markdown', +} + +templates_path = ['_templates'] +# Exclude root-level copies of user docs (rosdoc2 copies them to user_docs/ too, +# where they are included via the user_docs.rst glob toctree). +exclude_patterns = [ + '_build', + 'camera_api.rst', + 'filter_api.rst', + 'overview.rst', + 'plugin_api.rst', + 'user_api.rst', +] + +# -- HTML output options --------------------------------------------------- +html_theme = 'sphinx_rtd_theme' diff --git a/image_transport/doc/filter_api.rst b/image_transport/doc/filter_api.rst new file mode 100644 index 00000000..842ff284 --- /dev/null +++ b/image_transport/doc/filter_api.rst @@ -0,0 +1,63 @@ +Message Filter Integration +========================== + +``image_transport`` provides :cpp:class:`image_transport::SubscriberFilter`, a +drop-in replacement for ``message_filters::Subscriber`` that works with the +full suite of ``message_filters`` synchronisation policies (e.g. +``TimeSynchronizer``, ``ApproximateTime``). + +SubscriberFilter +---------------- + +:cpp:class:`image_transport::SubscriberFilter` is a +``message_filters``-compatible subscriber that decodes compressed image streams +before delivering them to the filter chain. + +See the full :ref:`exhale_class_classimage__transport_1_1SubscriberFilter` API reference. + +Usage Example +------------- + +The following example synchronises an image with a ``PointCloud2`` message +using ``message_filters::TimeSynchronizer``. + +.. code-block:: cpp + + #include + #include + #include + #include + #include + + class SyncNode : public rclcpp::Node + { + public: + SyncNode() : Node("sync_node") + { + image_sub_.subscribe(shared_from_this(), "camera/image_raw"); + cloud_sub_.subscribe(shared_from_this(), "points"); + + sync_ = std::make_shared< + message_filters::TimeSynchronizer< + sensor_msgs::msg::Image, + sensor_msgs::msg::PointCloud2>>(image_sub_, cloud_sub_, 10); + sync_->registerCallback( + std::bind(&SyncNode::callback, this, + std::placeholders::_1, std::placeholders::_2)); + } + + private: + void callback( + const sensor_msgs::msg::Image::ConstSharedPtr & img, + const sensor_msgs::msg::PointCloud2::ConstSharedPtr & cloud) + { + RCLCPP_INFO(get_logger(), "Synced frame at %u ns", + img->header.stamp.nanosec); + } + + image_transport::SubscriberFilter image_sub_; + message_filters::Subscriber cloud_sub_; + std::shared_ptr> sync_; + }; diff --git a/image_transport/doc/overview.rst b/image_transport/doc/overview.rst new file mode 100644 index 00000000..6cc5294e --- /dev/null +++ b/image_transport/doc/overview.rst @@ -0,0 +1,106 @@ +Overview +======== + +``image_transport`` is a ROS 2 library that provides a plugin-based framework +for publishing and subscribing to images. It acts as a transparent layer on +top of standard ROS 2 publishers and subscribers, allowing image data to be +transported in raw or compressed form without any changes to the application +code. + +Motivation +---------- + +Raw images are large. A single 1080p colour frame is roughly 6 MB. Sending +these frames over a network at 30 Hz consumes nearly 1.5 Gbit/s of bandwidth. +``image_transport`` solves this by: + +* Advertising a *family* of topics for every base image topic (e.g. + ``/camera/image_raw``, ``/camera/image_raw/compressed``, + ``/camera/image_raw/theora``, …). +* Letting subscribers pick the transport that best suits their network + conditions by setting the ``image_transport`` ROS parameter. +* Keeping the API identical to standard ``rclcpp`` publishers and subscribers + so that existing code requires minimal changes. + +Architecture +------------ + +.. code-block:: text + + Camera driver + │ + ▼ + image_transport::Publisher + ├─ raw topic ──► raw subscriber + ├─ compressed topic ──► compressed subscriber + └─ theora topic ──► theora subscriber + +The publisher side creates one sub-publisher per installed transport plugin. +The subscriber side picks exactly one transport based on the +``image_transport`` parameter (default: ``raw``). + +Plugin system +^^^^^^^^^^^^^ + +Transport plugins are discovered at runtime via ``pluginlib``. Each plugin +implements either :cpp:class:`image_transport::PublisherPlugin` or +:cpp:class:`image_transport::SubscriberPlugin`. The built-in ``raw`` transport +is provided by :cpp:class:`image_transport::RawPublisher` and +:cpp:class:`image_transport::RawSubscriber`. + +A list of all currently loaded transport plugins can be obtained with: + +.. code-block:: bash + + ros2 run image_transport list_transports + +Dependencies +------------ + +* ``rclcpp`` — ROS 2 C++ client library +* ``sensor_msgs`` — ``Image`` and ``CameraInfo`` message types +* ``message_filters`` — for :cpp:class:`image_transport::SubscriberFilter` +* ``pluginlib`` — runtime plugin loading +* ``rclcpp_components`` — composable node support (``republish``) + +ROS Parameters +-------------- + +.. list-table:: + :header-rows: 1 + + * - Parameter + - Type + - Default + - Description + * - ``image_transport`` + - string + - ``"raw"`` + - Transport to use when subscribing. Set per-subscriber via + :cpp:class:`image_transport::TransportHints`. + +Nodes +----- + +republish +^^^^^^^^^ + +Converts an image stream from one transport to another. + +.. code-block:: bash + + ros2 run image_transport republish \ + --ros-args \ + -p in_transport:=raw \ + -p out_transport:=compressed \ + --remap in:=/camera/image_raw \ + --remap out:=/camera/image_raw + +list_transports +^^^^^^^^^^^^^^^ + +Prints all transport plugins available in the current environment. + +.. code-block:: bash + + ros2 run image_transport list_transports diff --git a/image_transport/doc/plugin_api.rst b/image_transport/doc/plugin_api.rst new file mode 100644 index 00000000..916f260f --- /dev/null +++ b/image_transport/doc/plugin_api.rst @@ -0,0 +1,150 @@ +Writing a Transport Plugin +========================== + +A transport plugin is a pair of ``pluginlib`` plugins — one publisher and one +subscriber — that negotiate how image data is serialised on the wire. The +built-in ``raw`` transport (see ``RawPublisher`` / ``RawSubscriber``) is the +simplest possible example. + +Plugin Base Classes +------------------- + +PublisherPlugin +^^^^^^^^^^^^^^^ + +:cpp:class:`image_transport::PublisherPlugin` is the abstract base class for +all publisher-side transport plugins. + +See the full :ref:`exhale_class_classimage__transport_1_1PublisherPlugin` API reference. + +SubscriberPlugin +^^^^^^^^^^^^^^^^ + +:cpp:class:`image_transport::SubscriberPlugin` is the abstract base class for +all subscriber-side transport plugins. + +See the full :ref:`exhale_class_classimage__transport_1_1SubscriberPlugin` API reference. + +Convenience Base Classes +------------------------ + +Most transports communicate over a single ROS 2 topic using a +transport-specific message type. In that common case, derive from the +``Simple`` variants to avoid boilerplate. + +SimplePublisherPlugin +^^^^^^^^^^^^^^^^^^^^^ + +:cpp:class:`image_transport::SimplePublisherPlugin` provides a ready-made +publisher plugin that manages a single typed topic subscription internally. + +See the full :ref:`exhale_class_classimage__transport_1_1SimplePublisherPlugin` API reference. + +SimpleSubscriberPlugin +^^^^^^^^^^^^^^^^^^^^^^ + +:cpp:class:`image_transport::SimpleSubscriberPlugin` provides a ready-made +subscriber plugin that manages a single typed topic subscription internally. + +See the full :ref:`exhale_class_classimage__transport_1_1SimpleSubscriberPlugin` API reference. + +Built-in Raw Transport +---------------------- + +RawPublisher +^^^^^^^^^^^^ + +:cpp:class:`image_transport::RawPublisher` is the built-in raw transport +publisher, which publishes ``sensor_msgs/msg/Image`` directly without encoding. + +See the full :ref:`exhale_class_classimage__transport_1_1RawPublisher` API reference. + +RawSubscriber +^^^^^^^^^^^^^ + +:cpp:class:`image_transport::RawSubscriber` is the built-in raw transport +subscriber. + +See the full :ref:`exhale_class_classimage__transport_1_1RawSubscriber` API reference. + +Step-by-Step Guide +------------------ + +1. **Define the transport message** (optional). If the compressed format needs + its own message type, add it to a separate ``_msgs`` package. Otherwise + reuse an existing type. + +2. **Implement the publisher plugin.** Derive from + :cpp:class:`image_transport::SimplePublisherPlugin` and override + ``publish()`` to encode the raw ``sensor_msgs::msg::Image`` into your + transport-specific message. + + .. code-block:: cpp + + class MyPublisher + : public image_transport::SimplePublisherPlugin + { + public: + std::string getTransportName() const override { return "my_transport"; } + + protected: + void publish( + const sensor_msgs::msg::Image & message, + const PublishFn & publish_fn) const override + { + my_msgs::msg::MyImage encoded; + // ... encode message into encoded ... + publish_fn(encoded); + } + }; + +3. **Implement the subscriber plugin.** Derive from + :cpp:class:`image_transport::SimpleSubscriberPlugin` and override + ``internalCallback()`` to decode the transport-specific message back into + a ``sensor_msgs::msg::Image``. + + .. code-block:: cpp + + class MySubscriber + : public image_transport::SimpleSubscriberPlugin + { + public: + std::string getTransportName() const override { return "my_transport"; } + + protected: + void internalCallback( + const my_msgs::msg::MyImage::ConstSharedPtr & msg, + const Callback & user_cb) override + { + auto image = std::make_shared(); + // ... decode msg into image ... + user_cb(image); + } + }; + +4. **Register the plugins** in your ``CMakeLists.txt`` and export a + ``pluginlib`` XML manifest so that ``image_transport`` can discover them + at runtime. + + .. code-block:: xml + + + + My custom image transport publisher. + + + My custom image transport subscriber. + + + +5. **Export the XML manifest** from ``package.xml``: + + .. code-block:: xml + + + + diff --git a/image_transport/doc/user_api.rst b/image_transport/doc/user_api.rst new file mode 100644 index 00000000..7a180806 --- /dev/null +++ b/image_transport/doc/user_api.rst @@ -0,0 +1,105 @@ +User API +======== + +These are the classes and free functions intended for everyday use in +camera drivers and image-processing nodes. + +ImageTransport +-------------- + +:cpp:class:`image_transport::ImageTransport` is the entry point. Bind it to +a node and use it to create publishers and subscribers. + +See the full :ref:`exhale_class_classimage__transport_1_1ImageTransport` API reference. + +Publisher +--------- + +:cpp:class:`image_transport::Publisher` is the handle returned by +``ImageTransport::advertise()``. + +See the full :ref:`exhale_class_classimage__transport_1_1Publisher` API reference. + +Subscriber +---------- + +:cpp:class:`image_transport::Subscriber` is the handle returned by +``ImageTransport::subscribe()``. + +See the full :ref:`exhale_class_classimage__transport_1_1Subscriber` API reference. + +TransportHints +-------------- + +:cpp:class:`image_transport::TransportHints` controls which transport plugin +is selected for a subscriber. + +See the full :ref:`exhale_class_classimage__transport_1_1TransportHints` API reference. + +SingleSubscriberPublisher +------------------------- + +:cpp:class:`image_transport::SingleSubscriberPublisher` is passed to the +``connect_cb`` of a ``Publisher`` when a new subscriber arrives. + +See the full :ref:`exhale_class_classimage__transport_1_1SingleSubscriberPublisher` API reference. + +Free Functions +-------------- + +The free functions ``create_publisher``, ``create_subscription``, +``create_camera_publisher``, and ``create_camera_subscription`` are available +in the ``image_transport`` namespace. See the C++ API reference for the full +overload set. + + +Exceptions +---------- + +:cpp:class:`image_transport::Exception` is the base exception class. + +:cpp:class:`image_transport::TransportLoadException` is thrown when a +transport plugin cannot be loaded. + +See the full API reference: +:ref:`exhale_class_classimage__transport_1_1Exception`, +:ref:`exhale_class_classimage__transport_1_1TransportLoadException`. + +Usage Example +------------- + +.. code-block:: cpp + + #include + #include + #include + + class MyNode : public rclcpp::Node + { + public: + MyNode() : Node("my_node") + { + // Create ImageTransport bound to this node + it_ = std::make_shared( + shared_from_this()); + + // Publish on base topic — all transports are advertised automatically + pub_ = it_->advertise("camera/image", 1); + + // Subscribe — honours the 'image_transport' parameter + sub_ = it_->subscribe( + "camera/image", 1, + std::bind(&MyNode::imageCb, this, std::placeholders::_1)); + } + + private: + void imageCb(const sensor_msgs::msg::Image::ConstSharedPtr & msg) + { + RCLCPP_INFO(get_logger(), "Received image %ux%u", msg->width, msg->height); + pub_.publish(msg); + } + + std::shared_ptr it_; + image_transport::Publisher pub_; + image_transport::Subscriber sub_; + }; diff --git a/image_transport/include/image_transport/camera_common.hpp b/image_transport/include/image_transport/camera_common.hpp index f88afafd..e3e6e617 100644 --- a/image_transport/include/image_transport/camera_common.hpp +++ b/image_transport/include/image_transport/camera_common.hpp @@ -96,20 +96,20 @@ std::string erase_last_copy(const std::string & input, const std::string & searc * \brief Read the transport name declared in a plugin manifest XML for a given * class lookup name. * - * Searches the manifest for the \c element whose \c name attribute + * Searches the manifest for the \c <class> element whose \c name attribute * matches \p lookup_name. The transport name is resolved with the following * precedence (highest first): * - * 1. A \c text child of the matching \c element. - * 2. A \c text child of the enclosing \c element + * 1. A \c <transport_name> text child of the matching \c <class> element. + * 2. A \c <transport_name> text child of the enclosing \c <library> element * (shared default for all classes in that library). * * This allows a single shared library that bundles two distinct transports to - * give each \c its own \c , while still supporting the + * give each \c <class> its own \c <transport_name>, while still supporting the * common case where all classes share the same name declared once at library * level: * - * \code{.xml} + * \code{.none} * * * my_transport @@ -127,9 +127,9 @@ std::string erase_last_copy(const std::string & input, const std::string & searc * No plugin is instantiated during the search. * * \param manifest_path Absolute path to the plugin XML manifest file. - * \param lookup_name The \c name attribute of the target \c element. + * \param lookup_name The \c name attribute of the target \c <class> element. * \return The transport name string (e.g. \c "raw"), or an empty string - * if neither \c element is present or the file + * if neither \c <transport_name> element is present or the file * cannot be parsed. */ IMAGE_TRANSPORT_PUBLIC @@ -141,19 +141,19 @@ std::string get_transport_name_from_manifest( * \brief Read the message type declared in a plugin manifest XML for a given * class lookup name. * - * Searches the manifest for the \c element whose \c name attribute + * Searches the manifest for the \c <class> element whose \c name attribute * matches \p lookup_name. The message type is the primary ROS message type * used by the plugin and is resolved with the following precedence * (highest first): * - * 1. A \c text child of the matching \c element. - * 2. A \c text child of the enclosing \c element + * 1. A \c <message_type> text child of the matching \c <class> element. + * 2. A \c <message_type> text child of the enclosing \c <library> element * (shared default for all classes in that library). * - * This mirrors the resolution rules for \c and allows a + * This mirrors the resolution rules for \c <transport_name> and allows a * single shared library to bundle classes that publish different message types: * - * \code{.xml} + * \code{.none} * * * sensor_msgs/msg/CompressedImage @@ -171,9 +171,9 @@ std::string get_transport_name_from_manifest( * No plugin is instantiated during the search. * * \param manifest_path Absolute path to the plugin XML manifest file. - * \param lookup_name The \c name attribute of the target \c element. + * \param lookup_name The \c name attribute of the target \c <class> element. * \return The type string (e.g. \c "sensor_msgs/msg/Image"), or an empty - * string if neither \c element is present or the file + * string if neither \c <message_type> element is present or the file * cannot be parsed. */ IMAGE_TRANSPORT_PUBLIC diff --git a/image_transport/include/image_transport/camera_publisher.hpp b/image_transport/include/image_transport/camera_publisher.hpp index 8eb9e04c..a789b20b 100644 --- a/image_transport/include/image_transport/camera_publisher.hpp +++ b/image_transport/include/image_transport/camera_publisher.hpp @@ -68,6 +68,13 @@ class CameraPublisher IMAGE_TRANSPORT_PUBLIC CameraPublisher() = default; + /** + * \brief Constructor (deprecated). + * \deprecated Use CameraPublisher(RequiredInterfaces, ..., rclcpp::QoS) instead. + * \param node The node to use for advertising. + * \param base_topic The base image topic name. + * \param custom_qos QoS profile (rmw form). + */ [[deprecated("Use CameraPublisher(RequiredInterfaces node_interfaces, ..., rclcpp::QoS) " "instead.")]] IMAGE_TRANSPORT_PUBLIC @@ -77,6 +84,12 @@ class CameraPublisher rmw_qos_profile_t custom_qos = rmw_qos_profile_default, rclcpp::PublisherOptions = rclcpp::PublisherOptions()); + /** + * \brief Constructor. + * \param node_interfaces The node interfaces used for advertising. + * \param base_topic The base image topic name. + * \param custom_qos QoS profile. + */ IMAGE_TRANSPORT_PUBLIC CameraPublisher( RequiredInterfaces node_interfaces, @@ -160,15 +173,19 @@ class CameraPublisher IMAGE_TRANSPORT_PUBLIC void shutdown(); + /// \brief Returns non-null if this CameraPublisher is valid (i.e. advertised). IMAGE_TRANSPORT_PUBLIC operator void *() const; + /// \brief Less-than comparison based on internal implementation pointer. IMAGE_TRANSPORT_PUBLIC bool operator<(const CameraPublisher & rhs) const {return impl_ < rhs.impl_;} + /// \brief Inequality comparison based on internal implementation pointer. IMAGE_TRANSPORT_PUBLIC bool operator!=(const CameraPublisher & rhs) const {return impl_ != rhs.impl_;} + /// \brief Equality comparison based on internal implementation pointer. IMAGE_TRANSPORT_PUBLIC bool operator==(const CameraPublisher & rhs) const {return impl_ == rhs.impl_;} diff --git a/image_transport/include/image_transport/camera_subscriber.hpp b/image_transport/include/image_transport/camera_subscriber.hpp index 4e4ed57c..0fbe59dc 100644 --- a/image_transport/include/image_transport/camera_subscriber.hpp +++ b/image_transport/include/image_transport/camera_subscriber.hpp @@ -64,12 +64,21 @@ void callback(const sensor_msgs::msg::Image::ConstSharedPtr&, const sensor_msgs: class CameraSubscriber { public: + /// Callback signature: receives synchronized Image and CameraInfo pointers. typedef std::function Callback; IMAGE_TRANSPORT_PUBLIC CameraSubscriber() = default; + /** + * \brief Constructor (deprecated). + * \deprecated Use CameraSubscriber(RequiredInterfaces, ..., rclcpp::QoS) instead. + * \param node The node to subscribe on. + * \param base_topic The base image topic name. + * \param callback User callback invoked for each (image, info) pair. + * \param transport Transport hint string. + */ [[deprecated("Use CameraSubscriber(RequiredInterfaces node_interfaces, ..., rclcpp::QoS instead) " "instead.")]] IMAGE_TRANSPORT_PUBLIC @@ -80,13 +89,21 @@ class CameraSubscriber const std::string & transport, rmw_qos_profile_t = rmw_qos_profile_default); + /** + * \brief Constructor. + * \param node_interfaces The node interfaces used for subscribing. + * \param base_topic The base image topic name. + * \param callback User callback invoked for each (image, info) pair. + * \param transport Transport hint string. + * \param custom_qos QoS profile. + */ IMAGE_TRANSPORT_PUBLIC CameraSubscriber( RequiredInterfaces node_interfaces, const std::string & base_topic, const Callback & callback, const std::string & transport, - rclcpp::QoS); + rclcpp::QoS custom_qos); /** * \brief Get the base topic (on which the raw image is published). @@ -118,15 +135,19 @@ class CameraSubscriber IMAGE_TRANSPORT_PUBLIC void shutdown(); + /// \brief Returns non-null if this CameraSubscriber is valid (i.e. subscribed). IMAGE_TRANSPORT_PUBLIC operator void *() const; + /// \brief Less-than comparison based on internal implementation pointer. IMAGE_TRANSPORT_PUBLIC bool operator<(const CameraSubscriber & rhs) const {return impl_ < rhs.impl_;} + /// \brief Inequality comparison based on internal implementation pointer. IMAGE_TRANSPORT_PUBLIC bool operator!=(const CameraSubscriber & rhs) const {return impl_ != rhs.impl_;} + /// \brief Equality comparison based on internal implementation pointer. IMAGE_TRANSPORT_PUBLIC bool operator==(const CameraSubscriber & rhs) const {return impl_ == rhs.impl_;} diff --git a/image_transport/include/image_transport/exception.hpp b/image_transport/include/image_transport/exception.hpp index 82b1520e..5a013560 100644 --- a/image_transport/include/image_transport/exception.hpp +++ b/image_transport/include/image_transport/exception.hpp @@ -43,6 +43,8 @@ namespace image_transport class Exception : public std::runtime_error { public: + /// \brief Construct with an error message. + /// \param message Human-readable description of the error. explicit Exception(const std::string & message) : std::runtime_error(message) {} }; @@ -53,15 +55,22 @@ class Exception : public std::runtime_error class TransportLoadException : public Exception { public: + /** + * \brief Constructor. + * \param transport Name of the transport plugin that could not be loaded. + * \param message Detailed error string from pluginlib. + */ TransportLoadException(const std::string & transport, const std::string & message) : Exception("Unable to load plugin for transport '" + transport + "', error string:\n" + message), transport_(transport.c_str()) { } + /// \brief Returns the name of the transport that failed to load. std::string getTransport() const {return transport_;} protected: + /// \brief Name of the transport that could not be loaded. const char * transport_; }; diff --git a/image_transport/include/image_transport/image_transport.hpp b/image_transport/include/image_transport/image_transport.hpp index 41da190b..f7c7451d 100644 --- a/image_transport/include/image_transport/image_transport.hpp +++ b/image_transport/include/image_transport/image_transport.hpp @@ -154,20 +154,35 @@ std::vector getLoadableTransports(); class ImageTransport { public: + /// Shared void pointer, used internally by handle types. using VoidPtr = std::shared_ptr; + /// Convenience alias for a const-shared Image pointer. using ImageConstPtr = sensor_msgs::msg::Image::ConstSharedPtr; + /// Convenience alias for a const-shared CameraInfo pointer. using CameraInfoConstPtr = sensor_msgs::msg::CameraInfo::ConstSharedPtr; + /** + * \brief Constructor (deprecated). + * \deprecated Use ImageTransport(RequiredInterfaces) instead. + * \param node Shared pointer to the node to bind to. + */ [[deprecated("Use ImageTransport(RequiredInterfaces node_interfaces, ...) instead.")]] IMAGE_TRANSPORT_PUBLIC explicit ImageTransport(rclcpp::Node::SharedPtr node); + /** + * \brief Constructor. + * \param node_interfaces The node interfaces (parameters, topics, logging, timers, base) + * used for all advertisements and subscriptions. + */ IMAGE_TRANSPORT_PUBLIC explicit ImageTransport(RequiredInterfaces node_interfaces); + /// \brief Copy constructor. IMAGE_TRANSPORT_PUBLIC ImageTransport(const ImageTransport & other); + /// \brief Copy-assignment operator. IMAGE_TRANSPORT_PUBLIC ImageTransport & operator=(const ImageTransport & other); @@ -497,10 +512,12 @@ class ImageTransport std::unique_ptr impl_; }; +/// \cond INTERNAL struct ImageTransport::Impl { RequiredInterfaces required_interfaces_; }; +/// \endcond } // namespace image_transport diff --git a/image_transport/include/image_transport/publisher.hpp b/image_transport/include/image_transport/publisher.hpp index a51d44ab..54cc77c1 100644 --- a/image_transport/include/image_transport/publisher.hpp +++ b/image_transport/include/image_transport/publisher.hpp @@ -69,6 +69,15 @@ class Publisher IMAGE_TRANSPORT_PUBLIC Publisher() = default; + /** + * \brief Constructor (deprecated). + * \deprecated Use Publisher(RequiredInterfaces, ..., rclcpp::QoS, ...) instead. + * \param node The node to advertise on. + * \param base_topic The base image topic name. + * \param loader Plugin loader for publisher plugins. + * \param custom_qos QoS profile (rmw form). + * \param options Additional publisher options. + */ [[deprecated("Use Publisher(RequiredInterfaces node_interfaces, ..., rclcpp::QoS, ...) " "instead.")]] IMAGE_TRANSPORT_PUBLIC @@ -79,6 +88,14 @@ class Publisher rmw_qos_profile_t custom_qos, rclcpp::PublisherOptions options = rclcpp::PublisherOptions()); + /** + * \brief Constructor. + * \param node_interfaces The node interfaces used for advertising. + * \param base_topic The base image topic name. + * \param loader Plugin loader for publisher plugins. + * \param custom_qos QoS profile. + * \param options Additional publisher options. + */ IMAGE_TRANSPORT_PUBLIC Publisher( RequiredInterfaces node_interfaces, @@ -126,15 +143,19 @@ class Publisher IMAGE_TRANSPORT_PUBLIC void shutdown(); + /// \brief Returns non-null if this Publisher is valid (i.e. advertised). IMAGE_TRANSPORT_PUBLIC operator void *() const; + /// \brief Less-than comparison based on internal implementation pointer. IMAGE_TRANSPORT_PUBLIC bool operator<(const Publisher & rhs) const {return impl_ < rhs.impl_;} + /// \brief Inequality comparison based on internal implementation pointer. IMAGE_TRANSPORT_PUBLIC bool operator!=(const Publisher & rhs) const {return impl_ != rhs.impl_;} + /// \brief Equality comparison based on internal implementation pointer. IMAGE_TRANSPORT_PUBLIC bool operator==(const Publisher & rhs) const {return impl_ == rhs.impl_;} diff --git a/image_transport/include/image_transport/publisher_plugin.hpp b/image_transport/include/image_transport/publisher_plugin.hpp index 6b7c2e16..e485af9e 100644 --- a/image_transport/include/image_transport/publisher_plugin.hpp +++ b/image_transport/include/image_transport/publisher_plugin.hpp @@ -64,7 +64,7 @@ class PublisherPlugin * The default implementation auto-discovers the name from the pluginlib * manifest XML (without instantiating any plugin) by matching the demangled * C++ type name of \c *this against the \c type attribute of each - * \c element. The result is cached after the first call. + * \c <class> element. The result is cached after the first call. * * Plugins that override getTransportName() continue to work unchanged — * user-supplied overrides always take precedence over the base implementation. @@ -76,7 +76,7 @@ class PublisherPlugin /** * \brief Get the primary message type used by this plugin. * - * Returns the value of the \c element from the plugin + * Returns the value of the \c <message_type> element from the plugin * manifest XML (e.g. \c "sensor_msgs/msg/Image"). The result is cached * after the first call. Override this method if you need a different * value at runtime. diff --git a/image_transport/include/image_transport/raw_subscriber.hpp b/image_transport/include/image_transport/raw_subscriber.hpp index 3efce182..d816ecd4 100644 --- a/image_transport/include/image_transport/raw_subscriber.hpp +++ b/image_transport/include/image_transport/raw_subscriber.hpp @@ -52,6 +52,11 @@ class RawSubscriber : public SimpleSubscriberPlugin virtual ~RawSubscriber() {} protected: + /** + * \brief Pass the received raw Image message directly to the user callback. + * \param message The received Image message. + * \param user_cb The user-supplied subscriber callback. + */ void internalCallback( const std::shared_ptr & message, const Callback & user_cb) override diff --git a/image_transport/include/image_transport/republish.hpp b/image_transport/include/image_transport/republish.hpp index 9d74c0ce..1e21093c 100644 --- a/image_transport/include/image_transport/republish.hpp +++ b/image_transport/include/image_transport/republish.hpp @@ -41,6 +41,24 @@ namespace image_transport { + +/** + * \brief ROS 2 composable node that republishes images between transports. + * + * Republisher subscribes to an image topic using one transport (controlled by + * the \c in_transport parameter, default \c "raw") and re-publishes it using + * another transport (controlled by the \c out_transport parameter). + * + * Typical use: + * \code{.bash} + * ros2 run image_transport republish \ + * --ros-args \ + * -p in_transport:=raw \ + * -p out_transport:=compressed \ + * --remap in:=/camera/image_raw \ + * --remap out:=/camera/image_raw + * \endcode + */ class Republisher : public rclcpp::Node { public: diff --git a/image_transport/include/image_transport/simple_publisher_plugin.hpp b/image_transport/include/image_transport/simple_publisher_plugin.hpp index e65d94a1..b34aed18 100644 --- a/image_transport/include/image_transport/simple_publisher_plugin.hpp +++ b/image_transport/include/image_transport/simple_publisher_plugin.hpp @@ -67,6 +67,7 @@ class SimplePublisherPlugin : public PublisherPlugin public: virtual ~SimplePublisherPlugin() {} + /// \brief Returns the number of subscribers on the transport-specific topic. size_t getNumSubscribers() const override { if (simple_impl_) { @@ -75,12 +76,14 @@ class SimplePublisherPlugin : public PublisherPlugin return 0; } + /// \brief Returns the transport-specific topic name being advertised. std::string getTopic() const override { if (simple_impl_) {return simple_impl_->pub_->get_topic_name();} return std::string(); } + /// \brief Encode and publish \p message via the internal transport publisher. void publish(const sensor_msgs::msg::Image & message) const override { if (!simple_impl_ || !simple_impl_->pub_) { @@ -94,6 +97,7 @@ class SimplePublisherPlugin : public PublisherPlugin publish(message, simple_impl_->pub_); } + /// \brief Encode and publish \p message via the internal transport publisher (UniquePtr variant). void publishUniquePtr(sensor_msgs::msg::Image::UniquePtr message) const override { if (!simple_impl_ || !simple_impl_->pub_) { @@ -107,12 +111,21 @@ class SimplePublisherPlugin : public PublisherPlugin publish(std::move(message), simple_impl_->pub_); } + /// \brief Destroy the internal publisher and release resources. void shutdown() override { simple_impl_.reset(); } protected: + /** + * \brief Advertise the transport-specific topic (deprecated). + * \deprecated Use advertiseImpl(RequiredInterfaces, ...) instead. + * \param node The node to advertise on. + * \param base_topic The base image topic name. + * \param custom_qos QoS profile (rmw form). + * \param options Additional publisher options. + */ [[deprecated("Use advertiseImpl(RequiredInterfaces node_interfaces, ...) instead.")]] void advertiseImpl( rclcpp::Node * node, @@ -127,6 +140,13 @@ class SimplePublisherPlugin : public PublisherPlugin options); } + /** + * \brief Advertise the transport-specific topic. + * \param node_interfaces The node interfaces used for advertising. + * \param base_topic The base image topic name. + * \param custom_qos QoS profile. + * \param options Additional publisher options. + */ void advertiseImpl( RequiredInterfaces node_interfaces, const std::string & base_topic, @@ -145,6 +165,7 @@ class SimplePublisherPlugin : public PublisherPlugin transport_topic, custom_qos, options); } + /// Shared pointer to the internal rclcpp publisher for transport message type M. typedef typename rclcpp::Publisher::SharedPtr PublisherT; //! Generic function for publishing the internal message type. diff --git a/image_transport/include/image_transport/simple_subscriber_plugin.hpp b/image_transport/include/image_transport/simple_subscriber_plugin.hpp index ad25dc57..6e4448a1 100644 --- a/image_transport/include/image_transport/simple_subscriber_plugin.hpp +++ b/image_transport/include/image_transport/simple_subscriber_plugin.hpp @@ -65,6 +65,7 @@ class SimpleSubscriberPlugin : public SubscriberPlugin public: virtual ~SimpleSubscriberPlugin() {} + /// \brief Returns the transport-specific topic name being subscribed to. std::string getTopic() const override { if (impl_) { @@ -73,6 +74,7 @@ class SimpleSubscriberPlugin : public SubscriberPlugin return std::string(); } + /// \brief Returns the number of publishers on the transport-specific topic. size_t getNumPublishers() const override { if (impl_) { @@ -81,6 +83,7 @@ class SimpleSubscriberPlugin : public SubscriberPlugin return 0; } + /// \brief Destroy the internal subscription and release resources. void shutdown() override { impl_.reset(); @@ -108,6 +111,15 @@ class SimpleSubscriberPlugin : public SubscriberPlugin return base_topic + "/" + getTransportName(); } + /** + * \brief Subscribe to the transport-specific topic (deprecated). + * \deprecated Use subscribeImpl(RequiredInterfaces, ..., rclcpp::QoS, ...) instead. + * \param node The node to subscribe on. + * \param base_topic The base image topic name. + * \param callback User callback for received images. + * \param custom_qos QoS profile (rmw form). + * \param options Additional subscription options. + */ [[deprecated("Use subscribeImpl(RequiredInterfaces node_interfaces, ..., rclcpp::QoS, ...) " "instead")]] void subscribeImpl( @@ -121,6 +133,14 @@ class SimpleSubscriberPlugin : public SubscriberPlugin rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(custom_qos), custom_qos), options); } + /** + * \brief Subscribe to the transport-specific topic. + * \param node_interfaces The node interfaces used for subscribing. + * \param base_topic The base image topic name. + * \param callback User callback for received images. + * \param custom_qos QoS profile. + * \param options Additional subscription options. + */ void subscribeImpl( RequiredInterfaces node_interfaces, const std::string & base_topic, diff --git a/image_transport/include/image_transport/single_subscriber_publisher.hpp b/image_transport/include/image_transport/single_subscriber_publisher.hpp index e6347db8..86699ccc 100644 --- a/image_transport/include/image_transport/single_subscriber_publisher.hpp +++ b/image_transport/include/image_transport/single_subscriber_publisher.hpp @@ -51,27 +51,41 @@ class SingleSubscriberPublisher SingleSubscriberPublisher & operator=(const SingleSubscriberPublisher &) = delete; public: + /// Function type used to query the number of active subscribers. typedef std::function GetNumSubscribersFn; + /// Function type used to publish a single Image message. typedef std::function PublishFn; + /** + * \brief Constructor. Intended for internal use by Publisher. + * \param caller_id Identifier of the subscriber this publisher targets. + * \param topic The topic name. + * \param num_subscribers_fn Callable that returns the current subscriber count. + * \param publish_fn Callable that performs the actual publish. + */ IMAGE_TRANSPORT_PUBLIC SingleSubscriberPublisher( const std::string & caller_id, const std::string & topic, const GetNumSubscribersFn & num_subscribers_fn, const PublishFn & publish_fn); + /// \brief Returns the name (caller ID) of the targeted subscriber. IMAGE_TRANSPORT_PUBLIC std::string getSubscriberName() const; + /// \brief Returns the topic name. IMAGE_TRANSPORT_PUBLIC std::string getTopic() const; + /// \brief Returns the number of subscribers currently connected. IMAGE_TRANSPORT_PUBLIC size_t getNumSubscribers() const; + /// \brief Publish \p message to the targeted subscriber. IMAGE_TRANSPORT_PUBLIC void publish(const sensor_msgs::msg::Image & message) const; + /// \brief Publish \p message (shared pointer) to the targeted subscriber. IMAGE_TRANSPORT_PUBLIC void publish(const sensor_msgs::msg::Image::ConstSharedPtr & message) const; diff --git a/image_transport/include/image_transport/subscriber.hpp b/image_transport/include/image_transport/subscriber.hpp index a390ce42..dc2b271f 100644 --- a/image_transport/include/image_transport/subscriber.hpp +++ b/image_transport/include/image_transport/subscriber.hpp @@ -62,11 +62,23 @@ namespace image_transport class Subscriber { public: + /// Callback signature: receives a const-shared Image pointer. typedef std::function Callback; IMAGE_TRANSPORT_PUBLIC Subscriber() = default; + /** + * \brief Constructor (deprecated). + * \deprecated Use Subscriber(RequiredInterfaces, ..., rclcpp::QoS) instead. + * \param node The node to subscribe on. + * \param base_topic The base image topic name. + * \param callback User callback invoked for each received image. + * \param loader Plugin loader for subscriber plugins. + * \param transport Transport hint string. + * \param custom_qos QoS profile (rmw form). + * \param options Additional subscription options. + */ [[deprecated("Use Subscriber(RequiredInterfaces node_interfaces, ..., rclcpp::QoS) instead.")]] IMAGE_TRANSPORT_PUBLIC Subscriber( @@ -78,6 +90,16 @@ class Subscriber rmw_qos_profile_t custom_qos = rmw_qos_profile_default, rclcpp::SubscriptionOptions options = rclcpp::SubscriptionOptions()); + /** + * \brief Constructor. + * \param node_interfaces The node interfaces used for subscribing. + * \param base_topic The base image topic name. + * \param callback User callback invoked for each received image. + * \param loader Plugin loader for subscriber plugins. + * \param transport Transport hint string. + * \param custom_qos QoS profile. + * \param options Additional subscription options. + */ IMAGE_TRANSPORT_PUBLIC Subscriber( RequiredInterfaces node_interfaces, @@ -115,12 +137,16 @@ class Subscriber IMAGE_TRANSPORT_PUBLIC void shutdown(); + /// \brief Returns non-null if this Subscriber is valid (i.e. subscribed). IMAGE_TRANSPORT_PUBLIC operator void *() const; + /// \brief Less-than comparison based on internal implementation pointer. IMAGE_TRANSPORT_PUBLIC bool operator<(const Subscriber & rhs) const {return impl_ < rhs.impl_;} + /// \brief Inequality comparison based on internal implementation pointer. IMAGE_TRANSPORT_PUBLIC bool operator!=(const Subscriber & rhs) const {return impl_ != rhs.impl_;} + /// \brief Equality comparison based on internal implementation pointer. IMAGE_TRANSPORT_PUBLIC bool operator==(const Subscriber & rhs) const {return impl_ == rhs.impl_;} diff --git a/image_transport/include/image_transport/subscriber_filter.hpp b/image_transport/include/image_transport/subscriber_filter.hpp index 976794f8..9548d88f 100644 --- a/image_transport/include/image_transport/subscriber_filter.hpp +++ b/image_transport/include/image_transport/subscriber_filter.hpp @@ -66,14 +66,13 @@ class SubscriberFilter : public message_filters::SimpleFilter Callback; /** @@ -65,7 +66,7 @@ class IMAGE_TRANSPORT_PUBLIC SubscriberPlugin * The default implementation auto-discovers the name from the pluginlib * manifest XML (without instantiating any plugin) by matching the demangled * C++ type name of \c *this against the \c type attribute of each - * \c element. The result is cached after the first call. + * \c <class> element. The result is cached after the first call. * * Plugins that override getTransportName() continue to work unchanged — * user-supplied overrides always take precedence over the base implementation. @@ -76,7 +77,7 @@ class IMAGE_TRANSPORT_PUBLIC SubscriberPlugin /** * \brief Get the primary message type used by this plugin. * - * Returns the value of the \c element from the plugin + * Returns the value of the \c <message_type> element from the plugin * manifest XML (e.g. \c "sensor_msgs/msg/Image"). The result is cached * after the first call. Override this method if you need a different * value at runtime. @@ -244,6 +245,15 @@ class IMAGE_TRANSPORT_PUBLIC SubscriberPlugin /* * \brief Subscribe to an image transport topic. Must be implemented by the subclass. */ + /** + * \brief Subscribe to a transport-specific topic (deprecated). + * \deprecated Use subscribeImpl(RequiredInterfaces, ..., rclcpp::QoS, ...) instead. + * \param node The node to subscribe on. + * \param base_topic The base image topic name. + * \param callback User callback for received images. + * \param custom_qos QoS profile (rmw form). + * \param options Additional subscription options. + */ [[deprecated("Use subscribeImpl(RequiredInterfaces node_interfaces, .., rclcpp::QoS, ...) " "instead")]] virtual void subscribeImpl( @@ -257,6 +267,14 @@ class IMAGE_TRANSPORT_PUBLIC SubscriberPlugin rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(custom_qos), custom_qos), options); } + /** + * \brief Subscribe to a transport-specific topic. Must be implemented by the subclass. + * \param node_interfaces The node interfaces used for subscribing. + * \param base_topic The base image topic name. + * \param callback User callback for received images. + * \param custom_qos QoS profile. + * \param options Additional subscription options. + */ virtual void subscribeImpl( RequiredInterfaces node_interfaces, const std::string & base_topic, diff --git a/image_transport/include/image_transport/transport_hints.hpp b/image_transport/include/image_transport/transport_hints.hpp index fb8c4aae..381f42d3 100644 --- a/image_transport/include/image_transport/transport_hints.hpp +++ b/image_transport/include/image_transport/transport_hints.hpp @@ -54,9 +54,9 @@ class TransportHints * in the node's local namespace. For consistency across ROS applications, the * name of this parameter should not be changed without good reason. * - * @param node Node to use when looking up the transport parameter. - * @param default_transport Preferred transport to use - * @param parameter_name The name of the transport parameter + * @param node_interfaces Node interfaces used to look up the transport parameter. + * @param default_transport Preferred transport to use. + * @param parameter_name The name of the transport parameter. */ IMAGE_TRANSPORT_PUBLIC TransportHints( @@ -72,6 +72,13 @@ class TransportHints } } + /** + * \brief Constructor (deprecated). + * \deprecated Use TransportHints(RequiredInterfaces, ...) instead. + * \param node The node used to look up the transport parameter. + * \param default_transport Preferred transport if the parameter is not set. + * \param parameter_name Name of the ROS parameter holding the transport choice. + */ [[deprecated("Use TransportHints(RequiredInterfaces node_interfaces, ...) instead.")]] IMAGE_TRANSPORT_PUBLIC TransportHints( @@ -82,6 +89,7 @@ class TransportHints node->get_parameter_or(parameter_name, transport_, default_transport); } + /// \brief Returns the transport name to use for subscribing. IMAGE_TRANSPORT_PUBLIC const std::string & getTransport() const { diff --git a/image_transport/package.xml b/image_transport/package.xml index f66ed525..184f8f87 100644 --- a/image_transport/package.xml +++ b/image_transport/package.xml @@ -1,13 +1,7 @@ image_transport 6.4.7 - - - image_transport should always be used to subscribe to and publish images. It provides transparent - support for transporting images in low-bandwidth compressed formats. Examples (provided by separate - plugin packages) include JPEG/PNG compression and Theora streaming video. - - + Transparent publish and subscribe for images with support for compressed transports via plugins. Michael Carroll Patrick Mihelich @@ -41,5 +35,6 @@ ament_cmake + rosdoc2.yaml diff --git a/image_transport/rosdoc2.yaml b/image_transport/rosdoc2.yaml new file mode 100644 index 00000000..0981635c --- /dev/null +++ b/image_transport/rosdoc2.yaml @@ -0,0 +1,32 @@ +## Default configuration, generated by rosdoc2. + +## This 'attic section' self-documents this file's type and version. +type: 'rosdoc2 config' +version: 1 + +--- + +settings: + always_run_doxygen: true + +builders: + ## Each stanza represents a separate build step, performed by a specific 'builder'. + + - doxygen: { + name: 'image_transport Public C/C++ API', + output_dir: 'generated/doxygen', + extra_doxyfile_statements: [ + 'PREDEFINED = DOXYGEN_SHOULD_SKIP_THIS IMAGE_TRANSPORT_PUBLIC= IMAGE_TRANSPORT_LOCAL= IMAGE_TRANSPORT_PUBLIC_TYPE= IMAGE_TRANSPORT_EXPORT= IMAGE_TRANSPORT_IMPORT=', + 'EXTRACT_ALL = YES', + 'EXTRACT_PRIVATE = NO', + 'EXTRACT_STATIC = YES', + 'ENABLE_PREPROCESSING = YES', + 'QUIET = YES' + ] + } + - sphinx: { + name: 'image_transport', + sphinx_sourcedir: doc, + doxygen_xml_directory: 'generated/doxygen/xml', + output_dir: '' + }