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 * Follow the motor output of another Talon. 022 * <p> 023 * If Talon is in torque control, the torque is copied - which will increase the total torque applied. If 024 * Talon is in percent supply output control, the duty cycle is matched. Motor direction either matches 025 * master's configured direction or opposes it based on OpposeMasterDirection. 026 */ 027public class Follower extends ControlRequest implements Cloneable 028{ 029 /** 030 * Device ID of the master to follow. 031 */ 032 public int MasterID; 033 /** 034 * Set to false for motor invert to match the master's configured Invert - which 035 * is typical when master and follower are mechanically linked and spin in the 036 * same direction. Set to true for motor invert to oppose the master's 037 * configured Invert - this is typical where the the master and follower 038 * mechanically spin in opposite directions. 039 */ 040 public boolean OpposeMasterDirection; 041 042 /** 043 * The period at which this control will update at. 044 * This is designated in Hertz, with a minimum of 20 Hz 045 * (every 50 ms) and a maximum of 1000 Hz (every 1 ms). 046 * <p> 047 * If this field is set to 0 Hz, the control request will 048 * be sent immediately as a one-shot frame. This may be useful 049 * for advanced applications that require outputs to be 050 * synchronized with data acquisition. In this case, we 051 * recommend not exceeding 50 ms between control calls. 052 */ 053 public double UpdateFreqHz = 20; 054 055 /** 056 * Follow the motor output of another Talon. 057 * <p> 058 * If Talon is in torque control, the torque is copied - which will increase the 059 * total torque applied. If Talon is in percent supply output control, the duty 060 * cycle is matched. Motor direction either matches master's configured 061 * direction or opposes it based on OpposeMasterDirection. 062 * 063 * @param MasterID Device ID of the master to follow. 064 * @param OpposeMasterDirection Set to false for motor invert to match the 065 * master's configured Invert - which is typical 066 * when master and follower are mechanically 067 * linked and spin in the same direction. Set 068 * to true for motor invert to oppose the 069 * master's configured Invert - this is typical 070 * where the the master and follower 071 * mechanically spin in opposite directions. 072 */ 073 public Follower(int MasterID, boolean OpposeMasterDirection) 074 { 075 super("Follower"); 076 this.MasterID = MasterID; 077 this.OpposeMasterDirection = OpposeMasterDirection; 078 } 079 080 @Override 081 public String toString() 082 { 083 String ss = "Control: Follower\n"; 084 ss += " MasterID: " + MasterID + "\n"; 085 ss += " OpposeMasterDirection: " + OpposeMasterDirection + "\n"; 086 return ss; 087 } 088 089 @Override 090 public StatusCode sendRequest(String network, int deviceHash) 091 { 092 return StatusCode.valueOf(ControlJNI.JNI_RequestControlFollower( 093 network, deviceHash, UpdateFreqHz, MasterID, OpposeMasterDirection)); 094 } 095 096 /** 097 * Gets information about this control request. 098 * 099 * @return Map of control parameter names and corresponding applied values 100 */ 101 @Override 102 public Map<String, String> getControlInfo() 103 { 104 var controlInfo = new HashMap<String, String>(); 105 controlInfo.put("Name", getName()); 106 controlInfo.put("MasterID", String.valueOf(this.MasterID)); 107 controlInfo.put("OpposeMasterDirection", String.valueOf(this.OpposeMasterDirection)); 108 return controlInfo; 109 } 110 111 /** 112 * Modifies this Control Request's MasterID parameter and returns itself for 113 * method-chaining and easier to use request API. 114 * <p> 115 * Device ID of the master to follow. 116 * 117 * @param newMasterID Parameter to modify 118 * @return Itself 119 */ 120 public Follower withMasterID(int newMasterID) 121 { 122 MasterID = newMasterID; 123 return this; 124 } 125 126 /** 127 * Modifies this Control Request's OpposeMasterDirection parameter and returns itself for 128 * method-chaining and easier to use request API. 129 * <p> 130 * Set to false for motor invert to match the master's configured Invert - which 131 * is typical when master and follower are mechanically linked and spin in the 132 * same direction. Set to true for motor invert to oppose the master's 133 * configured Invert - this is typical where the the master and follower 134 * mechanically spin in opposite directions. 135 * 136 * @param newOpposeMasterDirection Parameter to modify 137 * @return Itself 138 */ 139 public Follower withOpposeMasterDirection(boolean newOpposeMasterDirection) 140 { 141 OpposeMasterDirection = newOpposeMasterDirection; 142 return this; 143 } 144 145 /** 146 * Sets the period at which this control will update at. 147 * This is designated in Hertz, with a minimum of 20 Hz 148 * (every 50 ms) and a maximum of 1000 Hz (every 1 ms). 149 * <p> 150 * If this field is set to 0 Hz, the control request will 151 * be sent immediately as a one-shot frame. This may be useful 152 * for advanced applications that require outputs to be 153 * synchronized with data acquisition. In this case, we 154 * recommend not exceeding 50 ms between control calls. 155 * 156 * @param newUpdateFreqHz Parameter to modify 157 * @return Itself 158 */ 159 @Override 160 public Follower withUpdateFreqHz(double newUpdateFreqHz) 161 { 162 UpdateFreqHz = newUpdateFreqHz; 163 return this; 164 } 165 166 /** 167 * Sets the period at which this control will update at. 168 * This is designated in Hertz, with a minimum of 20 Hz 169 * (every 50 ms) and a maximum of 1000 Hz (every 1 ms). 170 * <p> 171 * If this field is set to 0 Hz, the control request will 172 * be sent immediately as a one-shot frame. This may be useful 173 * for advanced applications that require outputs to be 174 * synchronized with data acquisition. In this case, we 175 * recommend not exceeding 50 ms between control calls. 176 * 177 * @param newUpdateFreqHz Parameter to modify 178 * @return Itself 179 */ 180 @Override 181 public Follower withUpdateFreqHz(Frequency newUpdateFreqHz) 182 { 183 UpdateFreqHz = newUpdateFreqHz.in(Hertz); 184 return this; 185 } 186 187 @Override 188 public Follower clone() 189 { 190 try { 191 return (Follower)super.clone(); 192 } catch (CloneNotSupportedException ex) { 193 /* this should never happen */ 194 throw new RuntimeException(ex); 195 } 196 } 197} 198