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

smach subscriber publisher

asked 2011-07-07 00:59:24 -0500

boy gravatar image

hello everyone,

I'm new to the ROS society, and I have some questions.

I've made a simple state machine,publisher and subscriber as was shown in the tutorials, but how can I use date obtained from the subscriber(e.g a simple String) to make a transition between two states in the state machine??


edit retag flag offensive close merge delete

3 Answers

Sort by ยป oldest newest most voted

answered 2011-07-07 09:55:01 -0500

Wim gravatar image

A smach state is simply a Python class (see the example in this tutorial), so you can add a normal ROS subscriber to that class if you want.

This means, in the subscriber callback you can store the message data (a string in your case) as a class memeber, and in the execute callback you can make decisions about outcomes based on tis class member.

edit flag offensive delete link more


Thanks for the answer Wim, but I still have some problems with it( Maybe its because I'm a rookie) . Could you(if it is not too much) give a small example??
boy gravatar image boy  ( 2011-07-07 21:48:21 -0500 )edit

answered 2011-07-07 22:39:43 -0500

Ugo gravatar image


This small (and untested) example subscribes on a topic and return success if 2 is received on this topic in the next 30 seconds.

#!/usr/bin/env python
import roslib; roslib.load_manifest('smach_example')
import rospy
import smach
import smach_ros
from std_msgs.msg import Int16
import time
import threading

class WaitForTwo(smach.State):
    def __init__(self):
        smach.State.__init__(self, outcomes=['success', 'in_progress', 'failed'])

        self.mutex = threading.Lock()
        self.two_received = False

        self.subscriber = rospy.Subscriber('/test', Int16, self.callback)

    def callback(self, data):
        if == 2:
            self.two_received = True

    def execute(self):
        #wait for a maximum of 30 seconds 
        for i in range(0, 300):
            if self.two_received:
                #ok we received 2
                return 'success'


            #still waiting
            return 'in_progress'
        #we didn't get 2 in the 30 sec
        return 'failed'
edit flag offensive delete link more

answered 2013-01-31 02:37:00 -0500

felix k gravatar image

updated 2013-02-01 03:58:54 -0500

Based on the callback-and-loop-in-execute-with-mutex scheme Ugo mentioned in his answer I made a fully generic message receiver smach.State class that helps a lot for receiving messages in a SMACH machine, as I couldn't made use of the the MonitorState.

The current feature set includes waiting, timeout, userdata access and latching, of course optional.

Class WaitForMsgState in module in unreleased package uashh_smach. The class CheckSmachEnabledState right underneath is a simple usage example

As the whole class has a lot of (docstring) lines I just post the up-to-date link to the module's file in the repository (and just for read only reference the commit-static link to its code line).

edit flag offensive delete link more



Felix, I just added this to a new page here to document 3rd party SMACH states:

jbohren gravatar image jbohren  ( 2013-01-31 03:15:08 -0500 )edit

Thanks alot for that cornerstone, that's exactly what I have been missing since I started using SMACH, a way to find existing useful SMACH code. (And what I planned to do after final code and modules cleanup..) I'll add my other states soon!

felix k gravatar image felix k  ( 2013-01-31 23:35:28 -0500 )edit

Hi, I am doing the same with my Smach machine.

Tony K gravatar image Tony K  ( 2013-07-11 14:28:04 -0500 )edit

Question Tools



Asked: 2011-07-07 00:59:24 -0500

Seen: 5,036 times

Last updated: Feb 01 '13