0
$\begingroup$

Rosanswers logo

My end goal is to have a callback receive a message and until the next message is received to run a few lines of code in an infinite loop.

My initial thought was to create a MultiThreadedSpinner and implement the callback like so. Where stop is a global variable.

void callback(const std_msgs::UInt8::ConstPtr &msg) {
  if (msg->data == 1) {
    stop = true;
    return;   
  }
  // else start the loop
  stop = false;
  while (!stop) {
    //simple serial connection code
    // sleep 500ms
  }
}

When the messages is received it would create a blacking callback. Then when a new message is received it would set the stop variable and the first started callback would then end. But from what I seem to have figured out the MultiThreadedSpinner will not call the same callback again while one is already running.

Hopefully that makes some sense. Any thoughts on how to do this?

EDIT - Bigger Picture My input device sends int as messages. Let's say it can be 0, 1 or 2. Where 0 is no action, 1 is action 1 and 2 is action 2. The way the device works is that it only sends a message on action change. Read differently, there are no messages when an action is held.

After action 1 or 2 you are guaranteed to receive action 0 first before anything else.

My output device needs to incrementally move a small delta (forward for 1 and reverse for 2) while an action is being performed and stop moving when the action stops being performed. Essentially I have to manually jog the robot by small increments when the first message is sent until the next message is sent.


Originally posted by kdorsel on ROS Answers with karma: 21 on 2015-03-16

Post score: 0


Original comments

Comment by gvdhoorn on 2015-03-17:
Could you perhaps tell us what it is that you are trying to achieve exactly? Trying to use loops in msg callbacks is often a sign of larger issues with the design of a node.

Comment by kdorsel on 2015-03-17:
I understand that callbacks should not be blocked, but I really can't see any other way to do this. I've update the question with more information.

Comment by gvdhoorn on 2015-03-17:
Also: what kind of robot are we talking about here? Perhaps there is an easier / better way of controlling it?

Comment by kdorsel on 2015-03-17:
Using a crs a255 5 axis robot. It doesn't have a continuous mode, only incremental or final destination. To move it while the action is happening I need to continuously send small increments.

Comment by gvdhoorn on 2015-03-17:
I've no experience with those robots, but from the RAPL-3 manual it looks like there may be some things possible. Have you considered writing a ROS driver for it?

Comment by kdorsel on 2015-03-17:
I've read through all the documentation i can find. This page from another document sums it up nicely. https://dl.dropboxusercontent.com/u/24907/crs-a255.png . There's no continuous motion for the RAPL-3 or ASH interface. I only have access to the jog type command

Comment by gvdhoorn on 2015-03-17:
What about using c(t)path(..) with plocs as teachables? I don't know about velocity, but that does seem to allow you to map a JointTrajectory msg to a trajectory for your ctrlr.

$\endgroup$

2 Answers 2

1
$\begingroup$

Rosanswers logo

I understand that callbacks should not be blocked, but I really can't see any other way to do this. I've update the question with more information.

Decoupling handling incoming msgs from actually processing them is an often used approach in ROS. Your cb can just append incoming msgs to a queue, which a separate thread processes. You could also think about adding a time or length field to your msgs, to sync processing to time. Provided enough accuracy (and synchronised clocks), you'd end up with a sort-of trajectory.


Edit:

[..] Essentially I have to manually jog the robot by small increments when the first message is sent until the next message is sent.

That last line suggests a state machine: NOT_JOGGING and JOGGING. The output of the state machine would be determined by the state. The transition between the states is then guarded by your input msgs. Seems straightforward enough to me?


Edit2:

So essentially create a secondary thread that monitors some global variables and sends the necessary jog commands to the robot. And have the cb just update those variables.

Depends on how 'clean' you want this. You could use a producer-consumer pattern between your state machine (SM) and your node. The SM then consumes incoming events as part of its update loop. Transitions are triggered based on input in the queue, etc. Callbacks write events to SM queue. You could even add more states to your machine, if you need them.


Originally posted by gvdhoorn with karma: 86574 on 2015-03-17

This answer was NOT ACCEPTED on the original site

Post score: 2


Original comments

Comment by kdorsel on 2015-03-17:
So essentially create a secondary thread that monitors some global variables and sends the necessary jog commands to the robot. And have the cb just update those variables.

Comment by gvdhoorn on 2015-03-17:
Btw, you don't necessarily need to spawn an additional thread: you could also just use ros::spinOnce(), or start an AsyncSpinner.

Comment by kdorsel on 2015-03-17:
I think the AsyncSpinner will be the next thing I try and have the SM loop right have the spinner.

$\endgroup$
0
$\begingroup$

Rosanswers logo

Have a look at the callback queue. http://wiki.ros.org/roscpp/Overview/Callbacks%20and%20Spinning http://docs.ros.org/api/roscpp/html/classros_1_1CallbackQueue.html

You could end your infinite loop when isEmpty() returns false.


Originally posted by BennyRe with karma: 2949 on 2015-03-17

This answer was NOT ACCEPTED on the original site

Post score: 1

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.