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

How to stop recording by camera node through an user input?

asked 2019-09-01 12:40:30 -0500

nav3128 gravatar image

updated 2019-09-01 14:45:34 -0500

I would like to stop the camera node through a different node. I was trying to implement this by sending a message through another node which is read by the camera node But, the problem is that the camera node runs on an infinite loop. Can I get a cpp implementation to stop this while loop through a subscribed message.

#include <ros/ros.h>
#include <image_transport/image_transport.h>
#include <opencv2/highgui/highgui.hpp>
#include <cv_bridge/cv_bridge.h>
#include <sstream> // for converting the command line parameter to integer
#include "std_msgs/Int32.h"

bool camOn = true;


void sendCamera(const std_msgs::Int32::ConstPtr& msg)
{
   if (msg->data == 1){
    camOn = true;}
   else if (msg->data == 2){
    camOn = false;}
}

int main(int argc, char** argv)
{


  ros::init(argc, argv, "image_publisher");
  ros::NodeHandle nh;
  ros::Subscriber sub = nh.subscribe("/camera_status", 1000, sendCamera);
  image_transport::ImageTransport it(nh);
  image_transport::Publisher pub = it.advertise("camera/image", 1);


  cv::VideoCapture cap(0);
  if(!cap.isOpened()) return 1;
  cv::Mat frame;
  sensor_msgs::ImagePtr msg;

  ros::Rate loop_rate(10);
    while(nh.ok()){
      while (camOn) {
        ros::Subscriber sub = nh.subscribe("/camera_status", 1000, sendCamera);
        cap >> frame;
        // Check if grabbed frame is actually full with some content
        if(!frame.empty()) {
          msg = cv_bridge::CvImage(std_msgs::Header(), "bgr8", frame).toImageMsg();
          pub.publish(msg);
          cv::waitKey(1);
        }

        ros::spin();
        loop_rate.sleep();
    }    
  }
}
edit retag flag offensive close merge delete

Comments

You could make the loop non-infinite.

Instead of

while(1){
}

you could use

while(keeprunning == 1){
}

and have a subscriber callback change to keeprunning = 0.

billy gravatar image billy  ( 2019-09-01 13:59:52 -0500 )edit

I have edited my question to show you my attempt. It's still not working.

nav3128 gravatar image nav3128  ( 2019-09-01 14:47:54 -0500 )edit

1 Answer

Sort by ยป oldest newest most voted
1

answered 2019-09-01 21:03:25 -0500

danscava gravatar image

You can subscribe a topic only once, there's no need to subscribe to the /camera_status every iteration in the loop.

Do you want to stop the camera recording or shutdown the node? I'm assuming you only want to stop the camera, not the node.

You should use spinOnce(), spin() will not return until your node receive a shutdown signal. There's no need for the inner while, you can check camOn using an if. Using the inner while, you can't shutdown the node properly when camOn is true.

Try this way:

while(nh.ok())
{
    if (camOn) 
    {
        cap >> frame;
        if(!frame.empty()) 
        {
          msg = cv_bridge::CvImage(std_msgs::Header(), "bgr8", frame).toImageMsg();
          pub.publish(msg);
          cv::waitKey(1);
        }        
    }
    ros::spinOnce();
    loop_rate.sleep();
}
edit flag offensive delete link more

Comments

Thank you so much for your answer. I am a beginner to ROS and I don't have a clear idea about spin function. Now, I think I have a fair understanding about it.

Thanks.

nav3128 gravatar image nav3128  ( 2019-09-02 02:45:31 -0500 )edit

In addition to this, I would advise using a service to trigger/toggle camOn or just a std_msgs/Bool would be enough since std_msgs::Int32 is an overkill for such a simple task:

void sendCamera(const std_msgs::Bool::ConstPtr &msg) {
  if (msg->data) {
    camOn = true;
  } else  {
    camOn = false;
  }
}
pavel92 gravatar image pavel92  ( 2019-09-02 02:48:36 -0500 )edit

Is it 'overkill' because of the bandwidth required or something else?

nav3128 gravatar image nav3128  ( 2019-09-02 03:00:08 -0500 )edit

Well the idea of your callback is to just set a global variable to true or false. I would personally use a service such as setBool to toggle the capturing to on/off. If you want to do it via a subscriber and a topic then I would use the Bool msg. In case of the bandwidth, the Int32 takes 4 bytes while the bool is just 1 byte. If you have more then 2 states to process in the callback then you can use an integer message, even Int8 would be enough it that case

pavel92 gravatar image pavel92  ( 2019-09-02 03:22:54 -0500 )edit

Question Tools

2 followers

Stats

Asked: 2019-09-01 12:40:30 -0500

Seen: 134 times

Last updated: Sep 01 '19