使用海康相机,通过视频码流进行数据的读取和topic发布,例如针对手头一款海康相机设置码流地址:rtsp://admin:Admin12345@192.168.1.65:554。
创建相机节点过程,参考第十一章创建bjtucar包的过程,创建一个bjtucamera的包。
节点的源码如下:
#include <ros/ros.h>
#include <cv_bridge/cv_bridge.h>
#include <std_msgs/String.h>
//#include <sensor_msgs/image_encodings.h>
#include <image_transport/image_transport.h>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
ros::init(argc, argv, "myCamera");
ros::NodeHandle nh; // 声明节点句柄
// ros::Publisher chatter_pub = nh.advertise<std_msgs::String>("image1", 1000);
image_transport::ImageTransport it(nh);
// 告诉节点管理器(roscore)我们要在camera1/image1话题上发布图像,
// 这里第一个参数是话题的名称,第二个是缓冲区的大小(即消息队列的长度,在发布图像消息时消息队列的长度只能是1)
image_transport::Publisher pub = it.advertise("/image_raw", 1);
ros::Rate loop_rate(1000);
VideoCapture vcap1;
Mat image1;
const string videoStreamAddress1 = "rtsp://admin:admin2024@192.168.1.17:554/cam/realmonitor?channel=1&subtype=0";
if(!vcap1.open(videoStreamAddress1))
{
cout << "Error opening video stream or file" << endl;
return -1;
}
sensor_msgs::ImagePtr msg;
while (ros::ok()) // 不能写while(1),否则程序无法用ctrl+c关掉
{
vcap1.read(image1);
// OpenCV格式的图像转化为ROS中的消息
msg = cv_bridge::CvImage(std_msgs::Header(), "bgr8", image1).toImageMsg(); // 根据运行时给定的参数(图像文件的路径)读取图像
// imshow("1", image1);
pub.publish(msg);
// ros::spinOnce();
loop_rate.sleep();
waitKey(10);
}
return 0;
}
因为需要调用opencv的函数,先要保证有opencv的环境。可通过指令查看已经安装的opencv版本号。
pkg-config --modversion opencv
修改Cmakelist.txt添加对opencv的依赖。
cmake_minimum_required(VERSION 3.0.2)
project(bjtucamera)
find_package(catkin REQUIRED COMPONENTS
OpenCV REQUIRED
roscpp
std_msgs
std_msgs
cv_bridge
image_transport
)
catkin_package(
)
include_directories(
# include
${catkin_INCLUDE_DIRS}
${OpenCV_INCLUDE_DIRS}
)
add_executable(bjtucamera ./src/myCamera.cpp)
target_link_libraries(bjtucamera ${catkin_LIBRARIES} ${OpenCV_LIBS})
分别打开三个窗口,运行并执行观察结果。
#新终端
roscore
#新终端
rosrun bjtucamera bjtucamera
#新终端
rviz
在rviz界面添加视频节点即可观察到发布的图像数据