Skip to content

Commit

Permalink
Merge pull request strongback#25 from Team3132/interfaceNetworkTable
Browse files Browse the repository at this point in the history
Create a way to tune PID values on all motors using network tables.
  • Loading branch information
mrwaldron authored Feb 29, 2020
2 parents d258516 + 4159c45 commit 80b5a90
Show file tree
Hide file tree
Showing 9 changed files with 154 additions and 94 deletions.
Original file line number Diff line number Diff line change
@@ -1,14 +1,36 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/

package frc.robot.interfaces;


public interface NetworkTableHelperInterface extends DashboardUpdater {
/**
* Gets a named double value from the network tables. If not found
* the defaultValue is returned.
* @param key the name to look up in the table
* @param defaultValue will be returned if key not found.
* @return the value in the table if found, defaultValue otherwise.
*/
public double get(String key, double defaultValue);
/**
* Gets a named Boolean value from the network tables. If not found
* the defaultValue is returned.
* @param key the name to look up in the table
* @param defaultValue will be returned if key not found.
* @return the value in the table if found, defaultValue otherwise.
*/
public boolean get(String key, boolean defaultValue);
/**
* Gets a named String value from the network tables. If not found
* the defaultValue is returned.
* @param key the name to look up in the table
* @param defaultValue will be returned if key not found.
* @return the value in the table if found, defaultValue otherwise.
*/
public String get(String key, String defaultValue);

/**
* Sets a named double value from the network tables.
* @param key the name to look up in the table.
* @param value the value set to the network table.
*/
public void set(String key, double value);
}
104 changes: 37 additions & 67 deletions src/main/java/frc/robot/lib/MotorFactory.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package frc.robot.lib;

import java.util.ArrayList;

import com.ctre.phoenix.motorcontrol.FeedbackDevice;
import com.ctre.phoenix.motorcontrol.LimitSwitchNormal;
import com.ctre.phoenix.motorcontrol.LimitSwitchSource;
Expand All @@ -21,15 +19,14 @@

