-
Notifications
You must be signed in to change notification settings - Fork 6
/
AutoAlignPointSelector.java
136 lines (122 loc) · 6.21 KB
/
AutoAlignPointSelector.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package com.team254.frc2023.planners;
import java.util.Map;
import java.util.Optional;
import com.team254.frc2023.Constants;
import com.team254.frc2023.field.AprilTag;
import com.team254.frc2023.field.Field;
import com.team254.lib.geometry.Pose2d;
import com.team254.lib.geometry.Rotation2d;
import edu.wpi.first.wpilibj.DriverStation;
import edu.wpi.first.wpilibj.DriverStation.Alliance;
public class AutoAlignPointSelector {
public enum RequestedAlignment {
CENTER, // force center (will do nothing if feeder)
RIGHT, // force right
LEFT, // force left
AUTO_CONE, // go to whatever position is closest that can score cubes mid or high
AUTO_CUBE, // go to whatever position is closest that can score cones mid or high
AUTO, // go to whatever position is closest
}
private static Map<Integer, AprilTag> getTagSet() {
if (DriverStation.getAlliance() == Alliance.Red) {
return Field.Red.kAprilTagMap;
} else {
return Field.Blue.kAprilTagMap;
}
}
private static Optional<AprilTag> getNearestTag(Map<Integer, AprilTag> tagMap, Pose2d point) {
double closestDistance = Integer.MAX_VALUE;
Optional<AprilTag> closestTag = Optional.empty();
for (int i : tagMap.keySet()) {
double distance = tagMap.get(i).getFieldToTag().distance(point);
if (distance < closestDistance) {
closestDistance = distance;
closestTag = Optional.of(tagMap.get(i));
}
}
return closestTag;
}
private static Optional<Pose2d> minimizeDistance(Pose2d from, Pose2d[] to) {
if (to.length == 0) {
return Optional.empty();
}
double closestDistance = Integer.MAX_VALUE;
Pose2d closestPose = to[0];
for (int i = 0; i < to.length; i++) {
double distance = from.distance(to[i]);
if (distance < closestDistance) {
closestDistance = distance;
closestPose = to[i];
}
}
return Optional.of(closestPose);
}
private static Optional<Pose2d> getNearestAlignment(AprilTag tag, Pose2d point, boolean cone, boolean cube) {
if (tag.isScoring()) {
Pose2d center = tag.getFieldToTag().transformBy(Pose2d.fromTranslation(tag.getTagToCenterAlign()));
center = new Pose2d(center.getTranslation(), Rotation2d.fromDegrees(180));
Pose2d left = tag.getFieldToTag().transformBy(Pose2d.fromTranslation(tag.getTagToLeftAlign()));
left = new Pose2d(left.getTranslation(), Rotation2d.fromDegrees(180));
Pose2d right = tag.getFieldToTag().transformBy(Pose2d.fromTranslation(tag.getTagToRightAlign()));
right = new Pose2d(right.getTranslation(), Rotation2d.fromDegrees(180));
if (cone) {
return minimizeDistance(point, new Pose2d[]{left,right});
} else if (cube) {
return Optional.of(center);
} else {
return minimizeDistance(point, new Pose2d[]{left,center,right});
}
} else {
Pose2d left = tag.getFieldToTag().transformBy(Pose2d.fromTranslation(tag.getTagToLeftAlign()));
left = new Pose2d(left.getTranslation(), Rotation2d.fromDegrees(0));
Pose2d right = tag.getFieldToTag().transformBy(Pose2d.fromTranslation(tag.getTagToRightAlign()));
right = new Pose2d(right.getTranslation(), Rotation2d.fromDegrees(0));
return minimizeDistance(point, new Pose2d[]{left,right});
}
}
public static Optional<Pose2d> chooseTargetPoint(Pose2d currentPoint, RequestedAlignment alignment) {
Map<Integer, AprilTag> mTagMap = getTagSet();
Optional<AprilTag> closestTag = getNearestTag(mTagMap, currentPoint);
if (closestTag.isEmpty()) {
return Optional.empty();
}
Optional<Pose2d> targetPose = Optional.empty();
if (alignment == RequestedAlignment.AUTO || alignment == RequestedAlignment.AUTO_CONE || alignment == RequestedAlignment.AUTO_CUBE) {
targetPose = getNearestAlignment(closestTag.get(), currentPoint,
alignment == RequestedAlignment.AUTO || alignment == RequestedAlignment.AUTO_CONE,
alignment == RequestedAlignment.AUTO || alignment == RequestedAlignment.AUTO_CUBE);
} else {
if (closestTag.get().isScoring()) {
switch (alignment) {
case CENTER:
targetPose = Optional.of(closestTag.get().getFieldToTag().transformBy(Pose2d.fromTranslation(closestTag.get().getTagToCenterAlign())));
break;
case LEFT:
targetPose = Optional.of(closestTag.get().getFieldToTag().transformBy(Pose2d.fromTranslation(closestTag.get().getTagToLeftAlign())));
break;
case RIGHT:
targetPose = Optional.of(closestTag.get().getFieldToTag().transformBy(Pose2d.fromTranslation(closestTag.get().getTagToRightAlign())));
break;
}
targetPose = Optional.of(new Pose2d(targetPose.get().getTranslation(), Rotation2d.fromDegrees(180)));
} else {
switch (alignment) {
case LEFT:
targetPose = Optional.of(closestTag.get().getFieldToTag().transformBy(Pose2d.fromTranslation(closestTag.get().getTagToLeftAlign())));
break;
case RIGHT:
targetPose = Optional.of(closestTag.get().getFieldToTag().transformBy(Pose2d.fromTranslation(closestTag.get().getTagToRightAlign())));
break;
default:
// center align in feeder is useless
return Optional.empty();
}
targetPose = Optional.of(new Pose2d(targetPose.get().getTranslation(), Rotation2d.fromDegrees(0)));
}
}
if (targetPose.isPresent() && targetPose.get().distance(currentPoint) > Constants.kAutoAlignAllowableDistance) {
return Optional.empty();
}
return targetPose;
}
}