You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 21:39:28