【ROS2】使用摄像头功能包 usb_cam

news2024/11/24 19:38:56

1、准备工作

因为本人使用VirtualBox虚拟机运行的ROS2,所以首先要让摄像头可以在虚拟机中运行

1.1 安装VirtualBox扩展包

1)下载地址:https://www.virtualbox.org/wiki/Downloads,注意扩展包的版本要和虚拟机的版本匹配

在这里插入图片描述
2)安装
打开虚拟机 ——》工具 ——》扩展 ——》安装

在这里插入图片描述
3)安装成功

在这里插入图片描述

1.2 在虚拟机中添加摄像头

在这里插入图片描述

1.3 测试摄像头

1)查看摄像头节点

~$ ls /dev/video* 
/dev/video0  /dev/video1

2)使用ffplay测试

ffplay /dev/video0

在这里插入图片描述

2、安装usb_cam

安装命令如下,注意本人的Ubuntu版本是22.04,对应ROS2版本为humble

sudo apt install ros-humble-usb-cam

在这里插入图片描述

3、命令测试

1)启动摄像头及显示

~$ ros2 launch usb_cam demo_launch.py
[INFO] [launch]: All log files can be found below /home/laoer/.ros/log/2023-06-09-10-03-47-100527-laoer-VirtualBox-8264
[INFO] [launch]: Default logging verbosity is set to INFO
/opt/ros/humble/share/usb_cam/config/params.yaml
……

从打印信息可以看出,摄像头相关参数的配置文件路径:/opt/ros/humble/share/usb_cam/config/params.yaml

2)只启动摄像头节点

ros2 run usb_cam usb_cam_node_exe --ros-args --params-file /opt/ros/humble/share/usb_cam/config/params.yaml

3)使用rqt_image_view显示图像
下载,注意版本,本人的ROS2版本为humble

sudo apt install ros-humble-rqt-image-view

在这里插入图片描述

4、编程测试

4.1 python编程测试

1)进入功能包源码目录(根据自己的环境创建)

cd ~/ros/eg/src/py

2)创建功能包

ros2 pkg create --build-type ament_python camera

3)编辑源码

cd camera
vi topic_camera_sub.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import rclpy                            # ROS2 Python接口库
from rclpy.node import Node             # ROS2 节点类
from sensor_msgs.msg import Image       # 图像消息类型
from cv_bridge import CvBridge          # ROS与OpenCV图像转换类
import cv2                              # Opencv图像处理库

class ImageSubscriber(Node):
    def __init__(self, name):
        super().__init__(name)                                  # ROS2节点父类初始化
        self.sub = self.create_subscription(
            Image, 'image_raw', self.listener_callback, 10)     # 创建订阅者对象(消息类型、话题名、订阅者回调函数、队列长度)
    self.cv_bridge = CvBridge()                             # 创建一个图像转换对象,用于OpenCV图像与ROS的图像消息的互相转换

def show(self, image):
    cv2.imshow("camera", image)                             # 使用OpenCV显示图像效果
    cv2.waitKey(10)

def listener_callback(self, data):
    self.get_logger().info('Receiving video frame')         # 输出日志信息,提示已进入回调函数
    image = self.cv_bridge.imgmsg_to_cv2(data, 'bgr8')      # 将ROS的图像消息转化成OpenCV图像
    self.show(image)                               

def main(args=None):                                        # ROS2节点主入口main函数
    rclpy.init(args=args)                                   # ROS2 Python接口初始化
    node = ImageSubscriber("topic_webcam_sub")              # 创建ROS2节点对象并进行初始化
    rclpy.spin(node)                                        # 循环等待ROS2退出
    node.destroy_node()                                     # 销毁节点对象
    rclpy.shutdown()                                        # 关闭ROS2 Python接口

4)修改配置
修改setup.py,添加入口
在entry_points中添加

'topic_camera_sub= camera.topic_camera_sub:main',

完整的setup.py如下

~/ros/eg/src/py/camera$ cat setup.py 
from setuptools import setup
package_name = 'camera'
setup(
    name=package_name,
    version='0.0.0',
    packages=[package_name],
    data_files=[
        ('share/ament_index/resource_index/packages',
            ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
    ],
    install_requires=['setuptools'],
    zip_safe=True,
    maintainer='laoer',
    maintainer_email='laoer@todo.todo',
    description='TODO: Package description',
    license='TODO: License declaration',
    tests_require=['pytest'],
    entry_points={
        'console_scripts': [
		'topic_camera_sub= camera.topic_camera_sub:main',
        ],
    },
)

5)编译
注意:在项目根目录中编译

cd ~/ros/eg
colcon build

6)运行
在终端1中启动摄像头

