001/* 002 * Copyright (C) Cross The Road Electronics. All rights reserved. 003 * License information can be found in CTRE_LICENSE.txt 004 * For support and suggestions contact support@ctr-electronics.com or file 005 * an issue tracker at https://github.com/CrossTheRoadElec/Phoenix-Releases 006 */ 007package com.ctre.phoenix6.controls; 008 009import com.ctre.phoenix6.CANBus; 010import com.ctre.phoenix6.StatusCode; 011import com.ctre.phoenix6.controls.jni.ControlJNI; 012import com.ctre.phoenix6.hardware.traits.*; 013 014import edu.wpi.first.units.*; 015import edu.wpi.first.units.measure.*; 016import static edu.wpi.first.units.Units.*; 017 018import java.util.HashMap; 019import java.util.Map; 020 021/** 022 * Requires Phoenix Pro and CANivore; 023 * Requests Motion Magic® to target a final position using a motion profile. 024 * This dynamic request allows runtime changes to Cruise Velocity, Acceleration, 025 * and (optional) Jerk. Users can optionally provide a duty cycle feedforward. 026 * <p> 027 * Motion Magic® produces a motion profile in real-time while attempting to honor the specified Cruise 028 * Velocity, Acceleration, and (optional) Jerk. This control mode does not use the Expo_kV or Expo_kA 029 * configs. 030 * <p> 031 * Target position can be changed on-the-fly and Motion Magic® will do its best to adjust the profile. This 032 * control mode is duty cycle based, so relevant closed-loop gains will use fractional duty cycle for the 033 * numerator: +1.0 represents full forward output. 034 */ 035public final class DynamicMotionMagicDutyCycle implements ControlRequest, Cloneable { 036 /** 037 * Position to drive toward in rotations. 038 * 039 * <ul> 040 * <li> Units: rotations 041 * </ul> 042 * 043 */ 044 public double Position; 045 /** 046 * Cruise velocity for profiling. The signage does not matter as the device 047 * will use the absolute value for profile generation. 048 * 049 * <ul> 050 * <li> Units: rotations per second 051 * </ul> 052 * 053 */ 054 public double Velocity; 055 /** 056 * Acceleration for profiling. The signage does not matter as the device will 057 * use the absolute value for profile generation 058 * 059 * <ul> 060 * <li> Units: rotations per second² 061 * </ul> 062 * 063 */ 064 public double Acceleration; 065 /** 066 * Jerk for profiling. The signage does not matter as the device will use the 067 * absolute value for profile generation. 068 * <p> 069 * Jerk is optional; if this is set to zero, then Motion Magic® will not apply a 070 * Jerk limit. 071 * 072 * <ul> 073 * <li> Units: rotations per second³ 074 * </ul> 075 * 076 */ 077 public double Jerk = 0.0; 078 /** 079 * Set to true to use FOC commutation (requires Phoenix Pro), which increases 080 * peak power by ~15% on supported devices (see {@link SupportsFOC}). Set to 081 * false to use trapezoidal commutation. 082 * <p> 083 * FOC improves motor performance by leveraging torque (current) control. 084 * However, this may be inconvenient for applications that require specifying 085 * duty cycle or voltage. CTR-Electronics has developed a hybrid method that 086 * combines the performances gains of FOC while still allowing applications to 087 * provide duty cycle or voltage demand. This not to be confused with simple 088 * sinusoidal control or phase voltage control which lacks the performance 089 * gains. 090 */ 091 public boolean EnableFOC = true; 092 /** 093 * Feedforward to apply in fractional units between -1 and +1. This is added to 094 * the output of the onboard feedforward terms. 095 * 096 * <ul> 097 * <li> Units: fractional 098 * </ul> 099 * 100 */ 101 public double FeedForward = 0.0; 102 /** 103 * Select which gains are applied by selecting the slot. Use the configuration 104 * api to set the gain values for the selected slot before enabling this 105 * feature. Slot must be within [0,2]. 106 */ 107 public int Slot = 0; 108 /** 109 * Set to true to static-brake the rotor when output is zero (or within 110 * deadband). Set to false to use the NeutralMode configuration setting 111 * (default). This flag exists to provide the fundamental behavior of this 112 * control when output is zero, which is to provide 0V to the motor. 113 */ 114 public boolean OverrideBrakeDurNeutral = false; 115 /** 116 * Set to true to force forward limiting. This allows users to use other limit 117 * switch sensors connected to robot controller. This also allows use of active 118 * sensors that require external power. 119 */ 120 public boolean LimitForwardMotion = false; 121 /** 122 * Set to true to force reverse limiting. This allows users to use other limit 123 * switch sensors connected to robot controller. This also allows use of active 124 * sensors that require external power. 125 */ 126 public boolean LimitReverseMotion = false; 127 /** 128 * Set to true to ignore hardware limit switches and the LimitForwardMotion and 129 * LimitReverseMotion parameters, instead allowing motion. 130 * <p> 131 * This can be useful on mechanisms such as an intake/feeder, where a limit 132 * switch stops motion while intaking but should be ignored when feeding to a 133 * shooter. 134 * <p> 135 * The hardware limit faults and Forward/ReverseLimit signals will still report 136 * the values of the limit switches regardless of this parameter. 137 */ 138 public boolean IgnoreHardwareLimits = false; 139 /** 140 * Set to true to ignore software limits, instead allowing motion. 141 * <p> 142 * This can be useful when calibrating the zero point of a mechanism such as an 143 * elevator. 144 * <p> 145 * The software limit faults will still report the values of the software limits 146 * regardless of this parameter. 147 */ 148 public boolean IgnoreSoftwareLimits = false; 149 /** 150 * Set to true to delay applying this control request until a timesync boundary 151 * (requires Phoenix Pro and CANivore). This eliminates the impact of 152 * nondeterministic network delays in exchange for a larger but deterministic 153 * control latency. 154 * <p> 155 * This requires setting the ControlTimesyncFreqHz config in MotorOutputConfigs. 156 * Additionally, when this is enabled, the UpdateFreqHz of this request should 157 * be set to 0 Hz. 158 */ 159 public boolean UseTimesync = false; 160 161 /** 162 * The frequency at which this control will update. 163 * This is designated in Hertz, with a minimum of 20 Hz 164 * (every 50 ms) and a maximum of 1000 Hz (every 1 ms). 165 * Some update frequencies are not supported and will be 166 * promoted up to the next highest supported frequency. 167 * <p> 168 * If this field is set to 0 Hz, the control request will 169 * be sent immediately as a one-shot frame. This may be useful 170 * for advanced applications that require outputs to be 171 * synchronized with data acquisition. In this case, we 172 * recommend not exceeding 50 ms between control calls. 173 */ 174 public double UpdateFreqHz = 100; 175 176 /** 177 * Requires Phoenix Pro and CANivore; 178 * Requests Motion Magic® to target a final position using a motion profile. 179 * This dynamic request allows runtime changes to Cruise Velocity, Acceleration, 180 * and (optional) Jerk. Users can optionally provide a duty cycle feedforward. 181 * <p> 182 * Motion Magic® produces a motion profile in real-time while attempting to 183 * honor the specified Cruise Velocity, Acceleration, and (optional) Jerk. This 184 * control mode does not use the Expo_kV or Expo_kA configs. 185 * <p> 186 * Target position can be changed on-the-fly and Motion Magic® will do its best 187 * to adjust the profile. This control mode is duty cycle based, so relevant 188 * closed-loop gains will use fractional duty cycle for the numerator: +1.0 189 * represents full forward output. 190 * 191 * @param Position Position to drive toward in rotations. 192 * @param Velocity Cruise velocity for profiling. The signage does not matter 193 * as the device will use the absolute value for profile 194 * generation. 195 * @param Acceleration Acceleration for profiling. The signage does not matter 196 * as the device will use the absolute value for profile 197 * generation 198 */ 199 public DynamicMotionMagicDutyCycle(double Position, double Velocity, double Acceleration) { 200 this.Position = Position; 201 this.Velocity = Velocity; 202 this.Acceleration = Acceleration; 203 } 204 205 /** 206 * Requires Phoenix Pro and CANivore; 207 * Requests Motion Magic® to target a final position using a motion profile. 208 * This dynamic request allows runtime changes to Cruise Velocity, Acceleration, 209 * and (optional) Jerk. Users can optionally provide a duty cycle feedforward. 210 * <p> 211 * Motion Magic® produces a motion profile in real-time while attempting to 212 * honor the specified Cruise Velocity, Acceleration, and (optional) Jerk. This 213 * control mode does not use the Expo_kV or Expo_kA configs. 214 * <p> 215 * Target position can be changed on-the-fly and Motion Magic® will do its best 216 * to adjust the profile. This control mode is duty cycle based, so relevant 217 * closed-loop gains will use fractional duty cycle for the numerator: +1.0 218 * represents full forward output. 219 * 220 * @param Position Position to drive toward in rotations. 221 * @param Velocity Cruise velocity for profiling. The signage does not matter 222 * as the device will use the absolute value for profile 223 * generation. 224 * @param Acceleration Acceleration for profiling. The signage does not matter 225 * as the device will use the absolute value for profile 226 * generation 227 */ 228 public DynamicMotionMagicDutyCycle(Angle Position, AngularVelocity Velocity, AngularAcceleration Acceleration) { 229 this(Position.in(Rotations), Velocity.in(RotationsPerSecond), Acceleration.in(RotationsPerSecondPerSecond)); 230 } 231 232 @Override 233 public String getName() { 234 return "DynamicMotionMagicDutyCycle"; 235 } 236 237 @Override 238 public String toString() { 239 String ss = "Control: DynamicMotionMagicDutyCycle\n"; 240 ss += " Position: " + Position + " rotations" + "\n"; 241 ss += " Velocity: " + Velocity + " rotations per second" + "\n"; 242 ss += " Acceleration: " + Acceleration + " rotations per second²" + "\n"; 243 ss += " Jerk: " + Jerk + " rotations per second³" + "\n"; 244 ss += " EnableFOC: " + EnableFOC + "\n"; 245 ss += " FeedForward: " + FeedForward + " fractional" + "\n"; 246 ss += " Slot: " + Slot + "\n"; 247 ss += " OverrideBrakeDurNeutral: " + OverrideBrakeDurNeutral + "\n"; 248 ss += " LimitForwardMotion: " + LimitForwardMotion + "\n"; 249 ss += " LimitReverseMotion: " + LimitReverseMotion + "\n"; 250 ss += " IgnoreHardwareLimits: " + IgnoreHardwareLimits + "\n"; 251 ss += " IgnoreSoftwareLimits: " + IgnoreSoftwareLimits + "\n"; 252 ss += " UseTimesync: " + UseTimesync + "\n"; 253 return ss; 254 } 255 256 @Override 257 public StatusCode sendRequest(CANBus network, int deviceHash) { 258 return StatusCode.valueOf(ControlJNI.JNI_RequestControlDynamicMotionMagicDutyCycle( 259 network.getNameUTF8Bytes(), deviceHash, UpdateFreqHz, Position, Velocity, Acceleration, Jerk, EnableFOC, FeedForward, Slot, OverrideBrakeDurNeutral, LimitForwardMotion, LimitReverseMotion, IgnoreHardwareLimits, IgnoreSoftwareLimits, UseTimesync)); 260 } 261 262 /** 263 * Gets information about this control request. 264 * 265 * @return Map of control parameter names and corresponding applied values 266 */ 267 @Override 268 public Map<String, String> getControlInfo() { 269 var controlInfo = new HashMap<String, String>(); 270 controlInfo.put("Name", getName()); 271 controlInfo.put("Position", String.valueOf(this.Position)); 272 controlInfo.put("Velocity", String.valueOf(this.Velocity)); 273 controlInfo.put("Acceleration", String.valueOf(this.Acceleration)); 274 controlInfo.put("Jerk", String.valueOf(this.Jerk)); 275 controlInfo.put("EnableFOC", String.valueOf(this.EnableFOC)); 276 controlInfo.put("FeedForward", String.valueOf(this.FeedForward)); 277 controlInfo.put("Slot", String.valueOf(this.Slot)); 278 controlInfo.put("OverrideBrakeDurNeutral", String.valueOf(this.OverrideBrakeDurNeutral)); 279 controlInfo.put("LimitForwardMotion", String.valueOf(this.LimitForwardMotion)); 280 controlInfo.put("LimitReverseMotion", String.valueOf(this.LimitReverseMotion)); 281 controlInfo.put("IgnoreHardwareLimits", String.valueOf(this.IgnoreHardwareLimits)); 282 controlInfo.put("IgnoreSoftwareLimits", String.valueOf(this.IgnoreSoftwareLimits)); 283 controlInfo.put("UseTimesync", String.valueOf(this.UseTimesync)); 284 return controlInfo; 285 } 286 287 /** 288 * Modifies this Control Request's Position parameter and returns itself for 289 * method-chaining and easier to use request API. 290 * <p> 291 * Position to drive toward in rotations. 292 * 293 * <ul> 294 * <li> Units: rotations 295 * </ul> 296 * 297 * 298 * @param newPosition Parameter to modify 299 * @return Itself 300 */ 301 public DynamicMotionMagicDutyCycle withPosition(double newPosition) { 302 Position = newPosition; 303 return this; 304 } 305 306 /** 307 * Modifies this Control Request's Position parameter and returns itself for 308 * method-chaining and easier to use request API. 309 * <p> 310 * Position to drive toward in rotations. 311 * 312 * <ul> 313 * <li> Units: rotations 314 * </ul> 315 * 316 * 317 * @param newPosition Parameter to modify 318 * @return Itself 319 */ 320 public DynamicMotionMagicDutyCycle withPosition(Angle newPosition) { 321 Position = newPosition.in(Rotations); 322 return this; 323 } 324 325 /** 326 * Helper method to get this Control Request's Position parameter converted 327 * to a unit type. If not using the Java units library, {@link #Position} 328 * can be accessed directly instead. 329 * <p> 330 * Position to drive toward in rotations. 331 * 332 * <ul> 333 * <li> Units: rotations 334 * </ul> 335 * 336 * 337 * @return Position 338 */ 339 public Angle getPositionMeasure() { 340 return Rotations.of(Position); 341 } 342 343 /** 344 * Modifies this Control Request's Velocity parameter and returns itself for 345 * method-chaining and easier to use request API. 346 * <p> 347 * Cruise velocity for profiling. The signage does not matter as the device 348 * will use the absolute value for profile generation. 349 * 350 * <ul> 351 * <li> Units: rotations per second 352 * </ul> 353 * 354 * 355 * @param newVelocity Parameter to modify 356 * @return Itself 357 */ 358 public DynamicMotionMagicDutyCycle withVelocity(double newVelocity) { 359 Velocity = newVelocity; 360 return this; 361 } 362 363 /** 364 * Modifies this Control Request's Velocity parameter and returns itself for 365 * method-chaining and easier to use request API. 366 * <p> 367 * Cruise velocity for profiling. The signage does not matter as the device 368 * will use the absolute value for profile generation. 369 * 370 * <ul> 371 * <li> Units: rotations per second 372 * </ul> 373 * 374 * 375 * @param newVelocity Parameter to modify 376 * @return Itself 377 */ 378 public DynamicMotionMagicDutyCycle withVelocity(AngularVelocity newVelocity) { 379 Velocity = newVelocity.in(RotationsPerSecond); 380 return this; 381 } 382 383 /** 384 * Helper method to get this Control Request's Velocity parameter converted 385 * to a unit type. If not using the Java units library, {@link #Velocity} 386 * can be accessed directly instead. 387 * <p> 388 * Cruise velocity for profiling. The signage does not matter as the device 389 * will use the absolute value for profile generation. 390 * 391 * <ul> 392 * <li> Units: rotations per second 393 * </ul> 394 * 395 * 396 * @return Velocity 397 */ 398 public AngularVelocity getVelocityMeasure() { 399 return RotationsPerSecond.of(Velocity); 400 } 401 402 /** 403 * Modifies this Control Request's Acceleration parameter and returns itself for 404 * method-chaining and easier to use request API. 405 * <p> 406 * Acceleration for profiling. The signage does not matter as the device will 407 * use the absolute value for profile generation 408 * 409 * <ul> 410 * <li> Units: rotations per second² 411 * </ul> 412 * 413 * 414 * @param newAcceleration Parameter to modify 415 * @return Itself 416 */ 417 public DynamicMotionMagicDutyCycle withAcceleration(double newAcceleration) { 418 Acceleration = newAcceleration; 419 return this; 420 } 421 422 /** 423 * Modifies this Control Request's Acceleration parameter and returns itself for 424 * method-chaining and easier to use request API. 425 * <p> 426 * Acceleration for profiling. The signage does not matter as the device will 427 * use the absolute value for profile generation 428 * 429 * <ul> 430 * <li> Units: rotations per second² 431 * </ul> 432 * 433 * 434 * @param newAcceleration Parameter to modify 435 * @return Itself 436 */ 437 public DynamicMotionMagicDutyCycle withAcceleration(AngularAcceleration newAcceleration) { 438 Acceleration = newAcceleration.in(RotationsPerSecondPerSecond); 439 return this; 440 } 441 442 /** 443 * Helper method to get this Control Request's Acceleration parameter converted 444 * to a unit type. If not using the Java units library, {@link #Acceleration} 445 * can be accessed directly instead. 446 * <p> 447 * Acceleration for profiling. The signage does not matter as the device will 448 * use the absolute value for profile generation 449 * 450 * <ul> 451 * <li> Units: rotations per second² 452 * </ul> 453 * 454 * 455 * @return Acceleration 456 */ 457 public AngularAcceleration getAccelerationMeasure() { 458 return RotationsPerSecondPerSecond.of(Acceleration); 459 } 460 461 /** 462 * Modifies this Control Request's Jerk parameter and returns itself for 463 * method-chaining and easier to use request API. 464 * <p> 465 * Jerk for profiling. The signage does not matter as the device will use the 466 * absolute value for profile generation. 467 * <p> 468 * Jerk is optional; if this is set to zero, then Motion Magic® will not apply a 469 * Jerk limit. 470 * 471 * <ul> 472 * <li> Units: rotations per second³ 473 * </ul> 474 * 475 * 476 * @param newJerk Parameter to modify 477 * @return Itself 478 */ 479 public DynamicMotionMagicDutyCycle withJerk(double newJerk) { 480 Jerk = newJerk; 481 return this; 482 } 483 484 /** 485 * Modifies this Control Request's Jerk parameter and returns itself for 486 * method-chaining and easier to use request API. 487 * <p> 488 * Jerk for profiling. The signage does not matter as the device will use the 489 * absolute value for profile generation. 490 * <p> 491 * Jerk is optional; if this is set to zero, then Motion Magic® will not apply a 492 * Jerk limit. 493 * 494 * <ul> 495 * <li> Units: rotations per second³ 496 * </ul> 497 * 498 * 499 * @param newJerk Parameter to modify 500 * @return Itself 501 */ 502 public DynamicMotionMagicDutyCycle withJerk(Velocity<AngularAccelerationUnit> newJerk) { 503 Jerk = newJerk.in(RotationsPerSecondPerSecond.per(Second)); 504 return this; 505 } 506 507 /** 508 * Helper method to get this Control Request's Jerk parameter converted 509 * to a unit type. If not using the Java units library, {@link #Jerk} 510 * can be accessed directly instead. 511 * <p> 512 * Jerk for profiling. The signage does not matter as the device will use the 513 * absolute value for profile generation. 514 * <p> 515 * Jerk is optional; if this is set to zero, then Motion Magic® will not apply a 516 * Jerk limit. 517 * 518 * <ul> 519 * <li> Units: rotations per second³ 520 * </ul> 521 * 522 * 523 * @return Jerk 524 */ 525 public Velocity<AngularAccelerationUnit> getJerkMeasure() { 526 return RotationsPerSecondPerSecond.per(Second).of(Jerk); 527 } 528 529 /** 530 * Modifies this Control Request's EnableFOC parameter and returns itself for 531 * method-chaining and easier to use request API. 532 * <p> 533 * Set to true to use FOC commutation (requires Phoenix Pro), which increases 534 * peak power by ~15% on supported devices (see {@link SupportsFOC}). Set to 535 * false to use trapezoidal commutation. 536 * <p> 537 * FOC improves motor performance by leveraging torque (current) control. 538 * However, this may be inconvenient for applications that require specifying 539 * duty cycle or voltage. CTR-Electronics has developed a hybrid method that 540 * combines the performances gains of FOC while still allowing applications to 541 * provide duty cycle or voltage demand. This not to be confused with simple 542 * sinusoidal control or phase voltage control which lacks the performance 543 * gains. 544 * 545 * @param newEnableFOC Parameter to modify 546 * @return Itself 547 */ 548 public DynamicMotionMagicDutyCycle withEnableFOC(boolean newEnableFOC) { 549 EnableFOC = newEnableFOC; 550 return this; 551 } 552 553 /** 554 * Modifies this Control Request's FeedForward parameter and returns itself for 555 * method-chaining and easier to use request API. 556 * <p> 557 * Feedforward to apply in fractional units between -1 and +1. This is added to 558 * the output of the onboard feedforward terms. 559 * 560 * <ul> 561 * <li> Units: fractional 562 * </ul> 563 * 564 * 565 * @param newFeedForward Parameter to modify 566 * @return Itself 567 */ 568 public DynamicMotionMagicDutyCycle withFeedForward(double newFeedForward) { 569 FeedForward = newFeedForward; 570 return this; 571 } 572 573 /** 574 * Modifies this Control Request's Slot parameter and returns itself for 575 * method-chaining and easier to use request API. 576 * <p> 577 * Select which gains are applied by selecting the slot. Use the configuration 578 * api to set the gain values for the selected slot before enabling this 579 * feature. Slot must be within [0,2]. 580 * 581 * @param newSlot Parameter to modify 582 * @return Itself 583 */ 584 public DynamicMotionMagicDutyCycle withSlot(int newSlot) { 585 Slot = newSlot; 586 return this; 587 } 588 589 /** 590 * Modifies this Control Request's OverrideBrakeDurNeutral parameter and returns itself for 591 * method-chaining and easier to use request API. 592 * <p> 593 * Set to true to static-brake the rotor when output is zero (or within 594 * deadband). Set to false to use the NeutralMode configuration setting 595 * (default). This flag exists to provide the fundamental behavior of this 596 * control when output is zero, which is to provide 0V to the motor. 597 * 598 * @param newOverrideBrakeDurNeutral Parameter to modify 599 * @return Itself 600 */ 601 public DynamicMotionMagicDutyCycle withOverrideBrakeDurNeutral(boolean newOverrideBrakeDurNeutral) { 602 OverrideBrakeDurNeutral = newOverrideBrakeDurNeutral; 603 return this; 604 } 605 606 /** 607 * Modifies this Control Request's LimitForwardMotion parameter and returns itself for 608 * method-chaining and easier to use request API. 609 * <p> 610 * Set to true to force forward limiting. This allows users to use other limit 611 * switch sensors connected to robot controller. This also allows use of active 612 * sensors that require external power. 613 * 614 * @param newLimitForwardMotion Parameter to modify 615 * @return Itself 616 */ 617 public DynamicMotionMagicDutyCycle withLimitForwardMotion(boolean newLimitForwardMotion) { 618 LimitForwardMotion = newLimitForwardMotion; 619 return this; 620 } 621 622 /** 623 * Modifies this Control Request's LimitReverseMotion parameter and returns itself for 624 * method-chaining and easier to use request API. 625 * <p> 626 * Set to true to force reverse limiting. This allows users to use other limit 627 * switch sensors connected to robot controller. This also allows use of active 628 * sensors that require external power. 629 * 630 * @param newLimitReverseMotion Parameter to modify 631 * @return Itself 632 */ 633 public DynamicMotionMagicDutyCycle withLimitReverseMotion(boolean newLimitReverseMotion) { 634 LimitReverseMotion = newLimitReverseMotion; 635 return this; 636 } 637 638 /** 639 * Modifies this Control Request's IgnoreHardwareLimits parameter and returns itself for 640 * method-chaining and easier to use request API. 641 * <p> 642 * Set to true to ignore hardware limit switches and the LimitForwardMotion and 643 * LimitReverseMotion parameters, instead allowing motion. 644 * <p> 645 * This can be useful on mechanisms such as an intake/feeder, where a limit 646 * switch stops motion while intaking but should be ignored when feeding to a 647 * shooter. 648 * <p> 649 * The hardware limit faults and Forward/ReverseLimit signals will still report 650 * the values of the limit switches regardless of this parameter. 651 * 652 * @param newIgnoreHardwareLimits Parameter to modify 653 * @return Itself 654 */ 655 public DynamicMotionMagicDutyCycle withIgnoreHardwareLimits(boolean newIgnoreHardwareLimits) { 656 IgnoreHardwareLimits = newIgnoreHardwareLimits; 657 return this; 658 } 659 660 /** 661 * Modifies this Control Request's IgnoreSoftwareLimits parameter and returns itself for 662 * method-chaining and easier to use request API. 663 * <p> 664 * Set to true to ignore software limits, instead allowing motion. 665 * <p> 666 * This can be useful when calibrating the zero point of a mechanism such as an 667 * elevator. 668 * <p> 669 * The software limit faults will still report the values of the software limits 670 * regardless of this parameter. 671 * 672 * @param newIgnoreSoftwareLimits Parameter to modify 673 * @return Itself 674 */ 675 public DynamicMotionMagicDutyCycle withIgnoreSoftwareLimits(boolean newIgnoreSoftwareLimits) { 676 IgnoreSoftwareLimits = newIgnoreSoftwareLimits; 677 return this; 678 } 679 680 /** 681 * Modifies this Control Request's UseTimesync parameter and returns itself for 682 * method-chaining and easier to use request API. 683 * <p> 684 * Set to true to delay applying this control request until a timesync boundary 685 * (requires Phoenix Pro and CANivore). This eliminates the impact of 686 * nondeterministic network delays in exchange for a larger but deterministic 687 * control latency. 688 * <p> 689 * This requires setting the ControlTimesyncFreqHz config in MotorOutputConfigs. 690 * Additionally, when this is enabled, the UpdateFreqHz of this request should 691 * be set to 0 Hz. 692 * 693 * @param newUseTimesync Parameter to modify 694 * @return Itself 695 */ 696 public DynamicMotionMagicDutyCycle withUseTimesync(boolean newUseTimesync) { 697 UseTimesync = newUseTimesync; 698 return this; 699 } 700 701 /** 702 * Sets the frequency at which this control will update. 703 * This is designated in Hertz, with a minimum of 20 Hz 704 * (every 50 ms) and a maximum of 1000 Hz (every 1 ms). 705 * Some update frequencies are not supported and will be 706 * promoted up to the next highest supported frequency. 707 * <p> 708 * If this field is set to 0 Hz, the control request will 709 * be sent immediately as a one-shot frame. This may be useful 710 * for advanced applications that require outputs to be 711 * synchronized with data acquisition. In this case, we 712 * recommend not exceeding 50 ms between control calls. 713 * 714 * @param newUpdateFreqHz Parameter to modify 715 * @return Itself 716 */ 717 @Override 718 public DynamicMotionMagicDutyCycle withUpdateFreqHz(double newUpdateFreqHz) { 719 UpdateFreqHz = newUpdateFreqHz; 720 return this; 721 } 722 723 /** 724 * Sets the frequency at which this control will update. 725 * This is designated in Hertz, with a minimum of 20 Hz 726 * (every 50 ms) and a maximum of 1000 Hz (every 1 ms). 727 * Some update frequencies are not supported and will be 728 * promoted up to the next highest supported frequency. 729 * <p> 730 * If this field is set to 0 Hz, the control request will 731 * be sent immediately as a one-shot frame. This may be useful 732 * for advanced applications that require outputs to be 733 * synchronized with data acquisition. In this case, we 734 * recommend not exceeding 50 ms between control calls. 735 * 736 * @param newUpdateFreqHz Parameter to modify 737 * @return Itself 738 */ 739 @Override 740 public DynamicMotionMagicDutyCycle withUpdateFreqHz(Frequency newUpdateFreqHz) { 741 UpdateFreqHz = newUpdateFreqHz.in(Hertz); 742 return this; 743 } 744 745 @Override 746 public DynamicMotionMagicDutyCycle clone() { 747 try { 748 return (DynamicMotionMagicDutyCycle)super.clone(); 749 } catch (CloneNotSupportedException ex) { 750 /* this should never happen */ 751 throw new RuntimeException(ex); 752 } 753 } 754} 755