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; 011 012import edu.wpi.first.units.*; 013import edu.wpi.first.units.measure.*; 014import static edu.wpi.first.units.Units.*; 015 016import java.util.HashMap; 017import java.util.Map; 018 019/** 020 * Requests Motion Magic® to target a final position using an exponential motion 021 * profile. Users can optionally provide a voltage feedforward. 022 * <p> 023 * Motion Magic® Expo produces a motion profile in real-time while attempting to honor the Cruise Velocity 024 * (optional) and the mechanism kV and kA, specified via the Motion Magic® configuration values. Note that 025 * unlike the slot gains, the Expo_kV and Expo_kA configs are always in output units of Volts. 026 * <p> 027 * Setting Cruise Velocity to 0 will allow the profile to run to the max possible velocity based on Expo_kV. 028 * This control mode does not use the Acceleration or Jerk 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 voltage-based, so relevant closed-loop gains will use Volts for the numerator. 032 */ 033public class MotionMagicExpoVoltage extends ControlRequest implements Cloneable 034{ 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 * Set to true to use FOC commutation (requires Phoenix Pro), which increases 046 * peak power by ~15%. Set to false to use trapezoidal commutation. 047 * <p> 048 * FOC improves motor performance by leveraging torque (current) control. 049 * However, this may be inconvenient for applications that require specifying 050 * duty cycle or voltage. CTR-Electronics has developed a hybrid method that 051 * combines the performances gains of FOC while still allowing applications to 052 * provide duty cycle or voltage demand. This not to be confused with simple 053 * sinusoidal control or phase voltage control which lacks the performance 054 * gains. 055 */ 056 public boolean EnableFOC = true; 057 /** 058 * Feedforward to apply in volts 059 * 060 * <ul> 061 * <li> Units: Volts 062 * </ul> 063 * 064 */ 065 public double FeedForward = 0.0; 066 /** 067 * Select which gains are applied by selecting the slot. Use the configuration 068 * api to set the gain values for the selected slot before enabling this 069 * feature. Slot must be within [0,2]. 070 */ 071 public int Slot = 0; 072 /** 073 * Set to true to static-brake the rotor when output is zero (or within 074 * deadband). Set to false to use the NeutralMode configuration setting 075 * (default). This flag exists to provide the fundamental behavior of this 076 * control when output is zero, which is to provide 0V to the motor. 077 */ 078 public boolean OverrideBrakeDurNeutral = false; 079 /** 080 * Set to true to force forward limiting. This allows users to use other limit 081 * switch sensors connected to robot controller. This also allows use of active 082 * sensors that require external power. 083 */ 084 public boolean LimitForwardMotion = false; 085 /** 086 * Set to true to force reverse limiting. This allows users to use other limit 087 * switch sensors connected to robot controller. This also allows use of active 088 * sensors that require external power. 089 */ 090 public boolean LimitReverseMotion = false; 091 /** 092 * Set to true to ignore hardware limit switches and the LimitForwardMotion and 093 * LimitReverseMotion parameters, instead allowing motion. 094 * <p> 095 * This can be useful on mechanisms such as an intake/feeder, where a limit 096 * switch stops motion while intaking but should be ignored when feeding to a 097 * shooter. 098 * <p> 099 * The hardware limit faults and Forward/ReverseLimit signals will still report 100 * the values of the limit switches regardless of this parameter. 101 */ 102 public boolean IgnoreHardwareLimits = false; 103 /** 104 * Set to true to delay applying this control request until a timesync boundary 105 * (requires Phoenix Pro and CANivore). This eliminates the impact of 106 * nondeterministic network delays in exchange for a larger but deterministic 107 * control latency. 108 * <p> 109 * This requires setting the ControlTimesyncFreqHz config in MotorOutputConfigs. 110 * Additionally, when this is enabled, the UpdateFreqHz of this request should 111 * be set to 0 Hz. 112 */ 113 public boolean UseTimesync = false; 114 115 /** 116 * The period at which this control will update at. 117 * This is designated in Hertz, with a minimum of 20 Hz 118 * (every 50 ms) and a maximum of 1000 Hz (every 1 ms). 119 * <p> 120 * If this field is set to 0 Hz, the control request will 121 * be sent immediately as a one-shot frame. This may be useful 122 * for advanced applications that require outputs to be 123 * synchronized with data acquisition. In this case, we 124 * recommend not exceeding 50 ms between control calls. 125 */ 126 public double UpdateFreqHz = 100; 127 128 /** 129 * Requests Motion Magic® to target a final position using an exponential motion 130 * profile. Users can optionally provide a voltage feedforward. 131 * <p> 132 * Motion Magic® Expo produces a motion profile in real-time while attempting to 133 * honor the Cruise Velocity (optional) and the mechanism kV and kA, specified 134 * via the Motion Magic® configuration values. Note that unlike the slot gains, 135 * the Expo_kV and Expo_kA configs are always in output units of Volts. 136 * <p> 137 * Setting Cruise Velocity to 0 will allow the profile to run to the max 138 * possible velocity based on Expo_kV. This control mode does not use the 139 * Acceleration or Jerk configs. 140 * <p> 141 * Target position can be changed on-the-fly and Motion Magic® will do its best 142 * to adjust the profile. This control mode is voltage-based, so relevant 143 * closed-loop gains will use Volts for the numerator. 144 * 145 * @param Position Position to drive toward in rotations. 146 */ 147 public MotionMagicExpoVoltage(double Position) 148 { 149 super("MotionMagicExpoVoltage"); 150 this.Position = Position; 151 } 152 153 /** 154 * Requests Motion Magic® to target a final position using an exponential motion 155 * profile. Users can optionally provide a voltage feedforward. 156 * <p> 157 * Motion Magic® Expo produces a motion profile in real-time while attempting to 158 * honor the Cruise Velocity (optional) and the mechanism kV and kA, specified 159 * via the Motion Magic® configuration values. Note that unlike the slot gains, 160 * the Expo_kV and Expo_kA configs are always in output units of Volts. 161 * <p> 162 * Setting Cruise Velocity to 0 will allow the profile to run to the max 163 * possible velocity based on Expo_kV. This control mode does not use the 164 * Acceleration or Jerk configs. 165 * <p> 166 * Target position can be changed on-the-fly and Motion Magic® will do its best 167 * to adjust the profile. This control mode is voltage-based, so relevant 168 * closed-loop gains will use Volts for the numerator. 169 * 170 * @param Position Position to drive toward in rotations. 171 */ 172 public MotionMagicExpoVoltage(Angle Position) 173 { 174 this(Position.in(Rotations)); 175 } 176 177 @Override 178 public String toString() 179 { 180 String ss = "Control: MotionMagicExpoVoltage\n"; 181 ss += " Position: " + Position + " rotations" + "\n"; 182 ss += " EnableFOC: " + EnableFOC + "\n"; 183 ss += " FeedForward: " + FeedForward + " Volts" + "\n"; 184 ss += " Slot: " + Slot + "\n"; 185 ss += " OverrideBrakeDurNeutral: " + OverrideBrakeDurNeutral + "\n"; 186 ss += " LimitForwardMotion: " + LimitForwardMotion + "\n"; 187 ss += " LimitReverseMotion: " + LimitReverseMotion + "\n"; 188 ss += " IgnoreHardwareLimits: " + IgnoreHardwareLimits + "\n"; 189 ss += " UseTimesync: " + UseTimesync + "\n"; 190 return ss; 191 } 192 193 @Override 194 public StatusCode sendRequest(String network, int deviceHash) 195 { 196 return StatusCode.valueOf(ControlJNI.JNI_RequestControlMotionMagicExpoVoltage( 197 network, deviceHash, UpdateFreqHz, Position, EnableFOC, FeedForward, Slot, OverrideBrakeDurNeutral, LimitForwardMotion, LimitReverseMotion, IgnoreHardwareLimits, UseTimesync)); 198 } 199 200 /** 201 * Gets information about this control request. 202 * 203 * @return Map of control parameter names and corresponding applied values 204 */ 205 @Override 206 public Map<String, String> getControlInfo() 207 { 208 var controlInfo = new HashMap<String, String>(); 209 controlInfo.put("Name", getName()); 210 controlInfo.put("Position", String.valueOf(this.Position)); 211 controlInfo.put("EnableFOC", String.valueOf(this.EnableFOC)); 212 controlInfo.put("FeedForward", String.valueOf(this.FeedForward)); 213 controlInfo.put("Slot", String.valueOf(this.Slot)); 214 controlInfo.put("OverrideBrakeDurNeutral", String.valueOf(this.OverrideBrakeDurNeutral)); 215 controlInfo.put("LimitForwardMotion", String.valueOf(this.LimitForwardMotion)); 216 controlInfo.put("LimitReverseMotion", String.valueOf(this.LimitReverseMotion)); 217 controlInfo.put("IgnoreHardwareLimits", String.valueOf(this.IgnoreHardwareLimits)); 218 controlInfo.put("UseTimesync", String.valueOf(this.UseTimesync)); 219 return controlInfo; 220 } 221 222 /** 223 * Modifies this Control Request's Position parameter and returns itself for 224 * method-chaining and easier to use request API. 225 * <p> 226 * Position to drive toward in rotations. 227 * 228 * <ul> 229 * <li> Units: rotations 230 * </ul> 231 * 232 * 233 * @param newPosition Parameter to modify 234 * @return Itself 235 */ 236 public MotionMagicExpoVoltage withPosition(double newPosition) 237 { 238 Position = newPosition; 239 return this; 240 } 241 242 /** 243 * Modifies this Control Request's Position parameter and returns itself for 244 * method-chaining and easier to use request API. 245 * <p> 246 * Position to drive toward in rotations. 247 * 248 * <ul> 249 * <li> Units: rotations 250 * </ul> 251 * 252 * 253 * @param newPosition Parameter to modify 254 * @return Itself 255 */ 256 public MotionMagicExpoVoltage withPosition(Angle newPosition) 257 { 258 Position = newPosition.in(Rotations); 259 return this; 260 } 261 262 /** 263 * Helper method to get this Control Request's Position parameter converted 264 * to a unit type. If not using the Java units library, {@link #Position} 265 * can be accessed directly instead. 266 * <p> 267 * Position to drive toward in rotations. 268 * 269 * <ul> 270 * <li> Units: rotations 271 * </ul> 272 * 273 * 274 * @return Position 275 */ 276 public Angle getPositionMeasure() 277 { 278 return Rotations.of(Position); 279 } 280 281 /** 282 * Modifies this Control Request's EnableFOC parameter and returns itself for 283 * method-chaining and easier to use request API. 284 * <p> 285 * Set to true to use FOC commutation (requires Phoenix Pro), which increases 286 * peak power by ~15%. Set to false to use trapezoidal commutation. 287 * <p> 288 * FOC improves motor performance by leveraging torque (current) control. 289 * However, this may be inconvenient for applications that require specifying 290 * duty cycle or voltage. CTR-Electronics has developed a hybrid method that 291 * combines the performances gains of FOC while still allowing applications to 292 * provide duty cycle or voltage demand. This not to be confused with simple 293 * sinusoidal control or phase voltage control which lacks the performance 294 * gains. 295 * 296 * @param newEnableFOC Parameter to modify 297 * @return Itself 298 */ 299 public MotionMagicExpoVoltage withEnableFOC(boolean newEnableFOC) 300 { 301 EnableFOC = newEnableFOC; 302 return this; 303 } 304 305 /** 306 * Modifies this Control Request's FeedForward parameter and returns itself for 307 * method-chaining and easier to use request API. 308 * <p> 309 * Feedforward to apply in volts 310 * 311 * <ul> 312 * <li> Units: Volts 313 * </ul> 314 * 315 * 316 * @param newFeedForward Parameter to modify 317 * @return Itself 318 */ 319 public MotionMagicExpoVoltage withFeedForward(double newFeedForward) 320 { 321 FeedForward = newFeedForward; 322 return this; 323 } 324 325 /** 326 * Modifies this Control Request's FeedForward parameter and returns itself for 327 * method-chaining and easier to use request API. 328 * <p> 329 * Feedforward to apply in volts 330 * 331 * <ul> 332 * <li> Units: Volts 333 * </ul> 334 * 335 * 336 * @param newFeedForward Parameter to modify 337 * @return Itself 338 */ 339 public MotionMagicExpoVoltage withFeedForward(Voltage newFeedForward) 340 { 341 FeedForward = newFeedForward.in(Volts); 342 return this; 343 } 344 345 /** 346 * Helper method to get this Control Request's FeedForward parameter converted 347 * to a unit type. If not using the Java units library, {@link #FeedForward} 348 * can be accessed directly instead. 349 * <p> 350 * Feedforward to apply in volts 351 * 352 * <ul> 353 * <li> Units: Volts 354 * </ul> 355 * 356 * 357 * @return FeedForward 358 */ 359 public Voltage getFeedForwardMeasure() 360 { 361 return Volts.of(FeedForward); 362 } 363 364 /** 365 * Modifies this Control Request's Slot parameter and returns itself for 366 * method-chaining and easier to use request API. 367 * <p> 368 * Select which gains are applied by selecting the slot. Use the configuration 369 * api to set the gain values for the selected slot before enabling this 370 * feature. Slot must be within [0,2]. 371 * 372 * @param newSlot Parameter to modify 373 * @return Itself 374 */ 375 public MotionMagicExpoVoltage withSlot(int newSlot) 376 { 377 Slot = newSlot; 378 return this; 379 } 380 381 /** 382 * Modifies this Control Request's OverrideBrakeDurNeutral parameter and returns itself for 383 * method-chaining and easier to use request API. 384 * <p> 385 * Set to true to static-brake the rotor when output is zero (or within 386 * deadband). Set to false to use the NeutralMode configuration setting 387 * (default). This flag exists to provide the fundamental behavior of this 388 * control when output is zero, which is to provide 0V to the motor. 389 * 390 * @param newOverrideBrakeDurNeutral Parameter to modify 391 * @return Itself 392 */ 393 public MotionMagicExpoVoltage withOverrideBrakeDurNeutral(boolean newOverrideBrakeDurNeutral) 394 { 395 OverrideBrakeDurNeutral = newOverrideBrakeDurNeutral; 396 return this; 397 } 398 399 /** 400 * Modifies this Control Request's LimitForwardMotion parameter and returns itself for 401 * method-chaining and easier to use request API. 402 * <p> 403 * Set to true to force forward limiting. This allows users to use other limit 404 * switch sensors connected to robot controller. This also allows use of active 405 * sensors that require external power. 406 * 407 * @param newLimitForwardMotion Parameter to modify 408 * @return Itself 409 */ 410 public MotionMagicExpoVoltage withLimitForwardMotion(boolean newLimitForwardMotion) 411 { 412 LimitForwardMotion = newLimitForwardMotion; 413 return this; 414 } 415 416 /** 417 * Modifies this Control Request's LimitReverseMotion parameter and returns itself for 418 * method-chaining and easier to use request API. 419 * <p> 420 * Set to true to force reverse limiting. This allows users to use other limit 421 * switch sensors connected to robot controller. This also allows use of active 422 * sensors that require external power. 423 * 424 * @param newLimitReverseMotion Parameter to modify 425 * @return Itself 426 */ 427 public MotionMagicExpoVoltage withLimitReverseMotion(boolean newLimitReverseMotion) 428 { 429 LimitReverseMotion = newLimitReverseMotion; 430 return this; 431 } 432 433 /** 434 * Modifies this Control Request's IgnoreHardwareLimits parameter and returns itself for 435 * method-chaining and easier to use request API. 436 * <p> 437 * Set to true to ignore hardware limit switches and the LimitForwardMotion and 438 * LimitReverseMotion parameters, instead allowing motion. 439 * <p> 440 * This can be useful on mechanisms such as an intake/feeder, where a limit 441 * switch stops motion while intaking but should be ignored when feeding to a 442 * shooter. 443 * <p> 444 * The hardware limit faults and Forward/ReverseLimit signals will still report 445 * the values of the limit switches regardless of this parameter. 446 * 447 * @param newIgnoreHardwareLimits Parameter to modify 448 * @return Itself 449 */ 450 public MotionMagicExpoVoltage withIgnoreHardwareLimits(boolean newIgnoreHardwareLimits) 451 { 452 IgnoreHardwareLimits = newIgnoreHardwareLimits; 453 return this; 454 } 455 456 /** 457 * Modifies this Control Request's UseTimesync parameter and returns itself for 458 * method-chaining and easier to use request API. 459 * <p> 460 * Set to true to delay applying this control request until a timesync boundary 461 * (requires Phoenix Pro and CANivore). This eliminates the impact of 462 * nondeterministic network delays in exchange for a larger but deterministic 463 * control latency. 464 * <p> 465 * This requires setting the ControlTimesyncFreqHz config in MotorOutputConfigs. 466 * Additionally, when this is enabled, the UpdateFreqHz of this request should 467 * be set to 0 Hz. 468 * 469 * @param newUseTimesync Parameter to modify 470 * @return Itself 471 */ 472 public MotionMagicExpoVoltage withUseTimesync(boolean newUseTimesync) 473 { 474 UseTimesync = newUseTimesync; 475 return this; 476 } 477 478 /** 479 * Sets the period at which this control will update at. 480 * This is designated in Hertz, with a minimum of 20 Hz 481 * (every 50 ms) and a maximum of 1000 Hz (every 1 ms). 482 * <p> 483 * If this field is set to 0 Hz, the control request will 484 * be sent immediately as a one-shot frame. This may be useful 485 * for advanced applications that require outputs to be 486 * synchronized with data acquisition. In this case, we 487 * recommend not exceeding 50 ms between control calls. 488 * 489 * @param newUpdateFreqHz Parameter to modify 490 * @return Itself 491 */ 492 @Override 493 public MotionMagicExpoVoltage withUpdateFreqHz(double newUpdateFreqHz) 494 { 495 UpdateFreqHz = newUpdateFreqHz; 496 return this; 497 } 498 499 /** 500 * Sets the period at which this control will update at. 501 * This is designated in Hertz, with a minimum of 20 Hz 502 * (every 50 ms) and a maximum of 1000 Hz (every 1 ms). 503 * <p> 504 * If this field is set to 0 Hz, the control request will 505 * be sent immediately as a one-shot frame. This may be useful 506 * for advanced applications that require outputs to be 507 * synchronized with data acquisition. In this case, we 508 * recommend not exceeding 50 ms between control calls. 509 * 510 * @param newUpdateFreqHz Parameter to modify 511 * @return Itself 512 */ 513 public MotionMagicExpoVoltage withUpdateFreqHz(Frequency newUpdateFreqHz) 514 { 515 UpdateFreqHz = newUpdateFreqHz.in(Hertz); 516 return this; 517 } 518 519 @Override 520 public MotionMagicExpoVoltage clone() 521 { 522 try { 523 return (MotionMagicExpoVoltage)super.clone(); 524 } catch (CloneNotSupportedException ex) { 525 /* this should never happen */ 526 throw new RuntimeException(ex); 527 } 528 } 529} 530