
🎬 渡水无言 :个人主页渡水无言
❄专栏传送门 : 《linux专栏》《嵌入式linux驱动开发》《linux系统移植专栏》
❄专栏传送门 : 《freertos专栏》 《STM32 HAL库专栏》《linux裸机开发专栏》
❄专栏传送门 :《产品测评专栏》 《Ai智能体专栏) 《ROS开发专栏》
⭐️流水不争先,争的是滔滔不绝
📚博主简介:第二十届中国研究生电子设计竞赛全国二等奖 |国家奖学金 | 省级三好学生
| 省级优秀毕业生获得者 | csdn新星杯TOP18 | 半导纵横专栏博主 | 211在读研究生
在这里主要分享自己学习的linux嵌入式领域知识;有分享错误或者不足的地方欢迎大佬指导,也欢迎各位大佬互相三连
目录
[二、新建视觉功能包 cv_pkg](#二、新建视觉功能包 cv_pkg)
[四、配置 CMakeLists.txt](#四、配置 CMakeLists.txt)
[五、配置 package.xml](#五、配置 package.xml)
前言
前几期博客我们已经完成了 ROS2 SLAM 建图、NAV2 自主导航、多航点巡航 整套移动机器人底盘导航开发,机器人已经可以依靠激光雷达实现环境感知、自主避障与定点行驶。
但仅靠激光雷达只能感知障碍物轮廓,无法识别颜色、目标物体、人脸等细节信息。想要让机器人具备更高阶的智能感知能力,就必须引入机器视觉。
从本期博客开始,我们正式进入 ROS2 + OpenCV 视觉应用 的学习。而视觉开发的第一步, 就是获取相机图像数据。只有成功订阅相机话题、完成 ROS 图像与 OpenCV 格式转换,才能开展后续颜色识别、目标追踪、人脸检测等高级功能。
本期博客我们就来实现获取相机图像数据的实验。
一、实验原理
视觉图像数据的获取是通过订阅相机驱动节点发布的话题,从话题中获取相机发出的消息包来实现的。
机器人头部安装的是Kinect V2 RGB-D相机,对应的话题名称为:
/kinect2/qhd/image_raw
话题中的消息包格式为:
cpp
sensor_msgs::Image

本次实验将会实现一个订阅者节点,订阅相机发布的话题"/kinect2/qhd/image_raw"。从此话题中接收sensor_msgs::Image类型的消息包,并将其中的图像数据转换成OpenCV的格式。最后使用OpenCV的图形显示接口,将图像显示在图形窗口中。
二、新建视觉功能包 cv_pkg
进入工作空间 src 目录,创建专用视觉功能包,在终端中输入以下指令:
cpp
cd ~/ros2_zice/src
ros2 pkg create cv_pkg
三、编写图像获取节点源码
首先我们来编写图像获取节点源码,此节点的作用为订阅相机发布的图像话题,通过 cv_bridge 转换成 OpenCV 格式,然后实时显示相机画面。
在 cv_pkg/src 目录下新建 cv_image.cpp,再输入以下代码:
cpp
#include <rclcpp/rclcpp.hpp>
#include <sensor_msgs/msg/image.hpp>
#include <cv_bridge/cv_bridge.h>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
std::shared_ptr<rclcpp::Node> node;
// 相机图像回调函数
void image_callback(const sensor_msgs::msg::Image::SharedPtr msg)
{
// 将ROS图像消息转为OpenCV格式
cv_bridge::CvImagePtr cv_ptr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);
// 显示图像
imshow("RGB Camera", cv_ptr->image);
waitKey(1);
}
int main(int argc, char **argv)
{
rclcpp::init(argc, argv);
node = std::make_shared<rclcpp::Node>("image_get_node");
// 订阅相机图像话题
auto sub = node->create_subscription<sensor_msgs::msg::Image>(
"/kinect2/qhd/image_raw", 10, image_callback);
// 循环监听
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
四、配置 CMakeLists.txt
我们需要在编译配置中声明 OpenCV、cv_bridge 等依赖,让系统能正确编译图像相关代码。
在CMakeLists.txt文件中输入以下代码:
cpp
cmake_minimum_required(VERSION 3.8)
project(cv_pkg)
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(cv_bridge REQUIRED)
find_package(OpenCV REQUIRED)
# 编译 cv_image.cpp,生成可执行节点 cv_image
add_executable(cv_image src/cv_image.cpp)
ament_target_dependencies(cv_image
rclcpp
sensor_msgs
cv_bridge
OpenCV
)
# 安装可执行文件
install(TARGETS
cv_image
DESTINATION lib/${PROJECT_NAME}
)
ament_package()
五、配置 package.xml
在 package.xml 中添加视觉开发必需的依赖项,保证编译和运行正常。
在 package.xml输入以下代码:
cpp
<?xml version="1.0"?>
<package format="3">
<name>cv_pkg</name>
<version>0.0.0</version>
<description>ROS2视觉功能包</description>
<maintainer email="todo@todo.todo">todo</maintainer>
<license>Apache-2.0</license>
<buildtool_depend>ament_cmake</buildtool_depend>
<depend>rclcpp</depend>
<depend>sensor_msgs</depend>
<depend>cv_bridge</depend>
<depend>OpenCV</depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<export>
<build_type>ament_cmake</build_type>
</export>
</package>
六、编译与运行
编译功能包
编译我们的视觉功能包,让代码生成可执行节点。打开终端,输入以下指令:
cpp
cd ~/ros2_zice
colcon build
source install/setup.bash
运行图像获取节点
1、先运行仿真程序
打开终端,输入以下指令:
cpp
source install/setup.bash
ros2 launch wpr_simulation2 wpb_balls.launch.py

2、运行节点程序
打开第2个子窗口,输入以下指令:
cpp
source install/setup.bash
ros2 run cv_pkg cv_image
节点运行起来之后,会弹出一个名为"RGB"窗口程序,显示机器人头部相机所看到的四个颜色球的图像。如下图所示:

为了测试这个图像是不是实时获取的,可以借助wpr_simulation2附带的程序让中间的桔色球动起来,以便进行对比观察。打开第3个子窗口。输入以下指令:
cpp
source install/setup.bash
ros2 run wpr_simulation2 ball_random_move
执行之后,可以看到仿真窗口里的桔色球开始随机运动。此时再切换到"RGB"窗口,可以看到图像中的桔色球也跟着运动,说明这个采集到的图像是实时更新的,如下图所示:

总结
本章我们完成了 ROS2 视觉开发的第一步,实现了仿真环境下相机图像的订阅、格式转换与实时显示,掌握了cv_bridge的核心用法,为后续颜色识别、目标跟随等高级视觉功能打下了数据基础。