├── .github
└── workflows
│ └── ci.yaml
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── image_transport_tutorials
├── CMakeLists.txt
├── LICENSE
├── include
│ └── image_transport_tutorials
│ │ ├── resized_publisher.hpp
│ │ └── resized_subscriber.hpp
├── msg
│ └── ResizedImage.msg
├── package.xml
├── resized_plugins.xml
└── src
│ ├── manifest.cpp
│ ├── my_publisher.cpp
│ ├── my_subscriber.cpp
│ ├── publisher_from_video.cpp
│ ├── resized_publisher.cpp
│ └── resized_subscriber.cpp
└── image_transport_tutorials_py
├── LICENSE
├── image_transport_tutorials_py
├── __init__.py
├── my_publisher.py
└── my_subscriber.py
├── package.xml
├── resource
└── image_transport_tutorials_py
├── setup.cfg
├── setup.py
└── test
├── test_copyright.py
├── test_flake8.py
└── test_pep257.py
/.github/workflows/ci.yaml:
--------------------------------------------------------------------------------
1 | name: Build and test
2 | on:
3 | # Run this action whenever a pull request is made
4 | pull_request:
5 | push:
6 | branches:
7 | - main
8 |
9 | jobs:
10 | # Note that we pass each job a different name to distinguish each linter job
11 | image_transport_tutorials_build_rolling:
12 | name: image_transport_tutorials_build_rolling
13 | runs-on: ubuntu-latest
14 | steps:
15 | - uses: ros-tooling/setup-ros@v0.7
16 | with:
17 | required-ros-distributions: rolling
18 | - uses: ros-tooling/action-ros-ci@v0.3
19 | with:
20 | package-name: image_transport_tutorials
21 | target-ros2-distro: rolling
22 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | Any contribution that you make to this repository will
2 | be under the Apache 2 License, as dictated by that
3 | [license](http://www.apache.org/licenses/LICENSE-2.0.html):
4 |
5 | ~~~
6 | 5. Submission of Contributions. Unless You explicitly state otherwise,
7 | any Contribution intentionally submitted for inclusion in the Work
8 | by You to the Licensor shall be under the terms and conditions of
9 | this License, without any additional terms or conditions.
10 | Notwithstanding the above, nothing herein shall supersede or modify
11 | the terms of any separate license agreement you may have executed
12 | with Licensor regarding such Contributions.
13 | ~~~
14 |
15 | Contributors must sign-off each commit by adding a `Signed-off-by: ...`
16 | line to commit messages to certify that they have the right to submit
17 | the code they are contributing to the project according to the
18 | [Developer Certificate of Origin (DCO)](https://developercertificate.org/).
19 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # image_transport_tutorials
2 |
3 | # Table of Contents
4 | 1. [Installation](#installation)
5 | 2. [Writing a Simple Image Publisher (C++)](#cpp_simple_image_pub)
6 | 3. [Writing a Simple Image Subscriber (C++)](#cpp_simple_image_sub)
7 | 4. [Running the Simple Image Publisher and Subscriber with Different Transport](#different_publisher_subscriber)
8 | 5. [Writing a Simple Image Publisher (Python)](#py_simple_image_pub)
9 | 6. [Writing a Simple Image Subscriber (Python)](#py_simple_image_sub)
10 |
11 | ## Installation
12 |
13 | Before starting any of the tutorials below, create a workspace and clone this repository so you can inspect and manipulate the code:
14 |
15 | ```
16 | $ mkdir -p ~/image_transport_tutorials_ws/src
17 | $ cd ~/image_transport_tutorials_ws/src
18 | $ git clone https://github.com/ros-perception/image_transport_tutorials.git
19 | ```
20 |
21 | Install needed dependencies:
22 |
23 | ```
24 | $ cd ~/image_transport_tutorials_ws/
25 | $ source /opt/ros/iron/setup.bash
26 | $ rosdep install -i --from-path src --rosdistro iron -y
27 | $ colcon build
28 | ```
29 |
30 | Make sure to include the correct setup file (in the above example it is for Iron on Ubuntu and for bash).
31 |
32 | ## Writing a Simple Image Publisher (C++)
33 | Description: This tutorial shows how to create a publisher node that will continually publish an image.
34 |
35 | Tutorial Level: Beginner
36 |
37 | Take a look at [my_publisher.cpp](image_transport_tutorials/src/my_publisher.cpp).
38 |
39 | ### The code explained
40 | Now, let's break down the code piece by piece.
41 | 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).
42 |
43 | ```
44 | #include "cv_bridge/cv_bridge.h"
45 | #include "image_transport/image_transport.hpp"
46 | #include "opencv2/highgui/highgui.hpp"
47 | #include "rclcpp/rclcpp.hpp"
48 | ```
49 |
50 | These headers will allow us to load an image using OpenCV, convert it to the ROS message format, and publish it.
51 |
52 | ```
53 | rclcpp::Node::SharedPtr node = rclcpp::Node::make_shared("image_publisher", options);
54 | image_transport::ImageTransport it(node);
55 | ```
56 |
57 | We create an `ImageTransport` instance, initializing it with our node.
58 | 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.
59 |
60 | ```
61 | image_transport::Publisher pub = it.advertise("camera/image", 1);
62 | ```
63 |
64 | Advertise that we are going to be publishing images on the base topic `camera/image`.
65 | Depending on whether more plugins are built, additional (per-plugin) topics derived from the base topic may also be advertised.
66 | The second argument is the size of our publishing queue.
67 |
68 | `advertise()` returns an `image_transport::Publisher` object, which serves two purposes:
69 | 1. It contains a `publish()` method that lets you publish images onto the base topic it was created with
70 | 2. When it goes out of scope, it will automatically unadvertise
71 |
72 | ```
73 | cv::Mat image = cv::imread(argv[1], cv::IMREAD_COLOR);
74 | std_msgs::msg::Header hdr;
75 | sensor_msgs::msg::Image::SharedPtr msg;
76 | msg = cv_bridge::CvImage(hdr, "bgr8", image).toImageMsg();
77 | ```
78 |
79 | 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`.
80 |
81 | ```
82 | rclcpp::WallRate loop_rate(5);
83 | while (rclcpp::ok()) {
84 | pub.publish(msg);
85 | rclcpp::spin_some(node);
86 | loop_rate.sleep();
87 | }
88 | ```
89 |
90 | We broadcast the image to anyone connected to one of our topics, exactly as we would have using an `rclcpp::Publisher`.
91 |
92 | ### Adding video stream from a webcam
93 | The example above requires a path to an image file to be added as a command line parameter.
94 | This image will be converted and sent as a message to an image subscriber.
95 | In most cases, however, this is not a very practical example as you are often required to handle streaming data.
96 | (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).
97 |
98 | 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).
99 | Take a look at [publisher_from_video.cpp](image_transport_tutorials/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.
100 |
101 | If you have a single device, you do not need to do the whole routine with passing a command line argument.
102 | 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).
103 | Multiple checks are also included here to make sure that the publisher does not break if the camera is shut down.
104 | 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.
105 |
106 | ## Writing a Simple Image Subscriber (C++)
107 | Description: This tutorial shows how to create a subscriber node that will display an image on the screen.
108 | By using the `image_transport` subscriber to subscribe to images, any image transport can be used at runtime.
109 | To learn how to actually use a specific image transport, see the next tutorial.
110 |
111 | Tutorial Level: Beginner
112 |
113 | Take a look at [my_subscriber.cpp](image_transport_tutorials/src/my_subscriber.cpp).
114 |
115 | ### The code explained
116 | Now, let's break down the code piece by piece.
117 |
118 | ```
119 | #include "cv_bridge/cv_bridge.h"
120 | #include "image_transport/image_transport.hpp"
121 | #include "opencv2/highgui/highgui.hpp"
122 | #include "rclcpp/logging.hpp"
123 | #include "rclcpp/rclcpp.hpp"
124 | ```
125 |
126 | These headers will allow us to subscribe to image messages, display images using OpenCV's simple GUI capabilities, and log errors.
127 |
128 | ```
129 | void imageCallback(const sensor_msgs::msg::Image::ConstSharedPtr & msg)
130 | ```
131 |
132 | This is the callback function that will be called when a new image has arrived on the `camera/image` topic.
133 | 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.
134 | All image encoding/decoding is handled automatically for you.
135 |
136 | ```
137 | try {
138 | cv::imshow("view", cv_bridge::toCvShare(msg, "bgr8")->image);
139 | cv::waitKey(10);
140 | } catch (cv_bridge::Exception & e) {
141 | auto logger = rclcpp::get_logger("my_subscriber");
142 | RCLCPP_ERROR(logger, "Could not convert from '%s' to 'bgr8'.", msg->encoding.c_str());
143 | ```
144 |
145 | The body of the callback.
146 | We convert the ROS image message into an OpenCV image with BGR pixel encoding, then show it in a display window.
147 |
148 | ```
149 | rclcpp::Node::SharedPtr node = rclcpp::Node::make_shared("image_listener", options);
150 | image_transport::ImageTransport it(node);
151 | ```
152 |
153 | We create an `ImageTransport` instance, initializing it with our node.
154 |
155 | ```
156 | image_transport::Subscriber sub = it.subscribe("camera/image", 1, imageCallback);
157 | ```
158 |
159 | Subscribe to the `camera/image` base topic.
160 | The actual ROS topic subscribed to depends on which transport is used.
161 | In the default case, "raw" transport, the topic is `camera/image` with type `sensor_msgs/msg/Image`.
162 | ROS will call the `imageCallback` function whenever a new image arrives.
163 | The 2nd argument is the queue size.
164 |
165 | `subscribe()` returns an `image_transport::Subscriber` object that you must hold on to until you want to unsubscribe.
166 | When the Subscriber object is destructed, it will automatically unsubscribe from the `camera/image` base topic.
167 |
168 | 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.
169 |
170 | ## Running the Simple Image Publisher and Subscriber with Different Transports
171 | Description: This tutorial discusses running the simple image publisher and subscriber using multiple transports.
172 |
173 | Tutorial Level: Beginner
174 |
175 | ### Running the publisher
176 | In a previous tutorial we made a publisher node called `my_publisher`.
177 | Now run the node with an image file as the command-line argument:
178 |
179 | ```
180 | $ ros2 run image_transport_tutorials my_publisher path/to/some/image.jpg
181 | ```
182 |
183 | To check that your node is running properly, list the topics being published:
184 |
185 | ```
186 | $ ros2 topic list
187 | ```
188 |
189 | You should see `/camera/image` in the output.
190 | You can also get more information about the topic:
191 |
192 | ```
193 | $ ros2 topic info /camera/image
194 | ```
195 |
196 | The output should be:
197 |
198 | ```
199 | Type: sensor_msgs/msg/Image
200 | Publisher count: 1
201 | Subscription count: 0
202 | ```
203 |
204 | ### Running the subscriber
205 | In the last tutorial, we made a subscriber node called `my_subscriber`. Now run it:
206 |
207 | ```
208 | $ ros2 run image_transport_tutorials my_subscriber
209 | ```
210 |
211 | You should see a window pop up with the image you gave to the publisher.
212 |
213 | ### Finding available transports
214 | `image_transport` searches your ROS installation for transport plugins at runtime and dynamically loads all that are built.
215 | This affords you great flexibility in adding additional transports, but makes it unclear which are available on your system.
216 | `image_transport` provides a `list_transports` executable for this purpose:
217 |
218 | ```
219 | $ ros2 run image_transport list_transports
220 | ```
221 |
222 | Which should show:
223 |
224 | ```
225 | Declared transports:
226 | image_transport/raw
227 |
228 | Details:
229 | ----------
230 | "image_transport/raw"
231 | - Provided by package: image_transport
232 | - Publisher:
233 | This is the default publisher. It publishes the Image as-is on the base topic.
234 |
235 | - Subscriber:
236 | This is the default pass-through subscriber for topics of type sensor_msgs/Image.
237 | ```
238 |
239 | This the expected output for an otherwise new ROS installation after completing the previous tutorials.
240 | Depending on your setup, you may already have "theora" or other transports available.
241 |
242 | ### Adding new transports
243 | Our nodes are currently communicating raw `sensor_msgs/msg/Image` messages, so we are not gaining anything over using `rclcpp::Publisher` and `rclcpp::Subscriber`.
244 | Let's change that by introducing a new transport.
245 |
246 | The `compressed_image_transport` package provides plugins for the "compressed" transport, which sends images over the wire in either JPEG- or PNG-compressed form.
247 | 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.
248 |
249 | The easiest way to add the "compressed" transport is to install the package:
250 |
251 | ```
252 | $ sudo apt-get install ros-iron-compressed-image-transport
253 | ```
254 |
255 | Or install all the transport plugins at once:
256 |
257 | ```
258 | $ sudo apt-get install ros-iron-image-transport-plugins
259 | ```
260 |
261 | But you can also build from source.
262 |
263 | ### Changing the transport used
264 | Now let's start up a new subscriber, this one using compressed transport.
265 | The key is that `image_transport` subscribers check the parameter `_image_transport` for the name of a transport to use in place of "raw".
266 | Let's set this parameter and start a subscriber node with name "compressed_listener":
267 |
268 | ```
269 | $ ros2 run image_transport_tutorials my_subscriber --ros-args --remap __name:=compressed_listener -p image_transport:=compressed
270 | ```
271 |
272 | You should see an identical image window pop up.
273 |
274 | `compressed_listener` is listening to a separate topic carrying JPEG-compressed versions of the same images published on `/camera/image`.
275 |
276 | ### Changing transport-specific behavior
277 | For a particular transport, we may want to tweak settings such as compression level, bit rate, etc.
278 | Transport plugins can expose such settings through ROS parameters.
279 | For example, `/camera/image/compressed` allows you to change the compression format and quality on the fly; see the package documentation for full details.
280 |
281 | For now let's adjust the JPEG quality.
282 | By default, the "compressed" transport uses JPEG compression at 80% quality.
283 | Let's change it to 15%.
284 | We can use the GUI, `rqt_reconfigure`, to change the quality:
285 |
286 | ```
287 | $ ros2 run rqt_reconfigure rqt_reconfigure
288 | ```
289 |
290 | Now pick `/image_publisher` in the drop-down menu and move the `jpeg_quality` slider down to 15%.
291 | Do you see the compression artifacts in your second view window?
292 |
293 | The `rqt_reconfigure` GUI has updated the ROS parameter `/image_publisher/jpeg_quality`.
294 | You can verify this by running:
295 |
296 | ```
297 | $ ros2 param get /image_publisher jpeg_quality
298 | ```
299 |
300 | This should display 15.
301 |
302 | ## Writing a Simple Image Publisher (Python)
303 |
304 | Description: This tutorial shows how to create a publisher node that will continually publish an image with random contents from Python.
305 |
306 | Tutorial Level: Beginner
307 |
308 | Take a look at [my_publisher.py](image_transport_tutorials_py/image_transport_tutorials_py/my_publisher.py).
309 |
310 | To publish images using `image_transport_py`, you create an `ImageTransport` object and use it to advertise an image topic. The first parameter for `ImageTransport` is the image transport
311 | node's name which needs to be unique in the namespace.
312 |
313 | Steps:
314 |
315 | 1. Import Necessary Modules:
316 |
317 | ```python
318 | import rclpy
319 | from rclpy.node import Node
320 | from sensor_msgs.msg import Image
321 | from image_transport_py import ImageTransport
322 | ```
323 |
324 | 2. Initialize the Node and ImageTransport:
325 |
326 | ```python
327 | def __init__(self):
328 | super().__init__('my_publisher')
329 |
330 | self.image_transport = ImageTransport(
331 | 'imagetransport_pub', image_transport='compressed'
332 | )
333 | self.img_pub = self.image_transport.advertise('camera/image', 10)
334 |
335 | self.bridge = CvBridge()
336 |
337 | timer_period = 0.5
338 | self.timer = self.create_timer(timer_period, self.timer_callback)
339 | ```
340 |
341 | 3. Publish Images in the Callback:
342 | ```python
343 | def publish_image(self):
344 | image_msg = .. # Read image from your devices
345 |
346 | image_msg.header.stamp = self.get_clock().now().to_msg()
347 | self.publisher.publish(image_msg)
348 | ```
349 |
350 | `advertise_camera` can publish `CameraInfo` along with `Image` message.
351 |
352 | ## Writing a Simple Image Subscriber (Python)
353 |
354 | Description: This tutorial shows how to create a subscriber node that will receive the contents of the published
355 | image. By using the `image_transport` subscriber to subscribe to images, any image transport can be used at runtime.
356 |
357 | Tutorial Level: Beginner
358 |
359 | Take a look at [my_subscriber.py](image_transport_tutorials_py/image_transport_tutorials_py/my_subscriber.py).
360 |
361 | To subscribe to images, use `ImageTransport` to create a subscription to the image topic.
362 |
363 | Steps:
364 |
365 | 1. Import Necessary Modules:
366 |
367 | ```python
368 | import rclpy
369 | from rclpy.node import Node
370 | from image_transport_py import ImageTransport
371 |
372 | ```
373 |
374 | 2. Initialize the Node and ImageTransport:
375 | ```python
376 | class MySubscriber(Node):
377 | def __init__(self):
378 | super().__init__('my_subscriber')
379 |
380 | image_transport = ImageTransport(
381 | 'imagetransport_sub', image_transport='compressed'
382 | )
383 | image_transport.subscribe('camera/image', 10, self.image_callback)
384 | ```
385 |
386 | 3. Handle Incoming Images:
387 | ```python
388 | def image_callback(self, msg):
389 | self.get_logger().info('got a new image from frame_id:=%s' % msg.header.frame_id)
390 | ```
391 |
392 | `subscribe_camera` will add `CameraInfo` along with `Image` message for the callback.
393 |
394 | ### Transport Selection
395 |
396 | By default, `image_transport` uses the `raw` transport. You can specify a different transport by passing `image_transport` parameter to `ImageTransport`. Alternatively,
397 | you can use your own ROS2 parameter file for the imagetransport node via `launch_params_filepath` parameter.
398 |
399 |
--------------------------------------------------------------------------------
/image_transport_tutorials/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.8)
2 | project(image_transport_tutorials)
3 |
4 | # Default to C++17
5 | if(NOT CMAKE_CXX_STANDARD)
6 | set(CMAKE_CXX_STANDARD 17)
7 | endif()
8 |
9 | if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
10 | add_compile_options(-Wall -Wextra -Wpedantic)
11 | endif()
12 |
13 | find_package(ament_cmake REQUIRED)
14 | find_package(cv_bridge REQUIRED)
15 | find_package(image_transport REQUIRED)
16 | find_package(OpenCV REQUIRED COMPONENTS highgui imgcodecs imgproc videoio)
17 | find_package(pluginlib REQUIRED)
18 | find_package(rclcpp REQUIRED)
19 | find_package(rosidl_default_generators REQUIRED)
20 | find_package(sensor_msgs REQUIRED)
21 | find_package(std_msgs REQUIRED)
22 |
23 | include_directories(include)
24 |
25 | # add the resized image message
26 | set(msg_files
27 | "msg/ResizedImage.msg"
28 | )
29 | rosidl_generate_interfaces(${PROJECT_NAME}
30 | ${msg_files}
31 | DEPENDENCIES sensor_msgs
32 | )
33 |
34 | rosidl_get_typesupport_target(cpp_typesupport_target "${PROJECT_NAME}" "rosidl_typesupport_cpp")
35 |
36 | # add the publisher example
37 | add_executable(my_publisher src/my_publisher.cpp)
38 | target_link_libraries(my_publisher PRIVATE
39 | cv_bridge::cv_bridge
40 | image_transport::image_transport
41 | opencv_imgcodecs
42 | rclcpp::rclcpp
43 | )
44 |
45 | # add the subscriber example
46 | add_executable(my_subscriber src/my_subscriber.cpp)
47 | target_link_libraries(my_subscriber
48 | cv_bridge::cv_bridge
49 | image_transport::image_transport
50 | opencv_highgui
51 | rclcpp::rclcpp
52 | )
53 |
54 | # add the plugin example
55 | add_library(resized_plugins src/manifest.cpp src/resized_publisher.cpp src/resized_subscriber.cpp)
56 | target_link_libraries(resized_plugins
57 | "${cpp_typesupport_target}"
58 | cv_bridge::cv_bridge
59 | image_transport::image_transport
60 | opencv_imgproc
61 | pluginlib::pluginlib
62 | rclcpp::rclcpp
63 | "${sensor_msgs_TARGETS}"
64 | )
65 |
66 | # add the publisher from video example
67 | add_executable(publisher_from_video src/publisher_from_video.cpp)
68 | target_link_libraries(publisher_from_video
69 | cv_bridge::cv_bridge
70 | image_transport::image_transport
71 | opencv_highgui
72 | opencv_videoio
73 | rclcpp::rclcpp
74 | "${sensor_msgs_TARGETS}"
75 | "${std_msgs_TARGETS}"
76 | )
77 |
78 | # Install plugin descriptions
79 | pluginlib_export_plugin_description_file(${PROJECT_NAME} resized_plugins.xml)
80 |
81 | # Install executables
82 | install(
83 | TARGETS my_publisher my_subscriber resized_plugins publisher_from_video
84 | RUNTIME DESTINATION lib/${PROJECT_NAME}
85 | )
86 |
87 | # Install include directories
88 | install(
89 | DIRECTORY include/
90 | DESTINATION include/${PROJECT_NAME}
91 | )
92 |
93 | ament_export_include_directories(include)
94 | ament_export_dependencies(cv_bridge image_transport pluginlib rosidl_default_runtime rclcpp sensor_msgs std_msgs)
95 |
96 | if(BUILD_TESTING)
97 | find_package(ament_lint_auto REQUIRED)
98 | ament_lint_auto_find_test_dependencies()
99 | endif()
100 |
101 | ament_package()
102 |
--------------------------------------------------------------------------------
/image_transport_tutorials/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/image_transport_tutorials/include/image_transport_tutorials/resized_publisher.hpp:
--------------------------------------------------------------------------------
1 | // Copyright 2021, Open Source Robotics Foundation, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #ifndef IMAGE_TRANSPORT_TUTORIALS__RESIZED_PUBLISHER_HPP_
16 | #define IMAGE_TRANSPORT_TUTORIALS__RESIZED_PUBLISHER_HPP_
17 |
18 | #include
19 |
20 | #include "sensor_msgs/msg/image.hpp"
21 |
22 | #include "image_transport/simple_publisher_plugin.hpp"
23 | #include "image_transport_tutorials/msg/resized_image.hpp"
24 |
25 |
26 | class ResizedPublisher : public image_transport::SimplePublisherPlugin
27 |
28 | {
29 | public:
30 | virtual std::string getTransportName() const
31 | {
32 | return "resized";
33 | }
34 |
35 | protected:
36 | virtual void publish(
37 | const sensor_msgs::msg::Image & message,
38 | const PublishFn & publish_fn) const;
39 | };
40 |
41 | #endif // IMAGE_TRANSPORT_TUTORIALS__RESIZED_PUBLISHER_HPP_
42 |
--------------------------------------------------------------------------------
/image_transport_tutorials/include/image_transport_tutorials/resized_subscriber.hpp:
--------------------------------------------------------------------------------
1 | // Copyright 2021, Open Source Robotics Foundation, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #ifndef IMAGE_TRANSPORT_TUTORIALS__RESIZED_SUBSCRIBER_HPP_
16 | #define IMAGE_TRANSPORT_TUTORIALS__RESIZED_SUBSCRIBER_HPP_
17 |
18 | #include
19 |
20 | #include "image_transport/simple_subscriber_plugin.hpp"
21 | #include "image_transport_tutorials/msg/resized_image.hpp"
22 |
23 | class ResizedSubscriber : public image_transport::SimpleSubscriberPlugin
24 |
25 | {
26 | public:
27 | virtual ~ResizedSubscriber() {}
28 |
29 | virtual std::string getTransportName() const
30 | {
31 | return "resized";
32 | }
33 |
34 | protected:
35 | virtual void internalCallback(
36 | const typename image_transport_tutorials::msg::ResizedImage::ConstSharedPtr & message,
37 | const Callback & user_cb);
38 | };
39 |
40 | #endif // IMAGE_TRANSPORT_TUTORIALS__RESIZED_SUBSCRIBER_HPP_
41 |
--------------------------------------------------------------------------------
/image_transport_tutorials/msg/ResizedImage.msg:
--------------------------------------------------------------------------------
1 | uint32 original_height
2 | uint32 original_width
3 | sensor_msgs/Image image
4 |
--------------------------------------------------------------------------------
/image_transport_tutorials/package.xml:
--------------------------------------------------------------------------------
1 |
2 | image_transport_tutorials
3 | 0.0.0
4 | Tutorials for image_transport.
5 | Vincent Rabaud
6 | Jacob Perron
7 | Apache 2.0
8 |
9 | ament_cmake_ros
10 | rosidl_default_generators
11 |
12 | cv_bridge
13 | image_transport
14 | libopencv-dev
15 | sensor_msgs
16 | std_msgs
17 |
18 | rosidl_default_runtime
19 | cv_bridge
20 | image_transport
21 | libopencv-dev
22 | sensor_msgs
23 | std_msgs
24 |
25 | ament_lint_auto
26 | ament_lint_common
27 |
28 | rosidl_interface_packages
29 |
30 |
31 | ament_cmake
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/image_transport_tutorials/resized_plugins.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | This plugin publishes a decimated version of the image.
5 |
6 |
7 |
8 |
9 |
10 | This plugin rescales a decimated image to its original size.
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/image_transport_tutorials/src/manifest.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2021, Open Source Robotics Foundation, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "pluginlib/class_list_macros.hpp"
16 |
17 | #include "image_transport_tutorials/resized_publisher.hpp"
18 | #include "image_transport_tutorials/resized_subscriber.hpp"
19 |
20 | PLUGINLIB_EXPORT_CLASS(ResizedPublisher, image_transport::PublisherPlugin)
21 | PLUGINLIB_EXPORT_CLASS(ResizedSubscriber, image_transport::SubscriberPlugin)
22 |
--------------------------------------------------------------------------------
/image_transport_tutorials/src/my_publisher.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2021, Open Source Robotics Foundation, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "cv_bridge/cv_bridge.hpp"
16 | #include "image_transport/image_transport.hpp"
17 | #include "opencv2/core/mat.hpp"
18 | #include "opencv2/imgcodecs.hpp"
19 | #include "rclcpp/rclcpp.hpp"
20 |
21 | int main(int argc, char ** argv)
22 | {
23 | rclcpp::init(argc, argv);
24 | rclcpp::NodeOptions options;
25 | rclcpp::Node::SharedPtr node = rclcpp::Node::make_shared("image_publisher", options);
26 | image_transport::ImageTransport it(node);
27 | image_transport::Publisher pub = it.advertise("camera/image", 1);
28 |
29 | cv::Mat image = cv::imread(argv[1], cv::IMREAD_COLOR);
30 | std_msgs::msg::Header hdr;
31 | sensor_msgs::msg::Image::SharedPtr msg = cv_bridge::CvImage(hdr, "bgr8", image).toImageMsg();
32 |
33 | rclcpp::WallRate loop_rate(5);
34 | while (rclcpp::ok()) {
35 | pub.publish(msg);
36 | rclcpp::spin_some(node);
37 | loop_rate.sleep();
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/image_transport_tutorials/src/my_subscriber.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2021, Open Source Robotics Foundation, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "cv_bridge/cv_bridge.hpp"
16 | #include "image_transport/image_transport.hpp"
17 | #include "opencv2/highgui.hpp"
18 | #include "rclcpp/logging.hpp"
19 | #include "rclcpp/rclcpp.hpp"
20 | #include "sensor_msgs/msg/image.hpp"
21 |
22 | void imageCallback(const sensor_msgs::msg::Image::ConstSharedPtr & msg)
23 | {
24 | try {
25 | cv::imshow("view", cv_bridge::toCvShare(msg, "bgr8")->image);
26 | cv::waitKey(10);
27 | } catch (const cv_bridge::Exception & e) {
28 | auto logger = rclcpp::get_logger("my_subscriber");
29 | RCLCPP_ERROR(logger, "Could not convert from '%s' to 'bgr8'.", msg->encoding.c_str());
30 | }
31 | }
32 |
33 | int main(int argc, char ** argv)
34 | {
35 | rclcpp::init(argc, argv);
36 | rclcpp::NodeOptions options;
37 | rclcpp::Node::SharedPtr node = rclcpp::Node::make_shared("image_listener", options);
38 | // TransportHints does not actually declare the parameter
39 | node->declare_parameter("image_transport", "raw");
40 | cv::namedWindow("view");
41 | cv::startWindowThread();
42 | image_transport::ImageTransport it(node);
43 | image_transport::TransportHints hints(node.get());
44 | image_transport::Subscriber sub = it.subscribe("camera/image", 1, imageCallback, &hints);
45 | rclcpp::spin(node);
46 | cv::destroyWindow("view");
47 |
48 | return 0;
49 | }
50 |
--------------------------------------------------------------------------------
/image_transport_tutorials/src/publisher_from_video.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2021, Open Source Robotics Foundation, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include
16 |
17 | #include "cv_bridge/cv_bridge.hpp"
18 | #include "image_transport/image_transport.hpp"
19 | #include "opencv2/core/mat.hpp"
20 | #include "opencv2/highgui.hpp"
21 | #include "opencv2/videoio.hpp"
22 | #include "rclcpp/rclcpp.hpp"
23 | #include "std_msgs/msg/header.hpp"
24 |
25 | int main(int argc, char ** argv)
26 | {
27 | // Check if video source has been passed as a parameter
28 | if (argv[1] == NULL) {
29 | return 1;
30 | }
31 |
32 | rclcpp::init(argc, argv);
33 | rclcpp::NodeOptions options;
34 | rclcpp::Node::SharedPtr node = rclcpp::Node::make_shared("image_publisher", options);
35 | image_transport::ImageTransport it(node);
36 | image_transport::Publisher pub = it.advertise("camera/image", 1);
37 |
38 | // Convert the command line parameter index for the video device to an integer
39 | std::istringstream video_sourceCmd(argv[1]);
40 | int video_source;
41 |
42 | // Check if it is indeed a number
43 | if (!(video_sourceCmd >> video_source)) {
44 | return 1;
45 | }
46 |
47 | cv::VideoCapture cap(video_source);
48 | // Check if video device can be opened with the given index
49 | if (!cap.isOpened()) {
50 | return 1;
51 | }
52 | cv::Mat frame;
53 | std_msgs::msg::Header hdr;
54 | sensor_msgs::msg::Image::SharedPtr msg;
55 |
56 | rclcpp::WallRate loop_rate(5);
57 | while (rclcpp::ok()) {
58 | cap >> frame;
59 | // Check if grabbed frame is actually full with some content
60 | if (!frame.empty()) {
61 | msg = cv_bridge::CvImage(hdr, "bgr8", frame).toImageMsg();
62 | pub.publish(msg);
63 | cv::waitKey(1);
64 | }
65 |
66 | rclcpp::spin_some(node);
67 | loop_rate.sleep();
68 | }
69 |
70 | return 0;
71 | }
72 |
--------------------------------------------------------------------------------
/image_transport_tutorials/src/resized_publisher.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2021, Open Source Robotics Foundation, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "image_transport_tutorials/resized_publisher.hpp"
16 |
17 | #include
18 |
19 | #include "cv_bridge/cv_bridge.hpp"
20 | #include "opencv2/core/mat.hpp"
21 | #include "opencv2/imgproc.hpp"
22 | #include "rclcpp/logging.hpp"
23 |
24 | void ResizedPublisher::publish(
25 | const sensor_msgs::msg::Image & message,
26 | const PublishFn & publish_fn) const
27 | {
28 | cv::Mat cv_image;
29 | std::shared_ptr tracked_object;
30 | try {
31 | cv_image = cv_bridge::toCvShare(message, tracked_object, message.encoding)->image;
32 | } catch (const cv::Exception & e) {
33 | auto logger = rclcpp::get_logger("resized_publisher");
34 | RCLCPP_ERROR(
35 | logger, "Could not convert from '%s' to '%s'.",
36 | message.encoding.c_str(), message.encoding.c_str());
37 | return;
38 | }
39 |
40 | // Rescale image
41 | double subsampling_factor = 2.0;
42 | int new_width = cv_image.cols / subsampling_factor + 0.5;
43 | int new_height = cv_image.rows / subsampling_factor + 0.5;
44 | cv::Mat buffer;
45 | cv::resize(cv_image, buffer, cv::Size(new_width, new_height));
46 |
47 | // Set up ResizedImage and publish
48 | image_transport_tutorials::msg::ResizedImage resized_image;
49 | resized_image.original_height = cv_image.rows;
50 | resized_image.original_width = cv_image.cols;
51 | resized_image.image = *(cv_bridge::CvImage(message.header, "bgr8", cv_image).toImageMsg());
52 | publish_fn(resized_image);
53 | }
54 |
--------------------------------------------------------------------------------
/image_transport_tutorials/src/resized_subscriber.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2021, Open Source Robotics Foundation, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "image_transport_tutorials/resized_subscriber.hpp"
16 |
17 | #include
18 |
19 | #include "cv_bridge/cv_bridge.hpp"
20 | #include "opencv2/core/mat.hpp"
21 | #include "opencv2/imgproc.hpp"
22 |
23 | void ResizedSubscriber::internalCallback(
24 | const image_transport_tutorials::msg::ResizedImage::ConstSharedPtr & msg,
25 | const Callback & user_cb)
26 | {
27 | // This is only for optimization, not to copy the image
28 | std::shared_ptr tracked_object_tmp;
29 | cv::Mat img_rsz = cv_bridge::toCvShare(msg->image, tracked_object_tmp)->image;
30 | // Resize the image to its original size
31 | cv::Mat img_restored;
32 | cv::resize(img_rsz, img_restored, cv::Size(msg->original_width, msg->original_height));
33 |
34 | // Call the user callback with the restored image
35 | cv_bridge::CvImage cv_img(msg->image.header, msg->image.encoding, img_restored);
36 | user_cb(cv_img.toImageMsg());
37 | }
38 |
--------------------------------------------------------------------------------
/image_transport_tutorials_py/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/image_transport_tutorials_py/image_transport_tutorials_py/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ros-perception/image_transport_tutorials/05423977d55619ca8a7c586104038f1703fa766f/image_transport_tutorials_py/image_transport_tutorials_py/__init__.py
--------------------------------------------------------------------------------
/image_transport_tutorials_py/image_transport_tutorials_py/my_publisher.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | #
3 | # Copyright 2024, Open Source Robotics Foundation, Inc.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | from cv_bridge import CvBridge
18 | from image_transport_py import ImageTransport
19 | import numpy as np
20 | import rclpy
21 | from rclpy.node import Node
22 |
23 |
24 | class MyPublisher(Node):
25 | def __init__(self):
26 | super().__init__('my_publisher')
27 |
28 | self.image_transport = ImageTransport(
29 | 'imagetransport_pub', image_transport='compressed'
30 | )
31 | self.img_pub = self.image_transport.advertise('camera/image', 10)
32 |
33 | self.bridge = CvBridge()
34 |
35 | timer_period = 0.5
36 | self.timer = self.create_timer(timer_period, self.timer_callback)
37 |
38 | def timer_callback(self):
39 | original = np.uint8(np.random.randint(0, 255, size=(640, 480, 3)))
40 | image_msg = self.bridge.cv2_to_imgmsg(original, encoding='bgr8')
41 | image_msg.header.stamp = self.get_clock().now().to_msg()
42 | image_msg.header.frame_id = 'camera'
43 |
44 | self.img_pub.publish(image_msg)
45 | self.get_logger().info('Publishing image')
46 |
47 |
48 | def main(args=None):
49 | rclpy.init(args=args)
50 | node = MyPublisher()
51 |
52 | try:
53 | rclpy.spin(node)
54 | except KeyboardInterrupt:
55 | pass
56 |
57 | # Destroy the node explicitly (optional)
58 | node.destroy_node()
59 | rclpy.shutdown()
60 |
61 |
62 | if __name__ == '__main__':
63 | main()
64 |
--------------------------------------------------------------------------------
/image_transport_tutorials_py/image_transport_tutorials_py/my_subscriber.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | #
3 | # Copyright 2024, Open Source Robotics Foundation, Inc.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | from image_transport_py import ImageTransport
18 | import rclpy
19 | from rclpy.node import Node
20 |
21 |
22 | class MySubscriber(Node):
23 | def __init__(self):
24 | super().__init__('my_subscriber')
25 |
26 | image_transport = ImageTransport(
27 | 'imagetransport_sub', image_transport='compressed'
28 | )
29 | image_transport.subscribe('camera/image', 10, self.image_callback)
30 |
31 | def image_callback(self, msg):
32 | self.get_logger().info('got a new image from frame_id:=%s' % msg.header.frame_id)
33 |
34 |
35 | def main(args=None):
36 | rclpy.init(args=args)
37 | node = MySubscriber()
38 |
39 | try:
40 | rclpy.spin(node)
41 | except KeyboardInterrupt:
42 | pass
43 |
44 | # Destroy the node explicitly (optional)
45 | node.destroy_node()
46 | rclpy.shutdown()
47 |
48 |
49 | if __name__ == '__main__':
50 | main()
51 |
--------------------------------------------------------------------------------
/image_transport_tutorials_py/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | image_transport_tutorials_py
5 | 0.0.0
6 | Tutorials for image_transport_py
7 | Tamas Foldi
8 | Apache-2.0
9 |
10 | rclpy
11 | image_transport
12 | image_transport_py
13 | sensor_msgs
14 | cv_bridge
15 |
16 | ament_copyright
17 | ament_flake8
18 | ament_pep257
19 | python3-pytest
20 |
21 |
22 | ament_python
23 |
24 |
25 |
--------------------------------------------------------------------------------
/image_transport_tutorials_py/resource/image_transport_tutorials_py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ros-perception/image_transport_tutorials/05423977d55619ca8a7c586104038f1703fa766f/image_transport_tutorials_py/resource/image_transport_tutorials_py
--------------------------------------------------------------------------------
/image_transport_tutorials_py/setup.cfg:
--------------------------------------------------------------------------------
1 | [develop]
2 | script_dir=$base/lib/image_transport_tutorials_py
3 | [install]
4 | install_scripts=$base/lib/image_transport_tutorials_py
5 |
--------------------------------------------------------------------------------
/image_transport_tutorials_py/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import find_packages, setup
2 |
3 | package_name = 'image_transport_tutorials_py'
4 |
5 | setup(
6 | name=package_name,
7 | version='0.0.0',
8 | packages=find_packages(exclude=['test']),
9 | data_files=[
10 | ('share/ament_index/resource_index/packages',
11 | ['resource/' + package_name]),
12 | ('share/' + package_name, ['package.xml']),
13 | ],
14 | install_requires=['setuptools', 'rclpy', 'image_transport_py'],
15 | zip_safe=True,
16 | maintainer='tamas.foldi',
17 | maintainer_email='tfoldi@xsi.hu',
18 | description='Tutorials for image_transport_py',
19 | license='Apache-2.0',
20 | tests_require=['pytest'],
21 | entry_points={
22 | 'console_scripts': [
23 | 'my_publisher = image_transport_tutorials_py.my_publisher:main',
24 | 'my_subscriber = image_transport_tutorials_py.my_subscriber:main',
25 | ],
26 | },
27 | )
28 |
--------------------------------------------------------------------------------
/image_transport_tutorials_py/test/test_copyright.py:
--------------------------------------------------------------------------------
1 | # Copyright 2024 Open Source Robotics Foundation, Inc.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | from ament_copyright.main import main
16 | import pytest
17 |
18 |
19 | # Remove the `skip` decorator once the source file(s) have a copyright header
20 | @pytest.mark.skip(reason='No copyright header has been placed in the generated source file.')
21 | @pytest.mark.copyright
22 | @pytest.mark.linter
23 | def test_copyright():
24 | rc = main(argv=['.', 'test'])
25 | assert rc == 0, 'Found errors'
26 |
--------------------------------------------------------------------------------
/image_transport_tutorials_py/test/test_flake8.py:
--------------------------------------------------------------------------------
1 | # Copyright 2024 Open Source Robotics Foundation, Inc.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | from ament_flake8.main import main_with_errors
16 | import pytest
17 |
18 |
19 | @pytest.mark.flake8
20 | @pytest.mark.linter
21 | def test_flake8():
22 | rc, errors = main_with_errors(argv=[])
23 | assert rc == 0, \
24 | 'Found %d code style errors / warnings:\n' % len(errors) + \
25 | '\n'.join(errors)
26 |
--------------------------------------------------------------------------------
/image_transport_tutorials_py/test/test_pep257.py:
--------------------------------------------------------------------------------
1 | # Copyright 2024 Open Source Robotics Foundation, Inc.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | from ament_pep257.main import main
16 | import pytest
17 |
18 |
19 | @pytest.mark.linter
20 | @pytest.mark.pep257
21 | def test_pep257():
22 | rc = main(argv=['.', 'test'])
23 | assert rc == 0, 'Found code style errors / warnings'
24 |
--------------------------------------------------------------------------------