Skip to content

Commit f3110c4

Browse files
committed
Update to moving while shooting and fix minor bugs.
1 parent 4ab1a1e commit f3110c4

File tree

11 files changed

+127
-39
lines changed

11 files changed

+127
-39
lines changed

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": "2.0.2",
4+
"version": "2.0.3",
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": "2.0.2"
16+
"version": "2.0.3"
1717
}
1818
],
1919
"requires": [

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import edu.wpi.first.util.sendable.Sendable;
66
import edu.wpi.first.wpilibj.AddressableLED;
77
import edu.wpi.first.wpilibj.AddressableLEDBuffer;
8+
import edu.wpi.first.wpilibj.DriverStation;
9+
import edu.wpi.first.wpilibj.RobotBase;
810
import edu.wpi.first.wpilibj.util.Color;
911

1012
/**
@@ -16,6 +18,7 @@ public class ExampleLEDs extends AbsoluteSubsystem {
1618
private final AddressableLED led;
1719
private final AddressableLEDBuffer buffer;
1820
private final AddressableLEDBufferView view;
21+
private final Simulation ledSim;
1922

2023
private LEDPattern currentPattern;
2124
private String currentPatternName = "Idle";
@@ -37,6 +40,12 @@ public ExampleLEDs() {
3740
// Create view for pattern application
3841
view = new AddressableLEDBufferView(buffer, 0, LED_LENGTH);
3942

43+
// Set up simulation
44+
ledSim = new Simulation();
45+
if (RobotBase.isSimulation()) {
46+
ledSim.setUp();
47+
}
48+
4049
// Start with idle pattern
4150
currentPattern = Patterns.idle();
4251
}
@@ -48,13 +57,18 @@ public void periodic() {
4857
currentPattern.applyTo(view);
4958
}
5059
led.setData(buffer);
60+
61+
// Update simulation display
62+
if (RobotBase.isSimulation()) {
63+
ledSim.update(buffer, led);
64+
}
5165
}
5266

5367
/**
5468
* Set idle pattern - gentle breathing effect.
5569
*/
5670
public void setIdle() {
57-
currentPattern = Patterns.idle();
71+
currentPattern = Patterns.scrollingIdle(DriverStation.getAlliance().orElse(DriverStation.Alliance.Red) == DriverStation.Alliance.Blue ? Color.kBlue : Color.kRed, 2);
5872
currentPatternName = "Idle";
5973
}
6074

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

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,21 +74,31 @@ private Fuel(Translation3d pos) {
7474
}
7575

7676
private void update() {
77-
pos = pos.plus(vel.times(PERIOD / subticks));
77+
double dt = PERIOD / subticks;
7878
if (pos.getZ() > FUEL_RADIUS) {
79-
vel = vel.plus(GRAVITY.times(PERIOD / subticks));
80-
// Air resistance: F_drag = -0.5 * rho * v^2 * Cd * A in direction of velocity
79+
Translation3d accel = GRAVITY;
8180
double speed = vel.getNorm();
8281
if (speed > 0.01) {
8382
double dragAccelMag = DRAG_FACTOR * speed * speed;
8483
Translation3d dragAccel = vel.div(speed).times(-dragAccelMag);
85-
vel = vel.plus(dragAccel.times(PERIOD / subticks));
84+
accel = accel.plus(dragAccel);
8685
}
86+
pos = pos.plus(vel.times(dt)).plus(accel.times(0.5 * dt * dt));
87+
Translation3d halfVel = vel.plus(accel.times(dt));
88+
Translation3d newAccel = GRAVITY;
89+
double newSpeed = halfVel.getNorm();
90+
if (newSpeed > 0.01) {
91+
double newDragAccelMag = DRAG_FACTOR * newSpeed * newSpeed;
92+
Translation3d newDragAccel = halfVel.div(newSpeed).times(-newDragAccelMag);
93+
newAccel = newAccel.plus(newDragAccel);
94+
}
95+
vel = vel.plus(accel.plus(newAccel).times(0.5 * dt));
96+
} else {
97+
pos = pos.plus(vel.times(dt));
8798
}
8899
if (Math.abs(vel.getZ()) < 0.05 && pos.getZ() <= FUEL_RADIUS + 0.03) {
89100
vel = new Translation3d(vel.getX(), vel.getY(), 0);
90-
vel = vel.times(1 - FRICTION * PERIOD / subticks);
91-
// pos = new Translation3d(pos.getX(), pos.getY(), FUEL_RADIUS);
101+
vel = vel.times(1 - FRICTION * dt);
92102
}
93103
handleFieldCollisions();
94104
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package frc.robot.subsystems;
2+
3+
import edu.wpi.first.wpilibj.AddressableLED;
4+
import edu.wpi.first.wpilibj.AddressableLEDBuffer;
5+
import edu.wpi.first.wpilibj.LEDPattern;
6+
import edu.wpi.first.wpilibj.util.Color;
7+
import edu.wpi.first.wpilibj2.command.Command;
8+
import edu.wpi.first.wpilibj2.command.SubsystemBase;
9+
10+
public class testLeds extends SubsystemBase {
11+
private static final int kPort = 9;
12+
private static final int kLength = 120;
13+
14+
private final AddressableLED m_led;
15+
private final AddressableLEDBuffer m_buffer;
16+
17+
public testLeds() {
18+
m_led = new AddressableLED(kPort);
19+
m_buffer = new AddressableLEDBuffer(kLength);
20+
m_led.setLength(kLength);
21+
m_led.start();
22+
23+
// Set the default command to turn the strip off, otherwise the last colors written by
24+
// the last command to run will continue to be displayed.
25+
// Note: Other default patterns could be used instead!
26+
setDefaultCommand(runPattern(LEDPattern.solid(Color.kBlack)).withName("Off"));
27+
}
28+
29+
@Override
30+
public void periodic() {
31+
// Periodically send the latest LED color data to the LED strip for it to display
32+
m_led.setData(m_buffer);
33+
}
34+
35+
/**
36+
* Creates a command that runs a pattern on the entire LED strip.
37+
*
38+
* @param pattern the LED pattern to run
39+
*/
40+
public Command runPattern(LEDPattern pattern) {
41+
return run(() -> pattern.applyTo(m_buffer));
42+
}
43+
}

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

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"fileName": "REVLib.json",
33
"name": "REVLib",
4-
"version": "2026.0.1",
4+
"version": "2026.0.2",
55
"frcYear": "2026",
66
"uuid": "3f48eb8c-50fe-43a6-9cb7-44c86353c4cb",
77
"mavenUrls": [
@@ -12,14 +12,14 @@
1212
{
1313
"groupId": "com.revrobotics.frc",
1414
"artifactId": "REVLib-java",
15-
"version": "2026.0.1"
15+
"version": "2026.0.2"
1616
}
1717
],
1818
"jniDependencies": [
1919
{
2020
"groupId": "com.revrobotics.frc",
2121
"artifactId": "REVLib-driver",
22-
"version": "2026.0.1",
22+
"version": "2026.0.2",
2323
"skipInvalidPlatforms": true,
2424
"isJar": false,
2525
"validPlatforms": [
@@ -34,7 +34,7 @@
3434
{
3535
"groupId": "com.revrobotics.frc",
3636
"artifactId": "RevLibBackendDriver",
37-
"version": "2026.0.1",
37+
"version": "2026.0.2",
3838
"skipInvalidPlatforms": true,
3939
"isJar": false,
4040
"validPlatforms": [
@@ -49,7 +49,7 @@
4949
{
5050
"groupId": "com.revrobotics.frc",
5151
"artifactId": "RevLibWpiBackendDriver",
52-
"version": "2026.0.1",
52+
"version": "2026.0.2",
5353
"skipInvalidPlatforms": true,
5454
"isJar": false,
5555
"validPlatforms": [
@@ -66,7 +66,7 @@
6666
{
6767
"groupId": "com.revrobotics.frc",
6868
"artifactId": "REVLib-cpp",
69-
"version": "2026.0.1",
69+
"version": "2026.0.2",
7070
"libName": "REVLib",
7171
"headerClassifier": "headers",
7272
"sharedLibrary": false,
@@ -83,7 +83,7 @@
8383
{
8484
"groupId": "com.revrobotics.frc",
8585
"artifactId": "REVLib-driver",
86-
"version": "2026.0.1",
86+
"version": "2026.0.2",
8787
"libName": "REVLibDriver",
8888
"headerClassifier": "headers",
8989
"sharedLibrary": false,
@@ -100,7 +100,7 @@
100100
{
101101
"groupId": "com.revrobotics.frc",
102102
"artifactId": "RevLibBackendDriver",
103-
"version": "2026.0.1",
103+
"version": "2026.0.2",
104104
"libName": "BackendDriver",
105105
"sharedLibrary": true,
106106
"skipInvalidPlatforms": true,
@@ -116,7 +116,7 @@
116116
{
117117
"groupId": "com.revrobotics.frc",
118118
"artifactId": "RevLibWpiBackendDriver",
119-
"version": "2026.0.1",
119+
"version": "2026.0.2",
120120
"libName": "REVLibWpi",
121121
"sharedLibrary": true,
122122
"skipInvalidPlatforms": true,

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": "2.0.0",
4+
"version": "2.0.2",
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": "2.0.0"
16+
"version": "2.0.2"
1717
}
1818
],
1919
"requires": [],

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"fileName": "yams.json",
33
"name": "Yet Another Mechanism System",
4-
"version": "2026.2.8",
4+
"version": "2026.2.14",
55
"frcYear": "2026",
66
"uuid": "a1051e86-a979-4880-a28b-a0d5362d1d96",
77
"mavenUrls": [
@@ -12,7 +12,7 @@
1212
{
1313
"groupId": "yams",
1414
"artifactId": "YAMS-java",
15-
"version": "2026.2.8"
15+
"version": "2026.2.14"
1616
}
1717
],
1818
"cppDependencies": [],

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=2.0.2
4+
version=2.0.3
55

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

src/main/java/ca/team4308/absolutelib/math/trajectories/SolverConstants.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ private SolverConstants() {
133133
* Min entry angle (deg) for a hit. Steeper = more likely to go in. 90 =
134134
* straight down, 0 = flat. Default: 30.0
135135
*/
136-
private static double minEntryAngleDegrees = 10.0;
136+
private static double minEntryAngleDegrees = 30.0;
137137

138138
/**
139139
* Rim clearance (m) the ball must clear above the target rim edge. Larger =

src/main/java/ca/team4308/absolutelib/math/trajectories/TrajectoryResult.java

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,27 +21,37 @@ public class TrajectoryResult {
2121
* visualization. This uses the simulated trajectory from the solver. The
2222
* trajectory naturally terminates when the ball lands at the target (on
2323
* descent). Returns an empty list if no valid solution exists.
24+
*
25+
* <p>When robot velocity is present in the input, the flight path includes
26+
* the inherited chassis velocity so the visualization matches what the
27+
* simulation (FuelSim) actually does with the ball.</p>
2428
*/
2529
public List<Pose3d> getFlightPath() {
26-
// Only provide a path if the solution is successful and input is available
2730
if (!isSuccess() || input == null) {
2831
return List.of();
2932
}
3033

3134
try {
35+
double yaw = input.getShooterYaw() + yawAdjustmentRadians;
36+
double hSpeed = requiredVelocityMps * Math.cos(pitchAngleRadians);
37+
double launchVx = hSpeed * Math.cos(yaw) + input.getRobotVx();
38+
double launchVy = hSpeed * Math.sin(yaw) + input.getRobotVy();
39+
double launchVz = requiredVelocityMps * Math.sin(pitchAngleRadians);
40+
double totalLaunchSpeed = Math.sqrt(launchVx * launchVx + launchVy * launchVy + launchVz * launchVz);
41+
double effectivePitch = Math.atan2(launchVz, Math.sqrt(launchVx * launchVx + launchVy * launchVy));
42+
double effectiveYaw = Math.atan2(launchVy, launchVx);
43+
3244
ca.team4308.absolutelib.math.trajectories.physics.ProjectileMotion projectileMotion
3345
= new ca.team4308.absolutelib.math.trajectories.physics.ProjectileMotion();
34-
// Pass targetRadius=0 so the simulation runs the full arc to the ground
35-
// instead of terminating early at the basket-descent condition.
3646
ca.team4308.absolutelib.math.trajectories.physics.ProjectileMotion.TrajectoryResult simResult = projectileMotion.simulate(
3747
gamePiece != null ? gamePiece : ca.team4308.absolutelib.math.trajectories.gamepiece.GamePieces.getCurrent(),
3848
input.getShooterX(), input.getShooterY(), input.getShooterZ(),
39-
requiredVelocityMps,
40-
pitchAngleRadians,
41-
input.getShooterYaw() + yawAdjustmentRadians,
42-
0, // spinRpm (not tracked in result)
49+
totalLaunchSpeed,
50+
effectivePitch,
51+
effectiveYaw,
52+
0,
4353
input.getTargetX(), input.getTargetY(), input.getTargetZ(),
44-
0 // targetRadius=0 to prevent early termination
54+
0
4555
);
4656

4757
int validCount = 0;
@@ -52,8 +62,6 @@ public List<Pose3d> getFlightPath() {
5262
validCount++;
5363
}
5464

55-
// Find the point of closest 3D approach to the target so the path
56-
// ends near the target instead of continuing to the ground.
5765
double tX = input.getTargetX();
5866
double tY = input.getTargetY();
5967
double tZ = input.getTargetZ();
@@ -73,8 +81,6 @@ public List<Pose3d> getFlightPath() {
7381
closestIndex = i;
7482
}
7583
}
76-
// Include a couple points past closest approach so the path visually
77-
// reaches the target area, but not the entire descent to the ground.
7884
int endIndex = Math.min(closestIndex + 2, validCount);
7985

8086
List<Pose3d> path = new ArrayList<>();

0 commit comments

Comments
 (0)