33import json
44import logging
55import time
6+ import threading
67from enum import Enum
78
89# Python 2/3 compatibility import list
@@ -553,6 +554,7 @@ def __init__(self, ros, name, action_type, reconnect_on_close=True):
553554 self ._service_callback = None
554555 self ._is_advertised = False
555556 self .reconnect_on_close = reconnect_on_close
557+ self .wait_results = {}
556558
557559 def send_goal (self , goal , resultback , feedback , errback ):
558560 """Start a call to an action.
@@ -572,6 +574,7 @@ def send_goal(self, goal, resultback, feedback, errback):
572574 return
573575
574576 action_goal_id = "send_action_goal:%s:%d" % (self .name , self .ros .id_counter )
577+ self .wait_results [action_goal_id ] = threading .Event ()
575578
576579 message = Message (
577580 {
@@ -584,7 +587,19 @@ def send_goal(self, goal, resultback, feedback, errback):
584587 }
585588 )
586589
587- self .ros .call_async_action (message , resultback , feedback , errback )
590+ def _internal_resultback (result ):
591+ wait_result_event = self .wait_results .get (action_goal_id )
592+ if wait_result_event is not None :
593+ wait_result_event .set ()
594+ resultback (result )
595+
596+ def _internal_errback (err ):
597+ wait_result_event = self .wait_results .get (action_goal_id )
598+ if wait_result_event is not None :
599+ wait_result_event .set ()
600+ errback (err )
601+
602+ self .ros .call_async_action (message , _internal_resultback , feedback , _internal_errback )
588603 return action_goal_id
589604
590605 def cancel_goal (self , goal_id ):
@@ -603,9 +618,28 @@ def cancel_goal(self, goal_id):
603618 }
604619 )
605620 self .ros .send_on_ready (message )
621+
606622 # Remove message_id from RosBridgeProtocol._pending_action_requests in comms.py?
607623 # Not needed since an action result is returned upon cancelation.
608624
625+ def wait_goal (self , goal_id , timeout = None ):
626+ """Block until the result is available.
627+
628+ If ``timeout`` is ``None``, it will wait indefinitely.
629+
630+ Args:
631+ goal_id: Goal ID returned from ``send_goal()``
632+ timeout (:obj:`int`): Timeout to wait for the result expressed in seconds.
633+ """
634+
635+ wait_result_event = self .wait_results .get (goal_id )
636+ if wait_result_event is None :
637+ raise ValueError ("Unknown goal ID" )
638+
639+ if not wait_result_event .wait (timeout ):
640+ raise RosTimeoutError ("Goal failed to receive result" )
641+
642+ self .wait_results .pop (goal_id , None )
609643
610644class Param (object ):
611645 """A ROS parameter.
0 commit comments