Repository navigation
Shooting while moving #222
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
Merged
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
45e2a45
initial commit
nirmalkozak 683f4b1
Merge branch 'main' into ShootOnTheMove
nirmalkozak cee9142
Merge branch 'main' into ShootOnTheMove
nirmalkozak 367259a
linting
nirmalkozak c9e7bcc
Merge branch 'ShootOnTheMove' of https://github.com/Frc5572/FRC2026 i…
nirmalkozak 011dbe2
Merge branch 'main' into ShootOnTheMove
nirmalkozak 32041bf
linting
nirmalkozak 53cf225
Merge branch 'ShootOnTheMove' of https://github.com/Frc5572/FRC2026 i…
nirmalkozak 457b8ac
linting
nirmalkozak debd605
linting
nirmalkozak 8bc00f6
checkstyle fixes
nirmalkozak b3b2a06
quick fix
nirmalkozak 6eb93b8
Merge branch 'main' into ShootOnTheMove
nirmalkozak 0f36676
java docs fix
nirmalkozak 6366a15
Merge branch 'ShootOnTheMove' of https://github.com/Frc5572/FRC2026 i…
nirmalkozak e9e3aaf
Integrating ShootOnMove
nirmalkozak 00ff93d
fixed stuff
nirmalkozak 84bf05f
linting
nirmalkozak 3686b48
It works
nirmalkozak File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| package frc.robot.math; | ||
|
|
||
| import static edu.wpi.first.units.Units.Degrees; | ||
| import static edu.wpi.first.units.Units.MetersPerSecond; | ||
| import static edu.wpi.first.units.Units.Radians; | ||
| import static edu.wpi.first.units.Units.RotationsPerSecond; | ||
| import org.littletonrobotics.junction.Logger; | ||
| import edu.wpi.first.math.geometry.Pose2d; | ||
| import edu.wpi.first.math.geometry.Rotation2d; | ||
| import edu.wpi.first.math.geometry.Translation2d; | ||
| import edu.wpi.first.math.kinematics.ChassisSpeeds; | ||
| import edu.wpi.first.units.measure.Angle; | ||
| import edu.wpi.first.units.measure.LinearVelocity; | ||
| import edu.wpi.first.wpilibj.Timer; | ||
| import frc.robot.Constants; | ||
| import frc.robot.shotdata.ShotData; | ||
| import frc.robot.shotdata.ShotData.ShotParams; | ||
|
|
||
| /** Shoot while moving */ | ||
| public class ShootOnMove { | ||
|
|
||
| /** Records moving shot */ | ||
| public static record MovingShot(Rotation2d turretAngleFieldRelative, Angle pitch, | ||
| LinearVelocity exitSpeed, boolean feasible) { | ||
| } | ||
|
|
||
| static final Translation2d SHOOTER_OFFSET = new Translation2d(-0.155575, -0.13335); | ||
| static final double LATENCY_SEC = 0.0; // tune: vision + feed + spin-up latency | ||
|
|
||
| static final Angle MIN_PITCH = Degrees | ||
| .of(90 - Constants.AdjustableHood.HoodOffset - Constants.AdjustableHood.maxHoodAngleDeg); | ||
| static final Angle MAX_PITCH = Degrees.of(90 - Constants.AdjustableHood.HoodOffset); | ||
| static final LinearVelocity MAX_EXIT_SPEED = MetersPerSecond | ||
| .of(Constants.Shooter.maxFlywheelSpeed.in(RotationsPerSecond) * Constants.Shooter.k); | ||
|
|
||
| /** solve moving shot */ | ||
| public static MovingShot solveMovingShot(Pose2d robotPose, ChassisSpeeds fieldSpeeds, | ||
| Translation2d hub, double flywheelSpeed, double trimUp, double trimLeft) { | ||
| double vx = fieldSpeeds.vxMetersPerSecond; | ||
| double vy = fieldSpeeds.vyMetersPerSecond; | ||
| double omega = fieldSpeeds.omegaRadiansPerSecond; | ||
| double currentFlywheelSpeed = flywheelSpeed; | ||
|
|
||
| // 1. Latency compensation: predict where the robot is when the ball leaves | ||
| Pose2d pose = new Pose2d( | ||
| robotPose.getTranslation().plus(new Translation2d(vx, vy).times(LATENCY_SEC)), | ||
| robotPose.getRotation().plus(new Rotation2d(omega * LATENCY_SEC))); | ||
|
|
||
| // 2. Shooter position and velocity in the field frame | ||
| // v_shooter = v_center + omega x r | ||
| Translation2d offsetField = SHOOTER_OFFSET.rotateBy(pose.getRotation()); | ||
| Translation2d shooterPos = pose.getTranslation().plus(offsetField); | ||
| double svx = vx - omega * offsetField.getY(); | ||
| double svy = vy + omega * offsetField.getX(); | ||
|
|
||
| // 3. Radial/tangential frame about the hub | ||
| Translation2d toHub = hub.minus(shooterPos); | ||
| double d = toHub.getNorm() + trimUp; | ||
| Logger.recordOutput("ShootOnMove/d", d); | ||
| Logger.recordOutput("ShootOnMove/time", Timer.getFPGATimestamp()); | ||
|
|
||
| Rotation2d rHat = toHub.getAngle(); | ||
| double cosR = rHat.getCos(); | ||
| double sinR = rHat.getSin(); | ||
|
|
||
| double vrRobot = svx * cosR + svy * sinR; // + toward hub | ||
| double vtRobot = -svx * sinR + svy * cosR; // + is CCW (r-hat rotated +90°) | ||
| double vzRobot = 0.0; // assume flat field | ||
|
|
||
| // 4. Stationary solution -> required field-relative ball velocity | ||
| ShotParams s = ShotData.staticShotParameters(d, currentFlywheelSpeed); | ||
| Logger.recordOutput("ShootOnMove/s", s); | ||
|
|
||
| double stationaryPitch = s.pitch().in(Radians); | ||
| Logger.recordOutput("ShootOnMove/stationaryPitch", stationaryPitch); | ||
|
|
||
| double stationarySpeed = s.exitSpeed().in(MetersPerSecond); | ||
| Logger.recordOutput("ShootOnMove/stationarySpeed", stationarySpeed); | ||
|
|
||
| double vrTarget = stationarySpeed * Math.cos(stationaryPitch); | ||
| Logger.recordOutput("ShootOnMove/vrTarget", vrTarget); | ||
|
|
||
| double vzTarget = stationarySpeed * Math.sin(stationaryPitch); | ||
| Logger.recordOutput("ShootOnMove/vzTarget", vzTarget); | ||
|
|
||
| // 5. Robot-relative launch vector = target field velocity - shooter velocity | ||
| double a = vrTarget - vrRobot; // radial | ||
| Logger.recordOutput("ShootOnMove/aRadial", a); | ||
|
|
||
| double b = -vtRobot; // tangential (target v_t is 0) | ||
| Logger.recordOutput("ShootOnMove/b", b); | ||
|
|
||
| double c = vzTarget - vzRobot; // vertical | ||
| Logger.recordOutput("ShootOnMove/c", c); | ||
|
|
||
|
|
||
| // 6. Convert to spherical coordinates | ||
| double h = Math.hypot(a, b); // horizontal launch speed, >= 0 | ||
| Logger.recordOutput("ShootOnMove/h", h); | ||
|
|
||
| double deltaYaw = Math.atan2(b, a); | ||
| Logger.recordOutput("ShootOnMove/deltaYaw", deltaYaw); | ||
|
|
||
| Angle pitch = Radians.of(Math.atan2(c, h)); | ||
| Logger.recordOutput("ShootOnMove/pitch", pitch); | ||
|
|
||
| LinearVelocity exitSpeed = MetersPerSecond.of(Math.sqrt(h * h + c * c)); | ||
| Logger.recordOutput("ShootOnMove/exitSpeed", exitSpeed); | ||
|
|
||
| // 7. Turret angle: field heading, then robot-relative | ||
| Rotation2d turretField = | ||
| rHat.plus(Rotation2d.fromRadians(deltaYaw)).plus(Rotation2d.fromDegrees(trimLeft)); | ||
| Logger.recordOutput("ShootOnMove/turretField", turretField); | ||
|
|
||
| // 8. Feasibility against mechanism limits | ||
| boolean feasible = | ||
| pitch.gte(MIN_PITCH) && pitch.lte(MAX_PITCH) && exitSpeed.lte(MAX_EXIT_SPEED); | ||
| Logger.recordOutput("ShootOnMove/feasible", feasible); | ||
|
|
||
| return new MovingShot(turretField, pitch, exitSpeed, feasible); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.