$search
00001 #!/usr/bin/python 00002 ################################################################# 00003 ##\file 00004 # 00005 # \note 00006 # Copyright (c) 2011 \n 00007 # Cardiff University \n\n 00008 # 00009 ################################################################# 00010 # 00011 # \note 00012 # Project name: Multi-Role Shadow Robotic System for Independent Living 00013 # \note 00014 # ROS stack name: srs 00015 # \note 00016 # ROS package name: srs_decision_making 00017 # 00018 # \author 00019 # Author: Renxi Qiu, email: renxi.qiu@gmail.com 00020 # 00021 # \date Date of creation: Oct 2011 00022 # 00023 # \brief 00024 # Task coordination and interfacing for SRS decision making 00025 # 00026 ################################################################# 00027 # 00028 # Redistribution and use in source and binary forms, with or without 00029 # modification, are permitted provided that the following conditions are met: 00030 # 00031 # - Redistributions of source code must retain the above copyright 00032 # notice, this list of conditions and the following disclaimer. \n 00033 # 00034 # - Redistributions in binary form must reproduce the above copyright 00035 # notice, this list of conditions and the following disclaimer in the 00036 # documentation and/or other materials provided with the distribution. \n 00037 # 00038 # This program is free software: you can redistribute it and/or modify 00039 # it under the terms of the GNU Lesser General Public License LGPL as 00040 # published by the Free Software Foundation, either version 3 of the 00041 # License, or (at your option) any later version. 00042 # 00043 # This program is distributed in the hope that it will be useful, 00044 # but WITHOUT ANY WARRANTY; without even the implied warranty of 00045 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00046 # GNU Lesser General Public License LGPL for more details. 00047 # 00048 # You should have received a copy of the GNU Lesser General Public 00049 # License LGPL along with this program. 00050 # If not, see <http://www.gnu.org/licenses/>. 00051 # 00052 ################################################################# 00053 00054 import roslib; roslib.load_manifest('srs_decision_making') 00055 00056 #roslib.load_manifest('knowledge_ros_service') 00057 00058 import rospy 00059 import smach 00060 import smach_ros 00061 import sys, os, traceback, optparse, time, string, threading 00062 from actionlib import * 00063 from actionlib.msg import * 00064 from smach import Iterator, StateMachine, CBState 00065 from smach_ros import ConditionState, IntrospectionServer 00066 00067 from srs_knowledge.srv import * 00068 from srs_knowledge.msg import * 00069 00070 #from cob_tray_sensors.srv import * 00071 00072 import util.json_parser as json_parser 00073 00074 """ 00075 smach introspection server not working in electric yet, modify the executive_smach/smach_msgs/msg/SmachContainerStatus.msg below can bypass error: 00076 00077 # A pickled user data structure 00078 string local_data 00079 to: 00080 # A pickled user data structure 00081 uint8[] local_data 00082 00083 and 00084 00085 --- a/smach_ros/src/smach_ros/introspection.py Tue Aug 02 10:31:19 2011 -0700 00086 +++ b/smach_ros/src/smach_ros/introspection.py Thu Sep 29 22:31:48 2011 +0900 00087 @@ -219,7 +219,7 @@ 00088 path, 00089 self._container.get_initial_states(), 00090 self._container.get_active_states(), 00091 - pickle.dumps(self._container.userdata._data,2), 00092 + "", 00093 info_str) 00094 # Publish message 00095 self._status_pub.publish(state_msg) 00096 """ 00097 from srs_configuration_statemachines import * 00098 00099 """ 00100 sub-statemachines in use: 00101 ########################################### 00102 sm_approach_pose_assisted() 00103 #assisted navigation, operator could specify intermediate position for final goal 00104 00105 sm_detect_asisted_pose() 00106 #operator or KB could adjust the scanning pose 00107 00108 sm_open_door() 00109 #open door from IPA example 00110 00111 sm_pick_object_basic() 00112 #basic routine for pick object from IPA example 00113 00114 sm_detect_asisted_region() 00115 #operator or KB could specify region of interest 00116 #require generic state detect_object()taking key_region as input_key 00117 00118 sm_detect_asisted_pose_region() 00119 #detect object, both base pose and region can be adjusted 00120 #require generic state detect_object()taking key_region as input_key 00121 00122 sm_pick_object_asisted() 00123 #pick object with user intervention for error handling 00124 #require generic state grasp_general()taking grasp_conf as input_key 00125 00126 sm_enviroment_object_update() 00127 #updating the environment and find object 00128 #require generic state verify_object() and update_env_model() 00129 00130 ########################################## 00131 00132 states need to be developed within SRS 00133 ########################################## 00134 detect_object() 00135 #taking key_region as input_key 00136 #from srs_asisted_detect module 00137 00138 grasp_general() 00139 #taking grasp_conf as input_key 00140 #from srs_asisted_grasp module 00141 00142 verify_object() 00143 # model fitting from PRO 00144 00145 00146 update_env_model() 00147 # update environment model from IPA 00148 ########################################## 00149 """ 00150 00151 00152 00153 #Customised Action sever designed for overwriting SimpleActionServer pre-empty sequence 00154 class SRSActionServer(SimpleActionServer): 00155 def _init_(self, name, ActionSpec, execute_cb, auto_start): 00156 super(SRSActionServer, self).__init__(name, ActionSpec, execute_cb, auto_start) 00157 00158 def take_next_goal(self): 00159 #accept the next goal 00160 rospy.loginfo("Receiving a new goal") 00161 self.current_goal = self.next_goal 00162 self.new_goal = False 00163 #set preempt to request to equal the preempt state of the new goal 00164 rospy.loginfo("preempt_request %s", self.preempt_request) 00165 rospy.loginfo("new_goal preempt_request %s", self.new_goal_preempt_request) 00166 self.preempt_request = self.new_goal_preempt_request 00167 self.new_goal_preempt_request = False 00168 #set the status of the current goal to be active 00169 self.current_goal.set_accepted("This goal has been accepted by the simple action server"); 00170 return self.current_goal.get_goal() 00171 00172 00173 def accept_new_goal(self): 00174 with self.lock: 00175 if not self.new_goal or not self.next_goal.get_goal(): 00176 rospy.loginfo("Attempting to accept the next goal when a new goal is not available"); 00177 return None; 00178 00179 #check if we need to send a preempted message for the goal that we're currently pursuing 00180 if self.is_active() and self.current_goal.get_goal() and self.current_goal != self.next_goal: 00181 #self.current_goal.set_canceled(None, "This goal was cancelled because another goal was received by the simple action server"); 00182 self.next_goal.set_rejected(None, "This goal was rejected because the server is busy with another task") 00183 rospy.loginfo("Postpone a new goal") 00184 else: 00185 #accept the next goal 00186 rospy.loginfo("Receiving a new goal") 00187 self.current_goal = self.next_goal 00188 self.new_goal = False 00189 #set preempt to request to equal the preempt state of the new goal 00190 rospy.loginfo("preempt_request %s", self.preempt_request) 00191 rospy.loginfo("new_goal preempt_request %s", self.new_goal_preempt_request) 00192 00193 self.preempt_request = self.new_goal_preempt_request 00194 self.new_goal_preempt_request = False 00195 #set the status of the current goal to be active 00196 self.current_goal.set_accepted("This goal has been accepted by the simple action server"); 00197 00198 00199 return self.current_goal.get_goal() 00200 00201 00202 """ 00203 with self.lock: 00204 if not self.new_goal or not self.next_goal.get_goal(): 00205 rospy.loginfo("Attempting to accept the next goal when a new goal is not available"); 00206 00207 global current_task_info 00208 00209 _result = xmsg.ExecutionResult() 00210 _result.return_value=3 00211 00212 00213 #check if we need to send a preempted message for the goal that we're currently pursuing 00214 if self.is_active() and self.current_goal.get_goal() and self.current_goal != self.next_goal: 00215 #self.current_goal.set_canceled(None, "This goal was cancelled because another goal was received by the simple action server"); 00216 self.next_goal.set_rejected(None, "This goal was rejected because the server is busy with another task") 00217 rospy.loginfo("Postpone a new goal") 00218 00219 elif self.next_goal.get_goal().action == 'pause': 00220 current_task_info.set_pause_required(True) 00221 self.next_goal.set_accepted("") 00222 self.next_goal.set_succeeded(_result, 'pause acknowledged') 00223 00224 elif self.next_goal.get_goal().action == 'resume': 00225 if current_task_info.get_pause_required() == True: # already paused 00226 current_task_info.set_pause_required(False) 00227 self.next_goal.set_accepted("") 00228 self.next_goal.set_succeeded(_result, 'resume acknowledged') 00229 else: 00230 _result.return_value = 2 00231 self.next_goal.set_aborted(_result, 'not paused, no need for resuming') 00232 pass 00233 00234 else: 00235 if not self.current_goal.get_goal(): 00236 # current goal is null 00237 return self.take_next_goal() 00238 if self.next_goal.get_goal().action == 'stop': 00239 current_task_info.set_stop_required(True) 00240 return self.take_next_goal() 00241 if self.next_goal.get_goal().priority > self.current_goal.get_goal().priority: 00242 current_task_info.set_customised_preempt_required(True) 00243 return self.take_next_goal() 00244 00245 return None 00246 """ 00247 00248 00249 class SRS_DM_ACTION(object): 00250 #action server for taking tasks 00251 def __init__(self, name): 00252 00253 self._action_name = name 00254 self._as = SRSActionServer(self._action_name, xmsg.ExecutionAction, self.execute_cb, auto_start=False) 00255 self._feedback = xmsg.ExecutionFeedback() 00256 self._result = xmsg.ExecutionResult() 00257 self._task = "" 00258 self._parameter = "" 00259 self._as.start() 00260 self.robot_initialised= False 00261 00262 00263 #self._as.register_goal_callback(self.goal_cb) 00264 self._as.register_preempt_callback(self.priority_cb) 00265 00266 rospy.loginfo("Waiting for wake up the server ...") 00267 00268 00269 00270 00271 def robot_initialisation_process(self): 00272 if not self.robot_initialised : 00273 #initialisation of the robot 00274 # move to initial positions 00275 global sss 00276 #handle_torso = sss.move("torso", "home", False) 00277 #handle_tray = sss.move("tray", "down", False) 00278 #handle_arm = sss.move("arm", "folded", False) 00279 #handle_sdh = sss.move("sdh", "cylclosed", False) 00280 #handle_head = sss.move("head", "front", False) 00281 00282 00283 # wait for initial movements to finish 00284 #handle_torso.wait() 00285 #handle_tray.wait() 00286 #handle_arm.wait() 00287 #handle_sdh.wait() 00288 #handle_head.wait() 00289 self.robot_initialised = True 00290 00291 00292 00293 00294 def init_sm(self): 00295 self.temp = smach.StateMachine(outcomes=['task_succeeded','task_aborted', 'task_preempted']) 00296 00297 # 00298 self.temp.userdata.target_base_pose=Pose2D() 00299 self.temp.userdata.target_object_name='' 00300 self.temp.userdata.target_object_pose=Pose() 00301 self.temp.userdata.the_target_object_found = 'sadsadsadsadsda' 00302 self.temp.userdata.verified_target_object_pose=Pose() 00303 00304 #session id for current task, on id per task. 00305 #session id can be shared by different clients 00306 self.session_id = 0 00307 00308 #user intervention is possible or not. 00309 #False, DM has to make all the decision by it self 00310 #True, suitable client has been connected, can be relied on 00311 self.temp.userdata.semi_autonomous_mode=True 00312 00313 00314 # open the container 00315 with self.temp: 00316 # add states to the container 00317 smach.StateMachine.add('INITIALISE', initialise(), 00318 transitions={'succeeded':'SEMANTIC_DM', 'failed':'task_aborted'}) 00319 00320 smach.StateMachine.add('SEMANTIC_DM', semantic_dm(), 00321 transitions={'succeeded':'task_succeeded', 00322 'failed':'task_aborted', 00323 'preempted':'task_preempted', 00324 'navigation':'SM_NAVIGATION', 00325 'detection':'SM_DETECTION', 00326 'simple_grasp':'SM_OLD_GRASP', 00327 'full_grasp':'SM_NEW_GRASP', 00328 'put_on_tray':'SM_PUT_ON_TRAY', 00329 'env_update':'SM_ENV_UPDATE'}, 00330 remapping={'target_base_pose':'target_base_pose', 00331 'target_object_name':'target_object_name', 00332 'target_object_pose':'target_object_pose', 00333 'target_object_id':'target_object_id', 00334 'target_object':'the_target_object_found', 00335 'target_workspace_name':'target_workspace_name', 00336 'semi_autonomous_mode':'semi_autonomous_mode', 00337 'grasp_categorisation':'grasp_categorisation', 00338 'scan_pose_list':'scan_pose_list'}) 00339 00340 smach.StateMachine.add('SM_NAVIGATION', srs_navigation_operation(), 00341 transitions={'succeeded':'SEMANTIC_DM', 'not_completed':'SEMANTIC_DM', 'failed':'SEMANTIC_DM','stopped':'task_preempted','preempted':'task_preempted'}, 00342 remapping={'target_base_pose':'target_base_pose', 00343 'semi_autonomous_mode':'semi_autonomous_mode'}) 00344 00345 smach.StateMachine.add('SM_DETECTION', srs_detection_operation(), 00346 transitions={'succeeded':'SEMANTIC_DM', 'not_completed':'SEMANTIC_DM', 'failed':'SEMANTIC_DM','stopped':'task_preempted','preempted':'task_preempted'}, 00347 remapping={'target_object_name':'target_object_name', 00348 'target_object_id':'target_object_id', 00349 'target_workspace_name':'target_workspace_name', 00350 'semi_autonomous_mode':'semi_autonomous_mode', 00351 'target_object':'the_target_object_found', 00352 'target_object_pose':'target_object_pose' }) 00353 00354 smach.StateMachine.add('SM_NEW_GRASP', srs_grasp_operation(), 00355 transitions={'succeeded':'SEMANTIC_DM', 'not_completed':'SEMANTIC_DM', 'failed':'SEMANTIC_DM','stopped':'task_preempted','preempted':'task_preempted'}, 00356 remapping={'target_object_name':'target_object_name', 00357 'target_object_id':'target_object_id', 00358 'target_workspace_name':'target_workspace_name', 00359 'semi_autonomous_mode':'semi_autonomous_mode', 00360 'target_object':'the_target_object_found', 00361 'target_object_pose':'target_object_pose', 00362 'grasp_categorisation':'grasp_categorisation'}) 00363 00364 ''' 00365 START 00366 #Old grasp added for backward compatible, should be removed after knowledge service updated completely 00367 ''' 00368 smach.StateMachine.add('SM_OLD_GRASP', srs_old_grasp_operation(), 00369 transitions={'succeeded':'SEMANTIC_DM', 'not_completed':'SEMANTIC_DM', 'failed':'SEMANTIC_DM','stopped':'task_preempted','preempted':'task_preempted'}, 00370 remapping={'target_object_name':'target_object_name', 00371 'semi_autonomous_mode':'semi_autonomous_mode', 00372 'target_object_id':'target_object_id', 00373 'target_object':'the_target_object_found', 00374 'grasp_categorisation':'grasp_categorisation'}) 00375 ''' 00376 #Old grasp added for backward compatible, should be removed after knowledge service updated completely 00377 END 00378 ''' 00379 00380 smach.StateMachine.add('SM_PUT_ON_TRAY', srs_put_on_tray_operation(), 00381 transitions={'succeeded':'SEMANTIC_DM', 'not_completed':'SEMANTIC_DM', 'failed':'SEMANTIC_DM','stopped':'task_preempted','preempted':'task_preempted'}, 00382 remapping={'grasp_categorisation':'grasp_categorisation' }) 00383 00384 smach.StateMachine.add('SM_ENV_UPDATE', srs_enviroment_update_operation(), 00385 transitions={'succeeded':'SEMANTIC_DM', 'not_completed':'SEMANTIC_DM', 'failed':'SEMANTIC_DM','stopped':'task_preempted','preempted':'task_preempted'}, 00386 remapping={'target_object_pose':'target_object_pose', 00387 'target_object_hh_id':'target_object_hh_id', 00388 'verified_target_object_pose':'verified_target_object_pose'}) 00389 00390 00391 00392 return self.temp 00393 00394 00395 00396 def priority_cb(self): 00397 #rospy.loginfo("setting priority") 00398 # when this function is called self._as.preempt_request = True due to default policy of the simple action server 00399 # this function override the default policy by compare the priority 00400 self._as.preempt_request = False # overwrite the default preempt policy of the simple action server 00401 00402 global current_task_info 00403 result = xmsg.ExecutionResult() 00404 result.return_value=3 00405 #checking if there is a new goal and comparing the priority 00406 if self._as.next_goal.get_goal() and self._as.new_goal: 00407 print self._as.next_goal.get_goal() 00408 print self._as.new_goal 00409 00410 #new goal exist 00411 if self._as.next_goal.get_goal().action == 'stop': 00412 current_task_info.set_stop_required(True) 00413 elif self._as.next_goal.get_goal().action == 'pause': 00414 current_task_info.set_pause_required(True) 00415 self._as.next_goal.set_accepted("") 00416 self._as.next_goal.set_succeeded(result, 'pause acknowledged') 00417 self._as.new_goal=False 00418 self._as.new_goal_preempt_request = False 00419 elif self._as.next_goal.get_goal().action == 'resume': 00420 if current_task_info.get_pause_required() == True: # already paused 00421 current_task_info.set_pause_required(False) 00422 self._as.next_goal.set_accepted("") 00423 self._as.next_goal.set_succeeded(result, 'resume acknowledged') 00424 else: 00425 result.return_value=2 00426 self._as.next_goal.set_accepted("") 00427 self._as.next_goal.set_aborted(result, 'not paused, no need for resuming') 00428 self._as.new_goal=False 00429 self._as.new_goal_preempt_request = False 00430 elif self._as.next_goal.get_goal().priority > self._as.current_goal.get_goal().priority: 00431 current_task_info.set_customised_preempt_required(True) 00432 else: 00433 # pre-empty request is come from the same goal 00434 self._sm_srs.request_preempt() 00435 00436 #def preempt_check(self): 00437 # if self.get_customised_preempt_required()==True: 00438 # self.set_customised_preempt_required(False) 00439 # return True 00440 # return False 00441 00442 00443 def execute_cb(self, gh): 00444 00445 self._feedback.current_state = "initialisation" 00446 self._feedback.solution_required = False 00447 self._feedback.exceptional_case_id = 0 00448 self._as.publish_feedback(self._feedback) 00449 #goal=self._as.current_goal.get_goal() 00450 rospy.Subscriber("fb_executing_solution", Bool, self.callback_fb_solution_req) 00451 rospy.Subscriber("fb_executing_state", String, self.callback_fb_current_state) 00452 00453 goal_handler = self._as.current_goal 00454 current_goal = goal_handler.get_goal() 00455 00456 #initialise task information for the state machine 00457 global current_task_info 00458 current_task_info.task_name = current_goal.action 00459 #if current_task_info.task_name=="": 00460 # current_task_info.task_name="get" 00461 current_task_info.task_parameter = current_goal.parameter 00462 00463 current_task_info.json_parameters = current_goal.json_parameters 00464 00465 ## added by Ze 00466 # current_task_info.task_parameters = current_goal.parameters 00467 00468 if current_task_info.task_name=='stop': 00469 current_task_info.set_stop_acknowledged(False) # 00470 current_task_info.set_stop_required(False) 00471 00472 print ("customised_preempt_acknowledged:", current_task_info.get_customised_preempt_acknowledged()) 00473 print ("customised_preempt_required:", current_task_info.get_customised_preempt_required()) 00474 print ("stop_acknowledged:", current_task_info.get_stop_acknowledged()) 00475 print ("stop_required:", current_task_info.get_stop_required()) 00476 print ("object_identification_state:", current_task_info.get_object_identification_state()) 00477 00478 00479 00480 if not self.robot_initialised: 00481 self.robot_initialisation_process() 00482 00483 current_task_info._srs_as = copy.copy(self) 00484 00485 00486 00487 ############################################## 00488 # taskrequest From Knowledge_ros_service 00489 ############################################## 00490 print '####################### Action Accept Command' 00491 print gh 00492 print 'Request new task' 00493 rospy.wait_for_service('task_request') 00494 try: 00495 requestNewTask = rospy.ServiceProxy('task_request', TaskRequest) 00496 #res = requestNewTask(current_task_info.task_name, current_task_info.task_parameter, None, None, None, None) 00497 req = TaskRequestRequest() 00498 req.task = current_task_info.task_name 00499 00500 ## added by ze 00501 pars = current_task_info.task_parameter.split("%") 00502 length = len(pars) 00503 if length == 1: 00504 req.content = current_task_info.task_parameter 00505 req.userPose = "order" 00506 elif length == 2: 00507 req.content = pars[0] 00508 req.userPose = pars[1] 00509 print req.content 00510 print req.userPose 00511 # req.parameters = current_task_info.parameters 00512 00513 00514 ### json parameters 00515 if not current_task_info.json_parameters == '': 00516 print current_task_info.json_parameters 00517 tasks = json_parser.Tasks(current_task_info.json_parameters) 00518 if len(tasks.tasks_list) > 0: 00519 #task_dict = tt.tasks[0] 00520 #task_json = tt.tasks_json[0] 00521 ## read parameter server 00522 grasp_type = rospy.get_param("srs/grasping_type") 00523 tasks.tasks_list[0].addItem('grasping_type', grasp_type) 00524 00525 req.json_parameters = tasks.tasks_list[0].task_json_string 00526 00527 res = requestNewTask(req) 00528 #res = requestNewTask(current_task_info.task_name, current_task_info.task_parameter, "order") 00529 print 'Task created with session id of: ' + str(res.sessionId) 00530 current_task_info.session_id = res.sessionId 00531 00532 if not current_task_info.json_parameters == '': 00533 #current_task_info.task_feedback = json_parser.Task_Feedback (gh.comm_state_machine.action_goal.goal_id.id , tasks.device_id, tasks.device_type, req.json_parameters) 00534 current_task_info.task_feedback = json_parser.Task_Feedback (current_task_info.session_id , tasks.device_id, tasks.device_type, req.json_parameters) 00535 00536 #### 00537 00538 if res.result == 1: 00539 self._as.set_aborted(self._result) 00540 return 00541 #elif res.result == 0: 00542 00543 except rospy.ServiceException, e: 00544 print "Service call failed: %s"%e 00545 ############################################## 00546 # END OF taskrequest From Knowledge_ros_service 00547 ############################################## 00548 00549 00550 00551 #initial internal state machine for task 00552 # As action server, the SRSActionServer is also a state machine with basic priority handling ability by itself, 00553 # Therefore there is no need for a 'idle'/'wait for task' state in this state machine. 00554 self._sm_srs = self.init_sm() 00555 self.sis=smach_ros.IntrospectionServer('TASK_SM',self._sm_srs,'/SM_ROOT') 00556 #display smach state 00557 self.sis.start() 00558 self._as.is_active() 00559 #run the state machine for the task 00560 outcome = self._sm_srs.execute() 00561 self.sis.stop() 00562 00563 #Testing recorded task execution history 00564 if len (current_task_info.last_step_info) > 1 : 00565 last_step=current_task_info.last_step_info.pop() 00566 rospy.loginfo("sm last step name: %s", last_step.step_name) 00567 rospy.loginfo("sm last step session ID: %s", current_task_info.session_id) 00568 00569 #set outcomes based on the execution result 00570 00571 #if self.preempt_check()==True: 00572 # self._result.return_value=2 00573 # self._as.set_preempted(self._result) 00574 # return 00575 00576 00577 current_task_info.set_customised_preempt_acknowledged(False) 00578 current_task_info.set_customised_preempt_required(False) 00579 current_task_info.set_stop_acknowledged(False) 00580 current_task_info.set_stop_required(False) 00581 current_task_info.set_object_identification_state(False) 00582 00583 #I am not sure this is needed, to be discussed with UI developers 00584 current_task_info.set_pause_required(False) 00585 00586 if outcome == "task_succeeded": 00587 self._result.return_value=3 00588 self._as.set_succeeded(self._result) 00589 return 00590 if outcome == "task_preempted": 00591 self._result.return_value=2 00592 self._as.set_preempted(self._result, "stopped before complete or preempted by another task") 00593 #for all other cases outcome == "task_aborted": 00594 self._result.return_value=4 00595 self._as.set_aborted(self._result) 00596 00597 00598 def callback_fb_solution_req(self, data): 00599 #rospy.loginfo("I heard %s",data.data) 00600 self._feedback.solution_required = data.data 00601 self._as.publish_feedback(self._feedback) 00602 00603 def callback_fb_current_state(self, data): 00604 #rospy.loginfo("I heard %s",data.data) 00605 self._feedback.current_state = data.data 00606 self._as.publish_feedback(self._feedback) 00607 00608 def task_executor(self, gh): 00609 pass 00610 00611 00612 if __name__ == '__main__': 00613 rospy.init_node('srs_decision_making_actions') 00614 SRS_DM_ACTION(rospy.get_name()) 00615 rospy.spin() 00616 #global listener 00617 #listener = tf.TransformListener() 00618