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