Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
97 commits
Select commit Hold shift + click to select a range
b34c8d4
good luck
Nonochen0104 Mar 10, 2026
0b3a0a6
Fixed hood angle
rainingmika Mar 10, 2026
70330fc
Updated LeftNeutralZoneAuto
Nonochen0104 Mar 11, 2026
d7a168a
Leftneutralauto&rightneutralauto, some changes to path planner
Nonochen0104 Mar 11, 2026
2ad2ed8
add the auto in constants
rainingmika Mar 11, 2026
73eeca6
neutral zone auto
Nonochen0104 Mar 11, 2026
6dac201
auto
Nonochen0104 Mar 11, 2026
846a68d
intake for auto
Nonochen0104 Mar 11, 2026
03b1378
left neutral zone auto
Nonochen0104 Mar 11, 2026
2f68283
Neutral auto
Nonochen0104 Mar 11, 2026
4fa4154
left neutral zone auto
Nonochen0104 Mar 11, 2026
e7a38c5
neutral zone with pathplanner
Nonochen0104 Mar 12, 2026
9e86162
auto
rainingmika Mar 12, 2026
90d54f5
auto trench path
Nonochen0104 Mar 12, 2026
4698853
pathplanner auto
Nonochen0104 Mar 12, 2026
db3a88c
trench auto fix
Nonochen0104 Mar 12, 2026
9ae23d3
left neutral zone auto fix
rainingmika Mar 12, 2026
1e94035
use the shooter too in the auto
Nonochen0104 Mar 12, 2026
1db00c3
value changes on left neutral zone auto
rainingmika Mar 13, 2026
4ab8dbe
Changed settings for the robot in pathplanner
Nonochen0104 Mar 13, 2026
166b09f
leftneutralzoneauto2 & rightneutralzoneauto
Nonochen0104 Mar 14, 2026
a066aa8
changes
rainingmika Mar 14, 2026
0936fca
drive path, DriveTestAuto
Nonochen0104 Mar 14, 2026
acb27df
pathplanner changes
Nonochen0104 Mar 14, 2026
ff092e3
pathplanner changes 2
Nonochen0104 Mar 14, 2026
4c37291
lowered visionCam resoution and made slightly more efficent
Seqii Mar 17, 2026
cc188e6
auto adjustments
Nonochen0104 Mar 17, 2026
9ae7df5
fix drift problem (maybe)
Nonochen0104 Mar 18, 2026
bc0ffff
auto position adjustments
rainingmika Mar 18, 2026
c568b5f
Auto
Nonochen0104 Mar 18, 2026
c1c6dfb
Tuned the driving speed up to 85%
Nonochen0104 Mar 20, 2026
47018b2
Pre10k odometry update (#28)
Seqii Mar 21, 2026
3ea7294
adjust auto
rainingmika Mar 21, 2026
97a429b
Pre10k odometry update (#29)
Seqii Mar 22, 2026
db9eec5
line 161 typo correction
Nonochen0104 Mar 23, 2026
fa033dc
Intake arm
Nonochen0104 Mar 23, 2026
3ec47b7
undo intake holddown
Nonochen0104 Mar 23, 2026
99bde61
auto adjustment
rainingmika Mar 24, 2026
64c9b12
velocity compensated intake velocityt proposal
jmmaloney3 Mar 24, 2026
8f0efbb
Deleted the intake during auto at the end
Nonochen0104 Mar 24, 2026
8592499
updated Where We Stand Today section to make it more clear
jmmaloney3 Mar 24, 2026
d595d2c
Add auto & make intake arm down movement more gently
Nonochen0104 Mar 25, 2026
6c6f1d6
Deleted unused imports
Nonochen0104 Mar 25, 2026
4b36bff
auto update
rainingmika Mar 26, 2026
a8704ed
auto
rainingmika Mar 26, 2026
925fdd5
auto 2
rainingmika Mar 26, 2026
f8affdc
auto change & increased driving speed
rainingmika Mar 26, 2026
b78f516
x-lock button on B (drive controller)
Nonochen0104 Mar 26, 2026
9bf2153
center to depot auto changes and x lock
rainingmika Mar 26, 2026
19b14ce
xlock control update
Nonochen0104 Mar 27, 2026
0d551c5
went over changes made today
Nonochen0104 Mar 27, 2026
9429499
auto changes
rainingmika Mar 27, 2026
a655266
center auto distances
rainingmika Mar 27, 2026
2ce7458
center shooting auto fix
rainingmika Mar 28, 2026
414376c
xlock
rainingmika Apr 13, 2026
68fe4c4
auto align
rainingmika Apr 17, 2026
87c746d
update simple auto align with more constants
rainingmika Apr 17, 2026
bee0fc9
pid
Seqii Apr 20, 2026
f058ba9
fixed bug with auto align (simple)
Seqii Apr 20, 2026
ab05e6a
new auto align lock
Seqii Apr 24, 2026
7d60fc0
Added hopper motor
Seqii Apr 25, 2026
e3f3b79
updated motor id
Seqii Apr 27, 2026
c5909c2
Updated Phoenix to 2026 2.0 version
Nonochen0104 Apr 30, 2026
33fd9c6
Change speed for Panther Party
Nonochen0104 Apr 30, 2026
2c260cc
Revert "Change speed for Panther Party"
Nonochen0104 May 1, 2026
c03e891
Revert "Updated Phoenix to 2026 2.0 version"
Nonochen0104 May 1, 2026
b5b3015
reverse motor
rainingmika May 4, 2026
a79fd18
target distance
rainingmika May 4, 2026
56f13a1
speed back to demo
rainingmika May 4, 2026
2715f14
fixed typo
Seqii May 4, 2026
8bee376
simple auto align
Nonochen0104 May 8, 2026
2d1fd01
changed the speed back up
Nonochen0104 May 8, 2026
92cdac5
speeded up auto align
Nonochen0104 May 8, 2026
976eed2
added hopper motor to autos and a new left neutral zone auto
Nonochen0104 May 11, 2026
7aa38bd
deleted unused auto imports
rainingmika May 11, 2026
d133bb4
edit leftneutralzone auto 2
Nonochen0104 May 11, 2026
ca7b999
Second intake in the neutral zone
Nonochen0104 May 11, 2026
f0f23bc
OMG
rainingmika May 12, 2026
ef80c69
new offsets and sparkmax id
rainingmika May 12, 2026
19cf279
e
rainingmika May 12, 2026
033bc72
auto align distance speed to 0
Nonochen0104 May 12, 2026
bdb0512
update neutral zone auto 2
Nonochen0104 May 12, 2026
0e72b84
commented distance alignment out
Nonochen0104 May 12, 2026
d2a97d9
rezero
Nonochen0104 May 12, 2026
1ed2af7
right neutral zone auto 2 with a 2nd neutral zone path, auto align ap…
rainingmika May 12, 2026
7d28c18
ok
Nonochen0104 May 12, 2026
60a9662
go with it
Nonochen0104 May 12, 2026
bdc5ad6
!@#$%^&*()_
Nonochen0104 May 12, 2026
4c24363
asdghjkl;'
rainingmika May 13, 2026
9787836
notime
Nonochen0104 May 13, 2026
13b4834
Revert "notime"
Nonochen0104 May 13, 2026
59da3ea
Auto update
Nonochen0104 May 15, 2026
d37d672
Merge branch 'pre-states' of https://github.com/mparobotics/2026-Rebu…
rainingmika May 15, 2026
8524c58
lower turn-timeout
rainingmika May 15, 2026
851ad6d
distance
rainingmika May 16, 2026
e4ff477
state
rainingmika May 17, 2026
5b9308d
Updated comments and cleaned unused imports
Seqii May 22, 2026
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
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,4 @@ Thumbs.db
.vscode/

# sim files
.ctre_sim/
ctre_sim/
233 changes: 233 additions & 0 deletions docs/intake/velocity-compensated-intake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
# Proposal: Velocity-Compensated Intake Roller Speed

## The Problem

When our robot drives toward a game piece, the intake rollers sometimes push it away instead of picking it up. This gets worse the faster we drive.

Here's why: if the robot approaches a piece at 2 m/s but the rollers only spin at a surface speed of 2 m/s, there's zero net "grabbing" force. The rollers need to spin **faster** than the robot is moving to reliably pull pieces in.

## What Other Teams Do

A widely referenced guideline (from Team 254, documented on [FRCDesign.org](https://www.frcdesign.org/learning-course/stage2/2C/intake-golden-rules/)) is:

> Intake roller surface speed should be at least **2x** the robot's ground speed.

Team 1678 [designed their Rapid React intake](https://www.frcdesign.org/mechanism-examples/intake/linkage/1678_2022_intake/) at 2.5x. The idea is simple: if you might drive at 3 m/s while intaking, your rollers should spin at 6+ m/s surface speed.

## Where We Stand Today

### Assumptions

The estimates below depend on the following values:

1. Auto commands `DRIVE_SPEED_MPS = 2` (`LeftNeutralZoneAuto1`, line 22). We assume the robot actually drives at approximately 2.0 m/s, which is good enough for the rough calculations in this section.

2. Roller surface speed can be estimated from physical parameters:
- Gear ratio: 18-tooth motor gear / 24-tooth roller gear = 0.75 reduction
- Roller OD: 1.25" base + 2 × ~1/8" silicone sleeve ≈ 1.5" (0.0381 m)
- Motor: NEO Vortex (published free speed 6784 RPM). Under load we estimate ~5400 RPM.
- Max roller surface speed: `5400 × 0.75 × π × 0.0381 / 60 ≈ 8.1 m/s`

### Current Auto Behavior

The following two constants are used to calculate the intake motor output used in `LeftNeutralZoneAuto1.java`:

The max percent output for the intake motor is specified on line 318 in `Constants.java`:

```java
INTAKE_SPEED = 0.50;
```

The intake power requested during auto is specified on line 35 of `LeftNeutralZoneAuto1.java`:
```java
INTAKE_POWER = -0.5; // negative means intake direction (positive would eject)
```

On lines 50 and 103 in `LeftNeutralZoneAuto1.java`, the auto routine calls `IntakeSubsystem.setIntakePower(double power)` with `power` argument equal to `INTAKE_POWER`. This sets the motor output to the following:
```java
INTAKE_POWER * INTAKE_SPEED = (-0.5) * 0.5 = -0.25
```

So actual motor output during auto is **25%**, giving a roller surface speed of roughly `8.1 × 0.25 ≈` **2.0 m/s**. Our auto drives at roughly **2.0 m/s** (see assumptions above), so that's approximately a **1:1 ratio** -- barely matching robot speed and well below the recommended 2x. This likely explains why intake is unreliable while moving.

## A Possible Approach

One option would be to make the intake aware of how fast the robot is driving and automatically set roller speed to maintain the 2x ratio. The operator model would be simplified to:

- **Stick forward** (past deadband) = intake on. Speed is automatic.
- **Stick backward** (past deadband) = eject at a fixed reverse speed.
- **Stick centered** = intake off.

The operator doesn't need to modulate roller speed -- the "right" speed is determined by the robot's velocity, not feel.

### The Core Math

When the intake is on, the roller output is:

```java
velocityBasedOutput = (robotForwardMps * INTAKE_SPEED_MULTIPLIER) / ROLLER_MAX_SURFACE_SPEED;
output = MathUtil.clamp(velocityBasedOutput, INTAKE_MIN_SPEED, 1.0);
```

Where:
- `robotForwardMps` comes from `SwerveSubsystem.getChassisSpeeds().vxMetersPerSecond`
- `INTAKE_SPEED_MULTIPLIER` is the target multiplier (e.g. 2.0, the minimum recommended by other teams) -- tunable
- `ROLLER_MAX_SURFACE_SPEED` is how fast our rollers spin at 100% output (see below)
- `INTAKE_MIN_SPEED` is the floor -- the slowest the rollers will ever spin when the intake is on (e.g. 0.30). This ensures the rollers still grab pieces when the robot is stationary or moving slowly, since the velocity formula would give near-zero at low speeds.

The `Math.max` handles the transition naturally: at low robot speeds `INTAKE_MIN_SPEED` applies; once the robot is fast enough that the 2x formula exceeds the minimum, velocity compensation takes over.

### Constants

**Tuning constants** (adjust based on testing):
- `INTAKE_MIN_SPEED` -- roller output floor when intake is on (e.g. 0.30)
- `INTAKE_SPEED_MULTIPLIER` -- target roller-to-ground-speed ratio (e.g. 2.0)
- `INTAKE_EJECT_SPEED` -- fixed reverse speed for ejecting

**Physical parameters** (tweak if the hardware changes):

```java
public static final double ROLLER_MOTOR_MAX_RPM = 5400; // measure this (see below)
public static final int ROLLER_GEAR_MOTOR_TEETH = 18; // gear on motor shaft
public static final int ROLLER_GEAR_ROLLER_TEETH = 24; // gear on roller shaft
public static final double ROLLER_BASE_DIAMETER = Units.inchesToMeters(1.25);
public static final double ROLLER_SLEEVE_THICKNESS = Units.inchesToMeters(0.125);
```

**Computed from the above** (not hardcoded):

```java
// Gear ratio: how many roller turns per motor turn (18:24 = 0.75)
public static final double ROLLER_GEAR_RATIO =
(double) ROLLER_GEAR_MOTOR_TEETH / ROLLER_GEAR_ROLLER_TEETH;

// Roller outer diameter including the silicone sleeve on each side
public static final double ROLLER_OUTER_DIAMETER =
ROLLER_BASE_DIAMETER + 2 * ROLLER_SLEEVE_THICKNESS;

// How far the roller surface travels in one full rotation
public static final double ROLLER_CIRCUMFERENCE =
Math.PI * ROLLER_OUTER_DIAMETER;

// Roller RPM = motor RPM scaled by gear ratio
public static final double ROLLER_MAX_RPM =
ROLLER_MOTOR_MAX_RPM * ROLLER_GEAR_RATIO;

// Surface speed (m/s) = roller RPM * circumference, converted from per-minute to per-second
public static final double ROLLER_MAX_SURFACE_SPEED =
ROLLER_MAX_RPM * ROLLER_CIRCUMFERENCE / 60.0;
```

Each physical parameter is its own constant so we can verify or adjust them independently. For example, if the silicone sleeve turns out to be thinner than 1/8", just change that one value and everything recalculates.

### Measuring ROLLER_MOTOR_MAX_RPM

The `5400` above is a placeholder. To get the real value:

1. Deploy code, open SmartDashboard
2. Lower the intake arm
3. Hold the intake stick at full power (the rollers don't touch the ground, so just run them)
4. Read the motor RPM from SmartDashboard (the SparkMax encoder reports this)
5. Update the constant with the observed value

This gives a real-world number that accounts for friction, belt/gear losses, etc.

## What Would Change in the Code

Three files would be touched. Auto routines would **not** need any changes.

### Constants.java

Add the physical parameter and tuning constants shown above.

### IntakeSubsystem.java

**Constructor** -- accept a `DoubleSupplier` so the subsystem can read the robot's forward speed each cycle:

```java
private final java.util.function.DoubleSupplier forwardSpeedSupplier;
private double requestedIntakePower = 0.0;

public IntakeSubsystem(java.util.function.DoubleSupplier forwardSpeedSupplier) {
this.forwardSpeedSupplier = forwardSpeedSupplier;
// ... rest of existing constructor unchanged ...
}
```

**`setIntakePower()`** -- instead of setting the motor directly, just store what the operator requested. The actual motor command happens in `periodic()`:

```java
public void setIntakePower(double power) {
// store the request power to be used by periodic()
requestedIntakePower = Math.max(-1.0, Math.min(1.0, power));
intakeOn = Math.abs(requestedIntakePower) > 0.0;
}
```

**`periodic()`** -- at the end, after the existing arm PID logic, add roller motor control. This is where the compensation actually happens:

```java
// Roller velocity compensation
double output = 0.0;

if (requestedIntakePower < 0) {
// Intaking: apply velocity compensation
double forwardMps = Math.max(0, forwardSpeedSupplier.getAsDouble());

// Output calculated from the robot's current velocity
double velocityBasedOutput =
(forwardMps * IntakeConstants.INTAKE_SPEED_MULTIPLIER) / IntakeConstants.ROLLER_MAX_SURFACE_SPEED;

// Clamp between INTAKE_MIN_SPEED (so we grab pieces even when stationary)
// and 1.0 (motor can't exceed 100%). Negate because intake direction is negative.
output = -MathUtil.clamp(velocityBasedOutput, IntakeConstants.INTAKE_MIN_SPEED, 1.0);

} else if (requestedIntakePower > 0) {
// Ejecting: fixed reverse speed
output = IntakeConstants.INTAKE_EJECT_SPEED;
}

intakeMotor.set(output);
```

The key idea: `periodic()` runs every 20ms, so the motor output continuously tracks the robot's speed even though `setIntakePower()` might only be called once (as in auto's `runOnce`).

### RobotContainer.java

One-line change to wire the swerve speed into the intake:

```java
// Before:
private final IntakeSubsystem m_intake = new IntakeSubsystem();

// After:
private final IntakeSubsystem m_intake = new IntakeSubsystem(
() -> m_drive.getChassisSpeeds().vxMetersPerSecond);
```

This works because `m_drive` is declared before `m_intake`, and the lambda is only called later at runtime.

## What This Would Look Like With Real Numbers

Assuming measured max surface speed ~8.1 m/s and `INTAKE_MIN_SPEED = 0.30`:

Motor output is the result of `max(INTAKE_MIN_SPEED, (robotSpeed * INTAKE_SPEED_MULTIPLIER) / ROLLER_MAX_SURFACE_SPEED)`. Roller-to-robot ratio is roller surface speed / robot speed (the 2x target).

| Scenario | Robot Speed | Motor Output | Roller Surface Speed | Roller:Robot Ratio | Notes |
|---|---|---|---|---|---|
| Stationary | 0 m/s | 30% | 2.4 m/s | n/a | Min speed applies |
| Slow drive | 1 m/s | 30% | 2.4 m/s | 2.4x | Min speed still higher than 2x formula |
| Auto | 2 m/s | 49% | 4.0 m/s | 2.0x | 2x formula takes over |
| Fast teleop | 3 m/s | 74% | 6.0 m/s | 2.0x | |
| Full speed | 5 m/s | 100% | 8.1 m/s | 1.62x | Mechanical limit |

## Also Worth Noting

There's a bug in `toggleIntake()` where the boolean assignments are flipped -- `intakeOn` gets set to `false` when turning on and `true` when turning off. Worth fixing regardless of whether we do velocity compensation.

## Open Questions for the Team

- Does the 2x ratio feel right as a starting point, or should we try something different?
- What should `INTAKE_MIN_SPEED` be? 0.30? Higher?
- Are there concerns about current draw from running the rollers harder at high speed?
- Does simplifying the stick to on/off/eject make sense, or do we want to keep variable speed control?
54 changes: 54 additions & 0 deletions src/main/deploy/pathplanner/paths/Neutral.path
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"version": "2025.0",
"waypoints": [
{
"anchor": {
"x": 7.734,
"y": 7.416
},
"prevControl": null,
"nextControl": {
"x": 7.724072048611112,
"y": 6.433763961226853
},
"isLocked": false,
"linkedName": null
},
{
"anchor": {
"x": 7.734,
"y": 4.550436342592593
},
"prevControl": {
"x": 7.781087601273149,
"y": 5.190860749421297
},
"nextControl": null,
"isLocked": false,
"linkedName": null
}
],
"rotationTargets": [],
"constraintZones": [],
"pointTowardsZones": [],
"eventMarkers": [],
"globalConstraints": {
"maxVelocity": 3.0,
"maxAcceleration": 3.0,
"maxAngularVelocity": 540.0,
"maxAngularAcceleration": 720.0,
"nominalVoltage": 12.0,
"unlimited": false
},
"goalEndState": {
"velocity": 0,
"rotation": -90.96353558963717
},
"reversed": false,
"folder": null,
"idealStartingState": {
"velocity": 0,
"rotation": -89.64693045105892
},
"useDefaultConstraints": true
}
54 changes: 54 additions & 0 deletions src/main/deploy/pathplanner/paths/Neutral2.path
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"version": "2025.0",
"waypoints": [
{
"anchor": {
"x": 7.734,
"y": 4.550436342592593
},
"prevControl": null,
"nextControl": {
"x": 6.758923828125001,
"y": 4.543087962962963
},
"isLocked": false,
"linkedName": null
},
{
"anchor": {
"x": 6.389864583333334,
"y": 4.550436342592593
},
"prevControl": {
"x": 7.1843425202546305,
"y": 4.545974826388889
},
"nextControl": null,
"isLocked": false,
"linkedName": null
}
],
"rotationTargets": [],
"constraintZones": [],
"pointTowardsZones": [],
"eventMarkers": [],
"globalConstraints": {
"maxVelocity": 3.0,
"maxAcceleration": 3.0,
"maxAngularVelocity": 540.0,
"maxAngularAcceleration": 720.0,
"nominalVoltage": 12.0,
"unlimited": false
},
"goalEndState": {
"velocity": 0,
"rotation": -90.96353558963717
},
"reversed": false,
"folder": null,
"idealStartingState": {
"velocity": 0,
"rotation": -91.28065898863989
},
"useDefaultConstraints": true
}
Loading
Loading