99import us .ihmc .commonWalkingControlModules .captureRegion .OneStepCaptureRegionCalculator ;
1010import us .ihmc .commonWalkingControlModules .configurations .SteppingParameters ;
1111import us .ihmc .commonWalkingControlModules .configurations .WalkingControllerParameters ;
12- import us .ihmc .commonWalkingControlModules .messageHandlers .WalkingMessageHandler ;
1312import us .ihmc .commons .lists .RecyclingArrayList ;
1413import us .ihmc .euclid .geometry .interfaces .ConvexPolygon2DReadOnly ;
1514import us .ihmc .euclid .referenceFrame .FrameConvexPolygon2D ;
1615import us .ihmc .euclid .referenceFrame .FramePoint2D ;
17- import us .ihmc .euclid .referenceFrame .FramePoint3D ;
1816import us .ihmc .euclid .referenceFrame .ReferenceFrame ;
1917import us .ihmc .euclid .referenceFrame .interfaces .*;
2018import us .ihmc .euclid .tuple2D .Point2D ;
@@ -49,6 +47,8 @@ public class ErrorBasedStepAdjustmentController implements StepAdjustmentControl
4947{
5048 private final YoRegistry registry = new YoRegistry (getClass ().getSimpleName ());
5149
50+ private static final double AREA_TO_CONSIDER_SWITCHING = 0.05 ;
51+
5252 private static final boolean VISUALIZE = true ;
5353 private static final boolean CONTINUOUSLY_UPDATE_DESIRED_POSITION = true ;
5454 private static final int minTicksIntoStep = 5 ;
@@ -78,7 +78,6 @@ public class ErrorBasedStepAdjustmentController implements StepAdjustmentControl
7878 private final RecyclingArrayList <Point2D > upcomingFootstepContactPoints = new RecyclingArrayList <>(Point2D .class );
7979 private final YoFramePoint3D referenceFootstepPosition = new YoFramePoint3D (yoNamePrefix + "ReferenceFootstepPosition" , worldFrame , registry );
8080
81- private final FramePoint3D tempPoint = new FramePoint3D ();
8281 private final FramePoint2D tempPoint2D = new FramePoint2D ();
8382
8483 private final YoFrameVector2D footstepAdjustment = new YoFrameVector2D (yoNamePrefix + "FootstepAdjustment" ,
@@ -101,6 +100,13 @@ public class ErrorBasedStepAdjustmentController implements StepAdjustmentControl
101100
102101 private final YoBoolean footstepWasAdjusted = new YoBoolean (yoNamePrefix + "FootstepWasAdjusted" , registry );
103102
103+ private enum ReachableRegion {FORWARD , BACKWARD , BASELINE }
104+ private final YoDouble forwardReachableArea = new YoDouble (yoNamePrefix + "ForwardReachableArea" , registry );
105+ private final YoDouble backwardReachableArea = new YoDouble (yoNamePrefix + "BackwardReachableArea" , registry );
106+ private final YoDouble baselineReachableArea = new YoDouble (yoNamePrefix + "BaselineReachableArea" , registry );
107+ private final YoDouble areaToConsiderSwitching = new YoDouble (yoNamePrefix + "areaToConsiderSwitching" , registry );
108+ private final YoEnum <ReachableRegion > selectedReachableRegion = new YoEnum <>(yoNamePrefix + "SelectedReachableRegion" ,registry , ReachableRegion .class , true );
109+
104110 private final BooleanProvider resetFootstepProjectionEachTick ;
105111 private final DoubleProvider minimumTimeForStepAdjustment ;
106112 private final DoubleParameter supportDistanceFromFront ;
@@ -125,7 +131,6 @@ public class ErrorBasedStepAdjustmentController implements StepAdjustmentControl
125131
126132 private final BipedSupportPolygons bipedSupportPolygons ;
127133
128- private final FramePoint3D vertexInWorld = new FramePoint3D ();
129134 private final FrameConvexPolygon2D allowableAreaForCoPInFoot = new FrameConvexPolygon2D ();
130135
131136 public ErrorBasedStepAdjustmentController (WalkingControllerParameters walkingControllerParameters ,
@@ -189,6 +194,7 @@ public ErrorBasedStepAdjustmentController(WalkingControllerParameters walkingCon
189194 DoubleProvider innerLimit = new DoubleParameter (yoNamePrefix + "MinReachabilityWidth" , registry , steppingParameters .getMinStepWidth ());
190195 DoubleProvider outerLimit = new DoubleParameter (yoNamePrefix + "MaxReachabilityWidth" , registry , steppingParameters .getMaxStepWidth ());
191196 DoubleProvider inPlaceWidth = new DoubleParameter (yoNamePrefix + "InPlaceWidth" , registry , steppingParameters .getInPlaceWidth ());
197+ areaToConsiderSwitching .set (AREA_TO_CONSIDER_SWITCHING );
192198
193199 reachabilityConstraintHandler = new StepAdjustmentReachabilityConstraint (soleZUpFrames ,
194200 lengthLimit ,
@@ -353,6 +359,7 @@ public void initialize(double initialTime, RobotSide supportSide)
353359 previousFootstepSolution .set (footstepSolution .getPosition ());
354360 totalStepAdjustment .setToZero ();
355361 controlTicksIntoStep .set (0 );
362+ selectedReachableRegion .set (null );
356363 }
357364
358365 @ Override
@@ -440,7 +447,8 @@ public void compute(double currentTime,
440447 if (environmentallyConstrained )
441448 {
442449 tempPoint2D .set (footstepSolution .getPosition ());
443- FrameConvexPolygon2DReadOnly reachability = getBestReachabilityConstraintToUseWhenNotIntersecting ();
450+ computeBestReachabilityConstraintToUseWhenNotIntersecting ();
451+ FrameConvexPolygon2DReadOnly reachability = getSelectedRegion ();
444452 if (!reachability .isPointInside (tempPoint2D ))
445453 reachability .orthogonalProjection (tempPoint2D );
446454 footstepSolution .getPosition ().set (tempPoint2D );
@@ -550,11 +558,13 @@ private void projectAdjustedStepIntoCaptureRegion(FramePoint3DReadOnly pointToPr
550558 if (!isTheCaptureRegionReachable ())
551559 {
552560 captureRegionInWorld .orthogonalProjection (adjustedSolution );
553- getBestReachabilityConstraintToUseWhenNotIntersecting ().orthogonalProjection (adjustedSolution );
561+ computeBestReachabilityConstraintToUseWhenNotIntersecting ();
562+ getSelectedRegion ().orthogonalProjection (adjustedSolution );
554563 }
555564 else
556565 {
557- getBestReachabilityConstraintToUseWhenIntersecting ().orthogonalProjection (adjustedSolution );
566+ computeBestReachabilityConstraintToUseWhenIntersecting ();
567+ getSelectedRegion ().orthogonalProjection (adjustedSolution );
558568 }
559569
560570 footstepAdjustment .set (adjustedSolution );
@@ -594,38 +604,56 @@ private boolean isTheCaptureRegionReachable()
594604 return intersect ;
595605 }
596606
597- private FrameConvexPolygon2DReadOnly getBestReachabilityConstraintToUseWhenNotIntersecting ()
607+ private void computeBestReachabilityConstraintToUseWhenNotIntersecting ()
598608 {
599609 if (!allowCrossOverSteps .getValue ())
600- return reachabilityConstraintHandler .getReachabilityConstraint ();
610+ {
611+ selectedReachableRegion .set (ReachableRegion .BASELINE );
612+ return ;
613+ }
601614
602615 double distanceToForward = reachabilityConstraintHandler .getForwardCrossOverPolygon ().distance (adjustedSolution );
603616 double distanceToBackward = reachabilityConstraintHandler .getBackwardCrossOverPolygon ().distance (adjustedSolution );
604617 double distanceToNominal = reachabilityConstraintHandler .getReachabilityConstraint ().distance (adjustedSolution );
605618
606- boolean forwardIsCloser = distanceToForward < distanceToBackward ;
607-
608- if (forwardIsCloser )
619+ double distanceToPreviouslySelectedRegion = distanceToNominal ;
620+ if (selectedReachableRegion .getEnumValue () != null )
609621 {
610- if (distanceToNominal < distanceToForward )
611- return reachabilityConstraintHandler .getReachabilityConstraint ();
622+ if (selectedReachableRegion .getEnumValue () == ReachableRegion .FORWARD )
623+ distanceToPreviouslySelectedRegion = distanceToForward ;
624+ else if (selectedReachableRegion .getEnumValue () == ReachableRegion .BACKWARD )
625+ distanceToPreviouslySelectedRegion = distanceToBackward ;
612626 else
613- return reachabilityConstraintHandler . getForwardCrossOverPolygon () ;
627+ distanceToPreviouslySelectedRegion = distanceToNominal ;
614628 }
615- else if ( distanceToNominal < distanceToBackward )
629+ else
616630 {
617- return reachabilityConstraintHandler .getReachabilityConstraint ();
631+ // initialize this as the default
632+ selectedReachableRegion .set (ReachableRegion .BASELINE );
618633 }
619- else
634+
635+ boolean forwardIsCloser = distanceToForward < distanceToBackward ;
636+
637+ if (forwardIsCloser )
638+ {
639+ if (distanceToForward < distanceToPreviouslySelectedRegion )
640+ {
641+ selectedReachableRegion .set (ReachableRegion .FORWARD );
642+ }
643+ }
644+ else if (distanceToBackward < distanceToPreviouslySelectedRegion )
620645 {
621- return reachabilityConstraintHandler . getBackwardCrossOverPolygon ( );
646+ selectedReachableRegion . set ( ReachableRegion . BACKWARD );
622647 }
623648 }
624649
625- private FrameConvexPolygon2DReadOnly getBestReachabilityConstraintToUseWhenIntersecting ()
650+ private void computeBestReachabilityConstraintToUseWhenIntersecting ()
626651 {
627652 if (!allowCrossOverSteps .getValue ())
628- return reachableCaptureRegion ;
653+ {
654+ selectedReachableRegion .set (ReachableRegion .BASELINE );
655+ return ;
656+ }
629657
630658 double forwardArea = forwardCrossOverReachableCaptureRegion .getArea ();
631659 double backwardArea = backwardCrossOverReachableCaptureRegion .getArea ();
@@ -635,23 +663,57 @@ private FrameConvexPolygon2DReadOnly getBestReachabilityConstraintToUseWhenInter
635663 backwardArea = Double .isNaN (backwardArea ) ? Double .NEGATIVE_INFINITY : backwardArea ;
636664 reachableArea = Double .isNaN (reachableArea ) ? Double .NEGATIVE_INFINITY : reachableArea ;
637665
666+ forwardReachableArea .set (forwardArea );
667+ backwardReachableArea .set (backwardArea );
668+ baselineReachableArea .set (reachableArea );
669+
670+ double areaOfPreviouslySelectedRegion = reachableArea ;
671+ if (selectedReachableRegion .getEnumValue () != null )
672+ {
673+ areaOfPreviouslySelectedRegion = getSelectedArea ();
674+ // Don't switch if the area of the previous selection isn't too low
675+ if (getSelectedArea () > areaToConsiderSwitching .getDoubleValue ())
676+ return ;
677+ }
678+ else
679+ {
680+ // initialize th is as the default
681+ selectedReachableRegion .set (ReachableRegion .BASELINE );
682+ }
683+
638684 boolean forwardIsLargestCrossoverArea = forwardArea > backwardArea ;
639685
640686 if (forwardIsLargestCrossoverArea )
641687 {
642- if (forwardArea > 2.0 * reachableArea )
643- return forwardCrossOverReachableCaptureRegion ;
644- else
645- return reachableCaptureRegion ;
688+ if (forwardArea > 2.0 * areaOfPreviouslySelectedRegion )
689+ {
690+ selectedReachableRegion . set ( ReachableRegion . FORWARD );
691+ }
646692 }
647- else if (backwardArea > 2.0 * reachableArea )
693+ else if (backwardArea > 2.0 * areaOfPreviouslySelectedRegion )
648694 {
649- return backwardCrossOverReachableCaptureRegion ;
695+ selectedReachableRegion . set ( ReachableRegion . BACKWARD ) ;
650696 }
651- else
697+ }
698+
699+ private double getSelectedArea ()
700+ {
701+ return switch (selectedReachableRegion .getEnumValue ())
652702 {
653- return reachableCaptureRegion ;
654- }
703+ case FORWARD -> forwardReachableArea .getDoubleValue ();
704+ case BACKWARD -> backwardReachableArea .getDoubleValue ();
705+ case BASELINE -> baselineReachableArea .getDoubleValue ();
706+ };
707+ }
708+
709+ private FrameConvexPolygon2DReadOnly getSelectedRegion ()
710+ {
711+ return switch (selectedReachableRegion .getEnumValue ())
712+ {
713+ case FORWARD -> forwardCrossOverReachableCaptureRegion ;
714+ case BACKWARD -> backwardCrossOverReachableCaptureRegion ;
715+ case BASELINE -> reachableCaptureRegion ;
716+ };
655717 }
656718
657719 private boolean deadbandAndApplyStepAdjustment ()
0 commit comments