Skip to content

Commit

Permalink
Add error checking for high frequency odometry Spark Max values
Browse files Browse the repository at this point in the history
  • Loading branch information
jwbonner committed Feb 21, 2024
1 parent 17fd193 commit 501a6c9
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.ctre.phoenix6.hardware.Pigeon2;
import edu.wpi.first.math.geometry.Rotation2d;
import edu.wpi.first.math.util.Units;
import java.util.OptionalDouble;
import java.util.Queue;

/** IO implementation for Pigeon2 */
Expand All @@ -44,7 +45,15 @@ public GyroIOPigeon2(boolean phoenixDrive) {
yawTimestampQueue = SparkMaxOdometryThread.getInstance().makeTimestampQueue();
yawPositionQueue =
SparkMaxOdometryThread.getInstance()
.registerSignal(() -> pigeon.getYaw().getValueAsDouble());
.registerSignal(
() -> {
boolean valid = yaw.refresh().getStatus().isOK();
if (valid) {
return OptionalDouble.of(yaw.getValueAsDouble());
} else {
return OptionalDouble.empty();
}
});
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@
import com.revrobotics.CANSparkLowLevel.MotorType;
import com.revrobotics.CANSparkLowLevel.PeriodicFrame;
import com.revrobotics.CANSparkMax;
import com.revrobotics.REVLibError;
import com.revrobotics.RelativeEncoder;
import edu.wpi.first.math.geometry.Rotation2d;
import edu.wpi.first.math.util.Units;
import edu.wpi.first.wpilibj.AnalogInput;
import edu.wpi.first.wpilibj.RobotController;
import java.util.OptionalDouble;
import java.util.Queue;

/**
Expand Down Expand Up @@ -116,9 +118,27 @@ public ModuleIOSparkMax(int index) {
PeriodicFrame.kStatus2, (int) (1000.0 / Module.ODOMETRY_FREQUENCY));
timestampQueue = SparkMaxOdometryThread.getInstance().makeTimestampQueue();
drivePositionQueue =
SparkMaxOdometryThread.getInstance().registerSignal(driveEncoder::getPosition);
SparkMaxOdometryThread.getInstance()
.registerSignal(
() -> {
double value = driveEncoder.getPosition();
if (driveSparkMax.getLastError() == REVLibError.kOk) {
return OptionalDouble.of(value);
} else {
return OptionalDouble.empty();
}
});
turnPositionQueue =
SparkMaxOdometryThread.getInstance().registerSignal(turnRelativeEncoder::getPosition);
SparkMaxOdometryThread.getInstance()
.registerSignal(
() -> {
double value = turnRelativeEncoder.getPosition();
if (driveSparkMax.getLastError() == REVLibError.kOk) {
return OptionalDouble.of(value);
} else {
return OptionalDouble.empty();
}
});

driveSparkMax.burnFlash();
turnSparkMax.burnFlash();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@
import edu.wpi.first.wpilibj.Notifier;
import java.util.ArrayList;
import java.util.List;
import java.util.OptionalDouble;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.function.DoubleSupplier;
import java.util.function.Supplier;
import org.littletonrobotics.junction.Logger;

/**
Expand All @@ -28,7 +29,7 @@
* blocking thread. A Notifier thread is used to gather samples with consistent timing.
*/
public class SparkMaxOdometryThread {
private List<DoubleSupplier> signals = new ArrayList<>();
private List<Supplier<OptionalDouble>> signals = new ArrayList<>();
private List<Queue<Double>> queues = new ArrayList<>();
private List<Queue<Double>> timestampQueues = new ArrayList<>();

Expand All @@ -53,7 +54,7 @@ public void start() {
}
}

public Queue<Double> registerSignal(DoubleSupplier signal) {
public Queue<Double> registerSignal(Supplier<OptionalDouble> signal) {
Queue<Double> queue = new ArrayBlockingQueue<>(20);
Drive.odometryLock.lock();
try {
Expand All @@ -80,11 +81,22 @@ private void periodic() {
Drive.odometryLock.lock();
double timestamp = Logger.getRealTimestamp() / 1e6;
try {
double[] values = new double[signals.size()];
boolean isValid = true;
for (int i = 0; i < signals.size(); i++) {
queues.get(i).offer(signals.get(i).getAsDouble());
OptionalDouble value = signals.get(i).get();
if (value.isPresent()) {
values[i] = value.getAsDouble();
} else {
isValid = false;
break;
}
}
for (int i = 0; i < timestampQueues.size(); i++) {
timestampQueues.get(i).offer(timestamp);
if (isValid) {
for (int i = 0; i < signals.size(); i++) {
queues.get(i).offer(values[i]);
timestampQueues.get(i).offer(timestamp);
}
}
} finally {
Drive.odometryLock.unlock();
Expand Down

0 comments on commit 501a6c9

Please sign in to comment.