11package frc .robot .commands ;
22
3- import static frc .robot .Constants .*;
4-
5- import java .util .Map ;
6- import java .util .Map .Entry ;
7- import java .util .Optional ;
83import java .util .function .Supplier ;
94
105import edu .wpi .first .math .geometry .Pose2d ;
11- import edu .wpi .first .math .geometry .Rotation2d ;
126import edu .wpi .first .math .geometry .Transform2d ;
137import edu .wpi .first .math .geometry .Translation2d ;
148import edu .wpi .first .wpilibj2 .command .Command ;
@@ -35,14 +29,102 @@ public class AlignCommand extends Command {
3529 * @return a {@code Commmand} for moving the robot to the specified
3630 * target
3731 */
38- public static DriveCommand moveTo (DriveSubsystem driveSubsystem ,
39- PoseEstimationSubsystem poseEstimationSubsystem ,
32+ public static DriveCommand moveTo (DriveSubsystem driveSubsystem , PoseEstimationSubsystem poseEstimationSubsystem ,
4033 Pose2d targetPose , double distanceTolerance , double angleTolerance ) {
41- return new DriveCommand (driveSubsystem , () -> poseEstimationSubsystem .getPose (),
42- () -> targetPose ,
34+ return moveTo (driveSubsystem , poseEstimationSubsystem , () -> targetPose , distanceTolerance , angleTolerance );
35+ }
36+
37+ /**
38+ * Constructs a {@code DriveCommand} for moving the robot to the specified
39+ * target.
40+ *
41+ * @param driveSubsystem the {@code DriveSubsystem} to use
42+ * @param poseEstimationSubsystem the {@code PoseEstimationSubsystem} to use
43+ * @param targetPoseSupplier a {@code Supplier<Pose2d>} that provides the
44+ * {@code Pose2d} of the target.
45+ * This is used at the commencement of the {@code DriveCommand} (i.e.,
46+ * when the scheduler begins to periodically execute the
47+ * {@code DriveCommand})
48+ * @param distanceTolerance the distance error in meters which is tolerable
49+ * @param angleTolerance the angle error in degrees which is tolerable
50+ * @return a {@code Commmand} for moving the robot to the specified
51+ * target
52+ */
53+ public static DriveCommand moveTo (DriveSubsystem driveSubsystem , PoseEstimationSubsystem poseEstimationSubsystem ,
54+ Supplier <Pose2d > targetPoseSupplier , double distanceTolerance , double angleTolerance ) {
55+ return new DriveCommand (driveSubsystem , () -> poseEstimationSubsystem .getEstimatedPose (),
56+ targetPoseSupplier ,
4357 distanceTolerance , angleTolerance );
4458 }
4559
60+ /**
61+ * Constructs a {@code DriveCommand} for turning the robot to the specified
62+ * target.
63+ *
64+ * @param driveSubsystem the {@code DriveSubsystem} to use
65+ * @param poseEstimationSubsystem the {@code PoseEstimationSubsystem} to use
66+ * @param targetPose the {@code Pose2d} of the target
67+ * @param distanceTolerance the distance error in meters which is tolerable
68+ * @param angleTolerance the angle error in degrees which is tolerable
69+ * @return a {@code Commmand} for turning the robot to the specified
70+ * target
71+ */
72+ public static DriveCommand turnTo (DriveSubsystem driveSubsystem , PoseEstimationSubsystem poseEstimationSubsystem ,
73+ Pose2d targetPose , double distanceTolerance , double angleTolerance ) {
74+ return turnTo (driveSubsystem , poseEstimationSubsystem , () -> targetPose , distanceTolerance , angleTolerance );
75+ }
76+
77+ /**
78+ * Constructs a {@code DriveCommand} for turning the robot to the specified
79+ * target.
80+ *
81+ * @param driveSubsystem the {@code DriveSubsystem} to use
82+ * @param poseEstimationSubsystem the {@code PoseEstimationSubsystem} to use
83+ * @param targetPoseSupplier a {@code Supplier<Pose2d>} that provides the
84+ * {@code Pose2d} of the target.
85+ * This is used at the commencement of the {@code DriveCommand} (i.e.,
86+ * when the scheduler begins to periodically execute the
87+ * {@code DriveCommand})
88+ * @param distanceTolerance the distance error in meters which is tolerable
89+ * @param angleTolerance the angle error in degrees which is tolerable
90+ * @return a {@code Commmand} for turning the robot to the specified
91+ * target
92+ */
93+ public static DriveCommand turnTo (DriveSubsystem driveSubsystem , PoseEstimationSubsystem poseEstimationSubsystem ,
94+ Supplier <Pose2d > targetPoseSupplier , double distanceTolerance , double angleTolerance ) {
95+ return new DriveCommand (driveSubsystem , () -> poseEstimationSubsystem .getEstimatedPose (),
96+ () -> {
97+ var transform = new Transform2d (0 , 0 ,
98+ poseEstimationSubsystem .angularDisplacement (targetPoseSupplier .get ()));
99+ return poseEstimationSubsystem .getEstimatedPose ().plus (transform );
100+ },
101+ distanceTolerance , angleTolerance );
102+ }
103+
104+ /**
105+ * Constructs a {@code DriveCommand} for moving the robot toward the specified
106+ * target position while ensuring that the robot is away from the target by the
107+ * specified distance.
108+ *
109+ * @param driveSubsystem the {@code DriveSubsystem} to use
110+ * @param poseEstimaitonSubsystem the {@code PoseEstimationSubsystem} to use
111+ * @param targetPosition a {@code Translation2d} (i.e., the position) of the
112+ * target.
113+ * @param distanceToTarget the desired distance between the robot and the
114+ * target position
115+ * @param distanceTolerance the distance error in meters which is tolerable
116+ * @param angleTolerance the angle error in degrees which is tolerable
117+ * @return a {@code Commmand} for turning the robot to the specified target
118+ * position
119+ */
120+ public static DriveCommand moveToward (DriveSubsystem driveSubsystem ,
121+ PoseEstimationSubsystem poseEstimaitonSubsystem , Translation2d targetPosition , double distanceToTarget ,
122+ double distanceTolerance , double angleTolerance ) {
123+ return moveToward (
124+ driveSubsystem , poseEstimaitonSubsystem , () -> targetPosition , distanceToTarget , distanceTolerance ,
125+ angleTolerance );
126+ }
127+
46128 /**
47129 * Constructs a {@code DriveCommand} for moving the robot toward the specified
48130 * target position while ensuring that the robot is away from the target by the
@@ -63,20 +145,20 @@ public static DriveCommand moveTo(DriveSubsystem driveSubsystem,
63145 * position
64146 */
65147 public static DriveCommand moveToward (DriveSubsystem driveSubsystem ,
66- PoseEstimationSubsystem poseEstimaitonSubsystem ,
67- Supplier <Translation2d > targetPositionSupplier ,
68- double distanceToTarget ,
69- double distanceTolerance ,
70- double angleTolerance ) {
71- Supplier <Pose2d > poseSupplier = () -> poseEstimaitonSubsystem .getPose ();
148+ PoseEstimationSubsystem poseEstimaitonSubsystem , Supplier <Translation2d > targetPositionSupplier ,
149+ double distanceToTarget , double distanceTolerance , double angleTolerance ) {
150+ Supplier <Pose2d > poseSupplier = () -> poseEstimaitonSubsystem .getEstimatedPose ();
72151 return new DriveCommand (driveSubsystem , poseSupplier ,
73- () -> poseSupplier .get ()
74- .plus (transformationToward (targetPositionSupplier .get (), poseSupplier .get (), distanceToTarget )),
152+ () -> {
153+ var transform = poseEstimaitonSubsystem
154+ .transformationToward (targetPositionSupplier .get (), distanceToTarget );
155+ return poseSupplier .get ().plus (transform );
156+ },
75157 distanceTolerance , angleTolerance );
76158 }
77159
78160 /**
79- * Constructs a {@code DriveCommand} for moving the robot to the specified
161+ * Constructs a {@code DriveCommand} for turning the robot to the specified
80162 * target.
81163 *
82164 * @param driveSubsystem the {@code DriveSubsystem} to use
@@ -85,112 +167,46 @@ public static DriveCommand moveToward(DriveSubsystem driveSubsystem,
85167 * which {@code AprilTag}s are considered (maximum: 180)
86168 * @param distanceThresholdInMeters the maximum distance (in meters) within
87169 * which {@code AprilTag}s are considered
88- * @param robotToTarget the {@code Pose2d} of the target relative to the
89- * {@code Pose2d} of the robot for the {@code DriveCommand} to finish
90170 * @param distanceTolerance the distance error in meters which is tolerable
91171 * @param angleTolerance the angle error in degrees which is tolerable
92- * @return a {@code Commmand} for moving the robot to the specified
172+ * @return a {@code Commmand} for turning the robot to the specified
93173 * target
94174 */
95- public static DriveCommand moveToClosestTag (DriveSubsystem driveSubsystem ,
175+ public static DriveCommand turnToClosestTag (DriveSubsystem driveSubsystem ,
96176 PoseEstimationSubsystem poseEstimationSubsystem , double angleOfCoverageInDegrees ,
97- double distanceThresholdInMeters ,
98- Transform2d robotToTarget , double distanceTolerance , double angleTolerance ) {
99- return new DriveCommand (driveSubsystem , () -> poseEstimationSubsystem .getPose (),
100- () -> kFieldLayout
101- .getTagPose (
102- closestTagID (
103- poseEstimationSubsystem .getPose (), angleOfCoverageInDegrees ,
104- distanceThresholdInMeters ))
105- .get ()
106- .toPose2d ()
107- .transformBy (robotToTarget ),
108- distanceTolerance , angleTolerance );
109- }
110-
111- /**
112- * Returns the transformation needed for the robot to face toward the specified
113- * target position and remain the specified distance away fron the target
114- * position.
115- *
116- * @param targetPosition the target position whose x and y-coordinate values
117- * are in meters
118- * @param distanceToTarget the desired distance in meters to the target
119- * @return the transformation needed for the robot to face toward the specified
120- * target position and remain the specified distance away fron the
121- * target position; {@code null} if it has not been
122- * possible to reliably estimate the pose of the robot
123- */
124- public static Transform2d transformationToward (Translation2d targetPosition , Pose2d currentPose ,
125- double distanceToTarget ) {
126- Translation2d diff = targetPosition .minus (currentPose .getTranslation ());
127- if (diff .getNorm () == 0 )
128- return null ;
129- var targetPose = new Pose2d (
130- currentPose .getTranslation ().plus (diff .times (1 - distanceToTarget / diff .getNorm ())),
131- diff .getAngle ());
132- return targetPose .minus (currentPose );
177+ double distanceThresholdInMeters , double distanceTolerance , double angleTolerance ) {
178+ return turnTo (
179+ driveSubsystem , poseEstimationSubsystem ,
180+ () -> poseEstimationSubsystem .closestTagPose (angleOfCoverageInDegrees , distanceThresholdInMeters ),
181+ distanceThresholdInMeters , angleTolerance );
133182 }
134183
135184 /**
136- * Determines the ID of the {@code AprilTag} that is closest to the specified
137- * {@code Pose2d} ({@code null} if no such {@code AprilTag}) .
185+ * Constructs a {@code DriveCommand} for moving the robot to the specified
186+ * target .
138187 *
139- * @param pose a {@code Pose2d}
188+ * @param driveSubsystem the {@code DriveSubsystem} to use
189+ * @param poseEstimationSubsystem the {@code PoseEstimationSubsystem} to use
140190 * @param angleOfCoverageInDegrees the angular coverage (in degrees) within
141191 * which {@code AprilTag}s are considered (maximum: 180)
142192 * @param distanceThresholdInMeters the maximum distance (in meters) within
143193 * which {@code AprilTag}s are considered
144- * @return the ID of the {@code AprilTag} that is closest to the specified
145- * {@code Pose2d} ({@code null} if no such {@code AprilTag})
146- */
147- public static Integer closestTagID (Pose2d pose , double angleOfCoverageInDegrees , double distanceThresholdInMeters ) {
148- var s = kFieldLayout .getTags ().stream ()
149- // consider only the tags facing toward the robot
150- .filter (
151- t -> Math .abs (
152- t .pose .getTranslation ().toTranslation2d ().minus (pose .getTranslation ()).getAngle ()
153- .minus (t .pose .toPose2d ().getRotation ()).getDegrees ()) > 90 )
154- .filter ( // consider only the tags within the angle of coverage
155- t -> Math .abs (
156- angularDisplacement (pose , t .pose .toPose2d ()).getDegrees ()) < angleOfCoverageInDegrees )
157- .map (t -> Map .entry (t .ID , Math .abs (translationalDisplacement (pose , t .pose .toPose2d ())))) // distance
158- .filter (t -> t .getValue () < distanceThresholdInMeters ); // only tags sufficently close
159- Optional <Entry <Integer , Double >> closest = s .reduce ((e1 , e2 ) -> e1 .getValue () < e2 .getValue () ? e1 : e2 );
160- if (closest .isPresent ()) {
161- return closest .get ().getKey ();
162- } else
163- return null ;
164- }
165-
166- /**
167- * Calculates the angular displacement given the initial and last
168- * {@code Pose2d}s.
169- *
170- * @param initial the initial {@code Pose2d}
171- * @param last the last {@code Pose2d}
172- * @return the angular displacement given the initial and last
173- * {@code Pose2d}s
174- */
175- public static Rotation2d angularDisplacement (Pose2d initial , Pose2d last ) {
176- var t = last .getTranslation ().minus (initial .getTranslation ());
177- return t .getAngle ().minus (initial .getRotation ());
178- }
179-
180- /**
181- * Calculates the translational displacement given the initial and last
182- * {@code Pose2d}s.
183- *
184- * @param initial the initial {@code Pose2d}
185- * @param last the last {@code Pose2d}
186- * @return the translational displacement given the initial and last
187- * {@code Pose2d}s
194+ * @param robotToTarget the {@code Pose2d} of the target relative to the
195+ * {@code Pose2d} of the robot for the {@code DriveCommand} to finish
196+ * @param distanceTolerance the distance error in meters which is tolerable
197+ * @param angleTolerance the angle error in degrees which is tolerable
198+ * @return a {@code Commmand} for moving the robot to the specified
199+ * target
188200 */
189- public static double translationalDisplacement (Pose2d initial , Pose2d last ) {
190- var t = last .getTranslation ().minus (initial .getTranslation ());
191- return Math .abs (t .getAngle ().minus (initial .getRotation ()).getDegrees ()) > 90
192- ? -t .getNorm ()
193- : t .getNorm ();
201+ public static DriveCommand moveToClosestTag (DriveSubsystem driveSubsystem ,
202+ PoseEstimationSubsystem poseEstimationSubsystem , double angleOfCoverageInDegrees ,
203+ double distanceThresholdInMeters , Transform2d robotToTarget , double distanceTolerance ,
204+ double angleTolerance ) {
205+ return moveTo (
206+ driveSubsystem , poseEstimationSubsystem ,
207+ () -> poseEstimationSubsystem .closestTagPose (angleOfCoverageInDegrees , distanceThresholdInMeters )
208+ .plus (robotToTarget ),
209+ distanceTolerance , angleTolerance );
194210 }
195211
196212}
0 commit comments