ROS中的USB_cam功能包是一个用于与USB摄像头交互的软件包。这个软件包可以订阅摄像头的图像话题,并将其发布到ROS中,从而允许用户在ROS系统中使用USB摄像头。 ???
功能:
?????USB_cam功能包主要用于获取USB摄像头的图像数据。
?????它通过调用V4L2(Video for Linux 2)接口来与摄像头硬件通信。
?????USB_cam发布图像数据为ROS的标准消息类型sensor_msgs/Image,这使得图像数据可以被其他ROS节点方便地订阅和处理。
用法:
????启动USB_cam节点:在终端中,进入USB_cam的launch文件目录,然后运行以下命令:
roslaunch usb_cam usb_cam-test.launch
这将会启动USB_cam节点,并开始从默认的USB摄像头获取图像。
参数配置:
USB_cam提供了一些参数供用户自定义,包括设备名称、图像大小、帧率、颜色模式等。这些参数可以在launch文件中进行修改,或者通过rosparam命令在运行时设置。
以下是一些常见的参数:
????video_device:?指定USB摄像头的设备路径,如 /dev/video0。
????image_width?和 image_height:?设置图像的分辨率。
????frame_rate: 设置帧率。
????pixel_format:?设置像素格式,如 yuyv 或 mjpeg。
订阅图像话题:
USB_cam发布的图像话题通常命名为/<camera_name>/image_raw,其中<camera_name>是你在启动节点时指定的名称,或者默认为usb_cam。
一般来说,需要配合image_transport和cv_bridge这两个功能包一起使用。image_transport用于处理图像传输,而cv_bridge则用于将OpenCV图像转换为ROS图像消息。
#include <ros/ros.h>
#include <image_transport/image_transport.h>
#include <cv_bridge/cv_bridge.h>
#include <sensor_msgs/Image.h>
int main(int argc, char** argv)
{
????ros::init(argc, argv, "usb_cam_example");
????ros::NodeHandle nh;
????image_transport::ImageTransport it(nh);
????image_transport::Publisher pub = it.advertise("camera/image_raw", 1);
????cv_bridge::CvImage cv_image;
????cv::Mat image;
????while (ros::ok())
????{
????????// 从USB摄像头获取图像
????????// ...
????????// 将OpenCV图像转换为ROS图像消息
????????cv_image = cv_bridge::CvImage(cv_image.encoding, cv_image.image.size(), image);
????????sensor_msgs::Image msg = cv_image.toImageMsg();
????????// 发布图像消息
????????pub.publish(msg);
? ? ? ? ros::spinOnce();
????}
? ?return 0;
}
在这个示例中,首先初始化了一个ROS节点,并创建了一个image_transport::ImageTransport对象和一个image_transport::Publisher对象。然后,在一个循环中不断地从USB摄像头获取图像,将其转换为ROS图像消息,并发布到"camera/image_raw"话题上。
image_transport是一个中间件,它为ROS中的图像消息传输提供了抽象层。它允许开发者选择不同的传输方式(插件)来优化图像数据的传输,如压缩、多分辨率传输等。
image_transport支持多种传输方式,如compressed, theora, jpeg, png, 和未压缩的raw格式。这些插件可以在运行时动态加载,提供了很大的灵活性。
双向通信:image_transport不仅支持发布图像,也支持订阅图像。
支持传输参数:可以通过ROS参数服务器配置传输参数,如压缩级别、帧率等。
1、发布图像
首先,需要包含相应的头文件并创建一个image_transport的Publisher:
#include <ros/ros.h>
#include <sensor_msgs/Image.h>
#include <image_transport/image_transport.h>
ros::NodeHandle nh;
image_transport::ImageTransport it(nh);
image_transport::Publisher pub = it.advertise("camera/image", 1);
然后,当有新图像数据可用时,可以使用pub.publish()方法发布图像:
sensor_msgs::ImagePtr image_msg(new sensor_msgs::Image());
// ...填充image_msg的数据...
pub.publish(image_msg);
2、订阅图像
创建一个image_transport的Subscriber来接收图像:
#include <ros/ros.h>
#include <sensor_msgs/Image.h>
#include <image_transport/image_transport.h>
#include <cv_bridge/cv_bridge.h>
#include <opencv2/highgui/highgui.hpp>
ros::NodeHandle nh;
image_transport::ImageTransport it(nh);
image_transport::Subscriber sub = it.subscribe("camera/image", 1, imageCallback);
void imageCallback(const sensor_msgs::ImageConstPtr& msg)
{
????cv_bridge::CvImagePtr cv_image = cv_bridge::toCvCopy(msg, "bgr8");
????cv::imshow("Image Window", cv_image->image);
????cv::waitKey(30);
}
在回调函数中,可以使用cv_bridge将接收到的ROS Image消息转换为OpenCV格式进行处理和显示。
其他功能:
Republish: 可以使用republish工具将一种传输方式的消息转换为另一种传输方式,
例如将未压缩的图像转换为压缩图像。
Display: display工具可以用于可视化接收到的图像。
cv_bridge它主要用于在ROS的图像消息格式和OpenCV的图像数据格式之间进行转换。
目的是解决ROS和OpenCV之间的图像数据格式差异。ROS使用自己的图像消息类型(sensor_msgs/Image),而OpenCV则使用其内部的数据结构(cv::Mat)。
1、从ROS消息转换到OpenCV图像:
#include <ros/ros.h>
#include <image_transport/image_transport.h>
#include <cv_bridge/cv_bridge.h>
#include <sensor_msgs/image_encodings.h>
#include <opencv2/highgui/highgui.hpp>
void imageCallback(const sensor_msgs::ImageConstPtr& msg)
{
??try
??{
????//将ROS图像消息转换为OpenCV格式
????cv::Mat frame = cv_bridge::toCvCopy(msg, "bgr8")->image;
????//可以将'frame'当作普通的OpenCV图像来使用
????cv::imshow("Image Window", frame);
????cv::waitKey(3);
??}
??catch (cv_bridge::Exception& e)
??{
????ROS_ERROR("Could not convert from ROS message to OpenCV image: %s", e.what());
??}
}
int main(int argc, char** argv)
{
??ros::init(argc, argv, "image_converter");
??ros::NodeHandle nh;
//创建一个ImageTransport对象,用于订阅和发布图像
??image_transport::ImageTransport it(nh);
//订阅输入图像主题
??image_transport::Subscriber sub = it.subscribe("/camera/image_raw", 1, imageCallback);
??ros::spin();
??return 0;
}
在这个例子中,首先创建了一个cv_bridge::CvImagePtr对象,然后使用toCvCopy()函数将ROS的图像消息转换为OpenCV的cv::Mat格式。
2、从OpenCV图像转换到ROS消息:
#include <ros/ros.h>
#include <image_transport/image_transport.h>
#include <cv_bridge/cv_bridge.h>
#include <sensor_msgs/image_encodings.h>
#include <opencv2/highgui/highgui.hpp>
void publishImage(const cv::Mat& frame)
{
//创建一个ROS图像消息
sensor_msgs::ImagePtrmsg=cv_bridge::CvImage(std_msgs::Header(),"bgr8",frame).toImageMsg();
?//发布图像消息
??image_pub.publish(msg);
}
int main(int argc, char** argv)
{
??ros::init(argc, argv, "opencv_to_ros_image");
??ros::NodeHandle nh;
//创建一个用于发布图像的ImageTransport对象
??image_transport::ImageTransport it(nh);
//创建一个用于输出图像主题的发布者(publisher)
??image_transport::Publisher image_pub = it.advertise("/output/image", 1);
??//加载一个OpenCV图像
??cv::Mat frame = cv::imread("input.jpg");
??// 将OpenCV图像转换并作为ROS消息发布出去
??publishImage(frame);
??ros::spin();
??return 0;
}
在这个例子中,首先创建了一个cv_bridge::CvImage对象,然后使用toImageMsg()函数将其转换为ROS的图像消息类型(sensor_msgs/Image)。最后,将这个消息发布到指定的图像主题。