22
33import static edu .wpi .first .math .util .Units .*;
44import static edu .wpi .first .wpilibj2 .command .Commands .*;
5- import static frc .robot .Constants .*;
5+ import static frc .robot .Constants .AutoAlignConstants .*;
6+ import static frc .robot .Constants .ElevatorConstants .*;
7+ import static frc .robot .Constants .WristConstants .*;
68import static frc .robot .subsystems .PoseEstimationSubsystem .*;
79
810import java .util .Arrays ;
911import java .util .LinkedList ;
1012import java .util .List ;
13+ import java .util .Map ;
1114import java .util .function .DoubleSupplier ;
1215import java .util .function .Supplier ;
1316
1417import edu .wpi .first .math .geometry .Pose2d ;
1518import edu .wpi .first .math .geometry .Transform2d ;
1619import edu .wpi .first .math .kinematics .ChassisSpeeds ;
20+ import edu .wpi .first .wpilibj .Alert ;
21+ import edu .wpi .first .wpilibj .Alert .AlertType ;
22+ import edu .wpi .first .wpilibj .DriverStation ;
23+ import edu .wpi .first .wpilibj .DriverStation .Alliance ;
1724import edu .wpi .first .wpilibj2 .command .Command ;
1825import edu .wpi .first .wpilibj2 .command .Commands ;
26+ import edu .wpi .first .wpilibj2 .command .SelectCommand ;
1927import edu .wpi .first .wpilibj2 .command .WaitCommand ;
2028import frc .robot .commands .DriveCommand ;
2129import frc .robot .commands .PathDriveCommand ;
@@ -32,6 +40,105 @@ public static void setSubsystems(DriveSubsystem driveSubsystem,
3240 m_poseEstimationSubsystem = poseEstimationSubsystem ;
3341 }
3442
43+ public static Command get3ScoreNorth () {
44+ return select (get3ScoreNorthRed (4 ), get3ScoreNorthBlue (4 ));
45+ }
46+
47+ public static Command get3ScoreSouth () {
48+ return select (get3ScoreSouthRed (4 ), get3ScoreSouthBlue (4 ));
49+ }
50+
51+ private static Command get3ScoreNorthBlue (int level ) {
52+ return get3ScoreOptimized (
53+ toTag (20 , level , kRobotToTagsRight ), toTag (19 , level , kRobotToTagsRight ),
54+ toTag (19 , level , kRobotToTagsLeft ),
55+ 13 , kRobotToTagsRightReady );
56+ }
57+
58+ private static Command get3ScoreNorthRed (int level ) {
59+ return get3ScoreOptimized (
60+ toTag (9 , level , kRobotToTagsLeft ), toTag (8 , level , kRobotToTagsLeft ),
61+ toTag (8 , level , kRobotToTagsRight ),
62+ 2 , kRobotToTagsLeftReady );
63+ }
64+
65+ private static Command get3ScoreSouthBlue (int level ) {
66+ return get3ScoreOptimized (
67+ toTag (22 , level , kRobotToTagsLeft ), toTag (17 , level , kRobotToTagsLeft ),
68+ toTag (17 , level , kRobotToTagsRight ),
69+ 12 , kRobotToTagsLeftReady );
70+ }
71+
72+ private static Command get3ScoreSouthRed (int level ) {
73+ return get3ScoreOptimized (
74+ toTag (11 , level , kRobotToTagsRight ), toTag (6 , level , kRobotToTagsRightReady ),
75+ toTag (6 , level , kRobotToTagsLeft ),
76+ 1 , kRobotToTagsRight );
77+ }
78+
79+ private static Command get3ScoreOptimized (Command align1 , Command align2 , Command align3 , int stationTagID ,
80+ Transform2d ... robotToTags ) {
81+ return sequence (
82+ scoreOptimized (align1 , 4 ),
83+ toStation (stationTagID , robotToTags ),
84+ scoreOptimized (align2 , goToBase (), 4 ),
85+ toStation (stationTagID , robotToTags ),
86+ scoreOptimized (align3 , goToBase (), 4 ));
87+ }
88+
89+ public static Command scoreOptimized (Command align , int level ) {
90+ return scoreOptimized (align , runOnce (() -> {
91+ }), level );
92+ }
93+
94+ public static Command scoreOptimized (Command align , Command pickup , int level ) {
95+ switch (level ) {
96+ case 4 :
97+ return score (
98+ align , pickup , kLevelFourHeight , kGrabberAngleLevelFour );
99+ case 3 :
100+ return score (align , pickup , kLevelThreeHeight , kGrabberAngleLevelThree );
101+ case 2 :
102+ return score (align , pickup , kLevelTwoHeight , kGrabberAngleOthers );
103+ case 1 :
104+ return score (align , pickup , kLevelOneHeight , kGrabberAngleOthers );
105+ }
106+ return runOnce (() -> {
107+ });
108+ }
109+
110+ private static Command score (Command align , Command pickup , double level , double wristAngle ) {
111+ return score (align , pickup , level , wristAngle , runOnce (() -> {
112+ }));
113+ }
114+
115+ private static Command score (Command align , Command pickup , double level , double wristAngle ,
116+ Command followup ) {
117+ return sequence (
118+ prepareToScore (align , pickup , level , wristAngle ),
119+ score (.2 , followup ));// TODO: Optimize
120+ }
121+
122+ static Command prepareToScore (Command align , double level , double wristAngle ) {
123+ return prepareToScore (align , runOnce (() -> {
124+ }), level , wristAngle );
125+ }
126+
127+ static Command prepareToScore (Command align , Command pickup , double level , double wristAngle ) {
128+ return parallel (
129+ align ,
130+ sequence (pickup ));
131+ }
132+
133+ public static Command score (double releaseDuration , Command followup ) {
134+ return sequence (followup );
135+ }
136+
137+ private static Command toStation (int tagID , Transform2d ... robotToTags ) {
138+ return parallel (
139+ toTag (tagID , robotToTags ), sequence ());
140+ }
141+
35142 /**
36143 * Creates a {@code Command} to automatically align the robot to the closest
37144 * {@code AprilTag}.
@@ -260,4 +367,105 @@ public static Command alignToTags(double distanceTolerance, double angleToleranc
260367 }
261368 return sequence (commands .toArray (new Command [0 ]));
262369 }
370+
371+ private static Command select (Command commandRedAlliance , Command commandBlueAlliance ) {
372+ return new SelectCommand <Object >(Map
373+ .of (Alliance .Red , commandRedAlliance , Alliance .Blue , commandBlueAlliance ),
374+ () -> {
375+ Alliance alliance = DriverStation .getAlliance ().get ();
376+ var middle = kFieldLayout .getFieldLength () / 2 ;
377+ try {
378+ var confidence = m_poseEstimationSubsystem .confidence ();
379+ if (confidence < 0.3 )
380+ return alert ("Pose Confidence (" + confidence + ") Too Low!" );
381+ var x = m_poseEstimationSubsystem .getEstimatedPose ().getX ();
382+ if ((alliance == DriverStation .Alliance .Blue && x > middle )
383+ || (alliance == DriverStation .Alliance .Red && x < middle )) {
384+ return alert ("Strange Robot Position (" + alliance + " Alliance)!" );
385+ }
386+ } catch (Exception e ) {
387+ }
388+ return alliance ;
389+ });
390+ }
391+
392+ private static Alert alert (String text ) {
393+ var a = new Alert (text , AlertType .kError );
394+ a .set (true );
395+ return a ;
396+ }
397+
398+ /**
399+ * Creates a {@code Command} to automatically align the robot to the target
400+ * {@code AprilTag}.
401+ *
402+ * @param tagID the ID of the target {@code AprilTag}
403+ * @param level the scoring level
404+ * @param robotToTags the {@code Tranform2d} representing the pose of the
405+ * target {@code AprilTag} relative to the robot when the robot is
406+ * aligned
407+ * @return a {@code Command} to automatically align the robot to the target
408+ * {@code AprilTag}
409+ */
410+ public static Command toTag (int tagID , int level , Transform2d ... robotToTags ) {
411+ return toTag (tagID , adjust (level , robotToTags ));
412+ }
413+
414+ /**
415+ * Creates a {@code Command} to automatically align the robot to the target
416+ * {@code AprilTag}.
417+ *
418+ * @param tagID the ID of the target {@code AprilTag}
419+ * @param robotToTags the {@code Tranform2d} representing the pose of the
420+ * target {@code AprilTag} relative to the robot when the robot is
421+ * aligned
422+ * @return a {@code Command} to automatically align the robot to the target
423+ * {@code AprilTag}
424+ */
425+ public static Command toTag (int tagID , Transform2d ... robotToTags ) {
426+ return new PathDriveCommand (m_driveSubsystem , 0.01 , 1 ,
427+ 0.05 , 5 , // TODO: Optimize
428+ posesToTag (tagID , robotToTags ));
429+ }
430+
431+ /**
432+ * Creates a list of {@code Pose2d}s to automatically align the robot to the
433+ * target {@code AprilTag}.
434+ *
435+ * @param tagID the ID of the target {@code AprilTag}
436+ * @param robotToTags the {@code Tranform2d} representing the pose of the
437+ * target {@code AprilTag} relative to the robot when the robot is
438+ * aligned
439+ * @return a list of {@code Pose2d}s to automatically align the robot to the
440+ * target {@code AprilTag}
441+ */
442+ public static List <Supplier <Pose2d >> posesToTag (int tagID ,
443+ Transform2d ... robotToTags ) {
444+ return Arrays .stream (robotToTags ).map (r -> (Supplier <Pose2d >) (() -> {
445+ Pose2d pose = pose (tagID );
446+ if (pose == null )
447+ return m_driveSubsystem .getPose ();
448+ return m_poseEstimationSubsystem .odometryCentricPose (pose .plus (r ));
449+ })).toList ();
450+ }
451+
452+ /**
453+ * Adjusts the specified the {@code Tranform2d}s by incorporating the offset
454+ * needed to score at the specified level.
455+ *
456+ * @param level the scoring level
457+ * @param robotToTags {@code Tranform2d}s
458+ * @return the adjusted {@code Tranform2d}s
459+ */
460+ private static Transform2d [] adjust (int level , Transform2d ... robotToTags ) {
461+ return Arrays .stream (robotToTags )
462+ .map (t -> new Transform2d (t .getX () - kOffsets .get (level ), t .getY (), t .getRotation ())).toList ()
463+ .toArray (new Transform2d [0 ]);
464+ }
465+
466+ public static Command goToBase () {
467+ return sequence (
468+ parallel ());
469+ }
470+
263471}
0 commit comments