Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

import org.team100.lib.commands.MoveAndHold;
import org.team100.lib.config.ElevatorUtil.ScoringLevel;
import org.team100.lib.config.Feedforward100;
import org.team100.lib.config.Identity;
import org.team100.lib.config.PIDConstants;
import org.team100.lib.geometry.AccelerationSE2;
Expand All @@ -29,6 +28,7 @@
import org.team100.lib.mechanism.RotaryMechanism;
import org.team100.lib.motor.MotorPhase;
import org.team100.lib.motor.NeutralMode;
import org.team100.lib.motor.ctre.Falcon6Motor;
import org.team100.lib.motor.ctre.Kraken6Motor;
import org.team100.lib.motor.sim.SimulatedBareMotor;
import org.team100.lib.music.Music;
Expand Down Expand Up @@ -170,7 +170,7 @@ public CalgamesMech(
100,
100,
PIDConstants.makePositionPID(elevatorfrontLog, 5),
Feedforward100.makeWCPSwerveTurningFalcon6(elevatorfrontLog));
Falcon6Motor.swerveSteerFF(elevatorfrontLog));
IncrementalBareEncoder elevatorFrontEncoder = elevatorFrontMotor.encoder();

m_elevatorFront = new LinearMechanism(
Expand All @@ -185,7 +185,7 @@ public CalgamesMech(
100, // orginally 60
100, // originally 90
PIDConstants.makePositionPID(elevatorbackLog, 5),
Feedforward100.makeWCPSwerveTurningFalcon6(elevatorbackLog));
Falcon6Motor.swerveSteerFF(elevatorbackLog));
Talon6Encoder elevatorBackEncoder = elevatorBackMotor.encoder();
m_elevatorBack = new LinearMechanism(
elevatorbackLog, elevatorBackMotor, elevatorBackEncoder,
Expand All @@ -200,7 +200,7 @@ public CalgamesMech(
100, // og 60
100, // og 90
PIDConstants.makePositionPID(shoulderLog, 5),
Feedforward100.makeWCPSwerveTurningFalcon6(shoulderLog));
Falcon6Motor.swerveSteerFF(shoulderLog));
Talon6Encoder shoulderEncoder = shoulderMotor.encoder();
// The shoulder has a 5048 on the intermediate shaft
AS5048RotaryPositionSensor shoulderSensor = new AS5048RotaryPositionSensor(
Expand Down Expand Up @@ -230,7 +230,7 @@ public CalgamesMech(
40, // og 60
60, // og 90
PIDConstants.makePositionPID(wristLog, 8), // og 10
Feedforward100.makeWCPSwerveTurningFalcon6(wristLog));
Falcon6Motor.swerveSteerFF(wristLog));
// the wrist has no angle sensor, so it needs to start in the "zero" position.
Talon6Encoder wristEncoder = wristMotor.encoder();
final double wristGearRatio = 55.710;
Expand Down
3 changes: 1 addition & 2 deletions lib/src/main/java/org/team100/frc2025/Climber/Climber.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import java.util.function.DoubleSupplier;

import org.team100.lib.config.Feedforward100;
import org.team100.lib.config.Identity;
import org.team100.lib.config.PIDConstants;
import org.team100.lib.controller.r1.PIDFeedback;
Expand Down Expand Up @@ -45,7 +44,7 @@ public Climber(LoggerFactory parent, CanId canID) {
Falcon6Motor motor = new Falcon6Motor(log, canID, NeutralMode.BRAKE, MotorPhase.REVERSE,
20, 20,
PIDConstants.makePositionPID(log, 1),
Feedforward100.makeArmPivot(log));
Falcon6Motor.ff2(log));

