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