在ROS中传递图像消息(一)
来源:互联网 发布:p2p网络推广方案 编辑:程序博客网 时间:2024/05/16 01:42
最近在学习如何在ROS中传递图像,在这里将自己的拙见与大家分享,希望大家多多指教。如果有错误的地方,希望各位大神不吝赐教。
1创建相关功能包
首先进入到你的工作空间,比如我的工作空间是catkin_ws
,然后进入src
目录下,使用catkin_create_pkg
命令创建你的功能包,以my_image_transport
功能包为例,注意功能包后面参数为该功能包的依赖项。
$ cd catkin_ws/$ cd src/$ catkin_create_pkg my_image_transport image_transport cv_bridge
然后回到工作空间内编译该功能包,
$ cd ..$ catkin_make
ps:如果不带任何参数的话,catkin_make
默认编译工作空间下的所有功能包,如果你不怕麻烦的话可以使用这个参数编译特定的功能包:catkin_make -DCATKIN_WHITELIST_PACKAGES="package1;package2"
或者使用catkin_make --pkg package_name
同时,更新初始化文件,
$ source devel/setup.bash
2在ROS中传递图像
在学习从摄像头获取视频之前,我们最好先学会如何发布一个图像消息,简单熟悉之后,再学习如何发布视频。
2.1创建一个图像发布者程序
首先进入功能包,创建src
目录,在里面创建如下代码:
$ cd src$ vi my_publisher.cpp
如果你已经对ros中的各种命令比较熟悉,你可以采取更简单的命令,这条命令是ros命令(你可以这样记rosed=ros+edit),它会根据你的设置来启动相应的编辑器编辑文件。
$ rosed my_image_transport my_publisher.cpp
ps: 如果上述命令不管用,那么在运行上述命令之前最好先运行下面的命令,每次遇到类似的问题都可以运行这条命令,屡试不爽!
$ . ~/catkin_ws/devel/setup.bash
下面是my_publisher.cpp
文件里的内容,你可以在这里下载该文件。
#include <ros/ros.h>#include <image_transport/image_transport.h>#include <opencv2/highgui/highgui.hpp>#include <cv_bridge/cv_bridge.h>int main(int argc, char** argv){ ros::init(argc, argv, "image_publisher"); ros::NodeHandle nh; image_transport::ImageTransport it(nh); image_transport::Publisher pub = it.advertise("camera/image", 1); cv::Mat image = cv::imread(argv[1], CV_LOAD_IMAGE_COLOR); sensor_msgs::ImagePtr msg = cv_bridge::CvImage(std_msgs::Header(), "bgr8", image).toImageMsg(); ros::Rate loop_rate(5); while (nh.ok()) { pub.publish(msg); ros::spinOnce(); loop_rate.sleep(); }}
我们来一步一步地分析一下这段代码。
#include <ros/ros.h>#include <image_transport/image_transport.h>#include <opencv2/highgui/highgui.hpp>#include <cv_bridge/cv_bridge.h>
首先ros.h
这个头文件是所有的ros节点中必须要包含的,下面三个分别是实现图像的发布和订阅,调用opencv库(当然前提是你在你的系统里已经安装了OpenCV),完成opencv图像格式转化为ROS图像格式所要用到的头文件。另外,在package.xml文件中我们也需要根据所需头文件配置相关的依赖。(下节我们会介绍到)
image_transport::ImageTransport it(nh);
用之前声明的节点句柄初始化it
,其实这里的it
和nh
的功能基本一样,你可以向之前一样使用it
来发布和订阅相消息。
image_transport::Publisher pub = it.advertise("camera/image", 1);
告诉节点管理器(roscore)我们要在camera/image
话题上发布图像,这里第一个参数是话题的名称,第二个是缓冲区的大小(即消息队列的长度,在发布图像消息时消息队列的长度只能是1)。
cv::Mat image = cv::imread(argv[1], CV_LOAD_IMAGE_COLOR);
根据运行时给定的参数(图像文件的路径)读取图像,这是opencv里面的函数,具体可以参考opencv的相关资料。
sensor_msgs::ImagePtr msg = cv_bridge::CvImage(std_msgs::Header(), "bgr8", image).toImageMsg();
将opencv格式的图像转化为ROS所支持的消息类型,从而发布到相应的话题上。
ros::Rate loop_rate(5); while (nh.ok()) { pub.publish(msg); ros::spinOnce(); loop_rate.sleep(); }}
发布图片消息,使消息类型匹配的节点订阅该消息。
2.2创建订阅者节点
#include <ros/ros.h>#include <image_transport/image_transport.h>#include <opencv2/highgui/highgui.hpp>#include <cv_bridge/cv_bridge.h>void imageCallback(const sensor_msgs::ImageConstPtr& msg){ try { cv::imshow("view", cv_bridge::toCvShare(msg, "bgr8")->image); } catch (cv_bridge::Exception& e) { ROS_ERROR("Could not convert from '%s' to 'bgr8'.", msg->encoding.c_str()); }}int main(int argc, char **argv){ ros::init(argc, argv, "image_listener"); ros::NodeHandle nh; cv::namedWindow("view"); cv::startWindowThread(); image_transport::ImageTransport it(nh); image_transport::Subscriber sub = it.subscribe("camera/image", 1, imageCallback); ros::spin(); cv::destroyWindow("view");}
前面重复的部分这里不在赘述,我只介绍一下几段新的代码。
void imageCallback(const sensor_msgs::ImageConstPtr& msg)
这是一个回调函数,当有新的图像消息到达camera/image
时,该函数就会被调用。
cv::imshow("view", cv_bridge::toCvShare(msg, "bgr8")->image);
这段代码用于显示捕捉到的图像,其中cv_bridge::toCvShare(msg, "bgr8")->image
用于将ROS图像消息转化为Opencv支持的图像格式(采用BGR8编码方式)。其实这部分代码的用法恰好与上一节中发布者节点中的CvImage(std_msgs::Header(), "bgr8", image).toImageMsg();
的作用相反。
2.3配置相关文件
为了使上述两个节点编译成功,我们必须对CMakeList.txt
和package.xml
做一些修改。首先在CMakeList.txt
添加如下几行代码,
find_package(OpenCV)include_directories(include ${OpenCV_INCLUDE_DIRS})#build my_publisher and my_subscriberadd_executable(my_publisher src/my_publisher.cpp)target_link_libraries(my_publisher ${catkin_LIBRARIES})add_executable(my_subscriber src/my_subscriber.cpp)target_link_libraries(my_subscriber ${catkin_LIBRARIES})
然后打开package.xml
,在里面添加如下两行代码,
<build_depend>opencv2</build_depend><run_depend>opencv2</run_depend>
配置好上述文件之后你就可以编译节点了!
$cd ~/catkin_ws$catkin_make -DCATKIN_WHITHELIST_PACKAGES="my_image_transport"
编译成功之后你就可以运行你写好的节点了。如果没有运行成功,就检查一下相关的配置文件或者节点代码中有无错误。在运行节点之前一定要先打开节点管理器。打开终端运行roscore
,然后打开另一终端运行下述命令,
$rosrun my_image_transport my_publisher /home/viki/Pictures/th.jpeg
上述命令有三个参数,分别是包名,节点名,所传递的图像的路径。如果不成功,就试试我之前提到的那个source
命令。
再打开一个终端,输入rostopic list
查看当前的主题清单。
下面运行订阅者节点,
$rosrun my_image_transport my_subscriber
运行效果如下图所示,
下面我们看一下当前活动的节点,
$rosnode list
为了便于理解各个节点之间的交互情况,我们可以运行一个辅助节点rqt_graph
。
$rosrun rqt_graph rqt_graph
如果你想优雅的关闭每个节点,那么请使用rosnode kill
命令。当然你使用ctrl+c
或者直接关闭终端也可以关闭节点,但这种方法不免过于简单粗暴,而且并未完全的关闭节点,因为节点管理器那里仍然有记录。
参考文献
[1]http://wiki.ros.org/image_transport/Tutorials
[2]http://wiki.ros.org/ROS/Tutorials/WritingPublisherSubscriber%28c%2B%2B%29
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
- 在ROS中传递图像消息(一)
- 在ROS中传递图像消息(二)
- (七)ROS使用OpenCV读取图像并发布图像消息在rviz中显示
- ROS学习笔记(一):在ROS中使用USB网络摄像头传输图像
- ROS使用OpenCV读取图像并发布图像消息在rviz中显示
- 在 Qt5中ROS开发(一)
- ROS 服务 消息传递
- 【ROS学习】(四)ROS消息传递——std_msgs
- ROS学习笔记(三):在ROS中使用USB网络摄像头传输图像
- ROS学习笔记(三):在ROS中使用USB网络摄像头传输图像
- 【ROS学习】(五)ROS消息传递——自定义消息
- ROS学习笔记(2):在ROS中使用OpenCV进行简单的图像处理---代码实现篇
- (九)ROS在rviz中实时显示轨迹(nav_msgs/Path消息的使用)
- (十)ROS在rviz中显示空间中的直线(visualization_msgs/Marker 消息)
- 复习在ROS机器人系统中打开摄像头,显示图像
- 在ROS中使用USB网络摄像头传输图像
- 在ROS中定义并使用自己的消息类型
- 在Ruby中使用flash传递消息
- GeekBand--第四周分享
- wordpress搬家插件cnblogs2wp,实测好用
- 如何由方法论设计敏捷实践, 改变团队成员既有的思维, 行为模式?
- acl权限和设置方法
- 用树莓派 + Python + OpenCV 实现家庭监控和移动目标探测(下)
- 在ROS中传递图像消息(一)
- 【HDU5651 BestCoder Round 77 (div1) A】【简单组合数】xiaoxin juju needs help 字符串位置重组构成回文串个数
- linux下chkconfig使用
- Cocos精灵
- JAVA文件中获取路径及WEB应用程序获取路径方法
- Cocos坐标体系
- tomcat部署
- Android Fragment嵌套ViewPager,ViewPager嵌套多个Fragment
- CSU 1697 Surface Area of Cubes (思维)