ros2 run usb_cam usb_cam_node_exe --ros-args --params-file /opt/ros/humble/share/usb_cam/config/params.yaml

在终端2中启动测试程序

cd ~/ros/eg
source install/setup.sh
ros2 run camera topic_camera_sub

4.2 c++编程测试

1)进入功能包源码目录(根据自己的环境创建)

cd ~/ros/eg/src/cpp

2)创建功能包

ros2 pkg create --build-type ament_cmake cpp_camera  --dependencies rclcpp OpenCV sensor_msgs cv_bridge

3)编辑源码

cd cpp_camera/src
vi camera_sub.cpp
#include <memory>
#include <opencv2/opencv.hpp>

#include "rclcpp/rclcpp.hpp"
#include "sensor_msgs/msg/image.hpp"
#include "cv_bridge/cv_bridge.h"

// std::bind占位符引用
using std::placeholders::_1;

class CameraSub : public rclcpp::Node
{
  public:
    CameraSub()
    : Node("cpp_camera_subscriber")
    {
      # a) 初始化订阅者,使用消息类型Image、主题名称image_raw */
      subscription_ = this->create_subscription<sensor_msgs::msg::Image>(
      "image_raw", 10, std::bind(&CameraSub::topic_callback, this, _1));
    }

  private:
    void topic_callback(const sensor_msgs::msg::Image & img) const
    {
      RCLCPP_INFO(this->get_logger(), "Receiving video frame");
      # b)cv_bridge::toCvCopy:Image 话题消息转 opencv 的 cv::Mat
      cv::imshow("camera", cv_bridge::toCvCopy(img, sensor_msgs::image_encodings::BGR8).get()->image);
      cv::waitKey(10);
    }

    rclcpp::Subscription<sensor_msgs::msg::Image>::SharedPtr subscription_;
};

int main(int argc, char * argv[])
{
  rclcpp::init(argc, argv);

  // 创建并运行
  rclcpp::spin(std::make_shared<CameraSub>());

  rclcpp::shutdown();
  return 0;
}

4)配置
修改CMakeLists.txt
添加引用

find_package(rclcpp REQUIRED)
find_package(sensor_msgs REQUIRED)
find_package(OpenCV REQUIRED)
find_package(cv_bridge REQUIRED)

生成可执行文件(使用对应的源码文件和依赖)

add_executable(camera_sub src/camera_sub.cpp)
ament_target_dependencies(camera_sub rclcpp sensor_msgs OpenCV cv_bridge)

添加安装规则

install(TARGETS
  camera_sub  
  DESTINATION lib/${PROJECT_NAME})

完整CM艾克List.txt如下

cmake_minimum_required(VERSION 3.8)
project(cpp_camera)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

find_package(ament_cmake REQUIRED)

find_package(rclcpp REQUIRED)
find_package(sensor_msgs REQUIRED)
find_package(OpenCV REQUIRED)
find_package(cv_bridge REQUIRED)

if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  set(ament_cmake_copyright_FOUND TRUE)
  set(ament_cmake_cpplint_FOUND TRUE)
  ament_lint_auto_find_test_dependencies()
endif()

add_executable(camera_sub src/camera_sub.cpp)
ament_target_dependencies(camera_sub rclcpp sensor_msgs OpenCV cv_bridge)

install(TARGETS
  camera_sub  
  DESTINATION lib/${PROJECT_NAME})

ament_package()

修改package.xml,添加依赖

  <depend>rclcpp</depend>
  <depend>OpenCV</depend>
  <depend>sensor_msgs</depend>
  <depend>cv_bridge</depend>

5)编译
注意:在项目根目录中编译

cd ~/ros/eg
colcon build

6)运行
在终端1中启动摄像头

ros2 run usb_cam usb_cam_node_exe --ros-args --params-file /opt/ros/humble/share/usb_cam/config/params.yaml

在终端2中启动测试程序

cd ~/ros/eg
source install/setup.sh
ros2 run cpp_camera camera_sub

5、话题消息

5.1 原始未压缩图像 ImageRaw

1)python数据描述
class Image_

    _fields_and_field_types = {
        'header': 	'std_msgs/Header',	// 话题消息队列头
        'height': 	'uint32',			// 图像高(单位像素)
        'width': 	'uint32',			// 图像宽(单位像素)
        'encoding':	'string',			// 像素格式,如“bgr8”
        'is_bigendian': 'uint8',		// 数据大小端字节序
        'step': 	'uint32',			// 步长(图像宽,单位字节)
        'data': 	'sequence<uint8>',	// 图像数据
    }

2)C++中的描述
C++中encoding(像素格式)定义在名字空间 sensor_msgs::image_encodings 中,如:

