How do you add more outcomes to a SMACH Monitor State?

asked 2021-09-28 13:54:39 -0500

ROSNewbie gravatar image

Hi all, currently I have a monitor state from the smach package that looks at a topic. When a message on that topic is received it goes to the callback function.

In that function I have a bunch of if statements that check what is the message it just received and performs an action.

Currently I have it returning to the monitor state and keep checking if a new message has come in.

My problem is that I want it to leave the monitor state, to other states, based on the received message but the outcome options are too limited. The following link shows how this is normally written :

http://wiki.ros.org/smach/Tutorials/M...

If the message is invalid they go to a next state, if not return to the monitor state. However I want to go to different states based on the message itself.

Here is a pseudocode of what I want to do

 If message_received == "one"
        return state1
 elif message_received == "two"
        return state2
 elif message_received == "three"
        return state3

However we can only return either of two states and one of them is already taken with returning to the monitor state. Looking at the "source code" we can't set the outcomes:

https://github.com/ros/executive_smac...

One attempt to bypass this was to save the message data in the userdata, then return to a state, pass the userdata from the monitor state to that other state and do all the fancy returns from that state. The issue with this is that I'd miss any incoming messages while in this other state.

Another possibility is editing the source code but that seems like a final option to me. Any advice?

edit retag flag offensive close merge delete

Comments

1

A suggestion is to inherit the Class MonitorState and modify it to your needs to handle multiple states. Since threads are required be mindful as you will need to manage them as well.

def _cb(self,msg,ud) :
    try:
        if self._cond_cb(ud, msg):
            self._n_checks +=1
        else:
            self._trigger_event.set()
    except Exception as e:
        rospy.logerr("Error thrown while executing condition callback %s: %s" % (str(self._cond_cb), e))
        self._trigger_event.set()
osilva gravatar image osilva  ( 2021-10-04 09:47:16 -0500 )edit

Hello osilva, your suggestion is great! However can you expand on the thread management part, as I've never used such packages before. Or suggest some resources to learn them. Also, in my code how after I define my inherited class how do I call it in the state constructor? The default way is smach_ros.MonitorState, how would I call the one I modified?

ROSNewbie gravatar image ROSNewbie  ( 2021-10-05 10:12:11 -0500 )edit

Look up for working with threads in Python. If you create a new class you will need to compile your modified smash ros package again. Your new class will have the option to manage more than one state

osilva gravatar image osilva  ( 2021-10-05 12:34:24 -0500 )edit