Skip to content

Commit 3cd9aa1

Browse files
committed
V1.3.5
1 parent 638871c commit 3cd9aa1

File tree

13 files changed

+634
-25
lines changed

13 files changed

+634
-25
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
# Changelog for AbsoluteLib V2
22

33

4+
# 1.3.5
5+
6+
- **Debugging!**: New Website part showing greaterlogs of the trajectorys that are generated to help debug and tune it.
7+
- **Path Visuals**: Re-added the 3D Array of path points.
8+
49
## 1.3.4
510
- **Hybrid shooter system** (`ca.team4308.absolutelib.math.trajectories.shooter`): New package that combines a lookup table, physics solver, RPM feedback, and movement compensation into a unified shot-calculation pipeline.
611
- **ShotLookupTable**: Fixed-size sorted lookup table with linear interpolation and edge clamping. Add tested distance/pitch/RPM entries and retrieve interpolated shot parameters in constant time.

absolutelib.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"fileName": "absolutelib.json",
33
"name": "absolutelib",
4-
"version": "1.3.4",
4+
"version": "1.3.5",
55
"frcYear": "2026",
66
"uuid": "a604c6de-3573-4ba6-ae4f-32778238b9de",
77
"mavenUrls": [
@@ -13,7 +13,7 @@
1313
{
1414
"groupId": "ca.team4308",
1515
"artifactId": "absolutelib-java",
16-
"version": "1.3.4"
16+
"version": "1.3.5"
1717
}
1818
],
1919
"requires": [

example/example-2026-Imported/src/main/java/frc/robot/subsystems/ExampleShooter.java

Lines changed: 110 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import edu.wpi.first.util.sendable.SendableBuilder;
2121
import edu.wpi.first.wpilibj2.command.Command;
2222

23+
import java.util.List;
2324
import java.util.function.Supplier;
2425

2526

@@ -84,8 +85,10 @@ public ExampleShooter() {
8485
solver = new TrajectorySolver(gamePiece, solverConfig);
8586

8687
shooterSystem = new ShooterSystem(config, table, solver);
87-
shooterSystem.setMode(ShotMode.LOOKUP_WITH_SOLVER_FALLBACK);
88+
shooterSystem.setMode(ShotMode.SOLVER_ONLY);
8889
shooterSystem.setFallbackShot(60.0, 3000);
90+
91+
solver.setDebugEnabled(true);
8992
}
9093

9194
public void setPoseSupplier(Supplier<Pose2d> supplier) { this.poseSupplier = supplier; }
@@ -138,6 +141,100 @@ public void periodic() {
138141
Pose3d goalPose = new Pose3d(targetPosition, new Rotation3d());
139142
Logger.recordOutput("ExampleShooter/GoalPose3d", goalPose);
140143
Logger.recordOutput("ExampleShooter/GoalPose3dArray", new Pose3d[] { goalPose });
144+
145+
recordOutput("TargetX", targetPosition.getX());
146+
recordOutput("TargetY", targetPosition.getY());
147+
recordOutput("TargetZ", targetPosition.getZ());
148+
recordOutput("ShooterHeight", shooterHeightMeters);
149+
recordOutput("ExitVelocity", currentShot.exitVelocityMps);
150+
151+
logTrajectoryDebug();
152+
}
153+
154+
private void logTrajectoryDebug() {
155+
TrajectoryResult trajResult = shooterSystem.getLastTrajectoryResult();
156+
if (trajResult == null) return;
157+
158+
recordOutput("Trajectory/Status", trajResult.getStatus().name());
159+
recordOutput("Trajectory/StatusMessage", trajResult.getStatusMessage());
160+
recordOutput("Trajectory/Confidence", trajResult.getConfidenceScore());
161+
162+
if (trajResult.isSuccess()) {
163+
recordOutput("Trajectory/PitchDeg", trajResult.getPitchAngleDegrees());
164+
recordOutput("Trajectory/YawAdjustDeg", trajResult.getYawAdjustmentDegrees());
165+
recordOutput("Trajectory/Velocity", trajResult.getRequiredVelocityMps());
166+
recordOutput("Trajectory/TimeOfFlight", trajResult.getTimeOfFlightSeconds());
167+
recordOutput("Trajectory/MaxHeight", trajResult.getMaxHeightMeters());
168+
recordOutput("Trajectory/Margin", trajResult.getMarginOfErrorMeters());
169+
recordOutput("Trajectory/RPM", trajResult.getRecommendedRpm());
170+
171+
List<Pose3d> flightPath = trajResult.getFlightPath();
172+
if (!flightPath.isEmpty()) {
173+
Logger.recordOutput("ExampleShooter/Trajectory/FlightPath",
174+
flightPath.toArray(new Pose3d[0]));
175+
176+
double[] pathX = new double[flightPath.size()];
177+
double[] pathY = new double[flightPath.size()];
178+
double[] pathZ = new double[flightPath.size()];
179+
for (int i = 0; i < flightPath.size(); i++) {
180+
pathX[i] = flightPath.get(i).getX();
181+
pathY[i] = flightPath.get(i).getY();
182+
pathZ[i] = flightPath.get(i).getZ();
183+
}
184+
recordOutput("Trajectory/PathX", pathX);
185+
recordOutput("Trajectory/PathY", pathY);
186+
recordOutput("Trajectory/PathZ", pathZ);
187+
recordOutput("Trajectory/PathLength", flightPath.size());
188+
}
189+
}
190+
191+
SolveDebugInfo debug = trajResult.getDebugInfo();
192+
if (debug != null) {
193+
recordOutput("Debug/Enabled", true);
194+
recordOutput("Debug/TotalTested", debug.getTotalTested());
195+
recordOutput("Debug/Accepted", debug.getAcceptedCount());
196+
recordOutput("Debug/TotalRejected", debug.getTotalRejected());
197+
recordOutput("Debug/RejectedCollision", debug.getRejectedCollisionCount());
198+
recordOutput("Debug/RejectedArcTooLow", debug.getRejectedArcTooLowCount());
199+
recordOutput("Debug/RejectedClearance", debug.getRejectedClearanceCount());
200+
recordOutput("Debug/RejectedMiss", debug.getRejectedMissCount());
201+
recordOutput("Debug/RejectedFlyover", debug.getRejectedFlyoverCount());
202+
recordOutput("Debug/BestScore", debug.getBestScore());
203+
recordOutput("Debug/BestPitchDeg", debug.getBestPitchDegrees());
204+
recordOutput("Debug/Summary", debug.getSummary());
205+
recordOutput("Debug/DetailedTable", debug.getDetailedTable());
206+
207+
List<SolveDebugInfo.CandidateInfo> accepted = debug.getAcceptedCandidates();
208+
double[] accPitch = new double[accepted.size()];
209+
double[] accScore = new double[accepted.size()];
210+
double[] accTOF = new double[accepted.size()];
211+
double[] accMaxH = new double[accepted.size()];
212+
for (int i = 0; i < accepted.size(); i++) {
213+
accPitch[i] = accepted.get(i).getPitchDegrees();
214+
accScore[i] = accepted.get(i).getScore();
215+
accTOF[i] = accepted.get(i).getTimeOfFlight();
216+
accMaxH[i] = accepted.get(i).getMaxHeight();
217+
}
218+
recordOutput("Debug/AcceptedPitches", accPitch);
219+
recordOutput("Debug/AcceptedScores", accScore);
220+
recordOutput("Debug/AcceptedTOF", accTOF);
221+
recordOutput("Debug/AcceptedMaxHeight", accMaxH);
222+
223+
List<SolveDebugInfo.CandidateInfo> all = debug.getCandidates();
224+
double[] allPitch = new double[all.size()];
225+
double[] allClosest = new double[all.size()];
226+
String[] allStatus = new String[all.size()];
227+
for (int i = 0; i < all.size(); i++) {
228+
allPitch[i] = all.get(i).getPitchDegrees();
229+
allClosest[i] = all.get(i).getClosestApproach();
230+
allStatus[i] = all.get(i).getRejection().name();
231+
}
232+
recordOutput("Debug/AllPitches", allPitch);
233+
recordOutput("Debug/AllClosest", allClosest);
234+
recordOutput("Debug/AllStatus", allStatus);
235+
} else {
236+
recordOutput("Debug/Enabled", false);
237+
}
141238
}
142239

143240
/**
@@ -168,10 +265,22 @@ private void updateShot() {
168265

169266
double measuredRpm = currentRpmSupplier != null ? currentRpmSupplier.get() : 0;
170267

268+
shooterSystem.setSolverInputTemplate(
269+
ShotInput.builder()
270+
.shooterPositionMeters(shooterX, shooterY, shooterHeightMeters)
271+
.shooterYawRadians(yawRad)
272+
.targetPositionMeters(targetPosition.getX(), targetPosition.getY(), targetPosition.getZ())
273+
.targetRadiusMeters(0.53)
274+
.includeAirResistance(true)
275+
.robotVelocity(vx, vy)
276+
);
277+
171278
currentShot = shooterSystem.calculate(lastDistanceMeters, measuredRpm, vx, vy, yawRad);
172279

173280
recordOutput("RobotX", pose.getX());
174281
recordOutput("RobotY", pose.getY());
282+
recordOutput("ShooterX", shooterX);
283+
recordOutput("ShooterY", shooterY);
175284
}
176285

177286
/**

example/example-2026-Imported/vendordeps/absolutelib.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"fileName": "absolutelib.json",
33
"name": "absolutelib",
4-
"version": "1.3.2",
4+
"version": "1.3.4",
55
"frcYear": "2026",
66
"uuid": "a604c6de-3573-4ba6-ae4f-32778238b9de",
77
"mavenUrls": [
@@ -13,7 +13,7 @@
1313
{
1414
"groupId": "ca.team4308",
1515
"artifactId": "absolutelib-java",
16-
"version": "1.3.2"
16+
"version": "1.3.4"
1717
}
1818
],
1919
"requires": [],

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
org.gradle.workers.max=1
22

33
group=ca.team4308
4-
version=1.3.4
4+
version=1.3.5
55

66
org.gradle.console=plain
77
org.gradle.logging.level=info

src/main/java/ca/team4308/absolutelib/math/trajectories/shooter/MovementCompensator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* {@code ShootOnTheFlyCalculator} and the hammerheads5000 {@code TurretCalculator},
1414
* but simplified to a linear correction term for speed and stability.</p>
1515
*
16-
* <h3>Usage</h3>
16+
* <h2>Usage</h2>
1717
* <pre>{@code
1818
* MovementCompensator comp = new MovementCompensator(config);
1919
* ShotParameters adjusted = comp.compensate(baseShotParams, vxMps, vyMps, yawToTargetRad);

src/main/java/ca/team4308/absolutelib/math/trajectories/shooter/RPMCorrector.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
* <p>This corrects for battery sag, wheel slip, motor heating, and gamepiece
1212
* compression changes — all without a full trajectory re-solve.</p>
1313
*
14-
* <h3>Usage</h3>
14+
* <h2>Usage</h2>
1515
* <pre>{@code
1616
* RPMCorrector corrector = new RPMCorrector(config);
1717
* ShotParameters corrected = corrector.correct(baseShotParams, measuredRpm);

src/main/java/ca/team4308/absolutelib/math/trajectories/shooter/ShooterConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*
66
* <p>Immutable after construction. Use the builder to create instances.</p>
77
*
8-
* <h3>Usage</h3>
8+
* <h2>Usage</h2>
99
* <pre>{@code
1010
* ShooterConfig config = ShooterConfig.builder()
1111
* .pitchLimits(30.0, 80.0)

src/main/java/ca/team4308/absolutelib/math/trajectories/shooter/ShooterSystem.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Hybrid shooter system that combines a lookup table, physics solver, RPM
99
* feedback, and movement compensation into a single easy-to-use API.
1010
*
11-
* <h3>Design Goals</h3>
11+
* <h2>Design Goals</h2>
1212
* <ul>
1313
* <li>Reliable in matches — lookup table as primary source</li>
1414
* <li>Easy to tune on the practice field — just add table entries</li>
@@ -57,6 +57,7 @@ public final class ShooterSystem {
5757
private ShotParameters lastResult = ShotParameters.invalid("Not yet calculated");
5858
private SafetyValidator.ValidationResult lastValidation;
5959
private String lastSourceDescription = "none";
60+
private TrajectoryResult lastTrajectoryResult;
6061

6162
private ShotInput.Builder solverInputTemplate = null;
6263

@@ -259,6 +260,7 @@ private ShotParameters solveWithSolver(double distanceMeters, double yawToTarget
259260
try {
260261
ShotInput input = solverInputTemplate.build();
261262
TrajectoryResult result = solver.solve(input);
263+
lastTrajectoryResult = result;
262264
if (result.isSuccess()) {
263265
double pitch = result.getPitchAngleDegrees();
264266
double rpm = result.getRecommendedRpm();
@@ -315,6 +317,17 @@ private ShotParameters blendResults(double distanceMeters, double yawToTargetRad
315317
/** Returns the safety validator for direct access. */
316318
public SafetyValidator getSafetyValidator() { return safetyValidator; }
317319

320+
/**
321+
* Returns the last trajectory result from the solver, or null if the solver
322+
* has not been called yet.
323+
*
324+
* @return the last trajectory result, or null
325+
*/
326+
public TrajectoryResult getLastTrajectoryResult() { return lastTrajectoryResult; }
327+
328+
/** Returns the underlying trajectory solver, or null if not configured. */
329+
public TrajectorySolver getSolver() { return solver; }
330+
318331
private static double lerp(double a, double b, double t) {
319332
return a + (b - a) * t;
320333
}

src/main/java/ca/team4308/absolutelib/math/trajectories/shooter/ShotLookupTable.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
* interpolates between them. When the distance is outside the range the
1212
* closest entry is returned (clamped).</p>
1313
*
14-
* <h3>Usage</h3>
14+
* <h2>Usage</h2>
1515
* <pre>{@code
1616
* ShotLookupTable table = new ShotLookupTable()
1717
* .addEntry(1.5, 75.0, 2000)

0 commit comments

Comments
 (0)