技术标签: 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中的各种命令比较熟悉,你可以采取更简单的命令
$ rosed my_image_transport my_publisher.cpp
ps: 如果上述命令不管用,那么在运行上述命令之前最好先运行下面的命令,每次遇到类似的问题都可以运行这条命令,屡试不爽!
$ source ~/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_subscriber
add_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,在里面添加如下代码,
<buildtool_depend>catkin</buildtool_depend>
<build_depend>cv_bridge</build_depend>
<build_depend>image_transport</build_depend>
<build_depend>roscpp</build_depend>
<build_depend>rospy</build_depend>
<build_depend>std_msgs</build_depend>
<build_export_depend>cv_bridge</build_export_depend>
<build_export_depend>image_transport</build_export_depend>
<build_export_depend>roscpp</build_export_depend>
<build_export_depend>rospy</build_export_depend>
<build_export_depend>std_msgs</build_export_depend>
<exec_depend>cv_bridge</exec_depend>
<exec_depend>image_transport</exec_depend>
<exec_depend>roscpp</exec_depend>
<exec_depend>rospy</exec_depend>
<exec_depend>std_msgs</exec_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或者直接关闭终端也可以关闭节点,但这种方法不免过于简单粗暴,而且并未完全的关闭节点,因为节点管理器那里仍然有记录。
现在我们已经学会了如何在ros网络里发布图像消息.现在我们同样可以用类似的方法发布视频消息,下面我们以从摄像头获取视频数据为例进行简单的讲解,当然你也可以读取视频文件再发布出去.
这里使用到的是ros indigo,由于当我们需要用到OpenCV时,通常都需要运用cv_bridge或者image_pipeline包来转换传输图片,而这两个包又是依赖于OpenCV 2.4.8来编译的,所以每当同时需要用到OpenCV3和cv_bridge的时候,便会产生如下错误:
No rule to make target `/usr/lib/x86_64-linux-gnu/libopencv_videostab.so.2.4.8'
所以,要解决这个问题,方法就是把cv_bridge和image_pipeline下载到本地的工作空间,并重新编译。但是因为他们基于OpenCV 2可以直接编译成功,所以在OpenCV 3下则需要相应做一些改动。这里有一个我从github上找到的,别人修改过的,可以直接下载并且使用OpenCV 3编译成功的cv_bridge包,网址如下:
https://github.com/mikejmills/vision_opencv
文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib
文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang
文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些
文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器
文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距
文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器
文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn
文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios
文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql
文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...
文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120
文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数