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