001/**
002 * Copyright 2024 The Space Cookies : Girl Scout Troop #62868 and FRC Team #1868
003 * Open Source Software; you may modify and/or share it under the terms of
004 * the 3-Clause BSD License found in the root directory of this project.
005 */
006
007package tagalong.commands.base;
008
009import java.util.function.BooleanSupplier;
010import java.util.function.DoubleSupplier;
011import tagalong.commands.TagalongCommand;
012import tagalong.subsystems.TagalongSubsystemBase;
013import tagalong.subsystems.micro.Pivot;
014import tagalong.subsystems.micro.augments.PivotAugment;
015
016/**
017 * Command that continuously moves the pivot to the goal supplier's target position
018 */
019public class PivotToDynamicCmd<T extends TagalongSubsystemBase & PivotAugment>
020    extends TagalongCommand {
021  /**
022   * Pivot microsystem
023   */
024  private final Pivot _pivot;
025  /**
026   * Supplier for the goal position in rotations
027   */
028  private final DoubleSupplier _goalSupplierRot;
029  /**
030   * The condition for starting the command
031   */
032  private final BooleanSupplier _startCondition;
033  /**
034   * Whether or not the pivot should maintain its position after reaching the target
035   */
036  private boolean _holdPositionAfter;
037  /**
038   * The maximum velocity of the pivot in rotations per second
039   */
040  private double _maxVelocityRPS;
041  /**
042   * Whether or not the pivot has started moving
043   */
044  private boolean _startedMovement;
045  /**
046   * The goal position in rotations
047   */
048  private double _goalPositionRot;
049
050  @Override
051  public void initialize() {
052    _pivot.setHoldPosition(false);
053    _startedMovement = false;
054  }
055
056  @Override
057  public void execute() {
058    // if pivot has not started moving, check for legal states
059    _goalPositionRot = _pivot.clampPivotPosition(_goalSupplierRot.getAsDouble());
060    if (_startedMovement) {
061      _pivot.setPivotProfile(_goalPositionRot, 0.0, _maxVelocityRPS);
062      _pivot.followLastProfile();
063    } else if (_startCondition.getAsBoolean()) {
064      _startedMovement = true;
065      _pivot.setPivotProfile(_goalPositionRot, 0.0, _maxVelocityRPS);
066      _pivot.followLastProfile();
067    }
068  }
069
070  @Override
071  public void end(boolean interrupted) {
072    _pivot.setHoldPosition(_holdPositionAfter);
073  }
074
075  @Override
076  public boolean isFinished() {
077    return false;
078  }
079
080  /**
081   * Continuously move to the double suppliers target position. The function is
082   * continuous, it has no end condition, so the user must interrupt the command
083   * or decorate the command with an end condition. Useful for dynamic movements
084   * that are dependent on sensor readings, field conditions, or driver
085   * configurations.
086   *
087   * @param id                Integer ID of the pivot microsystem inside the
088   *                          Tagalong Subsystem
089   * @param pivot             Tagalong Subsystem containing an pivot
090   *                          microsystem
091   * @param goalSupplierRot   DoubleSupplier for the pivot rotation
092   * @param holdPositionAfter If the pivot should hold position when the
093   *                          command completes
094   * @param maxVelocityRPS    Maximum velocity for the pivot during this command
095   * @param startSupplier     BooleanSupplier condition for movement to start,
096   *                          defaults to pivot::isSafeToMove
097   */
098  public PivotToDynamicCmd(
099      int id,
100      T pivot,
101      DoubleSupplier goalSupplierRot,
102      boolean holdPositionAfter,
103      double maxVelocityRPS,
104      BooleanSupplier startSupplier
105  ) {
106    _pivot = pivot.getPivot(id);
107    _goalSupplierRot = goalSupplierRot;
108    _holdPositionAfter = holdPositionAfter;
109    _maxVelocityRPS = maxVelocityRPS;
110    _startCondition = startSupplier;
111
112    addRequirements(pivot);
113  }
114
115  /**
116   * Continuously move to the double suppliers target position. The function is
117   * continuous, it has no end condition, so the user must interrupt the command
118   * or decorate the command with an end condition. Useful for dynamic movements
119   * that are dependent on sensor readings, field conditions, or driver
120   * configurations.
121   *
122   * @param pivot             Tagalong Subsystem containing an pivot
123   *                          microsystem
124   * @param goalSupplierRot   DoubleSupplier for the pivot rotation
125   * @param holdPositionAfter If the pivot should hold position when the
126   *                          command completes
127   * @param maxVelocityRPS    Maximum velocity for the pivot during this command
128   * @param startSupplier     BooleanSupplier condition for movement to start,
129   *                          defaults to pivot::isSafeToMove
130   */
131  public PivotToDynamicCmd(
132      T pivot,
133      DoubleSupplier goalSupplierRot,
134      boolean holdPositionAfter,
135      double maxVelocityRPS,
136      BooleanSupplier startSupplier
137  ) {
138    _pivot = pivot.getPivot();
139    _goalSupplierRot = goalSupplierRot;
140    _holdPositionAfter = holdPositionAfter;
141    _maxVelocityRPS = maxVelocityRPS;
142    _startCondition = startSupplier;
143
144    addRequirements(pivot);
145  }
146
147  /**
148   * Continuously move to the double suppliers target position. The function is
149   * continuous, it has no end condition, so the user must interrupt the command
150   * or decorate the command with an end condition. Useful for dynamic movements
151   * that are dependent on sensor readings, field conditions, or driver
152   * configurations.
153   *
154   * @param id                Integer ID of the pivot microsystem inside the
155   *                          Tagalong Subsystem
156   * @param pivot             Tagalong Subsystem containing an pivot
157   *                          microsystem
158   * @param goalSupplierRot   DoubleSupplier for the pivot rotation
159   * @param holdPositionAfter If the pivot should hold position when the
160   *                          command completes
161   * @param maxVelocityRPS    Maximum velocity for the pivot during this command
162   */
163  public PivotToDynamicCmd(
164      int id,
165      T pivot,
166      DoubleSupplier goalSupplierRot,
167      boolean holdPositionAfter,
168      double maxVelocityRPS
169  ) {
170    this(
171        id,
172        pivot,
173        goalSupplierRot,
174        holdPositionAfter,
175        maxVelocityRPS,
176        pivot.getPivot(id)::isSafeToMove
177    );
178  }
179
180  /**
181   * Continuously move to the double suppliers target position. The function is
182   * continuous, it has no end condition, so the user must interrupt the command
183   * or decorate the command with an end condition. Useful for dynamic movements
184   * that are dependent on sensor readings, field conditions, or driver
185   * configurations.
186   *
187   * @param pivot             Tagalong Subsystem containing an pivot
188   *                          microsystem
189   * @param goalSupplierRot   DoubleSupplier for the pivot rotation
190   * @param holdPositionAfter If the pivot should hold position when the
191   *                          command completes
192   * @param maxVelocityRPS    Maximum velocity for the pivot during this command
193   */
194  public PivotToDynamicCmd(
195      T pivot, DoubleSupplier goalSupplierRot, boolean holdPositionAfter, double maxVelocityRPS
196  ) {
197    this(pivot, goalSupplierRot, holdPositionAfter, maxVelocityRPS, pivot.getPivot()::isSafeToMove);
198  }
199
200  /**
201   * Continuously move to the double suppliers target position. The function is
202   * continuous, it has no end condition, so the user must interrupt the command
203   * or decorate the command with an end condition. Useful for dynamic movements
204   * that are dependent on sensor readings, field conditions, or driver
205   * configurations.
206   *
207   * @param id                Integer ID of the pivot microsystem inside the
208   *                          Tagalong Subsystem
209   * @param pivot             Tagalong Subsystem containing an pivot
210   *                          microsystem
211   * @param goalSupplierRot   DoubleSupplier for the pivot rotation
212   * @param holdPositionAfter If the pivot should hold position when the
213   *                          command completes
214   */
215  public PivotToDynamicCmd(
216      int id, T pivot, DoubleSupplier goalSupplierRot, boolean holdPositionAfter
217  ) {
218    this(id, pivot, goalSupplierRot, holdPositionAfter, pivot.getPivot(id)._maxVelocityRPS);
219  }
220
221  /**
222   * Continuously move to the double suppliers target position. The function is
223   * continuous, it has no end condition, so the user must interrupt the command
224   * or decorate the command with an end condition. Useful for dynamic movements
225   * that are dependent on sensor readings, field conditions, or driver
226   * configurations.
227   *
228   * @param pivot             Tagalong Subsystem containing an pivot
229   *                          microsystem
230   * @param goalSupplierRot   DoubleSupplier for the pivot rotation
231   * @param holdPositionAfter If the pivot should hold position when the
232   *                          command completes
233   *                          command
234   */
235  public PivotToDynamicCmd(T pivot, DoubleSupplier goalSupplierRot, boolean holdPositionAfter) {
236    this(pivot, goalSupplierRot, holdPositionAfter, pivot.getPivot()._maxVelocityRPS);
237  }
238
239  /**
240   * Continuously move to the double suppliers target position. The function is
241   * continuous, it has no end condition, so the user must interrupt the command
242   * or decorate the command with an end condition. Useful for dynamic movements
243   * that are dependent on sensor readings, field conditions, or driver
244   * configurations.
245   *
246   * @param id              Integer ID of the pivot microsystem inside the
247   *                        Tagalong Subsystem
248   * @param pivot           Tagalong Subsystem containing an pivot microsystem
249   * @param goalSupplierRot DoubleSupplier for the pivot rotation
250   */
251  public PivotToDynamicCmd(int id, T pivot, DoubleSupplier goalSupplierRot) {
252    this(id, pivot, goalSupplierRot, true);
253  }
254
255  /**
256   * Continuously move to the double suppliers target position. The function is
257   * continuous, it has no end condition, so the user must interrupt the command
258   * or decorate the command with an end condition. Useful for dynamic movements
259   * that are dependent on sensor readings, field conditions, or driver
260   * configurations.
261   *
262   * @param pivot           Tagalong Subsystem containing an pivot microsystem
263   * @param goalSupplierRot DoubleSupplier for the pivot rotation
264   */
265  public PivotToDynamicCmd(T pivot, DoubleSupplier goalSupplierRot) {
266    this(pivot, goalSupplierRot, true);
267  }
268}