Ask Your Question
0

Boost thread blocking ros::spin

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

space gravatar image

updated 2020-06-18 00:26:06 -0600

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

class SuperScanner {
     public:
      SuperScanner(ros::NodeHandle& nh, std::string cameraIP); 
       // Other functions
     private:
      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
  _motor.send();

  // Join thread
  threadPtr->join();

 _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);
  ros::spin();
  return 0;
}
edit retag flag offensive close merge delete

Comments

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 -0600 )edit

1 Answer

Sort by ยป oldest newest most voted
0

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

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

Comments

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 -0600 )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 -0600 )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 -0600 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

2 followers

Stats

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

Seen: 277 times

Last updated: Jun 18 '20