double inputOffset = 0.440602;
RotaryPositionSensor sensor = new AS5048RotaryPositionSensor(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.team100.frc2025.Climber;

import org.team100.lib.config.Feedforward100;
import org.team100.lib.config.Identity;
import org.team100.lib.config.PIDConstants;
import org.team100.lib.logging.LoggerFactory;
Expand Down Expand Up @@ -30,7 +29,7 @@ public ClimberIntake(LoggerFactory parent, CanId canID) {
20, // og 50
20, // og 2
PIDConstants.zero(log),
Feedforward100.makeKrakenClimberIntake(log));
Kraken6Motor.highFrictionFF(log));
}
default -> {
m_motor = new LazySimulatedBareMotor(
Expand Down
8 changes: 4 additions & 4 deletions lib/src/main/java/org/team100/frc2025/grip/Manipulator.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import java.util.List;

import org.team100.lib.config.Feedforward100;
import org.team100.lib.config.Identity;
import org.team100.lib.config.PIDConstants;
import org.team100.lib.logging.Level;
Expand All @@ -12,6 +11,7 @@
import org.team100.lib.motor.BareMotor;
import org.team100.lib.motor.MotorPhase;
import org.team100.lib.motor.NeutralMode;
import org.team100.lib.motor.ctre.Falcon6Motor;
import org.team100.lib.motor.ctre.Kraken6Motor;
import org.team100.lib.motor.sim.LazySimulatedBareMotor;
import org.team100.lib.motor.sim.SimulatedBareMotor;
Expand Down Expand Up @@ -56,19 +56,19 @@ public Manipulator(LoggerFactory parent) {
40, // og 40
40, // og 40
PIDConstants.zero(leftMotorLog),
Feedforward100.makeShooterFalcon6(leftMotorLog));
Falcon6Motor.ff(leftMotorLog));
Kraken6Motor rightMotor = new Kraken6Motor(rightMotorLog, new CanId(20), NeutralMode.COAST,
MotorPhase.REVERSE,
40, // og 40
40, // og 40
PIDConstants.zero(rightMotorLog),
Feedforward100.makeShooterFalcon6(rightMotorLog));
Falcon6Motor.ff(rightMotorLog));
Kraken6Motor algaeMotor = new Kraken6Motor(algaeMotorLog, new CanId(21), NeutralMode.COAST,
MotorPhase.FORWARD,
120, // og 120
120, // og 120
PIDConstants.zero(algaeMotorLog),
Feedforward100.makeShooterFalcon6(algaeMotorLog));
Falcon6Motor.ff(algaeMotorLog));
algaeMotor.setTorqueLimit(4);
m_algaeMotor = algaeMotor;
m_rightLaser = new LaserCan100(new CanId(17));
Expand Down
200 changes: 40 additions & 160 deletions lib/src/main/java/org/team100/lib/config/Feedforward100.java
Original file line number Diff line number Diff line change
@@ -1,33 +1,10 @@
package org.team100.lib.config;

import java.util.ArrayList;
import java.util.List;

import org.team100.lib.logging.LoggerFactory;
import org.team100.lib.tuning.Mutable;

