00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 from __future__ import with_statement
00036
00037 import time
00038
00039 import roslib.packages
00040 import rosmsg
00041 import rospy
00042
00043 import actionlib
00044 import rostopic
00045
00046 from rosh.impl.namespace import Namespace, Concept
00047 import rosh.impl.msg
00048 import rosh.impl.topic
00049
00050 class Container(object):
00051 def __init__(self):
00052 self.obj = None
00053 def __call__(self, arg):
00054 self.obj = arg
00055
00056
00057 class Goal(object):
00058
00059 def __init__(self, topic, goal_id):
00060 self.topic = topic
00061 self.goal_id = goal_id
00062
00063 def __repr__(self):
00064 return self.goal_id.id
00065
00066
00067
00068
00069 def cancel(self):
00070
00071
00072 self.topic.cancel(id=self.goal_id.id)
00073
00074 class Action(Namespace):
00075
00076 def __init__(self, name, config):
00077 """
00078 ctor.
00079 @param config: Namespace configuration instance with additional 'listener' attribute.
00080 @type config: L{NamespaceConfig}
00081 """
00082 super(Action, self).__init__(name, config)
00083 self._type = self._type_name = None
00084 self._goal = None
00085
00086 self._init_action()
00087
00088 def _get_type(self):
00089 "rostype() API"
00090 return self._type
00091
00092 def status(self):
00093 base_topic = self._config.ctx.topics[self._name]
00094 status_topic = base_topic['status']
00095
00096 c = Container()
00097 with rosh.impl.topic.subscribe(status_topic, c):
00098 while c.obj is None:
00099 time.sleep(0.001)
00100 return c.obj
00101
00102 def goals(self):
00103 s = self.status()
00104
00105 base_topic = self._config.ctx.topics[self._name]
00106 return [Goal(base_topic, s.goal_id) for s in s.status_list]
00107
00108 def __getitem__(self, key):
00109 if key in ['goals', 'status']:
00110 return object.__getattribute__(self, key)
00111 else:
00112 return super(Action, self).__getitem__(key)
00113
00114 def _list(self):
00115 """
00116 Override Namespace._list()
00117 """
00118 try:
00119
00120
00121
00122
00123 pubs = self._config.master.getPublishedTopics(self._ns)
00124 candidates = [p[0] for p in pubs if p[0].endswith('/status')]
00125 pub_names = [p[0] for p in pubs]
00126 matches = []
00127 for c in candidates:
00128 stem = c[:-len('status')]
00129 if stem and stem+'result' in pub_names:
00130 matches.append(stem)
00131 if self._name and matches:
00132 return matches + ['/goals', '/status']
00133 else:
00134 return matches
00135 except:
00136 return []
00137
00138 def __repr__(self):
00139 return self.__str__()
00140
00141 def __str__(self):
00142
00143 if self._type is None and self._type_name is not None:
00144 self._init_action()
00145
00146 if self._type is not None:
00147 return rosmsg.get_msg_text(self._goal._type)
00148 else:
00149 return self._ns
00150
00151 def _init_action(self):
00152 if self._ns == '/':
00153 return
00154 if self._type is None:
00155
00156 feedback_topic = roslib.names.ns_join(self._ns, 'feedback')
00157 feedback_type_name = rostopic.get_topic_type(feedback_topic, blocking=False)[0]
00158 if feedback_type_name and feedback_type_name.endswith('Feedback'):
00159 self._type_name = feedback_type_name[:-len('Feedback')]
00160 if not self._type_name.endswith('Action'):
00161
00162 self._type_name = None
00163 else:
00164
00165 self._type = rosh.impl.msg.get_message_class(self._type_name)
00166 if self._type is not None:
00167
00168 self._goal = rosh.impl.msg.get_message_class(self._type_name[:-len('Action')]+'Goal')
00169
00170 def __call__(self, *args, **kwds):
00171 """
00172 @return: current transform
00173 @rtype: L{Transform}
00174 """
00175 if self._type is None:
00176 self._init_action()
00177 goal = self._goal(*args, **kwds)
00178 client = actionlib.SimpleActionClient(self._name[1:], self._type)
00179 client.wait_for_server()
00180 client.send_goal(goal)
00181 client.wait_for_result()
00182 return client.get_result()
00183
00184 class Actions(Concept):
00185
00186 def __init__(self, ctx, lock):
00187 super(Actions, self).__init__(ctx, lock, Action)
00188