public class MotorFactory {

public static Motor getDriveMotor(String motorControllerType, int[] canIDsWithEncoders, int[] canIDsWithoutEncoders,
boolean leftMotor, boolean sensorPhase, double rampRate, boolean doCurrentLimiting, int contCurrent,
public static Motor getDriveMotor(String motorControllerType, int[] drivebaseCanIdsLeftWithEncoders, boolean leftMotor,
boolean sensorPhase, double rampRate, boolean doCurrentLimiting, int contCurrent,
int peakCurrent, double p, double i, double d, double f, Clock clock, Log log) {

switch (motorControllerType) {
case Constants.MOTOR_CONTROLLER_TYPE_SPARKMAX: {
HardwareSparkMAX spark = getSparkMAX(canIDsWithEncoders, leftMotor, NeutralMode.Brake, log);
HardwareSparkMAX spark = getSparkMAX(drivebaseCanIdsLeftWithEncoders, leftMotor, NeutralMode.Brake, log, p, i, d, f, new NetworkTablesHelper("drive"));
spark.setScale(Constants.DRIVE_MOTOR_POSITION_SCALE);
spark.setPIDF(0, p, i, d, f);
spark.setSensorPhase(sensorPhase);

/*
Expand All @@ -49,10 +46,9 @@ public static Motor getDriveMotor(String motorControllerType, int[] canIDsWithEn
// Falling through to TalonSRX.

case Constants.MOTOR_CONTROLLER_TYPE_TALONSRX:
HardwareTalonSRX talon = getTalon(canIDsWithEncoders, canIDsWithoutEncoders, leftMotor, NeutralMode.Brake,
clock, log); // don't invert output
HardwareTalonSRX talon = getTalon(drivebaseCanIdsLeftWithEncoders, leftMotor, NeutralMode.Coast, log, p, i, d, f,
new NetworkTablesHelper("drive")); // don't invert output
talon.setScale(Constants.DRIVE_MOTOR_POSITION_SCALE); // number of ticks per inch of travel.
talon.setPIDF(0, p, i, d, f);
talon.configSelectedFeedbackSensor(FeedbackDevice.QuadEncoder, 0, 10);
talon.setSensorPhase(sensorPhase);
talon.configClosedloopRamp(rampRate, 10);
Expand All @@ -72,49 +68,42 @@ public static Motor getDriveMotor(String motorControllerType, int[] canIDsWithEn
}
}

public static HardwareTalonSRX getIntakeMotor(int canID, boolean invert, Log log) {
HardwareTalonSRX motor = getTalon(canID, invert, NeutralMode.Brake, log);
public static HardwareTalonSRX getIntakeMotor(int canID, boolean invert, double p, double i, double d, double f, Log log) {
HardwareTalonSRX motor = getTalon(canID, invert, NeutralMode.Brake, log, p , i, d, f, new NetworkTablesHelper("intake"));
motor.configClosedloopRamp(.25, 10);
motor.configReverseSoftLimitEnable(false, 10);
motor.configReverseLimitSwitchSource(LimitSwitchSource.Deactivated, LimitSwitchNormal.NormallyClosed, 10);
motor.configVoltageCompSaturation(8, 10);
motor.enableVoltageCompensation(true);
return motor;
}

public static HardwareTalonSRX getColourWheelMotor(int canID, boolean invert, Log log) {
HardwareTalonSRX motor = getTalon(canID, invert, NeutralMode.Brake, log);
public static HardwareTalonSRX getColourWheelMotor(int canID, boolean invert, double p, double i, double d, double f,Log log) {
HardwareTalonSRX motor = getTalon(canID, invert, NeutralMode.Brake, log, p, i, d, f, new NetworkTablesHelper("colour"));
motor.configClosedloopRamp(.25, 10);
return motor;
}

public static HardwareTalonSRX getLoaderSpinnerMotor(int canID, boolean invert, double p, double i, double d, double f,Log log) {
HardwareTalonSRX motor = getTalon(canID, invert, NeutralMode.Brake, log);
HardwareTalonSRX motor = getTalon(canID, invert, NeutralMode.Brake, log, p, i, d, f, new NetworkTablesHelper("loader spinner"));
// In sensor (beambreak) for loader
motor.configForwardLimitSwitchSource(LimitSwitchSource.Deactivated, LimitSwitchNormal.NormallyOpen, 10);
// Out sensor (beambreak) for loader
motor.configReverseLimitSwitchSource(LimitSwitchSource.Deactivated, LimitSwitchNormal.NormallyOpen, 10);
motor.setPIDF(0, p, i, d, f);
motor.configSelectedFeedbackSensor(FeedbackDevice.QuadEncoder, 0, 10);
motor.setScale(Constants.LOADER_MAIN_MOTOR_SCALE); // number of ticks per rotation.
motor.configClosedloopRamp(0, 10);
NetworkTablesHelper helper = new NetworkTablesHelper("loader/spinnermotor/");
helper.set("p", p);
helper.set("i", i);
helper.set("d", d);
helper.set("f", f);
return motor;
}
public static HardwareTalonSRX getLoaderPassthroughMotor(int canID, boolean invert, Log log) {
HardwareTalonSRX motor = getTalon(canID, invert, NeutralMode.Brake, log);
public static HardwareTalonSRX getLoaderPassthroughMotor(int canID, boolean invert,double p, double i, double d, double f, Log log) {
HardwareTalonSRX motor = getTalon(canID, invert, NeutralMode.Brake, log, p, i, d, f, new NetworkTablesHelper("loader passthrough"));
motor.configClosedloopRamp(0.5, 10);
return motor;
}

public static HardwareTalonSRX getShooterMotor(int[] canIDs, boolean sensorPhase,
double p, double i, double d, double f, Clock clock, Log log) {
HardwareTalonSRX motor = getTalon(canIDs, false, NeutralMode.Coast, log); // don't invert output
motor.setPIDF(0, p, i, d, f);
double p, double i, double d, double f, Clock clock, Log log) {
HardwareTalonSRX motor = getTalon(canIDs, false, NeutralMode.Coast, log, p, i, d, f,
new NetworkTablesHelper("shooter")); // don't invert output
motor.setSensorPhase(sensorPhase);
motor.configSelectedFeedbackSensor(FeedbackDevice.QuadEncoder, 0, 10);
motor.setScale(36);
Expand All @@ -124,32 +113,6 @@ public static HardwareTalonSRX getShooterMotor(int[] canIDs, boolean sensorPhase

return motor;
}

/**
* Code to allow us to log output current per talon using redundant talons so if a talon or encoder
* fails, it will automatically log and switch to the next one.
* @param canIDsWithEncoders list of talons that can be the leader due to having an encoder.
* @param canIDsWithoutEncoders list of talons without encoders that can never be the leader.
* @param invert reverse the direction of the output.
* @param log logger.
* @return
*/
private static HardwareTalonSRX getTalon(int[] canIDsWithEncoders, int[] canIDsWithoutEncoders, boolean invert, NeutralMode mode, Clock clock, Log log) {
ArrayList<HardwareTalonSRX> potentialLeaders = getTalonList(canIDsWithEncoders, invert, mode, log);
ArrayList<HardwareTalonSRX> followers = getTalonList(canIDsWithoutEncoders, invert, mode, log);
return new RedundantTalonSRX(potentialLeaders, followers, clock, log);
}

private static ArrayList<HardwareTalonSRX> getTalonList(int[] canIDs, boolean invert, NeutralMode mode, Log log) {
ArrayList<HardwareTalonSRX> list = new ArrayList<>();
for (int i = 0; i < canIDs.length; i++) {
HardwareTalonSRX talon = Hardware.Motors.talonSRX(canIDs[i], invert, mode);
talon.configContinuousCurrentLimit(Constants.DEFAULT_TALON_CONTINUOUS_CURRENT_LIMIT, 10);
talon.configPeakCurrentLimit(Constants.DEFAULT_TALON_PEAK_CURRENT_LIMIT, 10);
list.add(talon);
}
return list;
}

/**
* Code to allow us to log output current per Spark MAX and set up followers so that
Expand All @@ -160,19 +123,20 @@ private static ArrayList<HardwareTalonSRX> getTalonList(int[] canIDs, boolean in
* @param log for registration of the current reporting.
* @return the leader HardwareTalonSRX
*/
private static HardwareTalonSRX getTalon(int[] canIDs, boolean invert, NeutralMode mode, Log log) {

private static HardwareTalonSRX getTalon(int[] canIDs, boolean invert, NeutralMode mode, Log log,
double p , double i, double d, double f, NetworkTablesHelper networkTable) {
HardwareTalonSRX leader = Hardware.Motors.talonSRX(abs(canIDs[0]), invert, mode);
log.register(false, () -> leader.getOutputCurrent(), "Talons/%d/Current", canIDs[0]);
leader.configContinuousCurrentLimit(Constants.DEFAULT_TALON_CONTINUOUS_CURRENT_LIMIT, 10);
leader.configPeakCurrentLimit(Constants.DEFAULT_TALON_PEAK_CURRENT_LIMIT, 10);
TunableMotor.tuneMotor(leader, abs(canIDs[0]), p, i, d, f, networkTable);

for (int i = 1; i < canIDs.length; i++) {
for (int n = 1; i < canIDs.length; n++) {
boolean shouldInvert = invert;
if (canIDs[i] < 0) shouldInvert = !shouldInvert;
HardwareTalonSRX follower = Hardware.Motors.talonSRX(abs(canIDs[i]), shouldInvert, mode);
if (canIDs[n] < 0) shouldInvert = !shouldInvert;
HardwareTalonSRX follower = Hardware.Motors.talonSRX(abs(canIDs[n]), shouldInvert, mode);
follower.getHWTalon().follow(leader.getHWTalon());
log.register(false, () -> follower.getOutputCurrent(), "Talons/%d/Current", canIDs[i]);
log.register(false, () -> follower.getOutputCurrent(), "Talons/%d/Current", canIDs[n]);
}
return leader;
}
Expand All @@ -185,11 +149,13 @@ private static HardwareTalonSRX getTalon(int[] canIDs, boolean invert, NeutralMo
* @param log for registration of the current values.
* @return the HardwareTalonSRX motor controller.
*/
private static HardwareTalonSRX getTalon(int canID, boolean invert, NeutralMode mode, Log log) {

private static HardwareTalonSRX getTalon(int canID, boolean invert, NeutralMode mode, Log log,
double p, double i, double d, double f, NetworkTablesHelper networkTable) {
log.sub("%s: " + canID, "talon");
int[] canIDs = new int[1];
canIDs[0] = canID;
return getTalon(canIDs, invert, mode, log);
return getTalon(canIDs, invert, mode, log, p, i, d, f, networkTable);
}

/**
Expand All @@ -201,18 +167,22 @@ private static HardwareTalonSRX getTalon(int canID, boolean invert, NeutralMode
* @param log for registration of the current reporting.
* @return the leader SparkMAX
*/
private static HardwareSparkMAX getSparkMAX(int[] canIDs, boolean invert, NeutralMode mode, Log log) {

private static HardwareSparkMAX getSparkMAX(int[] canIDs, boolean invert, NeutralMode mode, Log log, double p, double i, double d, double f, NetworkTablesHelper networkTable) {
HardwareSparkMAX leader = Hardware.Motors.sparkMAX(abs(canIDs[0]), MotorType.kBrushless, invert);
leader.setIdleMode(mode == NeutralMode.Brake ? IdleMode.kBrake : IdleMode.kCoast);
log.register(false, () -> leader.getOutputCurrent(), "SparkMAX/%d/Current", canIDs[0]);
leader.setSmartCurrentLimit(Constants.DEFAULT_TALON_CONTINUOUS_CURRENT_LIMIT, 10);
leader.setSecondaryCurrentLimit(Constants.DEFAULT_TALON_PEAK_CURRENT_LIMIT, 10);
for (int i = 1; i < canIDs.length; i++) {
TunableMotor.tuneMotor(leader, abs(canIDs[0]), p, i, d, f, networkTable);

for (int n = 1; n < canIDs.length; n++) {
boolean shouldInvert = invert;
if (canIDs[i] < 0) shouldInvert = !shouldInvert;
HardwareSparkMAX follower = Hardware.Motors.sparkMAX(abs(canIDs[i]), MotorType.kBrushless, shouldInvert);
if (canIDs[n] < 0)
shouldInvert = !shouldInvert;
HardwareSparkMAX follower = Hardware.Motors.sparkMAX(abs(canIDs[n]), MotorType.kBrushless, shouldInvert);
follower.getHWSpark().follow(leader.getHWSpark());
log.register(false, () -> follower.getOutputCurrent(), "SparkMAX/%d/Current", canIDs[i]);
log.register(false, () -> follower.getOutputCurrent(), "SparkMAX/%d/Current", canIDs[n]);
}
// Reset the scale. Normally velocity is in rpm when normally we'd like rps,
// which is easier to reason about. setScale() takes care of the converstion
Expand All @@ -221,11 +191,11 @@ private static HardwareSparkMAX getSparkMAX(int[] canIDs, boolean invert, Neutra
return leader;
}

private static HardwareSparkMAX getSparkMAX(int canID, boolean invert, NeutralMode mode, Log log) {
private static HardwareSparkMAX getSparkMAX(int canID, boolean invert, NeutralMode mode, Log log, double p, double i, double d, double f, NetworkTablesHelper networkTable) {
log.sub("%s: " + canID, " spark max");
int[] canIDs = new int[1];
canIDs[0] = canID;
return getSparkMAX(canIDs, invert, mode, log);
return getSparkMAX(canIDs, invert, mode, log, p, i, d, f, networkTable);
}

private static int abs(int value) {
Expand Down
15 changes: 10 additions & 5 deletions src/main/java/frc/robot/lib/NetworkTablesHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,6 @@ public double get(String key, double defaultValue) {
return entry.getDouble(defaultValue);
}

public void set(String key, double value) {
NetworkTableEntry entry = table.getEntry(key);
entry.setDouble(value);
}

// boolean
public boolean get(String key, boolean defaultValue) {
NetworkTableEntry entry = table.getEntry(key);
Expand All @@ -58,4 +53,14 @@ public String get(String key, String defaultValue) {
}
return entry.getString(defaultValue);
}
/**
* Sets a named double value from the network tables.
* @param key the name to look up in the table.
* @param value the value set to the network table.
*/
@Override
public void set(String key, double value) {
NetworkTableEntry entry = table.getEntry(key);
entry.setDouble(value);
}
}
1 change: 0 additions & 1 deletion src/main/java/frc/robot/lib/Position.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import frc.robot.Constants;
import frc.robot.lib.MathUtil;


/*
* The position class defines a position on the field.
* The rules for a position are:
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/frc/robot/lib/RobotConfiguration.java
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,10 @@ public class RobotConfiguration {

public boolean visionIsPresent = false;
public double visionHMin = Constants.VISION_H_MIN;
public double visionHMax = Constants.VISION_S_MAX;
public double visionSMin = Constants.VISION_H_MAX;
public double visionSMax = Constants.VISION_V_MIN;
public double visionVMin = Constants.VISION_S_MIN;
public double visionHMax = Constants.VISION_H_MAX;
public double visionSMin = Constants.VISION_S_MIN;
public double visionSMax = Constants.VISION_S_MAX;
public double visionVMin = Constants.VISION_V_MIN;
public double visionVMax = Constants.VISION_V_MAX;

public boolean buddyClimbIsPresent = false;
Expand Down
54 changes: 54 additions & 0 deletions src/main/java/frc/robot/lib/TunableMotor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package frc.robot.lib;

import org.strongback.Executable;
import org.strongback.Executor.Priority;
import org.strongback.Strongback;
import org.strongback.components.Motor;

import frc.robot.Constants;
import frc.robot.interfaces.NetworkTableHelperInterface;

/**
* Whenever a motor is created, networkTable for the motor PIDF values are implemented from here.
* The PIDF values are initiliased on the network table and and the motors are updated from the PIDF
* values in the network tables once per second. This allows the values to be updated on the fly by changing
* the values in the network tables.
*/

class TunableMotor implements Executable {
private final Motor motor;
private final NetworkTableHelperInterface networkTable;
private double lastUpdateSec = 0;

public static void tuneMotor(Motor motor, int id, double p, double i , double d , double f, NetworkTablesHelper networkTable) {
var tunable = new TunableMotor(motor, id, p, i, d, f, networkTable);
networkTable.set("p", p);
networkTable.set("i", i);
networkTable.set("d", d);
networkTable.set("f", f);
Strongback.executor().register(tunable, Priority.LOW);
}

public TunableMotor(Motor motor, int id, double p, double i, double d, double f, NetworkTablesHelper networkTable) {
this.motor = motor;
this.networkTable = networkTable;
}

// Executes the command 1 time every 1 second.
@Override
public void execute(long timeInMillis) {
double now = Strongback.timeSystem().currentTime();
if (now < lastUpdateSec + Constants.DASHBOARD_UPDATE_INTERVAL_SEC)
return;
update();
lastUpdateSec = now;
}

private void update() {
double p = networkTable.get("p", Constants.DRIVE_P);
double i = networkTable.get("i", Constants.DRIVE_I);
double d = networkTable.get("d", Constants.DRIVE_D);
double f = networkTable.get("f", Constants.DRIVE_F);
motor.setPIDF(0, p, i, d, f);
}
}
4 changes: 4 additions & 0 deletions src/main/java/frc/robot/mock/MockNetworkTableHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,9 @@ public String get(String key, String defaultValue) {
return defaultValue;
}

@Override
public void set(String key, double value) {
}


}
2 changes: 1 addition & 1 deletion src/main/java/frc/robot/subsystems/Loader.java
Original file line number Diff line number Diff line change
Expand Up @@ -180,4 +180,4 @@ public void updateDashboard() {
dashboard.putNumber(name + " ball count", getCount());
}
}
}
}
Loading

0 comments on commit 80b5a90

Please sign in to comment.