Skip to content

Commit 9625f0e

Browse files
caparomulanlaverdurePez357
authored
Remember verified scoring poses (#148)
* Convert cameras to subsystems, add function to get vision-only pose estimate, use it in pose-seek. * Added some code to store and load override values for coral pipe poses. * Finished logic for auto-align target correction. * Split X/Y gain for DriveToPose * Fix NaN test * Use wpilib Preferences not Java's * Create config class for accessing named preferences * Add d-padd button to fix auto-align pose * Revert DriveToPose speeds logic * Revert PID constants for DriveToPoseCommand * Switch to field April tags * Added Aapril tag json, removed reef offset, updated climber servo constants * Remove reef offset todo * morning tweaks * Fix elevator rocket * Move zorro controller command into teleop init. * sycronized blue and red auto logic * removed withtimout on elevator * added timout to both red and blue L4autos * Set default stop command for swerve in autonomous * Prevent elevator rocket in joystick command * made the elevator and robot move at the same time. * Tweaked the choro by 3 inches * Widen tolerance for pose seek display * Remove init from lifter joystick command * Tweaked the redCenterToL4G choreo * commented out the createjoystickcontrolcommand and tweaked choreo. * Another attempt to prevent skyrocket on teleop init * Adjusted path for 1 piece auto * Add a few metrics to smart dashboard * Slowed down the red Auto in Choero * Adjust Al;gae L3 height, comment out algae wrist set angle on grab * Uncomment jostick elevator control * Added pure odometry tracking for comparison with vision * Calibrate odometry in robot mode init functions * Replace Robot.updateOdometry() with DriveTrain.calibrateOdometry() * Remove unnecessary write of scheduler to NT * Record outtake pose as potential override * Add back stem gym tag layout * Reduce max velocity in DriveToPoseCommand * A little refactoring * Publish camera pose estimates to network tables * spotless * Fix null pointer in Vision camera polling. Switch to field layout * updated climber retract setpoint * invert logiv for intake supplier * intake corals in parallel with CG, and stop intaking when hasCoral * increase voltage of outtake algae to barge * spotless * Added Reef.Face.getNeareestPipe() * Update to wpilib 2025.3.2 * Infer target for validated scoring pose independent of auto-align * spotless * Push some outtake and override poses to network tables * Remove reef pipe dashboard publish * Don't publish target position array * spotless * finish merge and clean --------- Co-authored-by: nlaverdure <[email protected]> Co-authored-by: Pez357 <[email protected]>
1 parent fb28c84 commit 9625f0e

File tree

6 files changed

+127
-100
lines changed

6 files changed

+127
-100
lines changed

build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
plugins {
22
id "java"
3-
id "edu.wpi.first.GradleRIO" version "2025.3.1"
3+
id "edu.wpi.first.GradleRIO" version "2025.3.2"
44
id 'com.diffplug.spotless' version '6.23.3'
55
}
66

src/main/java/frc/game/Reef.java

+24-8
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
import edu.wpi.first.math.geometry.Transform2d;
1010
import edu.wpi.first.math.geometry.Translation2d;
1111
import edu.wpi.first.units.measure.Distance;
12-
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
1312
import frc.lib.AutoAlignTarget;
1413
import frc.lib.Config;
14+
import frc.lib.PoseLogger;
1515
import java.util.Optional;
1616

1717
/**
@@ -48,7 +48,7 @@ public static Reef getNearestReef(Pose2d atPose) {
4848
private Pose2d centerPose;
4949

5050
Reef(Pose2d centerPose) {
51-
var adjust = Config.getDefault().loadTransform("Reef." + this.name());
51+
var adjust = Config.getDefault().loadTransform("Reef." + name() + ".adjust");
5252
if (adjust.isPresent()) {
5353
centerPose = centerPose.transformBy(adjust.get());
5454
}
@@ -123,7 +123,17 @@ public enum Face {
123123
private Optional<Pose2d> memoLeftPipePose;
124124
private Optional<Pose2d> memoRightPipePose;
125125

126-
class PipeTarget extends AutoAlignTarget {
126+
public static PipeTarget getNearestPipe(Pose2d atPose) {
127+
var face = getNearestReef(atPose).getNearestFace(atPose);
128+
var leftDelta =
129+
atPose.getTranslation().minus(face.getLeftPipePose().getTranslation()).getNorm();
130+
var rightDelta =
131+
atPose.getTranslation().minus(face.getRightPipePose().getTranslation()).getNorm();
132+
return leftDelta < rightDelta ? face.getLeftPipe() : face.getRightPipe();
133+
}
134+
135+
public class PipeTarget extends AutoAlignTarget {
136+
127137
private final boolean isLeft;
128138

129139
public PipeTarget(boolean isLeft) {
@@ -166,7 +176,6 @@ public void memoize() {
166176

167177
memoLeftPipePose = Config.getDefault().loadPose2d("Reef.Face." + this.name() + ".leftPipe");
168178
memoRightPipePose = Config.getDefault().loadPose2d("Reef.Face." + this.name() + ".rightPipe");
169-
SmartDashboard.putString("Reef.Face." + this.name(), centerPose.toString());
170179
}
171180

172181
/**
@@ -192,7 +201,7 @@ public Pose2d getCenterPose() {
192201
*
193202
* @return left pipe target
194203
*/
195-
public AutoAlignTarget getLeftPipe() {
204+
public PipeTarget getLeftPipe() {
196205
return new PipeTarget(true);
197206
}
198207

@@ -201,7 +210,8 @@ public AutoAlignTarget getLeftPipe() {
201210
*
202211
* @return right pipe target
203212
*/
204-
public AutoAlignTarget getRightPipe() {
213+
public PipeTarget getRightPipe() {
214+
205215
return new PipeTarget(false);
206216
}
207217

@@ -241,7 +251,10 @@ public Pose2d getRightPipePose() {
241251
*/
242252
public void memoizeLeftPipePose(Pose2d pose) {
243253
memoLeftPipePose = Optional.of(pose);
244-
Config.getDefault().storePose2d("Reef.Face." + this.toString() + ".leftPipe", pose);
254+
var tag = "Reef.Face." + name() + ".leftPipe";
255+
Config.getDefault().storePose2d(tag, pose);
256+
PoseLogger.getDefault().publish(tag + ".old", leftPipePose);
257+
PoseLogger.getDefault().publish(tag + ".new", pose);
245258
}
246259

247260
/**
@@ -251,7 +264,10 @@ public void memoizeLeftPipePose(Pose2d pose) {
251264
*/
252265
public void memoizeRightPipePose(Pose2d pose) {
253266
memoRightPipePose = Optional.of(pose);
254-
Config.getDefault().storePose2d("Reef.Face." + this.toString() + ".rightPipe", pose);
267+
var tag = "Reef.Face." + name() + ".rightPipe";
268+
Config.getDefault().storePose2d(tag, pose);
269+
PoseLogger.getDefault().publish(tag + ".old", leftPipePose);
270+
PoseLogger.getDefault().publish(tag + ".new", pose);
255271
}
256272
}
257273
}

src/main/java/frc/robot/Robot.java

+59-48
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
package frc.robot;
22

3+
import static edu.wpi.first.units.Units.Inches;
4+
import static edu.wpi.first.units.Units.Meters;
35
import static edu.wpi.first.units.Units.Seconds;
46

57
import edu.wpi.first.math.geometry.Pose2d;
6-
import edu.wpi.first.networktables.NetworkTableInstance;
7-
import edu.wpi.first.networktables.StructArrayPublisher;
8-
import edu.wpi.first.networktables.StructPublisher;
98
import edu.wpi.first.wpilibj.DataLogManager;
109
import edu.wpi.first.wpilibj.DriverStation;
1110
import edu.wpi.first.wpilibj.DriverStation.Alliance;
@@ -55,8 +54,6 @@
5554
import frc.robot.vision.Camera;
5655
import frc.robot.vision.Vision;
5756
import java.util.Arrays;
58-
import java.util.HashMap;
59-
import java.util.Map;
6057
import java.util.Optional;
6158
import java.util.function.BooleanSupplier;
6259
import java.util.function.Supplier;
@@ -88,15 +85,10 @@ public class Robot extends TimedRobot {
8885
private BooleanSupplier algaeModeSupplier;
8986
private Supplier<Gamepiece> gamepieceSupplier;
9087
private int usbCheckDelay = OIConstants.kUSBCheckNumLoops;
91-
private Map<String, StructPublisher<Pose2d>> posePublishers = new HashMap<>();
9288
private Optional<AutoAlignTarget> currentAutoAlignTarget = Optional.empty();
93-
private Pose2d nearestLeftPipe;
94-
private Pose2d nearestRightPipe;
95-
96-
private StructArrayPublisher<Pose2d> reefTargetPositionsPublisher =
97-
NetworkTableInstance.getDefault()
98-
.getStructArrayTopic("Reef Target Positions", Pose2d.struct)
99-
.publish();
89+
private Optional<Pose2d> recentOuttakePose = Optional.empty();
90+
private Optional<Pose2d> nearestLeftPipe = Optional.empty();
91+
private Optional<Pose2d> nearestRightPipe = Optional.empty();
10092

10193
public Robot() {
10294
gamepieceSupplier =
@@ -139,12 +131,12 @@ public Gamepiece get() {
139131
logger.monitor(
140132
"nearestLeftPipe",
141133
() -> {
142-
return Optional.ofNullable(nearestLeftPipe);
134+
return nearestLeftPipe;
143135
});
144136
logger.monitor(
145137
"nearestRightPipe",
146138
() -> {
147-
return Optional.ofNullable(nearestRightPipe);
139+
return nearestRightPipe;
148140
});
149141
Arrays.stream(Camera.values())
150142
.forEach(
@@ -162,8 +154,6 @@ public void robotInit() {
162154
// https://docs.wpilib.org/en/stable/docs/software/telemetry/datalog.html#logging-joystick-data
163155
DataLogManager.start();
164156
DriverStation.startDataLog(DataLogManager.getLog());
165-
166-
reefTargetPositionsPublisher.set(DriveConstants.kReefTargetPoses);
167157
swerve.calibrateOdometry();
168158
}
169159

@@ -184,8 +174,8 @@ public void robotPeriodic() {
184174

185175
var nearestReef = Reef.getNearestReef(swerve.getPose());
186176
var nearestReefFace = nearestReef.getNearestFace(swerve.getPose());
187-
nearestLeftPipe = nearestReefFace.getLeftPipePose();
188-
nearestRightPipe = nearestReefFace.getRightPipePose();
177+
nearestLeftPipe = Optional.of(nearestReefFace.getLeftPipePose());
178+
nearestRightPipe = Optional.of(nearestReefFace.getRightPipePose());
189179
}
190180

191181
@Override
@@ -292,23 +282,58 @@ public void configureButtonBindings() {
292282
configureOperatorButtonBindings();
293283
}
294284

295-
/** Store the supplied auto-align target for possible fixing. */
296-
protected Supplier<Pose2d> startAutoAlign(AutoAlignTarget target) {
285+
/**
286+
* Store the supplied auto-align target for possible fixing.
287+
*
288+
* @return a supplier that will return the target pose
289+
*/
290+
protected Supplier<Pose2d> startAutoAlign(boolean isLeftPipe) {
291+
var pose = swerve.getPose();
292+
var face = Reef.getNearestReef(pose).getNearestFace(pose);
293+
var target = isLeftPipe ? face.getLeftPipe() : face.getRightPipe();
297294
currentAutoAlignTarget = Optional.of(target);
295+
PoseLogger.getDefault().publish("autoAlignTarget", target.getPose());
298296
return () -> target.getPose();
299297
}
300298

301-
protected void rememberOutputPose(Pose2d pose) {
302-
currentAutoAlignTarget.ifPresent(target -> target.setPose(pose));
299+
/**
300+
* Remember the last outtake pose for potential recording.
301+
*
302+
* @param pose
303+
*/
304+
protected void rememberOutputPose() {
305+
recentOuttakePose = Optional.of(swerve.getPose());
306+
PoseLogger.getDefault().publish("recentOuttakePose", recentOuttakePose.get());
303307
}
304308

305309
/**
306-
* Fix the most recent auto-align target by ammending its position with the one suppliked.
310+
* Note that the last outtake was done at a good position.
311+
*
312+
* <p>If the outtake command occurred within five inches of a coral pipe, or if the outtake
313+
* followed an auto-align command, then we will remember the outtake location for the
314+
* corresponding target.
307315
*
308316
* @param newPose new pose to use for this target
309317
*/
310-
protected void fixAutoAlign(Pose2d newPose) {
311-
currentAutoAlignTarget.ifPresent(target -> target.memoize());
318+
protected void lastOuttakeWasAtGoodLocation() {
319+
recentOuttakePose.ifPresent(
320+
pose -> {
321+
var target = Reef.Face.getNearestPipe(pose);
322+
var deltaInches =
323+
Meters.of(pose.getTranslation().minus(target.getPose().getTranslation()).getNorm())
324+
.in(Inches);
325+
if (deltaInches < 6) {
326+
target.setPose(pose);
327+
target.memoize();
328+
} else {
329+
currentAutoAlignTarget.ifPresent(
330+
autoTarget -> {
331+
autoTarget.setPose(pose);
332+
autoTarget.memoize();
333+
});
334+
}
335+
});
336+
recentOuttakePose = Optional.empty();
312337
currentAutoAlignTarget = Optional.empty();
313338
}
314339

@@ -322,31 +347,17 @@ private void configureDriverButtonBindings() {
322347
// swerve.initializeRelativeTurningEncoder();
323348
}).ignoringDisable(true));
324349

325-
// Drive to nearest pose
326-
// driver.AIn()
327-
// .whileTrue(new DriveToPoseCommand(swerve, () -> swerve.getNearestPose()));
328-
329-
//TODO: add a button binding to call fixAutoAlign(swerve.getPose())
330-
driver.AIn().whileTrue(new DriveToPoseCommand(swerve,
331-
() -> startAutoAlign(Reef.getNearestReef(swerve.getPose()).getNearestFace(swerve.getPose()).getLeftPipe()).get()));
332-
driver.DIn().whileTrue(new DriveToPoseCommand(swerve,
333-
() -> startAutoAlign(Reef.getNearestReef(swerve.getPose()).getNearestFace(swerve.getPose()).getRightPipe()).get()));
350+
driver.AIn().whileTrue(new DriveToPoseCommand(swerve, () -> startAutoAlign(true).get()));
351+
driver.DIn().whileTrue(new DriveToPoseCommand(swerve, () -> startAutoAlign(false).get()));
334352

335353
// Outtake grippers
336354
var outtaking = driver.HIn();
337-
outtaking.onTrue(new InstantCommand(() -> rememberOutputPose(swerve.getPose())));
338355
lifter.atProcessor.and(outtaking)
339356
.whileTrue(algaeRoller.outtakeToProcessor());
340-
lifter.atAlgaeElse.and(outtaking)
357+
lifter.atProcessor.negate().and(outtaking)
341358
.whileTrue(algaeRoller.outtakeToBarge());
342-
lifter.atCoralL1.and(outtaking)
343-
.whileTrue(coralRoller.outtakeToL1());
344-
lifter.atCoralL2.and(outtaking)
345-
.whileTrue(coralRoller.outtakeToL2());
346-
lifter.atCoralL3.and(outtaking)
347-
.whileTrue(coralRoller.outtakeToL3());
348-
lifter.atCoralElse.and(outtaking)
349-
.whileTrue(coralRoller.outtakeToL4());
359+
outtaking
360+
.onTrue(new InstantCommand(() -> rememberOutputPose()));
350361
}
351362

352363
private void configureOperatorButtonBindings() {
@@ -426,8 +437,8 @@ public boolean getAsBoolean() {
426437
* Left and right D-pad buttons will cause the robot to go to the left/right
427438
* pipe on the nearest reef face.
428439
*/
429-
operator.povLeft().onTrue(new InstantCommand(() -> fixAutoAlign(swerve.getPose())));
430-
operator.povRight().onTrue(new InstantCommand(() -> fixAutoAlign(swerve.getPose())));
440+
operator.povLeft().onTrue(new InstantCommand(() -> lastOuttakeWasAtGoodLocation()));
441+
operator.povRight().onTrue(new InstantCommand(() -> lastOuttakeWasAtGoodLocation()));
431442

432443

433444

@@ -510,7 +521,7 @@ protected Command createRollerAnimationCommand() {
510521
*/
511522
BooleanSupplier intakeSupplier =
512523
() -> {
513-
return coralRoller.getRollerVelocity() > 1 || algaeRoller.getRollerVelocity() > 1;
524+
return coralRoller.getRollerVelocity() < 1 || algaeRoller.getRollerVelocity() < 1;
514525
};
515526

516527
/*

0 commit comments

Comments
 (0)