namespace sensor_msgs
{
namespace image_encodings
{
	const char RGB8[] = "rgb8";
	const char RGBA8[] = "rgba8";
	const char RGB16[] = "rgb16";
	……

sensor_msgs::msg::Image_

this->header 	= const std_msgs::msg::Header_……
this->height 	= 0ul;
this->width 	= 0ul;
this->encoding 	= "";
this->is_bigendian = 0;
this->step 		= 0ul;
this->data 		= std::vector<uint8_t……

5.2 压缩图像 CompressedImage

压缩格式支持:jpeg、png、tiff
1)python

_fields_and_field_types = {
    'header': 'std_msgs/Header',
    'format': 'string',
    'data': 'sequence<uint8>',
}

2)C++

this->header	= const std_msgs::msg::Header_……
this->format	= ""; // 可选值:jpeg、png、tiff
this->data		= std::vector<uint8_t……

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/628059.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《C++高级编程》读书笔记(七:内存管理)

1、参考引用 C高级编程&#xff08;第4版&#xff0c;C17标准&#xff09;马克葛瑞格尔 2、建议先看《21天学通C》 这本书入门&#xff0c;笔记链接如下 21天学通C读书笔记&#xff08;文章链接汇总&#xff09; 1. 使用动态内存 1.1 如何描绘内存 在本书中&#xff0c;内存单…

Tik Tok的海外娱乐公会(中亚、巴西、美国、台湾)怎么申请?

TIKTOK 公会海外市场潜力巨大 自 2016 年始&#xff0c;多家直播平台陆续拓展至东南亚、中东、俄罗斯、日韩、 欧美、拉美等地区 海外市场作为直播发展新蓝海&#xff0c;2021 年直播行业整体规模达百亿美元&#xff0c; 并维持高速增长 TikTok 直播市场空间 TikTok 已经成…

Python3+Selenium2完整的自动化测试实现之旅(七):完整的轻量级自动化框架实现

一、前言 前面系列Python3Selenium2自动化系列博文&#xff0c;陆陆续续总结了自动化环境最基础环境的搭建、IE和Chrome浏览器驱动配置、selenium下的webdriver模块提供的元素定位和操作鼠标、键盘、警示框、浏览器cookie、多窗口切换等场景的方法、web自动化测试框架、python面…

如何系统的学习robo-gym

提醒&#xff1a;以下内容仅做参考&#xff0c;可自行发散。在发布作品前&#xff0c;请把不需要的内容删掉。无论是初学者还是有经验的专业人士&#xff0c;在学习一门新的IT技术时&#xff0c;都需要采取一种系统性的学习方法。那么作为一名技术er&#xff0c;你是如何系统的…

OpenPCDet安装、使用方式及自定义数据集训练

OpenPCDet安装、使用方式及自定义数据集训练 个人博客 OpenPCDet安装 # 先根据自己的cuda版本&#xff0c;安装对应的spconv pip install spconv-cu113# 下载OpenPCDet并安装 git clone https://github.com/open-mmlab/OpenPCDet.git cd OpenPCDet pip install -r requireme…

Jetpack Compose 中安全地消耗Flow

Jetpack Compose 中安全地消耗Flow 以 Lifecycle 为周期的方式收集流是在 Android 上收集流的推荐方式。如果您正在使用 Jetpack Compose 构建 Android 应用程序&#xff0c;则使用 collectAsStateWithLifecycle API 可以在 Lifecycle 为周期的方式下从您的 UI 中收集流。 co…

利用Jmeter做接口测试(功能测试)全流程分析

利用Jmeter做接口测试怎么做呢&#xff1f;过程真的是超级简单。 明白了原理以后&#xff0c;把零碎的知识点填充进去就可以了。所以在学习的过程中&#xff0c;不管学什么&#xff0c;我一直都强调的是要循序渐进&#xff0c;和明白原理和逻辑。这篇文章就来介绍一下如何利用…

CP2102 USB转UART国产桥接芯片 DPU02

芯片概述: DPU02是一个高度集成的USB转UART的桥接控制器&#xff0c;该产品提供了一个简单的解决方案&#xff0c;可将RS-232设计更新为USB设计&#xff0c;并简化PCB组件空间。该DPU02包括了一个USB2.0全速功能控制器、USB收发器、振荡器、EEPROM和带有完整调制解调控制信号的…

通过宝塔辅助部署本地Python爬虫项目到阿里云轻量服务器

文章目录 一、 上传项目文件二、准备项目环境2.1、安装 requirements.txt 依赖2.2、安装 node.js 环境2.3、阿里云服务器MySQL 8.0开启远程连接2.4、本地远程连接MySQL测试2.4.1、navicat 远程连接测试2.4.2、python 代码连接测试 笔记&#xff1a;最近想把本地的一套爬虫项目给…

