From 2dda726d3ec63968b233698b965b710b07ba6947 Mon Sep 17 00:00:00 2001 From: Oleg Kalachev Date: Mon, 31 Oct 2022 02:32:45 +0600 Subject: [PATCH 1/6] clover.launch: turn on disable_on_vpe by default --- clover/launch/clover.launch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clover/launch/clover.launch b/clover/launch/clover.launch index 8c77a0f4..d438bad5 100644 --- a/clover/launch/clover.launch +++ b/clover/launch/clover.launch @@ -45,7 +45,7 @@ - + From 45042cd6f51e60805847cf8f2222c9db00169ba7 Mon Sep 17 00:00:00 2001 From: Oleg Kalachev Date: Fri, 4 Nov 2022 03:05:59 +0600 Subject: [PATCH 2/6] docs: updates to camera and computer vision article --- docs/en/camera.md | 60 +++++++++++++++++++++++++---------------------- docs/ru/camera.md | 60 +++++++++++++++++++++++++---------------------- 2 files changed, 64 insertions(+), 56 deletions(-) diff --git a/docs/en/camera.md b/docs/en/camera.md index ba0dbd3a..a4079a45 100644 --- a/docs/en/camera.md +++ b/docs/en/camera.md @@ -14,7 +14,7 @@ The `clover` service must be restarted after the launch-file has been edited: sudo systemctl restart clover ``` -You may use rqt or [web_video_server](web_video_server.md) to view the camera stream. +You may use [rqt](rviz.md) or [web_video_server](web_video_server.md) to view the camera stream. ## Troubleshooting @@ -52,8 +52,6 @@ The [SD card image](image.md) comes with a preinstalled [OpenCV](https://opencv. ### Python -Main article: http://wiki.ros.org/cv_bridge/Tutorials/ConvertingBetweenROSImagesAndOpenCVImagesPython. - An example of creating a subscriber for a topic with an image from the main camera for processing with OpenCV: ```python @@ -61,12 +59,14 @@ import rospy import cv2 from sensor_msgs.msg import Image from cv_bridge import CvBridge +from clover import long_callback -rospy.init_node('computer_vision_sample') +rospy.init_node('cv') bridge = CvBridge() +@long_callback def image_callback(data): - cv_image = bridge.imgmsg_to_cv2(data, 'bgr8') # OpenCV image + img = bridge.imgmsg_to_cv2(data, 'bgr8') # OpenCV image # Do any image processing with cv2... image_sub = rospy.Subscriber('main_camera/image_raw', Image, image_callback) @@ -74,19 +74,31 @@ image_sub = rospy.Subscriber('main_camera/image_raw', Image, image_callback) rospy.spin() ``` +> **Note** Image processing may take significant time to finish. This can cause an [issue](https://github.com/ros/ros_comm/issues/1901) in rospy library, which would lead to processing stale camera frames. To solve this problem you need to use `long_callback` decorator from `clover` library, as in the example above. + +#### Limiting CPU usage + +When using the `main_camera/image_raw` topic, the script will process the maximum number of frames from the camera, actively utilizing the CPU (up to 100%). In tasks, where processing each camera frame is not critical, you can use the topic, where the frames are published at rate 5 Hz: `main_camera/image_raw_throttled`: + +```python +image_sub = rospy.Subscriber('main_camera/image_raw_throttled', Image, image_callback, queue_size=1) +``` + +#### Publishing images + To debug image processing, you can publish a separate topic with the processed image: ```python image_pub = rospy.Publisher('~debug', Image) ``` -Publishing the processed image (at the end of the image_callback function): +Publishing the processed image: ```python -image_pub.publish(bridge.cv2_to_imgmsg(cv_image, 'bgr8')) +image_pub.publish(bridge.cv2_to_imgmsg(img, 'bgr8')) ``` -The obtained images can be viewed using [web_video_server](web_video_server.md). +The published images can be viewed using [web_video_server](web_video_server.md) or [rqt](rviz.md). #### Retrieving one frame @@ -97,7 +109,7 @@ import rospy from sensor_msgs.msg import Image from cv_bridge import CvBridge -rospy.init_node('computer_vision_sample') +rospy.init_node('cv') bridge = CvBridge() # ... @@ -119,40 +131,32 @@ QR codes recognition in Python: ```python import rospy from pyzbar import pyzbar +import cv2 from cv_bridge import CvBridge from sensor_msgs.msg import Image +from clover import long_callback +rospy.init_node('cv') bridge = CvBridge() -rospy.init_node('barcode_test') - -# Image subscriber callback function -def image_callback(data): - cv_image = bridge.imgmsg_to_cv2(data, 'bgr8') # OpenCV image - barcodes = pyzbar.decode(cv_image) +@long_callback +def image_callback(msg): + img = bridge.imgmsg_to_cv2(msg, 'bgr8') + barcodes = pyzbar.decode(img) for barcode in barcodes: - b_data = barcode.data.decode("utf-8") + b_data = barcode.data.decode('utf-8') b_type = barcode.type (x, y, w, h) = barcode.rect xc = x + w/2 yc = y + h/2 - print("Found {} with data {} with center at x={}, y={}".format(b_type, b_data, xc, yc)) + print('Found {} with data {} with center at x={}, y={}'.format(b_type, b_data, xc, yc)) -image_sub = rospy.Subscriber('main_camera/image_raw', Image, image_callback, queue_size=1) +image_sub = rospy.Subscriber('main_camera/image_raw_throttled', Image, image_callback, queue_size=1) rospy.spin() ``` -The script will take up to 100% CPU capacity. To slow down the script artificially, you can use [throttling](http://wiki.ros.org/topic_tools/throttle) of frames from the camera, for example, at 5 Hz (`main_camera.launch`): - -> **Note** Starting from [image](image.md) version **0.24** `image_raw_throttled` topic is available without addition configuration. - -```xml - -``` - -The topic for the subscriber in this case should be changed for `main_camera/image_raw_throttled`. +> **Hint** See other computer vision examples in the `~/examples` directory of the [RPi image](image.md). ## Video recording diff --git a/docs/ru/camera.md b/docs/ru/camera.md index 0f9b6a14..ea4082c6 100644 --- a/docs/ru/camera.md +++ b/docs/ru/camera.md @@ -54,8 +54,6 @@ raspistill -o test.jpg ### Python -Основная статья: http://wiki.ros.org/cv_bridge/Tutorials/ConvertingBetweenROSImagesAndOpenCVImagesPython. - Пример создания подписчика на топик с изображением с основной камеры для обработки с использованием OpenCV: ```python @@ -63,12 +61,14 @@ import rospy import cv2 from sensor_msgs.msg import Image from cv_bridge import CvBridge +from clover import long_callback -rospy.init_node('computer_vision_sample') +rospy.init_node('cv') bridge = CvBridge() +@long_callback def image_callback(data): - cv_image = bridge.imgmsg_to_cv2(data, 'bgr8') # OpenCV image + img = bridge.imgmsg_to_cv2(data, 'bgr8') # OpenCV image # Do any image processing with cv2... image_sub = rospy.Subscriber('main_camera/image_raw', Image, image_callback) @@ -76,19 +76,31 @@ image_sub = rospy.Subscriber('main_camera/image_raw', Image, image_callback) rospy.spin() ``` +> **Note** Обработка изображения может занимать значительное время. Это может вызвать [проблему](https://github.com/ros/ros_comm/issues/1901) в библиотеке rospy, которая приведет к обработке устаревших кадров с камеры. Для решения этой проблемы необходимо использовать декоратор `long_callback` из библиотеки `clover`, как в примере выше. + +#### Ограничение использования CPU + +При использовании топика `main_camera/image_raw` скрипт будет обрабатывать максимальное количество кадров с камеры, активно используя CPU (вплоть до 100%). В задачах, где обработка каждого кадра не критична, можно использовать топик, где кадры публикуются с частотой 5 Гц: `main_camera/image_raw_throttled`: + +```python +image_sub = rospy.Subscriber('main_camera/image_raw_throttled', Image, image_callback, queue_size=1) +``` + +#### Публикация изображений + Для отладки обработки изображения можно публиковать отдельный топик с обработанным изображением: ```python image_pub = rospy.Publisher('~debug', Image) ``` -Публикация обработанного изображения (в конце функции image_callback): +Публикация обработанного изображения: ```python -image_pub.publish(bridge.cv2_to_imgmsg(cv_image, 'bgr8')) +image_pub.publish(bridge.cv2_to_imgmsg(img, 'bgr8')) ``` -Получаемые изображения можно просматривать используя [web_video_server](web_video_server.md). +Получаемые изображения можно просматривать используя [web_video_server](web_video_server.md) или [rqt](rviz.md). #### Получение одного кадра @@ -99,12 +111,12 @@ import rospy from sensor_msgs.msg import Image from cv_bridge import CvBridge -rospy.init_node('computer_vision_sample') +rospy.init_node('cv') bridge = CvBridge() # ... -# Получение кадра: +# Retrieve a frame: img = bridge.imgmsg_to_cv2(rospy.wait_for_message('main_camera/image_raw', Image), 'bgr8') ``` @@ -121,40 +133,32 @@ img = bridge.imgmsg_to_cv2(rospy.wait_for_message('main_camera/image_raw', Image ```python import rospy from pyzbar import pyzbar +import cv2 from cv_bridge import CvBridge from sensor_msgs.msg import Image +from clover import long_callback +rospy.init_node('cv') bridge = CvBridge() -rospy.init_node('barcode_test') - -# Image subscriber callback function -def image_callback(data): - cv_image = bridge.imgmsg_to_cv2(data, 'bgr8') # OpenCV image - barcodes = pyzbar.decode(cv_image) +@long_callback +def image_callback(msg): + img = bridge.imgmsg_to_cv2(msg, 'bgr8') + barcodes = pyzbar.decode(img) for barcode in barcodes: - b_data = barcode.data.decode("utf-8") + b_data = barcode.data.decode('utf-8') b_type = barcode.type (x, y, w, h) = barcode.rect xc = x + w/2 yc = y + h/2 - print("Found {} with data {} with center at x={}, y={}".format(b_type, b_data, xc, yc)) + print('Found {} with data {} with center at x={}, y={}'.format(b_type, b_data, xc, yc)) -image_sub = rospy.Subscriber('main_camera/image_raw', Image, image_callback, queue_size=1) +image_sub = rospy.Subscriber('main_camera/image_raw_throttled', Image, image_callback, queue_size=1) rospy.spin() ``` -Скрипт будет занимать 100% процессора. Для искусственного замедления работы скрипта можно запустить [throttling](http://wiki.ros.org/topic_tools/throttle) кадров с камеры, например, в 5 Гц (`main_camera.launch`): - -> **Note** Начиная с версии [образа](image.md) **0.24** топик `image_raw_throttled` доступен без дополнительной конфигурации. - -```xml - -``` - -Топик для подписчика в этом случае необходимо поменять на `main_camera/image_raw_throttled`. +> **Hint** Смотрите другие примеры по работе с компьютерным зрением в каталоге `~/examples` [образа для RPi](image.md). ## Запись видео From 976c7114e5b6ff0a22fb74d2326ecd40e9eab6c1 Mon Sep 17 00:00:00 2001 From: Oleg Kalachev Date: Sat, 26 Nov 2022 21:58:44 +0100 Subject: [PATCH 3/6] docs: update motion capture project link --- docs/en/copterhack2023.md | 2 +- docs/ru/copterhack2023.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/en/copterhack2023.md b/docs/en/copterhack2023.md index 89284d3a..d53ca911 100644 --- a/docs/en/copterhack2023.md +++ b/docs/en/copterhack2023.md @@ -22,7 +22,7 @@ The proposed projects are supposed to be open-source and be compatible with the ||🇰🇬 LiveSavers|[LiveSavers](https://github.com/Sarvar00/clover/blob/livesavers/docs/ru/livesaver.md)|| ||🇷🇺 C305|[Система радио-навигации](https://github.com/Lukerrr/clover-c305/blob/nav_beacon/docs/ru/nav-beacon.md)|| ||🇷🇺 XenCOM|[Bound by fate](https://github.com/xenkek/clover/blob/xenkek-patch-1/docs/ru/bound_by_fate.md)|| -||🇨🇦 Clover with Motion Capture System|[Clover with Motion Capture System](https://github.com/ssmith-81/clover/blob/MoCap_Clover/docs/en/MoCap-Clover)|| +||🇨🇦 Clover with Motion Capture System|[Clover with Motion Capture System](https://github.com/ssmith-81/clover/blob/MoCap_Clover/docs/en/mocap_clover.md)|| ||🇧🇷 Atena|[Swarm in Blocks 2](https://github.com/Grupo-SEMEAR-USP/clover/blob/swarm_in_blocks_2/docs/en/swarm_in_blocks_2.md)|| ||🇧🇾 FTL|[Advanced Clover 2](https://github.com/FTL-team/clover/blob/FTL-advancedClover3/docs/ru/advanced_clover_simulator_platform.md)|| ||🇷🇺 Лицей №128|[Платформа для зарядки квадрокоптера](https://github.com/Juli-Shvetsova/clover/blob/liceu128-1/docs/ru/liceu128.md)|| diff --git a/docs/ru/copterhack2023.md b/docs/ru/copterhack2023.md index a3225844..0d3ca4af 100644 --- a/docs/ru/copterhack2023.md +++ b/docs/ru/copterhack2023.md @@ -22,7 +22,7 @@ CopterHack 2023 — это международный конкурс по ра ||🇰🇬 LiveSavers|[LiveSavers](https://github.com/Sarvar00/clover/blob/livesavers/docs/ru/livesaver.md)|| ||🇷🇺 C305|[Система радио-навигации](https://github.com/Lukerrr/clover-c305/blob/nav_beacon/docs/ru/nav-beacon.md)|| ||🇷🇺 XenCOM|[Bound by fate](https://github.com/xenkek/clover/blob/xenkek-patch-1/docs/ru/bound_by_fate.md)|| -||🇨🇦 Clover with Motion Capture System|[Clover with Motion Capture System](https://github.com/ssmith-81/clover/blob/MoCap_Clover/docs/en/MoCap-Clover)|| +||🇨🇦 Clover with Motion Capture System|[Clover with Motion Capture System](https://github.com/ssmith-81/clover/blob/MoCap_Clover/docs/en/mocap_clover.md)|| ||🇧🇷 Atena|[Swarm in Blocks 2](https://github.com/Grupo-SEMEAR-USP/clover/blob/swarm_in_blocks_2/docs/en/swarm_in_blocks_2.md)|| ||🇧🇾 FTL|[Advanced Clover 2](https://github.com/FTL-team/clover/blob/FTL-advancedClover3/docs/ru/advanced_clover_simulator_platform.md)|| ||🇷🇺 Лицей №128|[Платформа для зарядки квадрокоптера](https://github.com/Juli-Shvetsova/clover/blob/liceu128-1/docs/ru/liceu128.md)|| From f3aadd11eca00da838fce357e751a7810dcd6361 Mon Sep 17 00:00:00 2001 From: "murata,katsutoshi" Date: Tue, 6 Dec 2022 06:01:28 +0900 Subject: [PATCH 4/6] docs: change the item name in summary (#480) --- docs/en/SUMMARY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/SUMMARY.md b/docs/en/SUMMARY.md index ab2c3239..1dd04778 100644 --- a/docs/en/SUMMARY.md +++ b/docs/en/SUMMARY.md @@ -36,7 +36,7 @@ * [Optical Flow](optical_flow.md) * [Autonomous flight (OFFBOARD)](simple_offboard.md) * [Coordinate systems (frames)](frames.md) - * [Code snippets](snippets.md) + * [Code examples](snippets.md) * [Interfacing with a laser rangefinder](laser.md) * [LED strip](leds.md) * [Working with GPIO](gpio.md) From 3b930d48d23a6a781c9cb159347cf1ac2530b124 Mon Sep 17 00:00:00 2001 From: Oleg Kalachev Date: Wed, 21 Dec 2022 11:34:04 +0300 Subject: [PATCH 5/6] Update build passing badge in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0f9c156a..2e695db1 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Clover drone is used on a wide range of educational events, including [Copter Ha Preconfigured image for Raspberry Pi with installed and configured software, ready to fly, is available [in the Releases section](https://github.com/CopterExpress/clover/releases). -![GitHub Workflow Status](https://img.shields.io/github/workflow/status/CopterExpress/clover/CI) +![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/CopterExpress/clover/build-image.yaml?branch=master) ![GitHub all releases](https://img.shields.io/github/downloads/CopterExpress/clover/total) Image features: From 460c3fdbe15c400dece9a73259db3d4d2d6736d8 Mon Sep 17 00:00:00 2001 From: Oleg Kalachev Date: Wed, 21 Dec 2022 20:49:46 +0300 Subject: [PATCH 6/6] Whitespaces fixes --- clover/examples/camera.py | 2 +- clover_blocks/www/python.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clover/examples/camera.py b/clover/examples/camera.py index 9f69d6de..33532146 100644 --- a/clover/examples/camera.py +++ b/clover/examples/camera.py @@ -5,7 +5,7 @@ # - cuts out a central square from the camera image; # - publishes this cropped image to the topic `/cv/center`; # - computes the average color of it; -# - prints its name to the console. +# - prints its name to the console. import rospy import cv2 diff --git a/clover_blocks/www/python.js b/clover_blocks/www/python.js index 1589cfdf..9cf67938 100644 --- a/clover_blocks/www/python.js +++ b/clover_blocks/www/python.js @@ -81,7 +81,7 @@ function generateROSDefinitions() { code += `get_telemetry = rospy.ServiceProxy('get_telemetry', srv.GetTelemetry)\n`; code += `navigate = rospy.ServiceProxy('navigate', srv.Navigate)\n`; if (rosDefinitions.navigateGlobal) { - code += `navigate_global = rospy.ServiceProxy('navigate_global', srv.NavigateGlobal)\n`; + code += `navigate_global = rospy.ServiceProxy('navigate_global', srv.NavigateGlobal)\n`; } if (rosDefinitions.setVelocity) { code += `set_velocity = rospy.ServiceProxy('set_velocity', srv.SetVelocity)\n`;