Repository navigation
Feature/more align controllers #372
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
Changes from all commits
3120775
666bdf3
2df0b0d
2085ac2
f5c8dd3
4ff8076
86449ba
ba5d3b4
a507243
3a156b3
b3bcd85
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Make everything private and make things final where you can; then name constants with UPPER_SNAKE_CASE
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also make |
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add a blank line between imports and class header? |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| package frc.robot.util.autoalign.system.controller.impl; | ||
|
|
||
| import com.pathplanner.lib.config.PIDConstants; | ||
|
|
||
| import edu.wpi.first.math.MathUtil; | ||
| import edu.wpi.first.math.controller.PIDController; | ||
| import edu.wpi.first.math.filter.SlewRateLimiter; | ||
| import edu.wpi.first.math.geometry.Pose2d; | ||
| import edu.wpi.first.math.geometry.Rotation2d; | ||
| import edu.wpi.first.math.kinematics.ChassisSpeeds; | ||
| import edu.wpi.first.math.util.Units; | ||
| import frc.robot.constants.RobotPIDConstants; | ||
| import frc.robot.subsystems.drive.DriveConstants; | ||
| import frc.robot.util.autoalign.system.controller.AlignControllerBase; | ||
| import frc.robot.util.autoalign.system.eventshandler.events.ECompleteReachPoint; | ||
| import frc.robot.util.autoalign.system.pointprovider.IAlignPointProvider; | ||
| public class LinearAlignController extends AlignControllerBase { | ||
| private final PIDController TRANSLATION_PID; | ||
| private final PIDController ROTATION_PID; | ||
|
|
||
| private final SlewRateLimiter ACCEL_LIMITER; | ||
| private final double maxAccelerationMetersPerSecondSquared = 3; | ||
|
|
||
| private final double OUTPUT_DEADBAND = 0.01; | ||
| private final double TRANSLATION_DEADBAND = 0.02; | ||
| private final double ROTATION_DEADBAND = Units.degreesToRadians(5); | ||
|
|
||
| public LinearAlignController(IAlignPointProvider pointProvider) { | ||
| super(pointProvider); | ||
|
|
||
| TRANSLATION_PID = RobotPIDConstants.constructPID(new PIDConstants(0.25, 0, 0)); | ||
| ROTATION_PID = RobotPIDConstants.constructPID(new PIDConstants(0.5, 0.001, 0.0001)); | ||
|
|
||
| ACCEL_LIMITER = new SlewRateLimiter(maxAccelerationMetersPerSecondSquared); | ||
| getListenerManager().registerEventTrigger(() -> isFinished(), new ECompleteReachPoint()); | ||
| } | ||
|
|
||
| @Override | ||
| public ChassisSpeeds calculate(ChassisSpeeds measuredSpeeds) { | ||
| Pose2d robot = pointProvider.getRobotPose(); | ||
| Pose2d target = pointProvider.getTargetPose(); | ||
|
|
||
| Rotation2d angleToTarget = robot.getTranslation().minus(target.getTranslation()).getAngle(); | ||
| double dist = robot.getTranslation().getDistance(target.getTranslation()); | ||
|
|
||
| double linearOutput = TRANSLATION_PID.calculate(dist, 0); | ||
| linearOutput = MathUtil.clamp(linearOutput, -1, 1); | ||
| linearOutput = MathUtil.applyDeadband(linearOutput, OUTPUT_DEADBAND); | ||
| linearOutput *= DriveConstants.maxSpeed; | ||
| linearOutput = ACCEL_LIMITER.calculate(linearOutput); | ||
|
|
||
| double rotationalOutput = ROTATION_PID.calculate(robot.getRotation().minus(target.getRotation()).getRadians(), | ||
| 0); | ||
| rotationalOutput = MathUtil.clamp(rotationalOutput, -1, 1); | ||
| rotationalOutput = MathUtil.applyDeadband(rotationalOutput, OUTPUT_DEADBAND); | ||
| rotationalOutput *= DriveConstants.maxOmega; | ||
|
|
||
| double xSpeed = Math.cos(angleToTarget.getRadians()) * linearOutput; | ||
| double ySpeed = Math.sin(angleToTarget.getRadians()) * linearOutput; | ||
| return new ChassisSpeeds(xSpeed, ySpeed, rotationalOutput); | ||
| } | ||
|
|
||
| @Override | ||
| public boolean isAligning() { | ||
| return !isFinished(); | ||
| } | ||
|
|
||
| public boolean isFinished() { | ||
| return pointProvider.getRobotPose().getTranslation() | ||
| .getDistance(pointProvider.getTargetPose().getTranslation()) < TRANSLATION_DEADBAND | ||
| && Math.abs(pointProvider.getRobotPose().getRotation() | ||
| .minus(pointProvider.getTargetPose().getRotation()).getRadians()) < ROTATION_DEADBAND; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| package frc.robot.util.eventbus.listenerHandler; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.HashMap; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.function.BooleanSupplier; | ||
|
|
||
| import frc.robot.util.periodic.PeriodicBase; | ||
| import frc.robot.util.eventbus.events.IEvent; | ||
| import frc.robot.util.eventbus.handler.EventBus; | ||
|
|
||
| public class ListenerManager extends PeriodicBase { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Make these variables private, and final if possible |
||
| private final Map<BooleanSupplier, List<IEvent>> fireEventHashMap; | ||
| private final List<BooleanSupplier> awaitingToggleBack; | ||
| private final EventBus eventBus; | ||
|
|
||
| public ListenerManager(EventBus eventBus) { | ||
| this.eventBus = eventBus; | ||
| this.fireEventHashMap = new HashMap<>(); | ||
| this.awaitingToggleBack = new ArrayList<>(); | ||
| } | ||
|
|
||
| public void registerEventTrigger(BooleanSupplier condition, IEvent fireEvent) { | ||
| List<IEvent> ev = fireEventHashMap.getOrDefault(condition, new ArrayList<>()); | ||
|
SpeedSlicer marked this conversation as resolved.
Resolved
|
||
| ev.add(fireEvent); | ||
| fireEventHashMap.put(condition, ev); | ||
| } | ||
|
|
||
| @Override | ||
|
SpeedSlicer marked this conversation as resolved.
Resolved
|
||
| public void periodic() { | ||
| // Source - https://stackoverflow.com/a/18448795 | ||
| // Posted by Kevin DiTraglia, modified by community. See post 'Timeline' for | ||
| // change history | ||
| // Retrieved 2026-10-07, License - CC BY-SA 4.0 | ||
|
|
||
| List<BooleanSupplier> toRemove = new ArrayList<BooleanSupplier>(); | ||
| for (BooleanSupplier bs : awaitingToggleBack) { | ||
| if (bs.getAsBoolean()) { | ||
| toRemove.add(bs); | ||
| } | ||
| } | ||
| awaitingToggleBack.removeAll(toRemove); | ||
|
|
||
| fireEventHashMap.keySet().forEach((x) -> { | ||
| if (x.getAsBoolean() && !awaitingToggleBack.contains(x)) { | ||
| for (IEvent event : fireEventHashMap.get(x)) { | ||
| eventBus.fireEvent(event); | ||
| } | ||
| } | ||
| awaitingToggleBack.add(x); | ||
| return; | ||
| }); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I notice that
goalPoseisn't used outside of assigningtarget. Maybe remove?