@@ -113,6 +113,14 @@ public class SwerveInputStream implements Supplier<ChassisSpeeds>
113
113
* Field oriented chassis output is relative to your current alliance.
114
114
*/
115
115
private Optional <BooleanSupplier > allianceRelative = Optional .empty ();
116
+ /**
117
+ * Heading offset enable state.
118
+ */
119
+ private Optional <BooleanSupplier > headingOffsetEnabled = Optional .empty ();
120
+ /**
121
+ * Heading offset to apply during heading based control.
122
+ */
123
+ private Optional <Rotation2d > headingOffset = Optional .empty ();
116
124
/**
117
125
* {@link SwerveController} for simple control over heading.
118
126
*/
@@ -206,6 +214,8 @@ public SwerveInputStream copy()
206
214
newStream .translationCube = translationCube ;
207
215
newStream .robotRelative = robotRelative ;
208
216
newStream .allianceRelative = allianceRelative ;
217
+ newStream .headingOffsetEnabled = headingOffsetEnabled ;
218
+ newStream .headingOffset = headingOffset ;
209
219
return newStream ;
210
220
}
211
221
@@ -233,6 +243,42 @@ public SwerveInputStream robotRelative(boolean enabled)
233
243
return this ;
234
244
}
235
245
246
+ /**
247
+ * Heading offset enabled boolean supplier.
248
+ *
249
+ * @param enabled Enable state
250
+ * @return self
251
+ */
252
+ public SwerveInputStream headingOffset (BooleanSupplier enabled )
253
+ {
254
+ headingOffsetEnabled = Optional .of (enabled );
255
+ return this ;
256
+ }
257
+
258
+ /**
259
+ * Heading offset enable
260
+ *
261
+ * @param enabled Enable state
262
+ * @return self
263
+ */
264
+ public SwerveInputStream headingOffset (boolean enabled )
265
+ {
266
+ headingOffsetEnabled = enabled ? Optional .of (() -> enabled ) : Optional .empty ();
267
+ return this ;
268
+ }
269
+
270
+ /**
271
+ * Set the heading offset angle.
272
+ *
273
+ * @param angle {@link Rotation2d} offset to apply
274
+ * @return self
275
+ */
276
+ public SwerveInputStream headingOffset (Rotation2d angle )
277
+ {
278
+ headingOffset = Optional .of (angle );
279
+ return this ;
280
+ }
281
+
236
282
/**
237
283
* Modify the output {@link ChassisSpeeds} so that it is always relative to your alliance.
238
284
*
@@ -709,6 +755,24 @@ private Rotation2d applyAllianceAwareRotation(Rotation2d fieldRelativeRotation)
709
755
return fieldRelativeRotation ;
710
756
}
711
757
758
+ /**
759
+ * Adds offset to rotation if one is set.
760
+ *
761
+ * @param fieldRelativeRotation Field-relative {@link Rotation2d} to offset
762
+ * @return Offsetted {@link Rotation2d}
763
+ */
764
+ private Rotation2d applyHeadingOffset (Rotation2d fieldRelativeRotation )
765
+ {
766
+ if (headingOffsetEnabled .isPresent () && headingOffsetEnabled .get ().getAsBoolean ())
767
+ {
768
+ if (headingOffset .isPresent ())
769
+ {
770
+ return fieldRelativeRotation .rotateBy (headingOffset .get ());
771
+ }
772
+ }
773
+ return fieldRelativeRotation ;
774
+ }
775
+
712
776
/**
713
777
* Gets a {@link ChassisSpeeds}
714
778
*
@@ -759,12 +823,14 @@ public ChassisSpeeds get()
759
823
case HEADING ->
760
824
{
761
825
omegaRadiansPerSecond = swerveController .headingCalculate (swerveDrive .getOdometryHeading ().getRadians (),
762
- applyAllianceAwareRotation (Rotation2d .fromRadians (
763
- swerveController .getJoystickAngle (
764
- controllerHeadingX .get ()
765
- .getAsDouble (),
766
- controllerHeadingY .get ()
767
- .getAsDouble ()))).getRadians ());
826
+ applyHeadingOffset (
827
+ applyAllianceAwareRotation (
828
+ Rotation2d .fromRadians (
829
+ swerveController .getJoystickAngle (
830
+ controllerHeadingX .get ()
831
+ .getAsDouble (),
832
+ controllerHeadingY .get ()
833
+ .getAsDouble ())))).getRadians ());
768
834
speeds = new ChassisSpeeds (vxMetersPerSecond , vyMetersPerSecond , omegaRadiansPerSecond );
769
835
break ;
770
836
}
0 commit comments