ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Hey thanks for getting back to me! I have implemented exactly what was suggested but I'm hitting a bit of a roadblock with the camera info. I used the opencv based camera driver found here (http://wiki.ros.org/video_stream_opencv) as my starting point. As you may know it publishes not only the image from the camera but also the camera information associated with a calibration. It seems that when you use more than one "camera_info_manager::CameraInfoManager" in the same place you get the following error message.

[ERROR] [1518120816.976389693]: Tried to advertise a service that is already advertised in this node [/camera/set_camera_info]

Does anyone have an idea how to get around this? You'll find my code and launch file below. I'm somewhat of a ROS newbie so if you happen to have more than one idea I'd love to hear the simplest one!

Also for reference here is the camera driver I found that does not work. http://wiki.ros.org/elp_stereo_camera

cpp file

/* * Software License Agreement (Modified BSD License) * * Copyright (c) 2016, PAL Robotics, S.L. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following *
disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of PAL Robotics, S.L. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @author Sammy Pfeiffer */

include <ros ros.h="">

include <image_transport image_transport.h="">

include <camera_info_manager camera_info_manager.h="">

include <opencv2 highgui="" highgui.hpp="">

include <opencv2 imgproc="" imgproc.hpp="">

include <cv_bridge cv_bridge.h="">

include <sstream>

include <boost assign="" list_of.hpp="">

// Based on the ros tutorial on transforming opencv images to Image messages

