Skip to content

Feature/alip calculator modifications #714

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 24 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
716b4a4
made ALIP tools class with static methods for ALIP calculations and c…
stefanfasano Feb 14, 2025
ed7e992
Merge branch 'develop' into feature/ALIP-calculator-modifications
stefanfasano Feb 18, 2025
47619a3
added raibert heuristic controller to ALIP tools
stefanfasano Feb 18, 2025
3fc6f1a
made full footstepDataList calculated using QFP, not fully working pr…
stefanfasano Feb 19, 2025
02bc312
removed reliance on reference frames in ALIP calculator tools class
stefanfasano Feb 19, 2025
d76bf05
can walk with all csg footsteps calculated via QFP, but turning is st…
stefanfasano Feb 19, 2025
cebff3c
turning in place and turning while walking now work
stefanfasano Feb 21, 2025
f05b474
Merge branch 'develop' into feature/ALIP-calculator-modifications
stefanfasano Mar 10, 2025
77021d1
fixed broken touchdown position visualizer
stefanfasano Mar 10, 2025
94446a7
Merge branch 'develop' into feature/ALIP-calculator-modifications
stefanfasano Mar 13, 2025
cf58f13
fixed some visualization stuff, made QFP state machine more synced wi…
stefanfasano Mar 17, 2025
e72af38
made ALIPCalculatorTools not completely static. Modified calculation …
stefanfasano Mar 19, 2025
6bba954
added documentation and Gong-based footstep control to ALIPCalculator…
stefanfasano Mar 20, 2025
f170671
Merge branch 'develop' into feature/ALIP-calculator-modifications
stefanfasano Mar 20, 2025
ff45efe
Merge branch 'develop' into feature/ALIP-calculator-modifications
stefanfasano Mar 25, 2025
8fe7701
first qfp step uses regular controller (longer) transfer duration to …
stefanfasano Mar 26, 2025
feaff72
added visualizers for future state. Added some double support conside…
stefanfasano Mar 28, 2025
aaab2af
Merge branch 'develop' into feature/ALIP-calculator-modifications
stefanfasano Apr 1, 2025
7286f87
added elliptical reachability constraint to csg
stefanfasano Apr 1, 2025
e34b5ba
fixed some bugs, but everything is worse now
stefanfasano Apr 2, 2025
bf134c2
all qfp tests passing at control dt
stefanfasano Apr 2, 2025
7a4fc78
increased min step width for elliptical reachability limiter
stefanfasano Apr 2, 2025
1e23892
Merge branch 'develop' into feature/ALIP-calculator-modifications
stefanfasano Apr 2, 2025
d888f7a
decreased ticks to interpolate cop feedback alpha
stefanfasano Apr 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ public MomentumRateCommand getMomentumRateCommand()
*/
public CenterOfPressureCommand getCenterOfPressureCommand()
{
return centerOfPressureCommand;
return centerOfPressureCommandCalculator.getCenterOfPressureCommand();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import us.ihmc.commonWalkingControlModules.capturePoint.ICPControlPolygons;
import us.ihmc.commonWalkingControlModules.capturePoint.ParameterizedICPControlGains;
import us.ihmc.commonWalkingControlModules.configurations.WalkingControllerParameters;
import us.ihmc.commons.InterpolationTools;
import us.ihmc.commons.MathTools;
import us.ihmc.euclid.referenceFrame.FramePoint2D;
import us.ihmc.euclid.referenceFrame.FrameVector2D;
import us.ihmc.euclid.referenceFrame.ReferenceFrame;
Expand Down Expand Up @@ -108,6 +110,7 @@ public class ICPController implements ICPControllerInterface
private final YoBoolean hasNotConvergedInPast = new YoBoolean(yoNamePrefix + "HasNotConvergedInPast", registry);
private final YoBoolean previousTickFailed = new YoBoolean(yoNamePrefix + "PreviousTickFailed", registry);
private final YoInteger hasNotConvergedCounts = new YoInteger(yoNamePrefix + "HasNotConvergedCounts", registry);
private final YoInteger ticksToInterpolateAlpha = new YoInteger("ticksToInterpolateAlpha", registry);

private final IntegerProvider maxNumberOfIterations = new IntegerParameter(yoNamePrefix + "MaxNumberOfIterations", registry, 100);

Expand Down Expand Up @@ -212,6 +215,8 @@ public ICPController(WalkingControllerParameters walkingControllerParameters,
parameters.createFeedbackAlphaCalculator(registry, null);
parameters.createFeedbackProjectionOperator(registry, null);

ticksToInterpolateAlpha.set(75);

if (yoGraphicsListRegistry != null)
setupVisualizers(yoGraphicsListRegistry);

Expand Down Expand Up @@ -452,14 +457,31 @@ private void extractSolutionsFromSolver(boolean converged)
integrator.update(desiredICPVelocity, currentCoMVelocity, icpError);
}

private int alphaInterpolationTicks = 0;
private void computeFeedForwardAndFeedBackAlphas()
{
if (disableCoPFeedback.getValue() || !useCoPFeedbackByDefault.getValue())
feedbackAlpha.set(1.0);
{
double maxNumberOfAlphaInterpolationTicks = MathTools.clamp(ticksToInterpolateAlpha.getIntegerValue(), 1, Integer.MAX_VALUE);
double interpolationFactor = (double) alphaInterpolationTicks / maxNumberOfAlphaInterpolationTicks;
interpolationFactor = MathTools.clamp(interpolationFactor, 0.0, 1.0);
double startValue = 0.0; //parameters.getFeedbackAlphaCalculator() != null ? parameters.getFeedbackAlphaCalculator().computeAlpha(currentICP, copConstraintHandler.getCoPConstraint()) : 0.0;
double endValue = 1.0;
double valueToUse = InterpolationTools.linearInterpolate(startValue, endValue, interpolationFactor);
feedbackAlpha.set(valueToUse);
if (alphaInterpolationTicks < maxNumberOfAlphaInterpolationTicks)
alphaInterpolationTicks++;
}
else if (parameters.getFeedbackAlphaCalculator() != null)
{
feedbackAlpha.set(parameters.getFeedbackAlphaCalculator().computeAlpha(currentICP, copConstraintHandler.getCoPConstraint()));
alphaInterpolationTicks = 0;
}
else
{
feedbackAlpha.set(0.0);
alphaInterpolationTicks = 0;
}

if (parameters.getFeedForwardAlphaCalculator() != null)
feedForwardAlpha.set(parameters.getFeedForwardAlphaCalculator()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
package us.ihmc.commonWalkingControlModules.desiredFootStep;

import us.ihmc.commons.MathTools;
import us.ihmc.euclid.referenceFrame.FramePoint2D;
import us.ihmc.euclid.referenceFrame.FramePoint3D;
import us.ihmc.euclid.referenceFrame.ReferenceFrame;
import us.ihmc.euclid.referenceFrame.interfaces.FixedFramePoint3DBasics;
import us.ihmc.euclid.referenceFrame.interfaces.FramePoint3DBasics;
import us.ihmc.euclid.referenceFrame.interfaces.FramePoint3DReadOnly;
import us.ihmc.euclid.tools.EuclidCoreTools;
import us.ihmc.robotics.geometry.GroundPlaneEstimator;
import us.ihmc.robotics.robotSide.RobotSide;

public class EllipticalStepPositionLimiter
{
public final static double NOMINAL_STANCE_WIDTH_DEFAULT = 0.25;
public final static double MAX_STEP_FORWARD_DEFAULT = 0.85;
public final static double MIN_STANCE_WIDTH_DEFAULT = 0.1;
public final static double MAX_STANCE_WIDTH_DEFAULT = 0.75;
public final static double MIN_DISTANCE_FROM_STANCE_FOOT_DEFAULT = 0.1;

private final FramePoint2D stanceFootPosition = new FramePoint2D();
private final FramePoint2D constrainedTouchdownPosition2D = new FramePoint2D();
private final FramePoint3DBasics constrainedSoleTouchdownPosition = new FramePoint3D();

public void enforceFootPositionConstraint(FramePoint3DReadOnly desiredSoleTouchdownPosition,
FixedFramePoint3DBasics constrainedSoleTouchdownPositionToPack,
ReferenceFrame desiredConstraintFrame,
ReferenceFrame stanceFootZUpFrame,
RobotSide swingSide)
{
enforceFootPositionConstraint(desiredSoleTouchdownPosition,
constrainedSoleTouchdownPositionToPack,
desiredConstraintFrame,
stanceFootZUpFrame,
NOMINAL_STANCE_WIDTH_DEFAULT,
MAX_STEP_FORWARD_DEFAULT,
MIN_STANCE_WIDTH_DEFAULT,
MAX_STANCE_WIDTH_DEFAULT,
MIN_DISTANCE_FROM_STANCE_FOOT_DEFAULT,
swingSide);
}

/**
* @param desiredSoleTouchdownPosition The unconstrained position. Not Modified.
* @param constrainedSoleTouchdownPositionToPack The step position that is constrained.
* @param desiredConstraintFrame The frame in which to apply the constraint.
*/
public boolean enforceFootPositionConstraint(FramePoint3DReadOnly desiredSoleTouchdownPosition,
FixedFramePoint3DBasics constrainedSoleTouchdownPositionToPack,
ReferenceFrame desiredConstraintFrame,
ReferenceFrame stanceFootZUpFrame,
double nominalStanceWidth,
double maxStepForward,
double minStanceWidth,
double maxStanceWidth,
double minDistanceFromStanceFoot,
RobotSide swingSide)
{
return enforceFootPositionConstraint(desiredSoleTouchdownPosition,
constrainedSoleTouchdownPositionToPack,
desiredConstraintFrame,
stanceFootZUpFrame,
null,
nominalStanceWidth,
maxStepForward,
minStanceWidth,
maxStanceWidth,
minDistanceFromStanceFoot,
swingSide);
}

/**
* @param desiredSoleTouchdownPosition The unconstrained position. Not Modified.
* @param constrainedSoleTouchdownPositionToPack The step position that is constrained.
* @param desiredConstraintFrame The frame in which to apply the constraint.
*/
public boolean enforceFootPositionConstraint(FramePoint3DReadOnly desiredSoleTouchdownPosition,
FixedFramePoint3DBasics constrainedSoleTouchdownPositionToPack,
ReferenceFrame desiredConstraintFrame,
ReferenceFrame stanceFootZUpFrame,
GroundPlaneEstimator groundPlaneEstimator,
double nominalStanceWidth,
double maxStepForward,
double minStanceWidth,
double maxStanceWidth,
double minDistanceFromStanceFoot,
RobotSide swingSide)
{
constrainedSoleTouchdownPosition.setIncludingFrame(desiredSoleTouchdownPosition);

boolean wasLimited = false;
wasLimited |= enforceMinimumStepWidthInConstraintFrame(constrainedSoleTouchdownPosition, desiredConstraintFrame, minStanceWidth, swingSide);

wasLimited |= enforceOuterEllipticalBoundInConstraintFrame(constrainedSoleTouchdownPosition,
desiredConstraintFrame,
nominalStanceWidth,
maxStepForward,
maxStanceWidth,
swingSide);

wasLimited |= enforceStepDistanceFromStance(constrainedSoleTouchdownPosition, stanceFootZUpFrame, minDistanceFromStanceFoot);

wasLimited |= enforceStepWidthFromStance(constrainedSoleTouchdownPosition, desiredConstraintFrame, stanceFootZUpFrame, minStanceWidth, swingSide);

//TODO do i need to do this on line 90?
constrainedSoleTouchdownPosition.changeFrame(desiredConstraintFrame);

//TODO limit z position as well
if (groundPlaneEstimator != null)
{
constrainedTouchdownPosition2D.setIncludingFrame(constrainedSoleTouchdownPosition);
// constrainedSoleTouchdownPosition.setMatchingFrame(groundPlaneEstimator.getGroundPosition(constrainedTouchdownPosition2D));
}

constrainedSoleTouchdownPositionToPack.setMatchingFrame(constrainedSoleTouchdownPosition);
return wasLimited;
}

static boolean enforceMinimumStepWidthInConstraintFrame(FramePoint3DBasics desiredStepPositionToConstrain,
ReferenceFrame desiredConstraintFrame,
double minStanceWidth,
RobotSide swingSide)
{
desiredStepPositionToConstrain.changeFrame(desiredConstraintFrame);

// make sure you don't step too narrowly. This is done by cropping the lateral position of the footstep.
// If the width is negative, we assume that we're allowing a cross over distance relative to the constraint frame. If it's positive, then that's the
// nominal stance width, as defined by one foot relative to the other. This means we then divide it by half when computing this value.
double desiredWidth = desiredStepPositionToConstrain.getY();
double widthBound = minStanceWidth < 0.0 ? minStanceWidth : 0.5 * minStanceWidth;
if (swingSide == RobotSide.LEFT)
{
if (desiredWidth < widthBound)
{
desiredStepPositionToConstrain.setY(widthBound);
return true;
}
}
else
{
if (desiredWidth > -widthBound)
{
desiredStepPositionToConstrain.setY(-widthBound);
return true;
}
}

return false;
}

/**
* The constraint frame is assumed to be the center of the pelvis, or the center of mass frame. So the ellipse is centered half the nominal stance width from
* the constraint frame.
* @param desiredStepPositionToConstrain
* @param constraintFrame
* @param nominalStanceWidth
* @param maxStepForward
* @param maxStanceWidth
* @param stepSide
* @return
*/
static boolean enforceOuterEllipticalBoundInConstraintFrame(FramePoint3DBasics desiredStepPositionToConstrain,
ReferenceFrame constraintFrame,
double nominalStanceWidth,
double maxStepForward,
double maxStanceWidth,
RobotSide stepSide)
{
ReferenceFrame originalFrame = desiredStepPositionToConstrain.getReferenceFrame();
desiredStepPositionToConstrain.changeFrame(constraintFrame);

double ellipseYOrigin = stepSide.negateIfRightSide(0.5 * nominalStanceWidth);
double ellipseYMax = maxStanceWidth - nominalStanceWidth;

double ellipseX = desiredStepPositionToConstrain.getX();
double ellipseY = desiredStepPositionToConstrain.getY() - ellipseYOrigin;

// check if the point is inside the ellipse
double r = MathTools.square(ellipseX / maxStepForward) + MathTools.square(ellipseY / ellipseYMax);

if (r <= 1.0)
{
desiredStepPositionToConstrain.changeFrame(originalFrame);
return false;
}

// project the constraint onto the ellipse bound, since it was outside
double theta = Math.atan2(desiredStepPositionToConstrain.getX(), ellipseYMax);
double sinTheta = Math.sin(theta);
double cosTheta = Math.cos(theta);
double k = maxStepForward * ellipseYMax / (Math.sqrt(MathTools.square(ellipseYMax * sinTheta) + MathTools.square(maxStepForward * cosTheta)));
double x = Math.abs(k * sinTheta) * Math.signum(ellipseX);
double y = Math.abs(k * cosTheta) * Math.signum(ellipseY);

y += ellipseYOrigin;

desiredStepPositionToConstrain.set(x, y, desiredStepPositionToConstrain.getZ());
desiredStepPositionToConstrain.changeFrame(originalFrame);

return true;
}

private static boolean enforceStepDistanceFromStance(FramePoint3DBasics desiredTouchdownInStanceFootToPack,
ReferenceFrame stanceFootZUpFrame,
double minDistanceFromStanceFoot)
{
// make sure you don't step too close to the stance foot. This is done by making sure the desired touchdown position stays outside a circle
// around the stance foot.
if (minDistanceFromStanceFoot > 0.0)
{
desiredTouchdownInStanceFootToPack.changeFrame(stanceFootZUpFrame);
double distanceFromStance = desiredTouchdownInStanceFootToPack.distanceXY(EuclidCoreTools.origin2D);
if (distanceFromStance < minDistanceFromStanceFoot)
{
double scaleFactor = minDistanceFromStanceFoot / distanceFromStance;
desiredTouchdownInStanceFootToPack.scale(scaleFactor, scaleFactor, 1.0);

return true;
}
}

return false;
}

private boolean enforceStepWidthFromStance(FramePoint3DBasics desiredStepPositionToConstrain,
ReferenceFrame desiredConstraintFrame,
ReferenceFrame stanceFootZUpFrame,
double minStanceWidth,
RobotSide swingSide)
{
// This makes sure step is no less than a defined distance in y away from the stance foot.
stanceFootPosition.setToZero(stanceFootZUpFrame);
stanceFootPosition.changeFrameAndProjectToXYPlane(desiredConstraintFrame);
desiredStepPositionToConstrain.changeFrame(desiredConstraintFrame);

if (swingSide == RobotSide.LEFT)
{
double innerYBound = stanceFootPosition.getY() + minStanceWidth;
if (innerYBound > desiredStepPositionToConstrain.getY())
{
desiredStepPositionToConstrain.setY(innerYBound);
return true;
}
}
else
{
double innerYBound = stanceFootPosition.getY() - minStanceWidth;
if (innerYBound < desiredStepPositionToConstrain.getY())
{
desiredStepPositionToConstrain.setY(innerYBound);
return true;
}
}

return false;
}
}
Loading
Loading