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

Boost thread blocking ros::spin

asked 2020-06-17 23:19:57 -0500

space gravatar image

updated 2022-01-22 16:10:37 -0500

Evgeny gravatar image

I have a class that has a member variable which is an object of another class

class SuperScanner {
      SuperScanner(ros::NodeHandle& nh, std::string cameraIP); 
       // Other functions
      Motor _motor;
      Camera _camera;
     // Other variables and functions

Within a function in the SuperScanner class, I'm creating a new thread that invokes image acquisition and then starts the motor motion. The camera needs to start recording before the motion starts, but must continue for a certain duration of time while the motor still moves.To do this, I'm using boost threads.

SuperScanner::getData() {
  boost::function<void()> scanFunc = boost::bind(&Camera::startAcquiring, _camera, scanTime, 
  boost::ref(cameraStatus), boost::ref(_results));

  // Start acquiring
  std::shared_ptr<boost::thread> threadPtr = std::make_shared<boost::thread>(scanFunc);

  // Send motor to target position

  // Join thread

 _log.print("Finished the acquisition");

This seems to run into trouble sometimes, with the ros spin thread getting blocked and not executing any callbacks to other topics subscribed to in SuperScanner. The "Finished the acquisition" statement does get printed out though, so I know the thread has joined. A ronsode info on the node shows the list of topics, but says "communication with node failed". Could this have anything to do with the member variables within the instance of the _camera object getting updated in its startAcquiring() function?

Here's how the node gets started:

int main(int argc, char** argv)
  ros::init(argc, argv, "super_scanner");
  ros::NodeHandle n("~");

  n.param("/camera_scanner/device_ip", deviceIP, deviceIP);
  SuperScanner superScanner(n, deviceIp);
  return 0;
edit retag flag offensive close merge delete


Maybe this comment is a little offtopic, but i personally feel like you could have better control of the system if you used a separate nodelet for image adquisition.

Solrac3589 gravatar image Solrac3589  ( 2020-06-18 00:54:24 -0500 )edit

1 Answer

Sort by ยป oldest newest most voted

answered 2020-06-18 00:23:25 -0500

fergs gravatar image

Looking at how your node get started - your SuperScanner class isn't even running - once you call "ros::spin()" that's will execute until the node is shutdown - it doesn't return. If you put a print statement in your SuperScanner constructor, you'll see that it won't print until after you CTRL-C the node. See the page on spinning for more details.

edit flag offensive delete link more


My bad. I removed some other classes that were being constructed in main() for clarity for this question and ended up putting that line in the wrong place. Edited to reflect the original sequence now.

space gravatar image space  ( 2020-06-18 00:28:12 -0500 )edit

in that case, your example code doesn't show how/who calls getData() - I presume it is a ROS service/subscriber callback? What does scanFunc do? If it is also relying on something ROS related, your spin() call is single-threaded, and your join() is going to block in that callback - meaning other callbacks won't get serviced. There is a multi-threaded spinner (see the same link I posted above) - but you'll want to make sure your callbacks are thread safe.

fergs gravatar image fergs  ( 2020-06-18 00:38:39 -0500 )edit

Yes, getData() is invoked in a ROS callback in the SuperScanner class. startAcquiring does not use any ROS callbacks though. In fact, the Camera object is an instance of a standalone, non ROS API for camera communication.

space gravatar image space  ( 2020-06-18 09:00:10 -0500 )edit

Question Tools



Asked: 2020-06-17 23:19:57 -0500

Seen: 914 times

Last updated: Jun 18 '20