001// Copyright (c) FIRST and other WPILib contributors.
002// Open Source Software; you can modify and/or share it under the terms of
003// the WPILib BSD license file in the root directory of this project.
004
005package edu.wpi.first.math.system.plant;
006
007import edu.wpi.first.math.system.plant.proto.DCMotorProto;
008import edu.wpi.first.math.system.plant.struct.DCMotorStruct;
009import edu.wpi.first.math.util.Units;
010import edu.wpi.first.util.protobuf.ProtobufSerializable;
011import edu.wpi.first.util.struct.StructSerializable;
012
013/** Holds the constants for a DC motor. */
014public class DCMotor implements ProtobufSerializable, StructSerializable {
015  /** Voltage at which the motor constants were measured. */
016  public final double nominalVoltageVolts;
017
018  /** Torque when stalled. */
019  public final double stallTorqueNewtonMeters;
020
021  /** Current draw when stalled. */
022  public final double stallCurrentAmps;
023
024  /** Current draw under no load. */
025  public final double freeCurrentAmps;
026
027  /** Angular velocity under no load. */
028  public final double freeSpeedRadPerSec;
029
030  /** Motor internal resistance. */
031  public final double rOhms;
032
033  /** Motor velocity constant. */
034  public final double KvRadPerSecPerVolt;
035
036  /** Motor torque constant. */
037  public final double KtNMPerAmp;
038
039  /** DCMotor protobuf for serialization. */
040  public static final DCMotorProto proto = new DCMotorProto();
041
042  /** DCMotor struct for serialization. */
043  public static final DCMotorStruct struct = new DCMotorStruct();
044
045  /**
046   * Constructs a DC motor.
047   *
048   * @param nominalVoltageVolts Voltage at which the motor constants were measured.
049   * @param stallTorqueNewtonMeters Torque when stalled.
050   * @param stallCurrentAmps Current draw when stalled.
051   * @param freeCurrentAmps Current draw under no load.
052   * @param freeSpeedRadPerSec Angular velocity under no load.
053   * @param numMotors Number of motors in a gearbox.
054   */
055  public DCMotor(
056      double nominalVoltageVolts,
057      double stallTorqueNewtonMeters,
058      double stallCurrentAmps,
059      double freeCurrentAmps,
060      double freeSpeedRadPerSec,
061      int numMotors) {
062    this.nominalVoltageVolts = nominalVoltageVolts;
063    this.stallTorqueNewtonMeters = stallTorqueNewtonMeters * numMotors;
064    this.stallCurrentAmps = stallCurrentAmps * numMotors;
065    this.freeCurrentAmps = freeCurrentAmps * numMotors;
066    this.freeSpeedRadPerSec = freeSpeedRadPerSec;
067
068    this.rOhms = nominalVoltageVolts / this.stallCurrentAmps;
069    this.KvRadPerSecPerVolt =
070        freeSpeedRadPerSec / (nominalVoltageVolts - rOhms * this.freeCurrentAmps);
071    this.KtNMPerAmp = this.stallTorqueNewtonMeters / this.stallCurrentAmps;
072  }
073
074  /**
075   * Calculate current drawn by motor with given speed and input voltage.
076   *
077   * @param speedRadiansPerSec The current angular velocity of the motor.
078   * @param voltageInputVolts The voltage being applied to the motor.
079   * @return The estimated current.
080   */
081  public double getCurrent(double speedRadiansPerSec, double voltageInputVolts) {
082    return -1.0 / KvRadPerSecPerVolt / rOhms * speedRadiansPerSec + 1.0 / rOhms * voltageInputVolts;
083  }
084
085  /**
086   * Calculate current drawn by motor for a given torque.
087   *
088   * @param torqueNm The torque produced by the motor.
089   * @return The current drawn by the motor.
090   */
091  public double getCurrent(double torqueNm) {
092    return torqueNm / KtNMPerAmp;
093  }
094
095  /**
096   * Calculate torque produced by the motor with a given current.
097   *
098   * @param currentAmpere The current drawn by the motor.
099   * @return The torque output.
100   */
101  public double getTorque(double currentAmpere) {
102    return currentAmpere * KtNMPerAmp;
103  }
104
105  /**
106   * Calculate the voltage provided to the motor for a given torque and angular velocity.
107   *
108   * @param torqueNm The torque produced by the motor.
109   * @param speedRadiansPerSec The current angular velocity of the motor.
110   * @return The voltage of the motor.
111   */
112  public double getVoltage(double torqueNm, double speedRadiansPerSec) {
113    return 1.0 / KvRadPerSecPerVolt * speedRadiansPerSec + 1.0 / KtNMPerAmp * rOhms * torqueNm;
114  }
115
116  /**
117   * Calculates the angular speed produced by the motor at a given torque and input voltage.
118   *
119   * @param torqueNm The torque produced by the motor.
120   * @param voltageInputVolts The voltage applied to the motor.
121   * @return The angular speed of the motor.
122   */
123  public double getSpeed(double torqueNm, double voltageInputVolts) {
124    return voltageInputVolts * KvRadPerSecPerVolt
125        - 1.0 / KtNMPerAmp * torqueNm * rOhms * KvRadPerSecPerVolt;
126  }
127
128  /**
129   * Returns a copy of this motor with the given gearbox reduction applied.
130   *
131   * @param gearboxReduction The gearbox reduction.
132   * @return A motor with the gearbox reduction applied.
133   */
134  public DCMotor withReduction(double gearboxReduction) {
135    return new DCMotor(
136        nominalVoltageVolts,
137        stallTorqueNewtonMeters * gearboxReduction,
138        stallCurrentAmps,
139        freeCurrentAmps,
140        freeSpeedRadPerSec / gearboxReduction,
141        1);
142  }
143
144  /**
145   * Return a gearbox of CIM motors.
146   *
147   * @param numMotors Number of motors in the gearbox.
148   * @return A gearbox of CIM motors.
149   */
150  public static DCMotor getCIM(int numMotors) {
151    return new DCMotor(
152        12, 2.42, 133, 2.7, Units.rotationsPerMinuteToRadiansPerSecond(5310), numMotors);
153  }
154
155  /**
156   * Return a gearbox of 775Pro motors.
157   *
158   * @param numMotors Number of motors in the gearbox.
159   * @return A gearbox of 775Pro motors.
160   */
161  public static DCMotor getVex775Pro(int numMotors) {
162    return new DCMotor(
163        12, 0.71, 134, 0.7, Units.rotationsPerMinuteToRadiansPerSecond(18730), numMotors);
164  }
165
166  /**
167   * Return a gearbox of NEO motors.
168   *
169   * @param numMotors Number of motors in the gearbox.
170   * @return A gearbox of NEO motors.
171   */
172  public static DCMotor getNEO(int numMotors) {
173    return new DCMotor(
174        12, 2.6, 105, 1.8, Units.rotationsPerMinuteToRadiansPerSecond(5676), numMotors);
175  }
176
177  /**
178   * Return a gearbox of MiniCIM motors.
179   *
180   * @param numMotors Number of motors in the gearbox.
181   * @return A gearbox of MiniCIM motors.
182   */
183  public static DCMotor getMiniCIM(int numMotors) {
184    return new DCMotor(
185        12, 1.41, 89, 3, Units.rotationsPerMinuteToRadiansPerSecond(5840), numMotors);
186  }
187
188  /**
189   * Return a gearbox of Bag motors.
190   *
191   * @param numMotors Number of motors in the gearbox.
192   * @return A gearbox of Bag motors.
193   */
194  public static DCMotor getBag(int numMotors) {
195    return new DCMotor(
196        12, 0.43, 53, 1.8, Units.rotationsPerMinuteToRadiansPerSecond(13180), numMotors);
197  }
198
199  /**
200   * Return a gearbox of Andymark RS775-125 motors.
201   *
202   * @param numMotors Number of motors in the gearbox.
203   * @return A gearbox of Andymark RS775-125 motors.
204   */
205  public static DCMotor getAndymarkRs775_125(int numMotors) {
206    return new DCMotor(
207        12, 0.28, 18, 1.6, Units.rotationsPerMinuteToRadiansPerSecond(5800.0), numMotors);
208  }
209
210  /**
211   * Return a gearbox of Banebots RS775 motors.
212   *
213   * @param numMotors Number of motors in the gearbox.
214   * @return A gearbox of Banebots RS775 motors.
215   */
216  public static DCMotor getBanebotsRs775(int numMotors) {
217    return new DCMotor(
218        12, 0.72, 97, 2.7, Units.rotationsPerMinuteToRadiansPerSecond(13050.0), numMotors);
219  }
220
221  /**
222   * Return a gearbox of Andymark 9015 motors.
223   *
224   * @param numMotors Number of motors in the gearbox.
225   * @return A gearbox of Andymark 9015 motors.
226   */
227  public static DCMotor getAndymark9015(int numMotors) {
228    return new DCMotor(
229        12, 0.36, 71, 3.7, Units.rotationsPerMinuteToRadiansPerSecond(14270.0), numMotors);
230  }
231
232  /**
233   * Return a gearbox of Banebots RS 550 motors.
234   *
235   * @param numMotors Number of motors in the gearbox.
236   * @return A gearbox of Banebots RS 550 motors.
237   */
238  public static DCMotor getBanebotsRs550(int numMotors) {
239    return new DCMotor(
240        12, 0.38, 84, 0.4, Units.rotationsPerMinuteToRadiansPerSecond(19000.0), numMotors);
241  }
242
243  /**
244   * Return a gearbox of NEO 550 motors.
245   *
246   * @param numMotors Number of motors in the gearbox.
247   * @return A gearbox of NEO 550 motors.
248   */
249  public static DCMotor getNeo550(int numMotors) {
250    return new DCMotor(
251        12, 0.97, 100, 1.4, Units.rotationsPerMinuteToRadiansPerSecond(11000.0), numMotors);
252  }
253
254  /**
255   * Return a gearbox of Falcon 500 motors.
256   *
257   * @param numMotors Number of motors in the gearbox.
258   * @return A gearbox of Falcon 500 motors.
259   */
260  public static DCMotor getFalcon500(int numMotors) {
261    return new DCMotor(
262        12, 4.69, 257, 1.5, Units.rotationsPerMinuteToRadiansPerSecond(6380.0), numMotors);
263  }
264
265  /**
266   * Return a gearbox of Falcon 500 motors with FOC (Field-Oriented Control) enabled.
267   *
268   * @param numMotors Number of motors in the gearbox.
269   * @return A gearbox of Falcon 500 FOC enabled motors.
270   */
271  public static DCMotor getFalcon500Foc(int numMotors) {
272    // https://store.ctr-electronics.com/falcon-500-powered-by-talon-fx/
273    return new DCMotor(
274        12, 5.84, 304, 1.5, Units.rotationsPerMinuteToRadiansPerSecond(6080.0), numMotors);
275  }
276
277  /**
278   * Return a gearbox of Romi/TI_RSLK MAX motors.
279   *
280   * @param numMotors Number of motors in the gearbox.
281   * @return A gearbox of Romi/TI_RSLK MAX motors.
282   */
283  public static DCMotor getRomiBuiltIn(int numMotors) {
284    // From https://www.pololu.com/product/1520/specs
285    return new DCMotor(
286        4.5, 0.1765, 1.25, 0.13, Units.rotationsPerMinuteToRadiansPerSecond(150.0), numMotors);
287  }
288
289  /**
290   * Return a gearbox of Kraken X60 brushless motors.
291   *
292   * @param numMotors Number of motors in the gearbox.
293   * @return a gearbox of Kraken X60 motors.
294   */
295  public static DCMotor getKrakenX60(int numMotors) {
296    // From https://store.ctr-electronics.com/announcing-kraken-x60/
297    return new DCMotor(
298        12, 7.09, 366, 2, Units.rotationsPerMinuteToRadiansPerSecond(6000), numMotors);
299  }
300
301  /**
302   * Return a gearbox of Kraken X60 brushless motors with FOC (Field-Oriented Control) enabled.
303   *
304   * @param numMotors Number of motors in the gearbox.
305   * @return A gearbox of Kraken X60 FOC enabled motors.
306   */
307  public static DCMotor getKrakenX60Foc(int numMotors) {
308    // From https://store.ctr-electronics.com/announcing-kraken-x60/
309    return new DCMotor(
310        12, 9.37, 483, 2, Units.rotationsPerMinuteToRadiansPerSecond(5800), numMotors);
311  }
312
313  /**
314   * Return a gearbox of Neo Vortex brushless motors.
315   *
316   * @param numMotors Number of motors in the gearbox.
317   * @return a gearbox of Neo Vortex motors.
318   */
319  public static DCMotor getNeoVortex(int numMotors) {
320    // From https://www.revrobotics.com/next-generation-spark-neo/
321    return new DCMotor(
322        12, 3.60, 211, 3.6, Units.rotationsPerMinuteToRadiansPerSecond(6784), numMotors);
323  }
324}