SpringBoot——启动源码(一)

SpringBootApplication注解 前言SpringBootApplicationSpringBootConfigurationEnableAutoConfigurationimport注解 ComponentScan 总结 前言 Springboot作为Spring的脚手架&#xff0c;其本质核心并不提供Spring核心功能&#xff0c;作用就是开发者快速构建&#xff0c;预置三…

怎么转换英文音频成文字?英文音频转文字app分享

两位朋友正在讨论如何将一段英文讲座的音频转换成文字&#xff0c;以便于学习和理解。 Sophia&#xff1a;嗨&#xff0c;我最近听了一段非常精彩的英文讲座&#xff0c;但是对于我来说&#xff0c;理解听到的内容有些困难。你知道有什么方法可以将英文音频转换成文字吗&#…

SpringBoot内置Logback日志的学习

一、日志级别 日志级别有TRACE,DEBUG,INFO,WARN,ERROR,FATAL,OFF。 TRACE级别最低 DEBUG 的级别低&#xff0c;当需要打印调试信息的话&#xff0c;就用这个级别&#xff0c;不建议在生产环境下使用。 INFO 的级别高一些&#xff0c;当一些重要的信息需要打印的时候&#x…

虹科多功能电流电压采集方案

01电流电压采集基础概念和应用 电流采集、电压采集、电能充电量测试和功率测试在不同领域都有着广泛的应用 ▲汽车电子&#xff1a;电池管理系统BMS、发动机控制系统、车身电子系统 ▲航空航天&#xff1a;飞行控制系统&#xff0c;航空电源管理系统、航空电子设备 ▲消费电…

如何学习和提升使用编程语言的能力? - 易智编译EaseEditing

学习编程语言并提升编程能力需要一定的学习方法和实践。以下是一些方法可以帮助你提升编程语言能力&#xff1a; 学习基本语法&#xff1a; 了解编程语言的基本语法和关键概念。可以通过阅读官方文档、教程、书籍或在线资源来学习。 编写代码&#xff1a; 编写实际的代码是提…

入门孪生网络Siamese Network,我将会分几个博客来逐步阐述我对孪生网络的理解和应用---初步介绍0

文章目录 前言一、孪生网络&#xff08;Siamese Network)的基本概念二、孪生网络&#xff08;Siamese Network)的优点三、利用孪生网络进行故障诊断/分类的思路假如我有一堆数据&#xff0c;它可以是轴承故障数值数据&#xff0c;也可以是图像数据&#xff0c;我想进行二分类&a…

ESP32-C2-12模组 AT固件例程

ESP32C2 AT固件使用 ESP32 C2模组&#xff0c;如图1-1所示 图1-1 ESP32 C2模组 ESP32 C2开发板&#xff0c;如图1-2所示 图1-2 ESP32 C2开发 方案亮点 1、完整的 WiFi 子系统&#xff0c;符合 IEEE 802.11b/g/n 协议&#xff0c;具有 Station 模式、SoftAP 模式、SoftAP Stat…

Vue中如何只传递一个人员Name同时把人员Id也传递过去

前言&#xff1a; 根据项目需求&#xff0c;在修改功能中&#xff0c;要求展示一个人员的下拉框&#xff0c;但是又要把人员ID在点击提交时传递过去&#xff0c;一般这种情况有2种解决方法&#xff1a;一是 通过map遍历匹配&#xff1b;二是 在选中人员时将人员ID获取到&#x…

编辑和校对魔法:让文字焕发生机的秘诀

编辑和校对是写作过程中的关键环节&#xff0c;可以让你的文字更加精炼、清晰、引人入胜。以下是一些编辑和校对的秘诀&#xff0c;可以让你的文字焕发生机。 1.保持客观 从读者的角度审视文章&#xff0c;保持客观和中立。确保内容清晰、观点明确&#xff0c;同时避免主观情感…

运筹系列81:LKH代码分析

1. 基本数据结构 基础的node定义在LKH.h中 用于2-level tree的segment定义如下&#xff1a; LKH可以使用3种数据结构&#xff0c;默认是2-level tree&#xff1a; 2-level tree的flip操作&#xff08;即2-opt算子&#xff09;&#xff0c;在Flip_SL.c中&#xff0c;特殊的地…

请问python如何处理url带有“?”参数的接口?

在Python中处理带有"?"参数的URL接口&#xff0c;可以使用urllib.parse库中的urlencode()函数来进行编码。以下是一些示例代码 如果你想学习自动化测试&#xff0c;我这边给你推荐一套视频&#xff0c;这个视频可以说是B站百万播放全网第一的自动化测试教程&#x…