1
2 import roslib; roslib.load_manifest('smach_ros')
3 import rospy
4
5 import threading
6 import traceback
7
8 import smach
9
10 __all__ = ['MonitorState']
11
13 """
14 A state that will check a given ROS topic with a condition function.
15 """
16 - def __init__(self, topic, msg_type, cond_cb, max_checks=-1,input_keys = [],output_keys=[]):
17 """State constructor
18 @type topic string
19 @param topic the topic to monitor
20
21 @type msg_type a ROS message type
22 @param msg_type determines the type of the monitored topic
23
24 @type max_checks int
25 @param max_checks the number of messages to receive and evaluate. If cond_cb returns False for any
26 of them, the state will finish with outcome 'invalid'. If cond_cb returns True for
27 all of them, the outcome will be 'valid'
28
29 """
30 smach.State.__init__(
31 self,
32 outcomes=['valid','invalid','preempted'],
33 input_keys = input_keys,
34 output_keys = output_keys)
35
36 self._topic = topic
37 self._msg_type = msg_type
38 self._cond_cb = cond_cb
39 self._max_checks = max_checks
40 self._n_checks = 0
41
42 self._trigger_event = threading.Event()
43
45
46 if self.preempt_requested():
47 self.service_preempt()
48 return 'preempted'
49
50 self._n_checks = 0
51 self._trigger_event.clear()
52
53 self._sub = rospy.Subscriber(self._topic, self._msg_type, self._cb, callback_args=ud)
54
55 self._trigger_event.wait()
56 self._sub.unregister()
57
58 if self.preempt_requested():
59 self.service_preempt()
60 return 'preempted'
61
62 if self._max_checks > 0 and self._n_checks >= self._max_checks:
63 return 'valid'
64
65 return 'invalid'
66
67 - def _cb(self,msg,ud) :
68 try:
69 if self._cond_cb(ud, msg):
70 self._n_checks +=1
71 else:
72 self._trigger_event.set()
73 except Exception as e:
74 rospy.logerr("Error thrown while executing condition callback %s: %s" % (str(self._cond_cb), e))
75 self._trigger_event.set()
76
77 if (self._max_checks > 0 and self._n_checks >= self._max_checks):
78 self._trigger_event.set()
79
83