-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAutoAim.java
More file actions
377 lines (347 loc) · 15.1 KB
/
AutoAim.java
File metadata and controls
377 lines (347 loc) · 15.1 KB
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
package frc.robot.utils.autoaim;
import edu.wpi.first.math.MathUtil;
import edu.wpi.first.math.geometry.Pose2d;
import edu.wpi.first.math.geometry.Rotation2d;
import edu.wpi.first.math.geometry.Transform2d;
import edu.wpi.first.math.geometry.Translation2d;
import edu.wpi.first.math.geometry.Twist2d;
import edu.wpi.first.math.kinematics.ChassisSpeeds;
import edu.wpi.first.math.util.Units;
import frc.robot.subsystems.shooter.TurretSubsystem;
import frc.robot.utils.FieldUtils;
import frc.robot.utils.autoaim.InterpolatingShotTree.ShotData;
import org.littletonrobotics.junction.Logger;
public class AutoAim {
private static boolean outOfRange = false; // TODO not sure if this should be true by default
public static double LATENCY_COMPENSATION_SECS =
// new LoggedTunableNumber("Latency time", 0.3).getAsDouble(); // 0.6; // TODO tune latency
// comp
0.3;
// public static double SPIN_UP_SECS = 0.0; // TODO tune spinup time
public static final InterpolatingShotTree ALPHA_HUB_SHOT_TREE = new InterpolatingShotTree();
public static final Rotation2d LEFT_FIXED_SHOT_TURRET_ANGLE = Rotation2d.fromDegrees(-73.916016);
public static final Rotation2d MID_FIXED_SHOT_TURRET_ANGLE = Rotation2d.fromDegrees(-82);
public static final Rotation2d RIGHT_FIXED_SHOT_TURRET_ANGLE =
Rotation2d.fromDegrees(-109.775391);
static { // For hub shot tree
ALPHA_HUB_SHOT_TREE.put(
Units.inchesToMeters(24 + 17), new ShotData(Rotation2d.fromDegrees(8), 27.5, 1.46));
ALPHA_HUB_SHOT_TREE.put(
Units.inchesToMeters(24 * Math.sqrt(2) + 6 + 12),
new ShotData(Rotation2d.fromDegrees(6), 30, 1.55));
ALPHA_HUB_SHOT_TREE.put(
Units.inchesToMeters(24 * Math.sqrt(2) + 6 + 3 * 12),
new ShotData(Rotation2d.fromDegrees(10.5), 30, 1.54));
ALPHA_HUB_SHOT_TREE.put(
Units.inchesToMeters(24 * Math.sqrt(2) + 6 + 5 * 12),
new ShotData(Rotation2d.fromDegrees(14.5), 30, 1.54));
ALPHA_HUB_SHOT_TREE.put(
Units.inchesToMeters(24 * Math.sqrt(2) + 6 + 7 * 12),
new ShotData(Rotation2d.fromDegrees(18.25), 30, 1.52));
ALPHA_HUB_SHOT_TREE.put(
Units.inchesToMeters(24 * Math.sqrt(2) + 6 + 9 * 12),
new ShotData(Rotation2d.fromDegrees(21.5), 30, 1.46));
ALPHA_HUB_SHOT_TREE.put(
Units.inchesToMeters(24 * Math.sqrt(2) + 6 + 11 * 12),
new ShotData(Rotation2d.fromDegrees(24.5), 30, 1.35));
ALPHA_HUB_SHOT_TREE.put(
Units.inchesToMeters(24 * Math.sqrt(2) + 6 + 13 * 12),
new ShotData(Rotation2d.fromDegrees(28), 30, 1.36));
}
public static final InterpolatingShotTree COMP_HUB_SHOT_TREE = new InterpolatingShotTree();
static {
COMP_HUB_SHOT_TREE.put(
1.716849,
new ShotData(
Rotation2d.fromDegrees(23 - 13.16),
30 * 0.84615384615 / TurretSubsystem.FLYWHEEL_GEAR_RATIO + 1,
0.8));
COMP_HUB_SHOT_TREE.put(
2.017596,
new ShotData(
Rotation2d.fromDegrees(23 - 13.16),
33 * 0.84615384615 / TurretSubsystem.FLYWHEEL_GEAR_RATIO + 1,
0.9));
COMP_HUB_SHOT_TREE.put(
2.423868,
new ShotData(
Rotation2d.fromDegrees(25 - 13.16),
35 * 0.84615384615 / TurretSubsystem.FLYWHEEL_GEAR_RATIO + 1,
1.1));
COMP_HUB_SHOT_TREE.put(
2.664198,
new ShotData(
Rotation2d.fromDegrees(26 - 13.16),
36 * 0.84615384615 / TurretSubsystem.FLYWHEEL_GEAR_RATIO + 1,
1.2));
COMP_HUB_SHOT_TREE.put(
2.903207,
new ShotData(
Rotation2d.fromDegrees(30 - 13.16),
35 * 0.84615384615 / TurretSubsystem.FLYWHEEL_GEAR_RATIO + 1,
1.2));
COMP_HUB_SHOT_TREE.put(
3.156802,
new ShotData(
Rotation2d.fromDegrees(32 - 13.16),
35 * 0.84615384615 / TurretSubsystem.FLYWHEEL_GEAR_RATIO + 1,
1.23));
COMP_HUB_SHOT_TREE.put(
3.437033,
new ShotData(
Rotation2d.fromDegrees(34 - 13.16),
35 * 0.84615384615 / TurretSubsystem.FLYWHEEL_GEAR_RATIO + 1,
1.25));
COMP_HUB_SHOT_TREE.put(
3.611052,
new ShotData(
Rotation2d.fromDegrees(38 - 13.16),
34 * 0.84615384615 / TurretSubsystem.FLYWHEEL_GEAR_RATIO + 1,
1.24));
COMP_HUB_SHOT_TREE.put(
3.773999,
new ShotData(
Rotation2d.fromDegrees(39 - 13.16),
34 * 0.84615384615 / TurretSubsystem.FLYWHEEL_GEAR_RATIO + 1,
1.21));
COMP_HUB_SHOT_TREE.put(
3.899275,
new ShotData(
Rotation2d.fromDegrees(40 - 13.16),
34 * 0.84615384615 / TurretSubsystem.FLYWHEEL_GEAR_RATIO + 1,
1.2));
COMP_HUB_SHOT_TREE.put(
4.138058,
new ShotData(
Rotation2d.fromDegrees(41 - 13.16),
34 * 0.84615384615 / TurretSubsystem.FLYWHEEL_GEAR_RATIO + 1,
1.13));
COMP_HUB_SHOT_TREE.put(
4.602258,
new ShotData(
Rotation2d.fromDegrees(43 - 13.16),
34.5 * 0.84615384615 / TurretSubsystem.FLYWHEEL_GEAR_RATIO + 1,
1.15));
COMP_HUB_SHOT_TREE.put(
4.893493,
new ShotData(
Rotation2d.fromDegrees(45 - 13.16),
35 * 0.84615384615 / TurretSubsystem.FLYWHEEL_GEAR_RATIO + 1,
1.2));
COMP_HUB_SHOT_TREE.put(
5.225402,
new ShotData(
Rotation2d.fromDegrees(47 - 13.16),
35 * 0.84615384615 / TurretSubsystem.FLYWHEEL_GEAR_RATIO + 1,
1.2));
COMP_HUB_SHOT_TREE.put(
5.584793,
new ShotData(
Rotation2d.fromDegrees(49 - 13.16),
35.5 * 0.84615384615 / TurretSubsystem.FLYWHEEL_GEAR_RATIO + 1,
1.17));
}
// Ig we'll see if we need more than 1 feed shot tree
public static final InterpolatingShotTree FEED_SHOT_TREE = new InterpolatingShotTree();
static { // For feed shot tree
FEED_SHOT_TREE.put(
Units.feetToMeters(2), new ShotData(Rotation2d.fromDegrees(23.16), 20 - 2, 0)); // - 2, 0));
FEED_SHOT_TREE.put(
Units.feetToMeters(4),
new ShotData(Rotation2d.fromDegrees(30), 40 - 2, 0.0)); // - 2, 0.0));
FEED_SHOT_TREE.put(
Units.feetToMeters(6),
new ShotData(Rotation2d.fromDegrees(40), 30 - 2, 0.0)); // - 2, 0.0));
FEED_SHOT_TREE.put(
Units.feetToMeters(8),
new ShotData(Rotation2d.fromDegrees(40), 32 - 2, 0.0)); // - 2, 0.0));
FEED_SHOT_TREE.put(
Units.feetToMeters(10),
new ShotData(Rotation2d.fromDegrees(40), 35 - 2, 0.0)); // - 2, 0.0));
FEED_SHOT_TREE.put(
Units.feetToMeters(12),
new ShotData(Rotation2d.fromDegrees(40), 40 - 2, 0.0)); // - 2, 0.0));
FEED_SHOT_TREE.put(
Units.feetToMeters(14),
new ShotData(Rotation2d.fromDegrees(45), 38 - 2, 0.0)); // - 2, 0.0));
FEED_SHOT_TREE.put(
Units.feetToMeters(16),
new ShotData(Rotation2d.fromDegrees(45), 40 - 2, 0.0)); // - 2, 0.0));
FEED_SHOT_TREE.put(
Units.feetToMeters(18),
new ShotData(Rotation2d.fromDegrees(40), 38 - 2, 1.42)); // - 2, 1.42));
FEED_SHOT_TREE.put(
Units.feetToMeters(20),
new ShotData(Rotation2d.fromDegrees(43), 40 - 2, 1.36)); // - 2, 1.36));
FEED_SHOT_TREE.put(
Units.feetToMeters(22),
new ShotData(Rotation2d.fromDegrees(45), 41 - 2, 1.34)); // - 2, 1.34));
FEED_SHOT_TREE.put(
Units.feetToMeters(24),
new ShotData(Rotation2d.fromDegrees(47), 42 - 2, 1.25)); // - 2, 1.25));
FEED_SHOT_TREE.put(
Units.feetToMeters(26),
new ShotData(Rotation2d.fromDegrees(48), 43 - 2, 1.28)); // - 2, 1.28));
FEED_SHOT_TREE.put(
Units.feetToMeters(28),
new ShotData(Rotation2d.fromDegrees(49), 45 - 2, 1.27)); // - 2, 1.27));
FEED_SHOT_TREE.put(
Units.feetToMeters(30),
new ShotData(Rotation2d.fromDegrees(49), 46 - 2, 1.32)); // - 2, 1.32));
FEED_SHOT_TREE.put(
Units.feetToMeters(32),
new ShotData(Rotation2d.fromDegrees(49), 48 - 2, 1.4)); // - 2, 1.4));
FEED_SHOT_TREE.put(
Units.feetToMeters(34),
new ShotData(Rotation2d.fromDegrees(52), 49 - 2, 1.3)); // - 2, 1.3));
FEED_SHOT_TREE.put(
Units.feetToMeters(36),
new ShotData(Rotation2d.fromDegrees(53), 53 - 2, 1.33)); // - 2, 1.33));
FEED_SHOT_TREE.put(
Units.feetToMeters(38),
new ShotData(Rotation2d.fromDegrees(53), 57 - 2, 1.3)); // - 2, 1.3));
FEED_SHOT_TREE.put(
Units.feetToMeters(40),
new ShotData(Rotation2d.fromDegrees(55), 57 - 2, 1.2)); // - 2, 1.2));
FEED_SHOT_TREE.put(
Units.feetToMeters(42),
new ShotData(Rotation2d.fromDegrees(56), 59 - 2, 1.2)); // - 2, 1.2));
// TODO: POPULATE beyond 24 feet and time of flight
}
public static double distanceToHub(Pose2d pose) {
double distance = pose.getTranslation().getDistance(FieldUtils.getCurrentHubTranslation());
Logger.recordOutput("Autoaim/Distance To Hub", distance);
return distance;
}
// lock in
public static Translation2d getVirtualSOTMTarget(
Translation2d target, ChassisSpeeds fieldRelativeSpeeds, double timeOfFlightSecs) {
// velocity times shot time is how translated it is
Translation2d vtarget =
target.minus(
new Translation2d(
fieldRelativeSpeeds.vxMetersPerSecond * timeOfFlightSecs,
fieldRelativeSpeeds.vyMetersPerSecond * timeOfFlightSecs));
Logger.recordOutput("Autoaim/Virtual Target", vtarget);
return vtarget;
}
public static Rotation2d getVirtualTargetYaw(
Translation2d target, ChassisSpeeds fieldRelativeSpeeds, Pose2d robotPose, double tof) {
Translation2d vtarget = getVirtualSOTMTarget(target, fieldRelativeSpeeds, tof);
return getTargetRotation(vtarget, robotPose);
}
public static Rotation2d getTargetRotation(Translation2d target, Pose2d robotPose) {
Translation2d robotToTarget = target.minus(robotPose.getTranslation());
Rotation2d rot = Rotation2d.fromRadians(Math.atan2(robotToTarget.getY(), robotToTarget.getX()));
Logger.recordOutput("Autoaim/Target Rotation", rot);
return rot;
}
// if we have a turret im going to assume we're on comp
public static Rotation2d getTurretTargetRotation(
Translation2d target,
Pose2d robotPose,
ChassisSpeeds chassisSpeeds,
InterpolatingShotTree shotTree) {
Pose2d turretPose =
robotPose.transformBy(
new Transform2d(TurretSubsystem.ROBOT_TO_TURRET_TRANSLATION, Rotation2d.kZero));
// get desired rotation to point at target
Rotation2d turretTargetRotation =
AutoAim.getVirtualTargetYaw(chassisSpeeds, target, turretPose, shotTree);
// subtract that from rotation to point at target
turretTargetRotation = turretTargetRotation.minus(robotPose.getRotation());
Logger.recordOutput("Turret/Unclamped target", turretTargetRotation);
// clamp between min and max turret angle
// turretTargetRotations =
// MathUtil.clamp(
// turretTargetRotations,
// TurretSubsystem.TURRET_MIN_ANGLE.getRotations(),
// TurretSubsystem.TURRET_MAX_ANGLE.getRotations());
double turretTargetDegrees = turretTargetRotation.getDegrees() - 5;
// If its in the deadzone, clamp to nearest hardstop
outOfRange =
turretTargetDegrees > TurretSubsystem.TURRET_FORWARD_HARDSTOP_ANGLE.getDegrees()
&& (turretTargetDegrees < TurretSubsystem.TURRET_LEFT_HARDSTOP_ANGLE.getDegrees());
if (outOfRange) {
turretTargetDegrees =
// If the requested angle is greater than the halfway point in the deadzone, go to the
// read hardstop, otherwise go to forward hardstop
turretTargetDegrees
> (TurretSubsystem.TURRET_FORWARD_HARDSTOP_ANGLE.getDegrees()
+ TurretSubsystem.TURRET_LEFT_HARDSTOP_ANGLE.getDegrees())
/ 2
? TurretSubsystem.TURRET_LEFT_HARDSTOP_ANGLE.getDegrees() + 2
: TurretSubsystem.TURRET_FORWARD_HARDSTOP_ANGLE.getDegrees() - 2;
}
Logger.recordOutput("Turret/Clamped target", Rotation2d.fromDegrees(turretTargetDegrees));
// Now we need to rewrap this angle to always be negative, with 0 as the forward hardstop
turretTargetDegrees = MathUtil.inputModulus(turretTargetDegrees, -360, 0);
Logger.recordOutput("Turret/Wrapped target", Rotation2d.fromDegrees(turretTargetDegrees));
// ship it
return Rotation2d.fromDegrees(turretTargetDegrees);
}
public static Rotation2d getTurretHubTargetRotation(
Translation2d target, Pose2d robotPose, ChassisSpeeds chassisSpeeds) {
return getTurretTargetRotation(target, robotPose, chassisSpeeds, COMP_HUB_SHOT_TREE);
}
public static Rotation2d getTurretFeedTargetRotation(
Translation2d target, Pose2d robotPose, ChassisSpeeds chassisSpeeds) {
return getTurretTargetRotation(target, robotPose, chassisSpeeds, FEED_SHOT_TREE);
}
public static Rotation2d getVirtualTargetYaw(
ChassisSpeeds fieldRelativeSpeeds,
Translation2d targetTranslation,
Pose2d robotPose,
InterpolatingShotTree tree) {
double tof = tree.calculateShot(robotPose, targetTranslation).timeOfFlightSecs();
return getVirtualTargetYaw(targetTranslation, fieldRelativeSpeeds, robotPose, tof);
}
public static ShotData getSOTMShotData(
Pose2d robotPose,
Translation2d targetTranslation,
ChassisSpeeds fieldRelativeSpeeds,
InterpolatingShotTree tree) {
ShotData unadjustedShot = tree.calculateShot(robotPose, targetTranslation);
Translation2d virtualTarget =
getVirtualSOTMTarget(
targetTranslation, fieldRelativeSpeeds, unadjustedShot.timeOfFlightSecs());
return tree.get(robotPose.getTranslation().getDistance(virtualTarget));
}
public static ShotData getCompensatedSOTMShotData(
Pose2d robotPose,
Translation2d targetTranslation,
ChassisSpeeds fieldRelativeSpeeds,
InterpolatingShotTree tree) {
ChassisSpeeds robotRelativeSpeeds =
ChassisSpeeds.fromFieldRelativeSpeeds(fieldRelativeSpeeds, robotPose.getRotation());
// calculate latency compensated pose
Pose2d compensatedPose =
robotPose.exp(
new Twist2d(
robotRelativeSpeeds.vxMetersPerSecond
* (LATENCY_COMPENSATION_SECS
// + SPIN_UP_SECS
),
robotRelativeSpeeds.vyMetersPerSecond
* (LATENCY_COMPENSATION_SECS
// + SPIN_UP_SECS
),
robotRelativeSpeeds.omegaRadiansPerSecond
* (LATENCY_COMPENSATION_SECS
// + SPIN_UP_SECS
)));
return getSOTMShotData(compensatedPose, targetTranslation, fieldRelativeSpeeds, tree);
}
public static boolean targetInTurretDeadzone() {
return outOfRange;
}
public static ShotData getLeftFixedShotData() {
return new ShotData(Rotation2d.fromDegrees(36), 36, 0);
}
public static ShotData getRightFixedShotData() {
return new ShotData(Rotation2d.fromDegrees(23.16), 35.7, 0);
}
public static ShotData getMidFixedShotData() {
return new ShotData(Rotation2d.fromDegrees(32.84), 35, 0);
}
}