/**
* The motor feedforward model includes four constants.
*
* @param kV Velocity: ratio between unloaded speed (rev/s) and voltage, so the
* units are VOLT-SEC/REV. This reflects the "Back EMF" aspect of a
* motor: it produces a voltage proportional to speed. The value is
* an intrinsic property of the motor.
* @param kA Acceleration: ratio between acceleration (rev/s^2) and voltage, so
* the units are VOLT-SEC^2/REV. This reflects torque production in
* the motor: torque is proportional to current, which is
* proportional to (net) voltage. The value will depend on the
* inertia of the mechanism.
* @param kD Deceleration: like kA but when the motor is braking, i.e.
* acceleration is opposite to the current speed. Motors seem to
* decelerate much better than they accelerate -- perhaps the current
* limit acts differently (or not at all)?
* @param kSS Static friction: voltage to get the motor moving from a stop, so
* the units are VOLTS. The value will depend on the "stickiness" of
* the mechanism.
* @param kDS Dynamic friction: voltage to just barely keep the motor moving,
* the units are VOLTS. The value will depend on the "viscosity" of
* the mechanism.
* Feedforward model with three constants, and friction.
*
* @see https://en.wikipedia.org/wiki/Motor_constants
* @see {@link edu.wpi.first.math.controller.SimpleMotorFeedforward} which uses
Expand All @@ -36,144 +13,52 @@
* models.
*/
public class Feedforward100 {
private final List<Runnable> m_listeners = new ArrayList<>();

private final Mutable kV;
private final Mutable kA;
private final Mutable kD;
private final Mutable kSS;
private final Mutable kDS;
private final double staticFrictionSpeedLimit;
private final Friction friction;

Feedforward100(
/**
* @param kV Back-EMF. Voltage to maintain speed against the back-EMF of
* the motor. V = kV * omega, so kV units are volt-sec/rev.
* The value is an intrinsic property of the motor.
* @param kA Acceleration. Voltage to produce acceleration of the motor
* shaft. V = kA * alpha, so kA units are volt-sec^2/rev.
* This reflects the motor torque and mechanism inertia. Torque
* is proportional to current, which is proportional to (net)
* voltage. The value will depend on the inertia of the
* mechanism.
* @param kD Deceleration. like kA but when the motor is braking, i.e.
* acceleration is opposite to the current speed. Motors
* typically decelerate ("plugging") much better than they
* accelerate ("motoring").
* @param friction Models static, dynamic, and viscous friction.
*/
public Feedforward100(
LoggerFactory log,
double kV,
double kA,
double kD,
double kSS,
double kDS,
double staticFrictionSpeedLimit) {
this.kV = new Mutable(log, "kV", kV, this::onChange);
this.kA = new Mutable(log, "kA", kA, this::onChange);
this.kD = new Mutable(log, "kD", kD, this::onChange);
this.kSS = new Mutable(log, "kSS", kSS, this::onChange);
this.kDS = new Mutable(log, "kDS", kDS, this::onChange);
this.staticFrictionSpeedLimit = staticFrictionSpeedLimit;
}

public static Feedforward100 makeNeo(LoggerFactory log) {
return new Feedforward100(log, 0.122, 0.000, 0.000, 0.5, 0.5, 0.5); //0.122, 0.000, 0.000, 0.1, 0.065, 0.5
}

public static Feedforward100 makeNeo2(LoggerFactory log) {
return new Feedforward100(log, 0.122, 0.05, 0.0250, 0.100, 0.065, 0.5);
}

public static Feedforward100 makeNeoArm(LoggerFactory log) {
return new Feedforward100(log, 0.22, 1, 1, 0, 0, 0);
}

public static Feedforward100 makeNeo550(LoggerFactory log) {
return new Feedforward100(log, 0.12, 0, 0, 0, .07, 0);
}

public static Feedforward100 makeArmPivot(LoggerFactory log) {
return new Feedforward100(
log,
0.09,
0.005,
0.005,
0.100,
0.065,
0.5);
}

public static Feedforward100 makeClimber(LoggerFactory log) {
return new Feedforward100(
log,
0.14,
0.05,
0.05,
0.100,
0.1,
0.0);
}

public static Feedforward100 zero(LoggerFactory log) {
return new Feedforward100(log, 0, 0, 0, 0, 0, 0);
}

public static Feedforward100 makeNeoVortex(LoggerFactory log) {
return new Feedforward100(log, 0.122, 0.000, 0.000, 0.100, 0.065, 0.5);
}

public static Feedforward100 makeWCPSwerveTurningFalcon(LoggerFactory log) {
return new Feedforward100(log, 0.110, 0.000, 0.000, 0.180, 0.010, 0.5);
Friction friction) {
LoggerFactory ffLog = log.type(this);
this.kV = new Mutable(ffLog, "kV", kV);
this.kA = new Mutable(ffLog, "kA", kA);
this.kD = new Mutable(ffLog, "kD", kD);
this.friction = friction;
}

/**
* 9/24/04
* Voltage feedforward for steering motors in air.
* Tuned in air, not on carpet, so probably the velocity number is too low.
* Voltage to maintain the specified velocity.
*
* @param motorRev_S setpoint speed
*/
public static Feedforward100 makeWCPSwerveTurningFalcon6(LoggerFactory log) {
return new Feedforward100(log, 0.150, 0.010, 0.010, 0.080, 0.100, 0.5);
}

public static Feedforward100 makeKrakenTurret(LoggerFactory log) {
return new Feedforward100(log, 0.150, 0.010, 0.010, 0.080, 0.100, 0.5);
}

public static Feedforward100 makeWCPSwerveDriveFalcon(LoggerFactory log) {
return new Feedforward100(log, 0.110, 0.000, 0.000, 0.375, 0.270, 0.5);
}

public static Feedforward100 makeWCPSwerveDriveFalcon6(LoggerFactory log) {
return new Feedforward100(log, 0.13, 0.017, 0.017, 0, 0.26, 0.06);
}

public static Feedforward100 makeWCPSwerveDriveKraken6(LoggerFactory log) {
return new Feedforward100(log, 0.13, 0.022, 0.007, 0.26, 0.26, 0.06); // WAS 0.115
}

public static Feedforward100 makeAMSwerveDriveFalcon6(LoggerFactory log) {
return new Feedforward100(log, 0.110, 0.000, 0.000, 0.180, 0.010, 0.1);
}

public static Feedforward100 makeSimple(LoggerFactory log) {
return new Feedforward100(log, 0.100, 0.100, 0.100, 0.100, 0.100, 0.1);
}

public static Feedforward100 makeShooterFalcon6(LoggerFactory log) {
return new Feedforward100(log, 0.110, 0.000, 0.000, 0.000, 0.900, 0.1);
}

public static Feedforward100 makeKraken6Elevator(LoggerFactory log) {
return new Feedforward100(log, 0.135, 0.005, 0.005, 0.005, 0.005, 0.1);
// return new Feedforward100(0, 0, 0, 0, 0);

}

public static Feedforward100 makeKraken6Wrist(LoggerFactory log) {
return new Feedforward100(log, 0.137, 0.0085, 0.002, 0.11, 0.11, 0.1);
// return new Feedforward100(log, 0.055, 0.025, 0.015, 0.005, 0.005, 0.1);

}

public static Feedforward100 makeKraken6WristWithLowerKd(LoggerFactory log) {
return new Feedforward100(log, 0.14, 0.013, 0.005, 0.2, 0.23, 0.1);
// return new Feedforward100(0, 0, 0, 0, 0);
}

public static Feedforward100 makeKrakenClimberIntake(LoggerFactory log) {
return new Feedforward100(log, 0.13, 0.022, 0.007, 0.26, 0.26, 0.06);
}

public double velocityFFVolts(double motorRev_S) {
return kV.getAsDouble() * motorRev_S;
}

/**
* Voltage to produce the specified acceleration.
*
* Uses kA when speed and accel are in the same direction.
* Uses kD when speed and accel are opposite.
*
Expand Down Expand Up @@ -203,27 +88,22 @@ public double accelFFVolts(double motorRev_S, double motorRev_S_S) {
}

/**
* Voltage to balance friction (i.e. this has the same sign as the supplied
* speed).
*
* @param motorRev_S setpoint speed
*/
public double frictionFFVolts(double motorRev_S) {
double direction = Math.signum(motorRev_S);
if (Math.abs(motorRev_S) < staticFrictionSpeedLimit) {
return kSS.getAsDouble() * direction;
}
return kDS.getAsDouble() * direction;
return friction.frictionFFVolts(motorRev_S);
}

public static Feedforward100 makeTest1(LoggerFactory log) {
return new Feedforward100(log, 0.3, 0.000, 0.000, 0.000, 0.100, 3.5);
}

/////////////////////////////////////////////////////////////////////////

public void register(Runnable listener) {
m_listeners.add(listener);
public static Feedforward100 zero(LoggerFactory log) {
return new Feedforward100(log, 0, 0, 0,
new Friction(log, 0, 0, 0.0, 0));
}

private void onChange(double ignored) {
m_listeners.stream().forEach(r -> r.run());
public static Feedforward100 test(LoggerFactory log) {
return new Feedforward100(log, 0.100, 0.100, 0.100,
new Friction(log, 0.100, 0.100, 0.0, 0.1));
}
}
Loading