sensor_msgs::CameraInfo get_default_camera_info_from_image(sensor_msgs::ImagePtr img){ sensor_msgs::CameraInfo cam_info_msg; cam_info_msg.header.frame_id = img->header.frame_id; // Fill image size cam_info_msg.height = img->height; cam_info_msg.width = img->width; ROS_INFO_STREAM("The image width is: " << img->width); ROS_INFO_STREAM("The image height is: " << img->height); // Add the most common distortion model as sensor_msgs/CameraInfo says cam_info_msg.distortion_model = "plumb_bob"; // Don't let distorsion matrix be empty cam_info_msg.D.resize(5, 0.0); // Give a reasonable default intrinsic camera matrix cam_info_msg.K = boost::assign::list_of(1.0) (0.0) (img->width/2.0) (0.0) (1.0) (img->height/2.0) (0.0) (0.0) (1.0); // Give a reasonable default rectification matrix cam_info_msg.R = boost::assign::list_of (1.0) (0.0) (0.0) (0.0) (1.0) (0.0) (0.0) (0.0) (1.0); // Give a reasonable default projection matrix cam_info_msg.P = boost::assign::list_of (1.0) (0.0) (img->width/2.0) (0.0) (0.0) (1.0) (img->height/2.0) (0.0) (0.0) (0.0) (1.0) (0.0); return cam_info_msg; }

int main(int argc, char** argv) { ros::init(argc, argv, "image_publisher"); ros::NodeHandle nh; ros::NodeHandle _nh("~"); // to get the private params image_transport::ImageTransport it(nh); image_transport::CameraPublisher pub_left = it.advertiseCamera("left", 1); image_transport::CameraPublisher pub_right = it.advertiseCamera("right", 1);

// provider can be an url (e.g.: rtsp://10.0.0.1:554) or a number of

device, (e.g.: 0 would be /dev/video0) std::string video_stream_provider; cv::VideoCapture cap; if (_nh.getParam("video_stream_provider", video_stream_provider)){ ROS_INFO_STREAM("Resource video_stream_provider: " << video_stream_provider); // If we are given a string of 4 chars or less (I don't think we'll have more than 100 video devices connected) // treat is as a number and act accordingly so we open up the videoNUMBER device if (video_stream_provider.size() < 4){ ROS_INFO_STREAM("Getting video from provider: /dev/video" << video_stream_provider); cap.open(atoi(video_stream_provider.c_str())); } else{ ROS_INFO_STREAM("Getting video from provider: " << video_stream_provider); cap.open(video_stream_provider); } } else{ ROS_ERROR("Failed to get param 'video_stream_provider'"); return -1; }

std::string camera_name;
_nh.param("camera_name", camera_name, std::string("camera"));
ROS_INFO_STREAM("Camera name: " << camera_name);

int fps;
_nh.param("fps", fps, 240);
ROS_INFO_STREAM("Throttling to fps: " << fps);

std::string frame_id;
_nh.param("frame_id", frame_id, std::string("camera"));
ROS_INFO_STREAM("Publishing with frame_id: " << frame_id);

std::string camera_info_url;
_nh.param("camera_info_url", camera_info_url, std::string(""));
ROS_INFO_STREAM("Provided camera_info_url: '" << camera_info_url

<< "'");

bool flip_horizontal;
_nh.param("flip_horizontal", flip_horizontal, false);
ROS_INFO_STREAM("Flip horizontal image is: " <<

((flip_horizontal)?"true":"false"));

bool flip_vertical;
_nh.param("flip_vertical", flip_vertical, false);
ROS_INFO_STREAM("Flip vertical image is: " <<

((flip_vertical)?"true":"false"));

int width_target;
int height_target;
_nh.param("width", width_target, 0);
_nh.param("height", height_target, 0);
if (width_target != 0 && height_target != 0){
    ROS_INFO_STREAM("Forced image width is: " << width_target);
    ROS_INFO_STREAM("Forced image height is: " << height_target);
}

// From http://docs.opencv.org/modules/core/doc/operations_on_arrays.html#void

flip(InputArray src, OutputArray dst, int flipCode) // FLIP_HORIZONTAL == 1, FLIP_VERTICAL == 0 or FLIP_BOTH == -1 bool flip_image = true; int flip_value; if (flip_horizontal && flip_vertical) flip_value = 0; // flip both, horizontal and vertical else if (flip_horizontal) flip_value = 1; else if (flip_vertical) flip_value = -1; else flip_image = false;

if(!cap.isOpened()){
    ROS_ERROR_STREAM("Could not open the stream.");
    return -1;
}
if (width_target != 0 && height_target != 0){
    cap.set(CV_CAP_PROP_FRAME_WIDTH,

width_target); cap.set(CV_CAP_PROP_FRAME_HEIGHT, height_target); }

ROS_INFO_STREAM("Opened the stream, starting to publish.");

cv::Mat frame;

sensor_msgs::ImagePtr msg_left;
sensor_msgs::ImagePtr msg_right;
sensor_msgs::CameraInfo cam_info_msg;
sensor_msgs::CameraInfo cam_info_msg_2;
std_msgs::Header header;
header.frame_id = frame_id;


camera_info_manager::CameraInfoManager

cam_info_manager(nh,"elp_left", camera_info_url); // Get the saved camera info if any cam_info_msg = cam_info_manager.getCameraInfo();

camera_info_manager::CameraInfoManager

cam_info_manager_2(nh, "elp_right", camera_info_url); // Get the saved camera info if any cam_info_msg_2 = cam_info_manager_2.getCameraInfo();

ros::Rate r(fps);
while (nh.ok()) {
    cap >> frame;

//check both publishers if (pub_left.getNumSubscribers() > 0 || pub_right.getNumSubscribers() > 0){

        // Check if grabbed frame is actually full with some content
        if(!frame.empty()) {
            // Flip the image if necessary
            if (flip_image)
                cv::flip(frame, frame, flip_value);
                  cv::Mat left_image=frame(cv::Rect(0,0,640,480));
  cv::Mat

right_image=frame(cv::Rect(640,0,640,480));

            msg_left = cv_bridge::CvImage(header, "bgr8",

left_image).toImageMsg(); msg_right = cv_bridge::CvImage(header, "bgr8", right_image).toImageMsg();

            // Create a default camera info if we didn't get a stored

one on initialization if (cam_info_msg.distortion_model == ""){ ROS_WARN_STREAM("No calibration file given, publishing a reasonable default camera info."); cam_info_msg = get_default_camera_info_from_image(msg_left); cam_info_manager.setCameraInfo(cam_info_msg); } // The timestamps are in sync thanks to this publisher ros::Time pub_time=ros::Time::now();

            pub_right.publish(*msg_right,

cam_info_msg, pub_time); pub_left.publish(*msg_left, cam_info_msg, pub_time);

        }

        ros::spinOnce();
    }
    r.sleep();
} }

Hey thanks for getting back to me! I have implemented exactly what was suggested but I'm hitting a bit of a roadblock with the camera info. I used the opencv based camera driver found here (http://wiki.ros.org/video_stream_opencv) as my starting point. As you may know it publishes not only the image from the camera but also the camera information associated with a calibration. It seems that when you use more than one "camera_info_manager::CameraInfoManager" in the same place you get the following error message.

[ERROR] [1518120816.976389693]: Tried to advertise a service that is already advertised in this node [/camera/set_camera_info]

Does anyone have an idea how to get around this? You'll find my code and launch file below. I'm somewhat of a ROS newbie so if you happen to have more than one idea I'd love to hear the simplest one!

Also for reference here is the camera driver I found that does not work. http://wiki.ros.org/elp_stereo_camera

cpp file

/* * Software License Agreement (Modified BSD License) * * Copyright (c) 2016, PAL Robotics, S.L. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following *
disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of PAL Robotics, S.L. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @author Sammy Pfeiffer */

include <ros ros.h="">

include <image_transport image_transport.h="">

include <camera_info_manager camera_info_manager.h="">

include <opencv2 highgui="" highgui.hpp="">

include <opencv2 imgproc="" imgproc.hpp="">

include <cv_bridge cv_bridge.h="">

include <sstream>

include <boost assign="" list_of.hpp="">

// Based on the ros tutorial on transforming opencv images to Image messages

sensor_msgs::CameraInfo get_default_camera_info_from_image(sensor_msgs::ImagePtr img){ sensor_msgs::CameraInfo cam_info_msg; cam_info_msg.header.frame_id = img->header.frame_id; // Fill image size cam_info_msg.height = img->height; cam_info_msg.width = img->width; ROS_INFO_STREAM("The image width is: " << img->width); ROS_INFO_STREAM("The image height is: " << img->height); // Add the most common distortion model as sensor_msgs/CameraInfo says cam_info_msg.distortion_model = "plumb_bob"; // Don't let distorsion matrix be empty cam_info_msg.D.resize(5, 0.0); // Give a reasonable default intrinsic camera matrix cam_info_msg.K = boost::assign::list_of(1.0) (0.0) (img->width/2.0) (0.0) (1.0) (img->height/2.0) (0.0) (0.0) (1.0); // Give a reasonable default rectification matrix cam_info_msg.R = boost::assign::list_of (1.0) (0.0) (0.0) (0.0) (1.0) (0.0) (0.0) (0.0) (1.0); // Give a reasonable default projection matrix cam_info_msg.P = boost::assign::list_of (1.0) (0.0) (img->width/2.0) (0.0) (0.0) (1.0) (img->height/2.0) (0.0) (0.0) (0.0) (1.0) (0.0); return cam_info_msg; }

int main(int argc, char** argv) { ros::init(argc, argv, "image_publisher"); ros::NodeHandle nh; ros::NodeHandle _nh("~"); // to get the private params image_transport::ImageTransport it(nh); image_transport::CameraPublisher pub_left = it.advertiseCamera("left", 1); image_transport::CameraPublisher pub_right = it.advertiseCamera("right", 1);

// provider can be an url (e.g.: rtsp://10.0.0.1:554) or a number of

device, (e.g.: 0 would be /dev/video0) std::string video_stream_provider; cv::VideoCapture cap; if (_nh.getParam("video_stream_provider", video_stream_provider)){ ROS_INFO_STREAM("Resource video_stream_provider: " << video_stream_provider); // If we are given a string of 4 chars or less (I don't think we'll have more than 100 video devices connected) // treat is as a number and act accordingly so we open up the videoNUMBER device if (video_stream_provider.size() < 4){ ROS_INFO_STREAM("Getting video from provider: /dev/video" << video_stream_provider); cap.open(atoi(video_stream_provider.c_str())); } else{ ROS_INFO_STREAM("Getting video from provider: " << video_stream_provider); cap.open(video_stream_provider); } } else{ ROS_ERROR("Failed to get param 'video_stream_provider'"); return -1; }

std::string camera_name;
_nh.param("camera_name", camera_name, std::string("camera"));
ROS_INFO_STREAM("Camera name: " << camera_name);

int fps;
_nh.param("fps", fps, 240);
ROS_INFO_STREAM("Throttling to fps: " << fps);

std::string frame_id;
_nh.param("frame_id", frame_id, std::string("camera"));
ROS_INFO_STREAM("Publishing with frame_id: " << frame_id);

std::string camera_info_url;
_nh.param("camera_info_url", camera_info_url, std::string(""));
ROS_INFO_STREAM("Provided camera_info_url: '" << camera_info_url

<< "'");

bool flip_horizontal;
_nh.param("flip_horizontal", flip_horizontal, false);
ROS_INFO_STREAM("Flip horizontal image is: " <<

((flip_horizontal)?"true":"false"));

bool flip_vertical;
_nh.param("flip_vertical", flip_vertical, false);
ROS_INFO_STREAM("Flip vertical image is: " <<

((flip_vertical)?"true":"false"));

int width_target;
int height_target;
_nh.param("width", width_target, 0);
_nh.param("height", height_target, 0);
if (width_target != 0 && height_target != 0){
    ROS_INFO_STREAM("Forced image width is: " << width_target);
    ROS_INFO_STREAM("Forced image height is: " << height_target);
}

// From http://docs.opencv.org/modules/core/doc/operations_on_arrays.html#void

flip(InputArray src, OutputArray dst, int flipCode) // FLIP_HORIZONTAL == 1, FLIP_VERTICAL == 0 or FLIP_BOTH == -1 bool flip_image = true; int flip_value; if (flip_horizontal && flip_vertical) flip_value = 0; // flip both, horizontal and vertical else if (flip_horizontal) flip_value = 1; else if (flip_vertical) flip_value = -1; else flip_image = false;

if(!cap.isOpened()){
    ROS_ERROR_STREAM("Could not open the stream.");
    return -1;
}
if (width_target != 0 && height_target != 0){
    cap.set(CV_CAP_PROP_FRAME_WIDTH,

width_target); cap.set(CV_CAP_PROP_FRAME_HEIGHT, height_target); }

ROS_INFO_STREAM("Opened the stream, starting to publish.");

cv::Mat frame;

sensor_msgs::ImagePtr msg_left;
sensor_msgs::ImagePtr msg_right;
sensor_msgs::CameraInfo cam_info_msg;
sensor_msgs::CameraInfo cam_info_msg_2;
std_msgs::Header header;
header.frame_id = frame_id;


camera_info_manager::CameraInfoManager

cam_info_manager(nh,"elp_left", camera_info_url); // Get the saved camera info if any cam_info_msg = cam_info_manager.getCameraInfo();

camera_info_manager::CameraInfoManager

cam_info_manager_2(nh, "elp_right", camera_info_url); // Get the saved camera info if any cam_info_msg_2 = cam_info_manager_2.getCameraInfo();

ros::Rate r(fps);
while (nh.ok()) {
    cap >> frame;

//check both publishers if (pub_left.getNumSubscribers() > 0 || pub_right.getNumSubscribers() > 0){

        // Check if grabbed frame is actually full with some content
        if(!frame.empty()) {
            // Flip the image if necessary
            if (flip_image)
                cv::flip(frame, frame, flip_value);
                  cv::Mat left_image=frame(cv::Rect(0,0,640,480));
  cv::Mat

right_image=frame(cv::Rect(640,0,640,480));

            msg_left = cv_bridge::CvImage(header, "bgr8",

left_image).toImageMsg(); msg_right = cv_bridge::CvImage(header, "bgr8", right_image).toImageMsg();

            // Create a default camera info if we didn't get a stored

one on initialization if (cam_info_msg.distortion_model == ""){ ROS_WARN_STREAM("No calibration file given, publishing a reasonable default camera info."); cam_info_msg = get_default_camera_info_from_image(msg_left); cam_info_manager.setCameraInfo(cam_info_msg); } // The timestamps are in sync thanks to this publisher ros::Time pub_time=ros::Time::now();

            pub_right.publish(*msg_right,

cam_info_msg, pub_time); pub_left.publish(*msg_left, cam_info_msg, pub_time);

        }

        ros::spinOnce();
    }
    r.sleep();
} }

Hey thanks for getting back to me! I have implemented exactly what was suggested but I'm hitting a bit of a roadblock with the camera info. I used the opencv based camera driver found here (http://wiki.ros.org/video_stream_opencv) as my starting point. As you may know it publishes not only the image from the camera but also the camera information associated with a calibration. It seems that when you use more than one "camera_info_manager::CameraInfoManager" in the same place you get the following error message.

[ERROR] [1518120816.976389693]: Tried to advertise a service that is already advertised in this node [/camera/set_camera_info]

Does anyone have an idea how to get around this? You'll find my code and launch file below. I'm somewhat of a ROS newbie so if you happen to have more than one idea I'd love to hear the simplest one!

Also for reference here is the camera driver I found that does not work. http://wiki.ros.org/elp_stereo_camera

cpp file

include <ros ros.h="">

include <image_transport image_transport.h="">

include <camera_info_manager camera_info_manager.h="">

include <opencv2 highgui="" highgui.hpp="">

include <opencv2 imgproc="" imgproc.hpp="">

include <cv_bridge cv_bridge.h="">

include <sstream>

include <boost assign="" list_of.hpp="">

// Based on the ros tutorial on transforming opencv images to Image messages

sensor_msgs::CameraInfo get_default_camera_info_from_image(sensor_msgs::ImagePtr img){ sensor_msgs::CameraInfo cam_info_msg; cam_info_msg.header.frame_id = img->header.frame_id; // Fill image size cam_info_msg.height = img->height; cam_info_msg.width = img->width; ROS_INFO_STREAM("The image width is: " << img->width); ROS_INFO_STREAM("The image height is: " << img->height); // Add the most common distortion model as sensor_msgs/CameraInfo says cam_info_msg.distortion_model = "plumb_bob"; // Don't let distorsion matrix be empty cam_info_msg.D.resize(5, 0.0); // Give a reasonable default intrinsic camera matrix cam_info_msg.K = boost::assign::list_of(1.0) (0.0) (img->width/2.0) (0.0) (1.0) (img->height/2.0) (0.0) (0.0) (1.0); // Give a reasonable default rectification matrix cam_info_msg.R = boost::assign::list_of (1.0) (0.0) (0.0) (0.0) (1.0) (0.0) (0.0) (0.0) (1.0); // Give a reasonable default projection matrix cam_info_msg.P = boost::assign::list_of (1.0) (0.0) (img->width/2.0) (0.0) (0.0) (1.0) (img->height/2.0) (0.0) (0.0) (0.0) (1.0) (0.0); return cam_info_msg; }

int main(int argc, char** argv) { ros::init(argc, argv, "image_publisher"); ros::NodeHandle nh; ros::NodeHandle _nh("~"); // to get the private params image_transport::ImageTransport it(nh); image_transport::CameraPublisher pub_left = it.advertiseCamera("left", 1); image_transport::CameraPublisher pub_right = it.advertiseCamera("right", 1);

// provider can be an url (e.g.: rtsp://10.0.0.1:554) or a number of

device, (e.g.: 0 would be /dev/video0) std::string video_stream_provider; cv::VideoCapture cap; if (_nh.getParam("video_stream_provider", video_stream_provider)){ ROS_INFO_STREAM("Resource video_stream_provider: " << video_stream_provider); // If we are given a string of 4 chars or less (I don't think we'll have more than 100 video devices connected) // treat is as a number and act accordingly so we open up the videoNUMBER device if (video_stream_provider.size() < 4){ ROS_INFO_STREAM("Getting video from provider: /dev/video" << video_stream_provider); cap.open(atoi(video_stream_provider.c_str())); } else{ ROS_INFO_STREAM("Getting video from provider: " << video_stream_provider); cap.open(video_stream_provider); } } else{ ROS_ERROR("Failed to get param 'video_stream_provider'"); return -1; }

std::string camera_name;
_nh.param("camera_name", camera_name, std::string("camera"));
ROS_INFO_STREAM("Camera name: " << camera_name);

int fps;
_nh.param("fps", fps, 240);
ROS_INFO_STREAM("Throttling to fps: " << fps);

std::string frame_id;
_nh.param("frame_id", frame_id, std::string("camera"));
ROS_INFO_STREAM("Publishing with frame_id: " << frame_id);

std::string camera_info_url;
_nh.param("camera_info_url", camera_info_url, std::string(""));
ROS_INFO_STREAM("Provided camera_info_url: '" << camera_info_url

<< "'");

bool flip_horizontal;
_nh.param("flip_horizontal", flip_horizontal, false);
ROS_INFO_STREAM("Flip horizontal image is: " <<

((flip_horizontal)?"true":"false"));

bool flip_vertical;
_nh.param("flip_vertical", flip_vertical, false);
ROS_INFO_STREAM("Flip vertical image is: " <<

((flip_vertical)?"true":"false"));

int width_target;
int height_target;
_nh.param("width", width_target, 0);
_nh.param("height", height_target, 0);
if (width_target != 0 && height_target != 0){
    ROS_INFO_STREAM("Forced image width is: " << width_target);
    ROS_INFO_STREAM("Forced image height is: " << height_target);
}

// From http://docs.opencv.org/modules/core/doc/operations_on_arrays.html#void

flip(InputArray src, OutputArray dst, int flipCode) // FLIP_HORIZONTAL == 1, FLIP_VERTICAL == 0 or FLIP_BOTH == -1 bool flip_image = true; int flip_value; if (flip_horizontal && flip_vertical) flip_value = 0; // flip both, horizontal and vertical else if (flip_horizontal) flip_value = 1; else if (flip_vertical) flip_value = -1; else flip_image = false;

if(!cap.isOpened()){
    ROS_ERROR_STREAM("Could not open the stream.");
    return -1;
}
if (width_target != 0 && height_target != 0){
    cap.set(CV_CAP_PROP_FRAME_WIDTH,

width_target); cap.set(CV_CAP_PROP_FRAME_HEIGHT, height_target); }

ROS_INFO_STREAM("Opened the stream, starting to publish.");

cv::Mat frame;

sensor_msgs::ImagePtr msg_left;
sensor_msgs::ImagePtr msg_right;
sensor_msgs::CameraInfo cam_info_msg;
sensor_msgs::CameraInfo cam_info_msg_2;
std_msgs::Header header;
header.frame_id = frame_id;


camera_info_manager::CameraInfoManager

cam_info_manager(nh,"elp_left", camera_info_url); // Get the saved camera info if any cam_info_msg = cam_info_manager.getCameraInfo();

camera_info_manager::CameraInfoManager

cam_info_manager_2(nh, "elp_right", camera_info_url); // Get the saved camera info if any cam_info_msg_2 = cam_info_manager_2.getCameraInfo();

ros::Rate r(fps);
while (nh.ok()) {
    cap >> frame;

//check both publishers if (pub_left.getNumSubscribers() > 0 || pub_right.getNumSubscribers() > 0){

        // Check if grabbed frame is actually full with some content
        if(!frame.empty()) {
            // Flip the image if necessary
            if (flip_image)
                cv::flip(frame, frame, flip_value);
                  cv::Mat left_image=frame(cv::Rect(0,0,640,480));
  cv::Mat

right_image=frame(cv::Rect(640,0,640,480));

            msg_left = cv_bridge::CvImage(header, "bgr8",

left_image).toImageMsg(); msg_right = cv_bridge::CvImage(header, "bgr8", right_image).toImageMsg();

            // Create a default camera info if we didn't get a stored

one on initialization if (cam_info_msg.distortion_model == ""){ ROS_WARN_STREAM("No calibration file given, publishing a reasonable default camera info."); cam_info_msg = get_default_camera_info_from_image(msg_left); cam_info_manager.setCameraInfo(cam_info_msg); } // The timestamps are in sync thanks to this publisher ros::Time pub_time=ros::Time::now();

            pub_right.publish(*msg_right,

cam_info_msg, pub_time); pub_left.publish(*msg_left, cam_info_msg, pub_time);

        }

        ros::spinOnce();
    }
    r.sleep();
} }