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