@@ -690,7 +690,7 @@ async def is_robot_stopped(self, threshold_speed: float = 2.0) -> bool:
690690
691691 async def wait_motion_complete (
692692 self ,
693- timeout : float = 90 .0 ,
693+ timeout : float = 10 .0 ,
694694 settle_window : float = 0.25 ,
695695 speed_threshold : float = 2.0 ,
696696 angle_threshold : float = 0.5 ,
@@ -727,57 +727,53 @@ async def wait_motion_complete(
727727 if timeout_task .done ():
728728 return False
729729
730- # Check speeds from status
730+ # Check speeds and angles from status
731731 speeds = status .get ("speeds" )
732+ angles = status .get ("angles" )
733+
734+ max_speed = None
732735 if speeds and isinstance (speeds , Iterable ):
733736 max_speed = max (abs (s ) for s in speeds )
734737
735- # Phase 1: Wait for motion to start
736- if not motion_started :
737- if max_speed >= speed_threshold :
738- motion_started = True
739- settle_start = None # Reset settle timer
740- elif time .time () - start_time > motion_start_timeout :
741- # Motion never started - consider complete
742- # This handles cases where command was invalid or no-op
743- motion_started = True
744-
745- # Phase 2: Wait for motion to complete
746- if motion_started :
747- if max_speed < speed_threshold :
748- if settle_start is None :
749- settle_start = time .time ()
750- elif time .time () - settle_start > settle_window :
751- return True
752- else :
753- settle_start = None
754-
755- # Also check angles as fallback
756- angles = status .get ("angles" )
757- if angles and not speeds :
758- if last_angles is not None :
759- max_change = max (
760- abs (a - b )
761- for a , b in zip (angles , last_angles , strict = False )
762- )
763-
764- # Detect motion start from angle changes
765- if not motion_started :
766- if max_change >= angle_threshold :
767- motion_started = True
768- settle_start = None
769- elif time .time () - start_time > motion_start_timeout :
770- motion_started = True
771-
772- if motion_started :
773- if max_change < angle_threshold :
774- if settle_start is None :
775- settle_start = time .time ()
776- elif time .time () - settle_start > settle_window :
777- return True
778- else :
779- settle_start = None
738+ max_angle_change = None
739+ if angles and last_angles is not None :
740+ max_angle_change = max (
741+ abs (a - b ) for a , b in zip (angles , last_angles , strict = False )
742+ )
743+ if angles :
780744 last_angles = angles
745+
746+ # Phase 1: Wait for motion to start
747+ if not motion_started :
748+ started_by_speed = (
749+ max_speed is not None and max_speed >= speed_threshold
750+ )
751+ started_by_angle = (
752+ max_angle_change is not None
753+ and max_angle_change >= angle_threshold
754+ )
755+ if started_by_speed or started_by_angle :
756+ motion_started = True
757+ settle_start = None
758+ elif time .time () - start_time > motion_start_timeout :
759+ # Motion never started - consider complete
760+ motion_started = True
761+
762+ # Phase 2: Wait for motion to complete
763+ if motion_started :
764+ # Check if settled: require ALL available metrics to be below threshold
765+ speed_settled = max_speed is None or max_speed < speed_threshold
766+ angle_settled = (
767+ max_angle_change is None or max_angle_change < angle_threshold
768+ )
769+
770+ if speed_settled and angle_settled :
771+ if settle_start is None :
772+ settle_start = time .time ()
773+ elif time .time () - settle_start > settle_window :
774+ return True
775+ else :
776+ settle_start = None
781777 finally :
782778 timeout_task .cancel ()
783779 try :
0 commit comments