001/* 002 * Copyright (c) 2021 REV Robotics 003 * 004 * Redistribution and use in source and binary forms, with or without 005 * modification, are permitted provided that the following conditions are met: 006 * 007 * 1. Redistributions of source code must retain the above copyright notice, 008 * this list of conditions and the following disclaimer. 009 * 2. Redistributions in binary form must reproduce the above copyright 010 * notice, this list of conditions and the following disclaimer in the 011 * documentation and/or other materials provided with the distribution. 012 * 3. Neither the name of REV Robotics nor the names of its 013 * contributors may be used to endorse or promote products derived from 014 * this software without specific prior written permission. 015 * 016 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 017 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 018 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 019 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 020 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 021 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 022 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 023 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 024 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 025 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 026 * POSSIBILITY OF SUCH DAMAGE. 027 */ 028 029package com.revrobotics; 030 031import com.revrobotics.jni.CANSparkMaxJNI; 032 033/** Get an instance of this class by using {@link CANSparkMax#getPIDController()}. */ 034public class SparkMaxPIDController implements CANPIDController { 035 private final CANSparkMax sparkMax; 036 037 public enum AccelStrategy { 038 kTrapezoidal(0), 039 kSCurve(1); 040 041 @SuppressWarnings("MemberName") 042 public final int value; 043 044 AccelStrategy(int value) { 045 this.value = value; 046 } 047 048 public static AccelStrategy fromInt(int value) { 049 switch (value) { 050 case 0: 051 return kTrapezoidal; 052 case 1: 053 return kSCurve; 054 default: 055 return kTrapezoidal; 056 } 057 } 058 } 059 060 public enum ArbFFUnits { 061 kVoltage(0), 062 kPercentOut(1); 063 064 @SuppressWarnings("MemberName") 065 public final int value; 066 067 ArbFFUnits(int value) { 068 this.value = value; 069 } 070 } 071 072 // package-private (can only be used by other classes in this package) 073 SparkMaxPIDController(CANSparkMax device) { 074 sparkMax = device; 075 } 076 077 /** 078 * Set the controller reference value based on the selected control mode. 079 * 080 * @param value The value to set depending on the control mode. For basic duty cycle control this 081 * should be a value between -1 and 1 Otherwise: Voltage Control: Voltage (volts) Velocity 082 * Control: Velocity (RPM) Position Control: Position (Rotations) Current Control: Current 083 * (Amps). Native units can be changed using the setPositionConversionFactor() or 084 * setVelocityConversionFactor() methods of the CANEncoder class 085 * @param ctrl the control type 086 * @return {@link REVLibError#kOk} if successful 087 */ 088 public REVLibError setReference(double value, CANSparkMax.ControlType ctrl) { 089 sparkMax.throwIfClosed(); 090 return setReference(value, ctrl, 0); 091 } 092 093 /** 094 * Set the controller reference value based on the selected control mode. 095 * 096 * @param value The value to set depending on the control mode. For basic duty cycle control this 097 * should be a value between -1 and 1 Otherwise: Voltage Control: Voltage (volts) Velocity 098 * Control: Velocity (RPM) Position Control: Position (Rotations) Current Control: Current 099 * (Amps). Native units can be changed using the setPositionConversionFactor() or 100 * setVelocityConversionFactor() methods of the CANEncoder class 101 * @param ctrl the control type 102 * @return {@link REVLibError#kOk} if successful 103 * @deprecated Use {@link #setReference(double, CANSparkMax.ControlType)} instead. 104 */ 105 @Deprecated(forRemoval = true) 106 @SuppressWarnings("removal") 107 public REVLibError setReference(double value, ControlType ctrl) { 108 sparkMax.throwIfClosed(); 109 return setReference(value, ctrl, 0); 110 } 111 112 /** 113 * Set the controller reference value based on the selected control mode. This will override the 114 * pre-programmed control mode but not change what is programmed to the controller. 115 * 116 * @param value The value to set depending on the control mode. For basic duty cycle control this 117 * should be a value between -1 and 1 Otherwise: Voltage Control: Voltage (volts) Velocity 118 * Control: Velocity (RPM) Position Control: Position (Rotations) Current Control: Current 119 * (Amps). Native units can be changed using the setPositionConversionFactor() or 120 * setVelocityConversionFactor() methods of the CANEncoder class 121 * @param ctrl Is the control type to override with 122 * @param pidSlot for this command 123 * @return {@link REVLibError#kOk} if successful 124 */ 125 public REVLibError setReference(double value, CANSparkMax.ControlType ctrl, int pidSlot) { 126 sparkMax.throwIfClosed(); 127 return setReference(value, ctrl, pidSlot, 0); 128 } 129 130 /** 131 * Set the controller reference value based on the selected control mode. This will override the 132 * pre-programmed control mode but not change what is programmed to the controller. 133 * 134 * @param value The value to set depending on the control mode. For basic duty cycle control this 135 * should be a value between -1 and 1 Otherwise: Voltage Control: Voltage (volts) Velocity 136 * Control: Velocity (RPM) Position Control: Position (Rotations) Current Control: Current 137 * (Amps). Native units can be changed using the setPositionConversionFactor() or 138 * setVelocityConversionFactor() methods of the CANEncoder class 139 * @param ctrl Is the control type to override with 140 * @param pidSlot for this command 141 * @return {@link REVLibError#kOk} if successful 142 * @deprecated Use {@link #setReference(double, CANSparkMax.ControlType, int)} instead. 143 */ 144 @Deprecated(forRemoval = true) 145 @SuppressWarnings("removal") 146 public REVLibError setReference(double value, ControlType ctrl, int pidSlot) { 147 sparkMax.throwIfClosed(); 148 return setReference(value, ctrl, pidSlot, 0); 149 } 150 151 /** 152 * Set the controller reference value based on the selected control mode. This will override the 153 * pre-programmed control mode but not change what is programmed to the controller. 154 * 155 * @param value The value to set depending on the control mode. For basic duty cycle control this 156 * should be a value between -1 and 1 Otherwise: Voltage Control: Voltage (volts) Velocity 157 * Control: Velocity (RPM) Position Control: Position (Rotations) Current Control: Current 158 * (Amps). Native units can be changed using the setPositionConversionFactor() or 159 * setVelocityConversionFactor() methods of the CANEncoder class 160 * @param ctrl Is the control type to override with 161 * @param pidSlot for this command 162 * @param arbFeedforward A value from which is represented in voltage applied to the motor after 163 * the result of the specified control mode. The units for the parameter is Volts. This value 164 * is set after the control mode, but before any current limits or ramp rates. 165 * @return {@link REVLibError#kOk} if successful 166 */ 167 public REVLibError setReference( 168 double value, CANSparkMax.ControlType ctrl, int pidSlot, double arbFeedforward) { 169 sparkMax.throwIfClosed(); 170 return sparkMax.setpointCommand(value, ctrl, pidSlot, arbFeedforward); 171 } 172 173 /** 174 * Set the controller reference value based on the selected control mode. This will override the 175 * pre-programmed control mode but not change what is programmed to the controller. 176 * 177 * @param value The value to set depending on the control mode. For basic duty cycle control this 178 * should be a value between -1 and 1 Otherwise: Voltage Control: Voltage (volts) Velocity 179 * Control: Velocity (RPM) Position Control: Position (Rotations) Current Control: Current 180 * (Amps). Native units can be changed using the setPositionConversionFactor() or 181 * setVelocityConversionFactor() methods of the CANEncoder class 182 * @param ctrl Is the control type to override with 183 * @param pidSlot for this command 184 * @param arbFeedforward A value from which is represented in voltage applied to the motor after 185 * the result of the specified control mode. The units for the parameter is Volts. This value 186 * is set after the control mode, but before any current limits or ramp rates. 187 * @return {@link REVLibError#kOk} if successful 188 * @deprecated Use {@link #setReference(double, CANSparkMax.ControlType, int, double)} instead. 189 */ 190 @Deprecated(forRemoval = true) 191 @SuppressWarnings("removal") 192 public REVLibError setReference( 193 double value, ControlType ctrl, int pidSlot, double arbFeedforward) { 194 sparkMax.throwIfClosed(); 195 return sparkMax.setpointCommand(value, ctrl, pidSlot, arbFeedforward); 196 } 197 198 /** 199 * Set the controller reference value based on the selected control mode. This will override the 200 * pre-programmed control mode but not change what is programmed to the controller. 201 * 202 * @param value The value to set depending on the control mode. For basic duty cycle control this 203 * should be a value between -1 and 1 Otherwise: Voltage Control: Voltage (volts) Velocity 204 * Control: Velocity (RPM) Position Control: Position (Rotations) Current Control: Current 205 * (Amps). Native units can be changed using the setPositionConversionFactor() or 206 * setVelocityConversionFactor() methods of the CANEncoder class 207 * @param ctrl Is the control type to override with 208 * @param pidSlot for this command 209 * @param arbFeedforward A value from which is represented in voltage applied to the motor after 210 * the result of the specified control mode. The units for the parameter is Volts. This value 211 * is set after the control mode, but before any current limits or ramp rates. 212 * @param arbFFUnits The units the arbitrary feed forward term is in 213 * @return {@link REVLibError#kOk} if successful 214 */ 215 public REVLibError setReference( 216 double value, 217 CANSparkMax.ControlType ctrl, 218 int pidSlot, 219 double arbFeedforward, 220 ArbFFUnits arbFFUnits) { 221 sparkMax.throwIfClosed(); 222 return sparkMax.setpointCommand(value, ctrl, pidSlot, arbFeedforward, arbFFUnits.value); 223 } 224 225 /** 226 * Set the controller reference value based on the selected control mode. This will override the 227 * pre-programmed control mode but not change what is programmed to the controller. 228 * 229 * @param value The value to set depending on the control mode. For basic duty cycle control this 230 * should be a value between -1 and 1 Otherwise: Voltage Control: Voltage (volts) Velocity 231 * Control: Velocity (RPM) Position Control: Position (Rotations) Current Control: Current 232 * (Amps). Native units can be changed using the setPositionConversionFactor() or 233 * setVelocityConversionFactor() methods of the CANEncoder class 234 * @param ctrl Is the control type to override with 235 * @param pidSlot for this command 236 * @param arbFeedforward A value from which is represented in voltage applied to the motor after 237 * the result of the specified control mode. The units for the parameter is Volts. This value 238 * is set after the control mode, but before any current limits or ramp rates. 239 * @param arbFFUnits The units the arbitrary feed forward term is in 240 * @return {@link REVLibError#kOk} if successful 241 * @deprecated Use {@link #setReference(double, CANSparkMax.ControlType, int, double, 242 * SparkMaxPIDController.ArbFFUnits)} instead. 243 */ 244 @SuppressWarnings("removal") 245 @Deprecated(forRemoval = true) 246 public REVLibError setReference( 247 double value, 248 ControlType ctrl, 249 int pidSlot, 250 double arbFeedforward, 251 CANPIDController.ArbFFUnits arbFFUnits) { 252 sparkMax.throwIfClosed(); 253 return sparkMax.setpointCommand(value, ctrl, pidSlot, arbFeedforward, arbFFUnits.value); 254 } 255 256 /** 257 * Set the Proportional Gain constant of the PIDF controller on the SPARK MAX. This uses the Set 258 * Parameter API and should be used infrequently. The parameter does not presist unless 259 * burnFlash() is called. The recommended method to configure this parameter is use to SPARK MAX 260 * GUI to tune and save parameters. 261 * 262 * @param gain The proportional gain value, must be positive 263 * @return {@link REVLibError#kOk} if successful 264 */ 265 public REVLibError setP(double gain) { 266 sparkMax.throwIfClosed(); 267 return setP(gain, 0); 268 } 269 270 /** 271 * Set the Proportional Gain constant of the PIDF controller on the SPARK MAX. This uses the Set 272 * Parameter API and should be used infrequently. The parameter does not presist unless 273 * burnFlash() is called. The recommended method to configure this parameter is use to SPARK MAX 274 * GUI to tune and save parameters. 275 * 276 * @param gain The proportional gain value, must be positive 277 * @param slotID Is the gain schedule slot, the value is a number between 0 and 3. Each slot has 278 * its own set of gain values and can be changed in each control frame using SetReference(). 279 * @return {@link REVLibError#kOk} if successful 280 */ 281 public REVLibError setP(double gain, int slotID) { 282 sparkMax.throwIfClosed(); 283 return REVLibError.fromInt( 284 CANSparkMaxJNI.c_SparkMax_SetP(sparkMax.sparkMaxHandle, slotID, (float) gain)); 285 } 286 287 /** 288 * Set the Integral Gain constant of the PIDF controller on the SPARK MAX. This uses the Set 289 * Parameter API and should be used infrequently. The parameter does not presist unless 290 * burnFlash() is called. The recommended method to configure this parameter is use to SPARK MAX 291 * GUI to tune and save parameters. 292 * 293 * @param gain The integral gain value, must be positive 294 * @return {@link REVLibError#kOk} if successful 295 */ 296 public REVLibError setI(double gain) { 297 sparkMax.throwIfClosed(); 298 return setI(gain, 0); 299 } 300 301 /** 302 * Set the Integral Gain constant of the PIDF controller on the SPARK MAX. This uses the Set 303 * Parameter API and should be used infrequently. The parameter does not presist unless 304 * burnFlash() is called. The recommended method to configure this parameter is use to SPARK MAX 305 * GUI to tune and save parameters. 306 * 307 * @param gain The integral gain value, must be positive 308 * @param slotID Is the gain schedule slot, the value is a number between 0 and 3. Each slot has 309 * its own set of gain values and can be changed in each control frame using SetReference(). 310 * @return {@link REVLibError#kOk} if successful 311 */ 312 public REVLibError setI(double gain, int slotID) { 313 sparkMax.throwIfClosed(); 314 return REVLibError.fromInt( 315 CANSparkMaxJNI.c_SparkMax_SetI(sparkMax.sparkMaxHandle, slotID, (float) gain)); 316 } 317 318 /** 319 * Set the Derivative Gain constant of the PIDF controller on the SPARK MAX. This uses the Set 320 * Parameter API and should be used infrequently. The parameter does not presist unless 321 * burnFlash() is called. The recommended method to configure this parameter is use to SPARK MAX 322 * GUI to tune and save parameters. 323 * 324 * @param gain The derivative gain value, must be positive 325 * @return {@link REVLibError#kOk} if successful 326 */ 327 public REVLibError setD(double gain) { 328 sparkMax.throwIfClosed(); 329 return setD(gain, 0); 330 } 331 332 /** 333 * Set the Derivative Gain constant of the PIDF controller on the SPARK MAX. This uses the Set 334 * Parameter API and should be used infrequently. The parameter does not presist unless 335 * burnFlash() is called. The recommended method to configure this parameter is use to SPARK MAX 336 * GUI to tune and save parameters. 337 * 338 * @param gain The derivative gain value, must be positive 339 * @param slotID Is the gain schedule slot, the value is a number between 0 and 3. Each slot has 340 * its own set of gain values and can be changed in each control frame using SetReference(). 341 * @return {@link REVLibError#kOk} if successful 342 */ 343 public REVLibError setD(double gain, int slotID) { 344 sparkMax.throwIfClosed(); 345 return REVLibError.fromInt( 346 CANSparkMaxJNI.c_SparkMax_SetD(sparkMax.sparkMaxHandle, slotID, (float) gain)); 347 } 348 349 /** 350 * Set the Derivative Filter constant of the PIDF controller on the SPARK MAX. This uses the Set 351 * Parameter API and should be used infrequently. The parameter does not presist unless 352 * burnFlash() is called. 353 * 354 * @param gain The derivative filter value, must be a positive number between 0 and 1 355 * @return {@link REVLibError#kOk} if successful 356 */ 357 public REVLibError setDFilter(double gain) { 358 sparkMax.throwIfClosed(); 359 return setDFilter(gain, 0); 360 } 361 362 /** 363 * Set the Derivative Filter constant of the PIDF controller on the SPARK MAX. This uses the Set 364 * Parameter API and should be used infrequently. The parameter does not presist unless 365 * burnFlash() is called. 366 * 367 * @param gain The derivative filter value, must be a positive number between 0 and 1 368 * @param slotID Is the gain schedule slot, the value is a number between 0 and 3. Each slot has 369 * its own set of gain values and can be changed in each control frame using SetReference(). 370 * @return {@link REVLibError#kOk} if successful 371 */ 372 public REVLibError setDFilter(double gain, int slotID) { 373 sparkMax.throwIfClosed(); 374 return REVLibError.fromInt( 375 CANSparkMaxJNI.c_SparkMax_SetDFilter(sparkMax.sparkMaxHandle, slotID, (float) gain)); 376 } 377 378 /** 379 * Set the Feed-froward Gain constant of the PIDF controller on the SPARK MAX. This uses the Set 380 * Parameter API and should be used infrequently. The parameter does not presist unless 381 * burnFlash() is called. The recommended method to configure this parameter is use to SPARK MAX 382 * GUI to tune and save parameters. 383 * 384 * @param gain The feed-forward gain value 385 * @return {@link REVLibError#kOk} if successful 386 */ 387 public REVLibError setFF(double gain) { 388 sparkMax.throwIfClosed(); 389 return setFF(gain, 0); 390 } 391 392 /** 393 * Set the Feed-froward Gain constant of the PIDF controller on the SPARK MAX. This uses the Set 394 * Parameter API and should be used infrequently. The parameter does not presist unless 395 * burnFlash() is called. The recommended method to configure this parameter is use to SPARK MAX 396 * GUI to tune and save parameters. 397 * 398 * @param gain The feed-forward gain value 399 * @param slotID Is the gain schedule slot, the value is a number between 0 and 3. Each slot has 400 * its own set of gain values and can be changed in each control frame using SetReference(). 401 * @return {@link REVLibError#kOk} if successful 402 */ 403 public REVLibError setFF(double gain, int slotID) { 404 sparkMax.throwIfClosed(); 405 return REVLibError.fromInt( 406 CANSparkMaxJNI.c_SparkMax_SetFF(sparkMax.sparkMaxHandle, slotID, (float) gain)); 407 } 408 409 /** 410 * Set the IZone range of the PIDF controller on the SPARK MAX. This value specifies the range the 411 * |error| must be within for the integral constant to take effect. 412 * 413 * <p>This uses the Set Parameter API and should be used infrequently. The parameter does not 414 * presist unless burnFlash() is called. The recommended method to configure this parameter is to 415 * use the SPARK MAX GUI to tune and save parameters. 416 * 417 * @param IZone The IZone value, must be positive. Set to 0 to disable 418 * @return {@link REVLibError#kOk} if successful 419 */ 420 public REVLibError setIZone(double IZone) { 421 sparkMax.throwIfClosed(); 422 return setIZone(IZone, 0); 423 } 424 425 /** 426 * Set the IZone range of the PIDF controller on the SPARK MAX. This value specifies the range the 427 * |error| must be within for the integral constant to take effect. 428 * 429 * <p>This uses the Set Parameter API and should be used infrequently. The parameter does not 430 * presist unless burnFlash() is called. The recommended method to configure this parameter is to 431 * use the SPARK MAX GUI to tune and save parameters. 432 * 433 * @param IZone The IZone value, must be positive. Set to 0 to disable 434 * @param slotID Is the gain schedule slot, the value is a number between 0 and 3. Each slot has 435 * its own set of gain values and can be changed in each control frame using SetReference(). 436 * @return {@link REVLibError#kOk} if successful 437 */ 438 public REVLibError setIZone(double IZone, int slotID) { 439 sparkMax.throwIfClosed(); 440 return REVLibError.fromInt( 441 CANSparkMaxJNI.c_SparkMax_SetIZone(sparkMax.sparkMaxHandle, slotID, (float) IZone)); 442 } 443 444 /** 445 * Set the min amd max output for the closed loop mode. 446 * 447 * <p>This uses the Set Parameter API and should be used infrequently. The parameter does not 448 * presist unless burnFlash() is called. The recommended method to configure this parameter is to 449 * use the SPARK MAX GUI to tune and save parameters. 450 * 451 * @param min Reverse power minimum to allow the controller to output 452 * @param max Forward power maximum to allow the controller to output 453 * @return {@link REVLibError#kOk} if successful 454 */ 455 public REVLibError setOutputRange(double min, double max) { 456 sparkMax.throwIfClosed(); 457 return setOutputRange(min, max, 0); 458 } 459 460 /** 461 * Set the min amd max output for the closed loop mode. 462 * 463 * <p>This uses the Set Parameter API and should be used infrequently. The parameter does not 464 * presist unless burnFlash() is called. The recommended method to configure this parameter is to 465 * use the SPARK MAX GUI to tune and save parameters. 466 * 467 * @param min Reverse power minimum to allow the controller to output 468 * @param max Forward power maximum to allow the controller to output 469 * @param slotID Is the gain schedule slot, the value is a number between 0 and 3. Each slot has 470 * its own set of gain values and can be changed in each control frame using SetReference(). 471 * @return {@link REVLibError#kOk} if successful 472 */ 473 public REVLibError setOutputRange(double min, double max, int slotID) { 474 sparkMax.throwIfClosed(); 475 return REVLibError.fromInt( 476 CANSparkMaxJNI.c_SparkMax_SetOutputRange( 477 sparkMax.sparkMaxHandle, slotID, (float) min, (float) max)); 478 } 479 480 /** 481 * Get the Proportional Gain constant of the PIDF controller on the SPARK MAX. 482 * 483 * <p>This uses the Get Parameter API and should be used infrequently. This function uses a 484 * non-blocking call and will return a cached value if the parameter is not returned by the 485 * timeout. The timeout can be changed by calling SetCANTimeout(int milliseconds) 486 * 487 * @return double P Gain value 488 */ 489 public double getP() { 490 sparkMax.throwIfClosed(); 491 return getP(0); 492 } 493 494 /** 495 * Get the Proportional Gain constant of the PIDF controller on the SPARK MAX. 496 * 497 * <p>This uses the Get Parameter API and should be used infrequently. This function uses a 498 * non-blocking call and will return a cached value if the parameter is not returned by the 499 * timeout. The timeout can be changed by calling SetCANTimeout(int milliseconds) 500 * 501 * @param slotID Is the gain schedule slot, the value is a number between 0 and 3. Each slot has 502 * its own set of gain values and can be changed in each control frame using SetReference(). 503 * @return double P Gain value 504 */ 505 public double getP(int slotID) { 506 sparkMax.throwIfClosed(); 507 return CANSparkMaxJNI.c_SparkMax_GetP(sparkMax.sparkMaxHandle, slotID); 508 } 509 510 /** 511 * Get the Integral Gain constant of the PIDF controller on the SPARK MAX. 512 * 513 * <p>This uses the Get Parameter API and should be used infrequently. This function uses a 514 * non-blocking call and will return a cached value if the parameter is not returned by the 515 * timeout. The timeout can be changed by calling SetCANTimeout(int milliseconds) 516 * 517 * @return double I Gain value 518 */ 519 public double getI() { 520 sparkMax.throwIfClosed(); 521 return getI(0); 522 } 523 524 /** 525 * Get the Integral Gain constant of the PIDF controller on the SPARK MAX. 526 * 527 * <p>This uses the Get Parameter API and should be used infrequently. This function uses a 528 * non-blocking call and will return a cached value if the parameter is not returned by the 529 * timeout. The timeout can be changed by calling SetCANTimeout(int milliseconds) 530 * 531 * @param slotID Is the gain schedule slot, the value is a number between 0 and 3. Each slot has 532 * its own set of gain values and can be changed in each control frame using SetReference(). 533 * @return double I Gain value 534 */ 535 public double getI(int slotID) { 536 sparkMax.throwIfClosed(); 537 return CANSparkMaxJNI.c_SparkMax_GetI(sparkMax.sparkMaxHandle, slotID); 538 } 539 540 /** 541 * Get the Derivative Gain constant of the PIDF controller on the SPARK MAX. 542 * 543 * <p>This uses the Get Parameter API and should be used infrequently. This function uses a 544 * non-blocking call and will return a cached value if the parameter is not returned by the 545 * timeout. The timeout can be changed by calling SetCANTimeout(int milliseconds) 546 * 547 * @return double D Gain value 548 */ 549 public double getD() { 550 sparkMax.throwIfClosed(); 551 return getD(0); 552 } 553 554 /** 555 * Get the Derivative Gain constant of the PIDF controller on the SPARK MAX. 556 * 557 * <p>This uses the Get Parameter API and should be used infrequently. This function uses a 558 * non-blocking call and will return a cached value if the parameter is not returned by the 559 * timeout. The timeout can be changed by calling SetCANTimeout(int milliseconds) 560 * 561 * @param slotID Is the gain schedule slot, the value is a number between 0 and 3. Each slot has 562 * its own set of gain values and can be changed in each control frame using SetReference(). 563 * @return double D Gain value 564 */ 565 public double getD(int slotID) { 566 sparkMax.throwIfClosed(); 567 return CANSparkMaxJNI.c_SparkMax_GetD(sparkMax.sparkMaxHandle, slotID); 568 } 569 570 /** 571 * Get the Derivative Filter constant of the PIDF controller on the SPARK MAX. 572 * 573 * <p>This uses the Get Parameter API and should be used infrequently. This function uses a 574 * non-blocking call and will return a cached value if the parameter is not returned by the 575 * timeout. The timeout can be changed by calling SetCANTimeout(int milliseconds) 576 * 577 * @param slotID Is the gain schedule slot, the value is a number between 0 and 3. Each slot has 578 * its own set of gain values and can be changed in each control frame using SetReference(). 579 * @return double D Filter value 580 */ 581 public double getDFilter(int slotID) { 582 sparkMax.throwIfClosed(); 583 return CANSparkMaxJNI.c_SparkMax_GetDFilter(sparkMax.sparkMaxHandle, slotID); 584 } 585 586 /** 587 * Get the Feed-forward Gain constant of the PIDF controller on the SPARK MAX. 588 * 589 * <p>This uses the Get Parameter API and should be used infrequently. This function uses a 590 * non-blocking call and will return a cached value if the parameter is not returned by the 591 * timeout. The timeout can be changed by calling SetCANTimeout(int milliseconds) 592 * 593 * @return double F Gain value 594 */ 595 public double getFF() { 596 sparkMax.throwIfClosed(); 597 return getFF(0); 598 } 599 600 /** 601 * Get the Feed-forward Gain constant of the PIDF controller on the SPARK MAX. 602 * 603 * <p>This uses the Get Parameter API and should be used infrequently. This function uses a 604 * non-blocking call and will return a cached value if the parameter is not returned by the 605 * timeout. The timeout can be changed by calling SetCANTimeout(int milliseconds) 606 * 607 * @param slotID Is the gain schedule slot, the value is a number between 0 and 3. Each slot has 608 * its own set of gain values and can be changed in each control frame using SetReference(). 609 * @return double F Gain value 610 */ 611 public double getFF(int slotID) { 612 sparkMax.throwIfClosed(); 613 return CANSparkMaxJNI.c_SparkMax_GetFF(sparkMax.sparkMaxHandle, slotID); 614 } 615 616 /** 617 * Get the IZone constant of the PIDF controller on the SPARK MAX. 618 * 619 * <p>This uses the Get Parameter API and should be used infrequently. This function uses a 620 * non-blocking call and will return a cached value if the parameter is not returned by the 621 * timeout. The timeout can be changed by calling SetCANTimeout(int milliseconds) 622 * 623 * @return double IZone value 624 */ 625 public double getIZone() { 626 sparkMax.throwIfClosed(); 627 return getIZone(0); 628 } 629 630 /** 631 * Get the IZone constant of the PIDF controller on the SPARK MAX. 632 * 633 * <p>This uses the Get Parameter API and should be used infrequently. This function uses a 634 * non-blocking call and will return a cached value if the parameter is not returned by the 635 * timeout. The timeout can be changed by calling SetCANTimeout(int milliseconds) 636 * 637 * @param slotID Is the gain schedule slot, the value is a number between 0 and 3. Each slot has 638 * its own set of gain values and can be changed in each control frame using SetReference(). 639 * @return double IZone value 640 */ 641 public double getIZone(int slotID) { 642 sparkMax.throwIfClosed(); 643 return CANSparkMaxJNI.c_SparkMax_GetIZone(sparkMax.sparkMaxHandle, slotID); 644 } 645 646 /** 647 * Get the derivative filter constant of the PIDF controller on the SPARK MAX. 648 * 649 * <p>This uses the Get Parameter API and should be used infrequently. This function uses a 650 * non-blocking call and will return a cached value if the parameter is not returned by the 651 * timeout. The timeout can be changed by calling SetCANTimeout(int milliseconds) 652 * 653 * @param slotID Is the gain schedule slot, the value is a number between 0 and 3. Each slot has 654 * its own set of gain values and can be changed in each control frame using SetReference(). 655 * @return double D Filter 656 */ 657 // public double getDFilter(int slotID = 0); 658 659 /** 660 * Get the min output of the PIDF controller on the SPARK MAX. 661 * 662 * <p>This uses the Get Parameter API and should be used infrequently. This function uses a 663 * non-blocking call and will return a cached value if the parameter is not returned by the 664 * timeout. The timeout can be changed by calling SetCANTimeout(int milliseconds) 665 * 666 * @return double min value 667 */ 668 public double getOutputMin() { 669 sparkMax.throwIfClosed(); 670 return getOutputMin(0); 671 } 672 673 /** 674 * Get the min output of the PIDF controller on the SPARK MAX. 675 * 676 * <p>This uses the Get Parameter API and should be used infrequently. This function uses a 677 * non-blocking call and will return a cached value if the parameter is not returned by the 678 * timeout. The timeout can be changed by calling SetCANTimeout(int milliseconds) 679 * 680 * @param slotID Is the gain schedule slot, the value is a number between 0 and 3. Each slot has 681 * its own set of gain values and can be changed in each control frame using SetReference(). 682 * @return double min value 683 */ 684 public double getOutputMin(int slotID) { 685 sparkMax.throwIfClosed(); 686 return CANSparkMaxJNI.c_SparkMax_GetOutputMin(sparkMax.sparkMaxHandle, slotID); 687 } 688 689 /** 690 * Get the max output of the PIDF controller on the SPARK MAX. 691 * 692 * <p>This uses the Get Parameter API and should be used infrequently. This function uses a 693 * non-blocking call and will return a cached value if the parameter is not returned by the 694 * timeout. The timeout can be changed by calling SetCANTimeout(int milliseconds) 695 * 696 * @return double max value 697 */ 698 public double getOutputMax() { 699 sparkMax.throwIfClosed(); 700 return getOutputMax(0); 701 } 702 703 /** 704 * Get the max output of the PIDF controller on the SPARK MAX. 705 * 706 * <p>This uses the Get Parameter API and should be used infrequently. This function uses a 707 * non-blocking call and will return a cached value if the parameter is not returned by the 708 * timeout. The timeout can be changed by calling SetCANTimeout(int milliseconds) 709 * 710 * @param slotID Is the gain schedule slot, the value is a number between 0 and 3. Each slot has 711 * its own set of gain values and can be changed in each control frame using SetReference(). 712 * @return double max value 713 */ 714 public double getOutputMax(int slotID) { 715 sparkMax.throwIfClosed(); 716 return CANSparkMaxJNI.c_SparkMax_GetOutputMax(sparkMax.sparkMaxHandle, slotID); 717 } 718 719 /** 720 * Configure the maximum velocity of the SmartMotion mode. This is the velocity that is reached in 721 * the middle of the profile and is what the motor should spend most of its time at 722 * 723 * @param maxVel The maxmimum cruise velocity for the motion profile in RPM 724 * @param slotID Is the gain schedule slot, the value is a number between 0 and 3. Each slot has 725 * its own set of gain values and can be changed in each control frame using SetReference(). 726 * @return {@link REVLibError#kOk} if successful 727 */ 728 public REVLibError setSmartMotionMaxVelocity(double maxVel, int slotID) { 729 sparkMax.throwIfClosed(); 730 return REVLibError.fromInt( 731 CANSparkMaxJNI.c_SparkMax_SetSmartMotionMaxVelocity( 732 sparkMax.sparkMaxHandle, slotID, (float) maxVel)); 733 } 734 735 /** 736 * Configure the maximum acceleration of the SmartMotion mode. This is the accleration that the 737 * motor velocity will increase at until the max velocity is reached 738 * 739 * @param maxAccel The maxmimum acceleration for the motion profile in RPM per second 740 * @param slotID Is the gain schedule slot, the value is a number between 0 and 3. Each slot has 741 * its own set of gain values and can be changed in each control frame using SetReference(). 742 * @return {@link REVLibError#kOk} if successful 743 */ 744 public REVLibError setSmartMotionMaxAccel(double maxAccel, int slotID) { 745 sparkMax.throwIfClosed(); 746 return REVLibError.fromInt( 747 CANSparkMaxJNI.c_SparkMax_SetSmartMotionMaxAccel( 748 sparkMax.sparkMaxHandle, slotID, (float) maxAccel)); 749 } 750 751 /** 752 * Configure the mimimum velocity of the SmartMotion mode. Any requested velocities below this 753 * value will be set to 0. 754 * 755 * @param minVel The minimum velocity for the motion profile in RPM 756 * @param slotID Is the gain schedule slot, the value is a number between 0 and 3. Each slot has 757 * its own set of gain values and can be changed in each control frame using SetReference(). 758 * @return {@link REVLibError#kOk} if successful 759 */ 760 public REVLibError setSmartMotionMinOutputVelocity(double minVel, int slotID) { 761 sparkMax.throwIfClosed(); 762 return REVLibError.fromInt( 763 CANSparkMaxJNI.c_SparkMax_SetSmartMotionMinOutputVelocity( 764 sparkMax.sparkMaxHandle, slotID, (float) minVel)); 765 } 766 767 /** 768 * Configure the allowed closed loop error of SmartMotion mode. This value is how much deviation 769 * from your setpoint is tolerated and is useful in preventing oscillation around your setpoint. 770 * 771 * @param allowedErr The allowed deviation for your setpoint vs actual position in rotations 772 * @param slotID Is the gain schedule slot, the value is a number between 0 and 3. Each slot has 773 * its own set of gain values and can be changed in each control frame using SetReference(). 774 * @return {@link REVLibError#kOk} if successful 775 */ 776 public REVLibError setSmartMotionAllowedClosedLoopError(double allowedErr, int slotID) { 777 sparkMax.throwIfClosed(); 778 return REVLibError.fromInt( 779 CANSparkMaxJNI.c_SparkMax_SetSmartMotionAllowedClosedLoopError( 780 sparkMax.sparkMaxHandle, slotID, (float) allowedErr)); 781 } 782 783 /** 784 * NOTE: As of the 2022 FRC season, the firmware only supports the trapezoidal motion profiling 785 * acceleration strategy. 786 * 787 * <p>Configure the acceleration strategy used to control acceleration on the motor. 788 * 789 * @param accelStrategy The acceleration strategy to use for the automatically generated motion 790 * profile 791 * @param slotID Is the gain schedule slot, the value is a number between 0 and 3. Each slot has 792 * its own set of gain values and can be changed in each control frame using SetReference(). 793 * @return {@link REVLibError#kOk} if successful 794 */ 795 public REVLibError setSmartMotionAccelStrategy(AccelStrategy accelStrategy, int slotID) { 796 sparkMax.throwIfClosed(); 797 return REVLibError.fromInt( 798 CANSparkMaxJNI.c_SparkMax_SetSmartMotionAccelStrategy( 799 sparkMax.sparkMaxHandle, slotID, accelStrategy.value)); 800 } 801 802 /** 803 * NOTE: As of the 2022 FRC season, the firmware only supports the trapezoidal motion profiling 804 * acceleration strategy. 805 * 806 * <p>Configure the acceleration strategy used to control acceleration on the motor. The current 807 * strategy is trapezoidal motion profiling. 808 * 809 * @param accelStrategy The acceleration strategy to use for the automatically generated motion 810 * profile 811 * @param slotID Is the gain schedule slot, the value is a number between 0 and 3. Each slot has 812 * its own set of gain values and can be changed in each control frame using SetReference(). 813 * @return {@link REVLibError#kOk} if successful 814 * @deprecated Use {@link #setSmartMotionAccelStrategy(AccelStrategy, int)} instead. 815 */ 816 @SuppressWarnings("removal") 817 @Deprecated(forRemoval = true) 818 public REVLibError setSmartMotionAccelStrategy( 819 CANPIDController.AccelStrategy accelStrategy, int slotID) { 820 sparkMax.throwIfClosed(); 821 return REVLibError.fromInt( 822 CANSparkMaxJNI.c_SparkMax_SetSmartMotionAccelStrategy( 823 sparkMax.sparkMaxHandle, slotID, accelStrategy.value)); 824 } 825 826 /** 827 * Get the maximum velocity of the SmartMotion mode. This is the velocity that is reached in the 828 * middle of the profile and is what the motor should spend most of its time at 829 * 830 * @param slotID Is the gain schedule slot, the value is a number between 0 and 3. Each slot has 831 * its own set of gain values and can be changed in each control frame using SetReference(). 832 * @return The maxmimum cruise velocity for the motion profile in RPM 833 */ 834 public double getSmartMotionMaxVelocity(int slotID) { 835 sparkMax.throwIfClosed(); 836 return CANSparkMaxJNI.c_SparkMax_GetSmartMotionMaxVelocity(sparkMax.sparkMaxHandle, slotID); 837 } 838 839 /** 840 * Get the maximum acceleration of the SmartMotion mode. This is the accleration that the motor 841 * velocity will increase at until the max velocity is reached 842 * 843 * @param slotID Is the gain schedule slot, the value is a number between 0 and 3. Each slot has 844 * its own set of gain values and can be changed in each control frame using SetReference(). 845 * @return The maxmimum acceleration for the motion profile in RPM per second 846 */ 847 public double getSmartMotionMaxAccel(int slotID) { 848 sparkMax.throwIfClosed(); 849 return CANSparkMaxJNI.c_SparkMax_GetSmartMotionMaxAccel(sparkMax.sparkMaxHandle, slotID); 850 } 851 852 /** 853 * Get the mimimum velocity of the SmartMotion mode. Any requested velocities below this value 854 * will be set to 0. 855 * 856 * @param slotID Is the gain schedule slot, the value is a number between 0 and 3. Each slot has 857 * its own set of gain values and can be changed in each control frame using SetReference(). 858 * @return The minimum velocity for the motion profile in RPM 859 */ 860 public double getSmartMotionMinOutputVelocity(int slotID) { 861 sparkMax.throwIfClosed(); 862 return CANSparkMaxJNI.c_SparkMax_GetSmartMotionMinOutputVelocity( 863 sparkMax.sparkMaxHandle, slotID); 864 } 865 866 /** 867 * Get the allowed closed loop error of SmartMotion mode. This value is how much deviation from 868 * your setpoint is tolerated and is useful in preventing oscillation around your setpoint. 869 * 870 * @param slotID Is the gain schedule slot, the value is a number between 0 and 3. Each slot has 871 * its own set of gain values and can be changed in each control frame using SetReference(). 872 * @return The allowed deviation for your setpoint vs actual position in rotations 873 */ 874 public double getSmartMotionAllowedClosedLoopError(int slotID) { 875 sparkMax.throwIfClosed(); 876 return CANSparkMaxJNI.c_SparkMax_GetSmartMotionAllowedClosedLoopError( 877 sparkMax.sparkMaxHandle, slotID); 878 } 879 880 /** 881 * Get the acceleration strategy used to control acceleration on the motor. As of the 2022 FRC 882 * season, the strategy is always trapezoidal motion profiling, regardless of what the device may 883 * report. 884 * 885 * @param slotID Is the gain schedule slot, the value is a number between 0 and 3. Each slot has 886 * its own set of gain values and can be changed in each control frame using SetReference(). 887 * @return The acceleration strategy to use for the automatically generated motion profile. 888 */ 889 public AccelStrategy getSmartMotionAccelStrategy(int slotID) { 890 sparkMax.throwIfClosed(); 891 return AccelStrategy.fromInt( 892 CANSparkMaxJNI.c_SparkMax_GetSmartMotionAccelStrategy(sparkMax.sparkMaxHandle, slotID)); 893 } 894 895 /** 896 * Configure the maximum I accumulator of the PID controller. This value is used to constrain the 897 * I accumulator to help manage integral wind-up 898 * 899 * @param iMaxAccum The max value to contrain the I accumulator to 900 * @param slotID Is the gain schedule slot, the value is a number between 0 and 3. Each slot has 901 * its own set of gain values and can be changed in each control frame using SetReference(). 902 * @return {@link REVLibError#kOk} if successful 903 */ 904 public REVLibError setIMaxAccum(double iMaxAccum, int slotID) { 905 sparkMax.throwIfClosed(); 906 return REVLibError.fromInt( 907 CANSparkMaxJNI.c_SparkMax_SetIMaxAccum(sparkMax.sparkMaxHandle, slotID, (float) iMaxAccum)); 908 } 909 910 /** 911 * Get the maximum I accumulator of the PID controller. This value is used to constrain the I 912 * accumulator to help manage integral wind-up 913 * 914 * @param slotID Is the gain schedule slot, the value is a number between 0 and 3. Each slot has 915 * its own set of gain values and can be changed in each control frame using SetReference(). 916 * @return The max value to contrain the I accumulator to 917 */ 918 public double getIMaxAccum(int slotID) { 919 sparkMax.throwIfClosed(); 920 return (double) CANSparkMaxJNI.c_SparkMax_GetIMaxAccum(sparkMax.sparkMaxHandle, slotID); 921 } 922 923 /** 924 * Set the I accumulator of the PID controller. This is useful when wishing to force a reset on 925 * the I accumulator of the PID controller. You can also preset values to see how it will respond 926 * to certain I characteristics 927 * 928 * <p>To use this function, the controller must be in a closed loop control mode by calling 929 * setReference() 930 * 931 * @param iAccum The value to set the I accumulator to 932 * @return {@link REVLibError#kOk} if successful 933 */ 934 public REVLibError setIAccum(double iAccum) { 935 sparkMax.throwIfClosed(); 936 return REVLibError.fromInt( 937 CANSparkMaxJNI.c_SparkMax_SetIAccum(sparkMax.sparkMaxHandle, (float) iAccum)); 938 } 939 940 /** 941 * Get the I accumulator of the PID controller. This is useful when wishing to see what the I 942 * accumulator value is to help with PID tuning 943 * 944 * @return The value of the I accumulator 945 */ 946 public double getIAccum() { 947 sparkMax.throwIfClosed(); 948 return CANSparkMaxJNI.c_SparkMax_GetIAccum(sparkMax.sparkMaxHandle); 949 } 950 951 /** 952 * Set the controller's feedback device 953 * 954 * <p>The default feedback device in brushless mode is assumed to be the integrated encoder and 955 * the default feedback device in brushed mode is assumed to be a quadrature encoder. This is used 956 * to changed to another feedback device for the controller, such as an analog sensor. 957 * 958 * <p>If there is a limited range on the feedback sensor that should be observed by the 959 * PIDController, it can be set by calling SetFeedbackSensorRange() on the sensor object. 960 * 961 * @param sensor The sensor to use as a feedback device 962 * @return {@link REVLibError#kOk} if successful 963 */ 964 // TODO(Noah): Figure out what's going on with setFeedbackSensorRange() 965 public REVLibError setFeedbackDevice(final MotorFeedbackSensor sensor) { 966 //noinspection removal 967 return setFeedbackDevice((CANSensor) sensor); 968 } 969 970 /** @deprecated Use {@link #setFeedbackDevice(MotorFeedbackSensor)} instead */ 971 @SuppressWarnings("removal") 972 @Deprecated(forRemoval = true) 973 public REVLibError setFeedbackDevice(final CANSensor sensor) { 974 sparkMax.throwIfClosed(); 975 976 if (sensor instanceof SparkMaxRelativeEncoder 977 || sensor instanceof SparkMaxAlternateEncoder 978 || sensor instanceof SparkMaxAnalogSensor) { 979 // Handle sensors that are directly connected to the SPARK Max 980 CANSparkMax sparkMaxSensorIsConnectedTo; 981 int feedbackDeviceId; 982 983 if (sensor instanceof SparkMaxRelativeEncoder) { 984 sparkMaxSensorIsConnectedTo = ((SparkMaxRelativeEncoder) sensor).sparkMax; 985 feedbackDeviceId = ((SparkMaxRelativeEncoder) sensor).getSparkMaxFeedbackDeviceId(); 986 } else if (sensor instanceof SparkMaxAlternateEncoder) { 987 sparkMaxSensorIsConnectedTo = ((SparkMaxAlternateEncoder) sensor).sparkMax; 988 feedbackDeviceId = ((SparkMaxAlternateEncoder) sensor).getSparkMaxFeedbackDeviceId(); 989 } else { 990 sparkMaxSensorIsConnectedTo = ((SparkMaxAnalogSensor) sensor).sparkMax; 991 feedbackDeviceId = ((SparkMaxAnalogSensor) sensor).getSparkMaxFeedbackDeviceId(); 992 } 993 994 if (sparkMaxSensorIsConnectedTo != this.sparkMax) { 995 throw new IllegalArgumentException( 996 "A sensor attached to one SPARK MAX cannot be used as a feedback device for a different SPARK MAX"); 997 } 998 999 return REVLibError.fromInt( 1000 CANSparkMaxJNI.c_SparkMax_SetFeedbackDevice(sparkMax.sparkMaxHandle, feedbackDeviceId)); 1001 1002 } else { 1003 // Right now, the SPARK MAX does not support sensors that are not directly connected to itself 1004 throw new IllegalArgumentException( 1005 sensor.getClass().getSimpleName() 1006 + " cannot be used as a feedback device for a SPARK MAX at this time"); 1007 } 1008 } 1009}