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