Linux下双Lumenera相机C++ ROS节点帧率下降问题
问题说明
在Linux(Ubuntu 18.04)系统下开发了一款基于C++的ROS节点,功能为采集相机图像并发布至ROS话题。
使用的两台Lumenera相机在2048*2048分辨率下,单台最高可输出90帧/秒的图像。
实际运行测试中,单台相机接入时节点图像发布帧率可达90帧/秒,与相机最高帧率一致;但同时接入两台相机时,发布帧率下降至45帧/秒。
程序实现逻辑为每台相机分配独立线程,每个线程单独负责对应相机的图像读取与发布操作。双相机运行时查看系统CPU、RAM占用情况,剩余资源充足,暂无法定位帧率下降的根因。
程序核心实现代码如下,完整代码可访问对应GitHub仓库的src文件夹查看。
核心实现代码
#define LUMENERA_LINUX_API #undef LUMENERA_MAC_API #undef LUMENERA_WINDOWS_API #include <ros/ros.h> #include <iostream> #include <vector> #include <string> #include <thread> #include <lucamapi.h> #include <lucamerr.h> #include "Camera.h" #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <sensor_msgs/Image.h> #include <sensor_msgs/image_encodings.h> #include <cv_bridge/cv_bridge.h> using namespace cv; using std::cout; using std::endl; void publish_camera_on_topic(std::vector<Camera> cameras, const std::vector<ros::Publisher> publishers, const int camera_index) { ROS_INFO_STREAM( "Start thread for " << camera_index << "." << std::endl); int frameSize; BYTE *imagePtr; // frame id int frame_id = 0; cv_bridge::CvImage img_bridge; sensor_msgs::Image img_msg; while (ros::ok() && ros::master::check()) { // Grab and display a single image from each camera imagePtr = cameras[camera_index].getRawImage(); frameSize = cameras[camera_index].getFrameSize(); cameras[camera_index].createRGBImage(imagePtr,frameSize); unsigned char* pImage = cameras[camera_index].getImage(); if (NULL != pImage) { Mat image(cameras[camera_index].getMatSize(), CV_8UC3, pImage, Mat::AUTO_STEP); // release asap cameras[camera_index].releaseImage(); //cvtColor(image, image, CV_BGR2RGB,3); // publish on ROS topic std_msgs::Header header; // empty header header.seq = frame_id; // user defined counter header.stamp = ros::Time::now(); // time img_bridge = cv_bridge::CvImage(header, sensor_msgs::image_encodings::RGB8, image); img_bridge.toImageMsg(img_msg); // from cv_bridge to sensor_msgs::Image publishers[camera_index].publish(img_msg); // ros::Publisher pub_img = node.advertise<sensor_msgs::Image>("topic", queuesize); } // increase frame Id frame_id = frame_id + 1; } ROS_INFO_STREAM( "ROS closing for thread of camera " << camera_index << " recieved." << std::endl); } int main( int argc, char** argv ) { std::thread * th; // ROS node name ros::init(argc, argv, "lumenera_camera_node"); // ros node handle ros::NodeHandle nh; // ros rate Hz ros::Rate rate(90); // print start of node ROS_INFO("Node: [lumenera_camera_node] has been started."); bool displaySobelImage = false; if (argc > 1) { displaySobelImage = true; } int numCameras = LucamNumCameras(); ROS_INFO_STREAM("Found " << numCameras << " camera" << std::string((1 == numCameras) ? "" : "s") << endl); if (0 == numCameras) { return 0; } // For now, limit ourselves to 1 camera numCameras = std::max(numCameras, 1); std::vector<Camera> cameras(numCameras); // Initialize each camera for(size_t i=0; i < cameras.size(); i++) { ROS_INFO_STREAM("Initializing Camera #" << i+1 << endl); cameras[i].init(i+1, displaySobelImage ? "Sobel" : ""); } // Start streaming on each camera for(size_t i=0; i < cameras.size(); i++) { ROS_INFO_STREAM("Starting streaming on Camera #" << i+1 << endl); cameras[i].startStreaming(); } // const int scale = 1; const int delta = 0; const int ddepth = CV_16S; // image publisher // for each camera create an publisher std::vector<ros::Publisher> publishers; for (size_t i = 0; i < cameras.size(); i++) { char topic_name[200]; sprintf(topic_name, "/lumenera_camera_package/%d", i + 1); publishers.push_back(nh.advertise<sensor_msgs::Image>(topic_name, 10)); } // work with each camera on a seprate thread std::vector<std::thread *> thread_vector; for(size_t camera_index=0; camera_index < cameras.size(); camera_index++) { th = new std::thread; *th = std::thread(publish_camera_on_topic, cameras, publishers, camera_index); thread_vector.push_back(th); } ros::spin(); for(size_t camera_index=0; camera_index < cameras.size(); camera_index++) { thread_vector[camera_index]->join(); delete thread_vector[camera_index]; } for(size_t camera_index=0; camera_index < cameras.size(); camera_index++) { cameras[camera_index].stopStreaming(); } ROS_INFO("Node: [lumenera_camera_node] has been Ended."); return 0; }
内容的提问来源于stack exchange,提问作者CVDE
相关产品推荐
相关产品推荐

