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.kinematics;
006
007import static edu.wpi.first.units.Units.MetersPerSecond;
008
009import edu.wpi.first.math.kinematics.proto.DifferentialDriveWheelSpeedsProto;
010import edu.wpi.first.math.kinematics.struct.DifferentialDriveWheelSpeedsStruct;
011import edu.wpi.first.units.Distance;
012import edu.wpi.first.units.Measure;
013import edu.wpi.first.units.Velocity;
014
015/** Represents the wheel speeds for a differential drive drivetrain. */
016public class DifferentialDriveWheelSpeeds {
017  /** Speed of the left side of the robot. */
018  public double leftMetersPerSecond;
019
020  /** Speed of the right side of the robot. */
021  public double rightMetersPerSecond;
022
023  public static final DifferentialDriveWheelSpeedsProto proto =
024      new DifferentialDriveWheelSpeedsProto();
025  public static final DifferentialDriveWheelSpeedsStruct struct =
026      new DifferentialDriveWheelSpeedsStruct();
027
028  /** Constructs a DifferentialDriveWheelSpeeds with zeros for left and right speeds. */
029  public DifferentialDriveWheelSpeeds() {}
030
031  /**
032   * Constructs a DifferentialDriveWheelSpeeds.
033   *
034   * @param leftMetersPerSecond The left speed.
035   * @param rightMetersPerSecond The right speed.
036   */
037  public DifferentialDriveWheelSpeeds(double leftMetersPerSecond, double rightMetersPerSecond) {
038    this.leftMetersPerSecond = leftMetersPerSecond;
039    this.rightMetersPerSecond = rightMetersPerSecond;
040  }
041
042  /**
043   * Constructs a DifferentialDriveWheelSpeeds.
044   *
045   * @param left The left speed.
046   * @param right The right speed.
047   */
048  public DifferentialDriveWheelSpeeds(
049      Measure<Velocity<Distance>> left, Measure<Velocity<Distance>> right) {
050    this(left.in(MetersPerSecond), right.in(MetersPerSecond));
051  }
052
053  /**
054   * Renormalizes the wheel speeds if any either side is above the specified maximum.
055   *
056   * <p>Sometimes, after inverse kinematics, the requested speed from one or more wheels may be
057   * above the max attainable speed for the driving motor on that wheel. To fix this issue, one can
058   * reduce all the wheel speeds to make sure that all requested module speeds are at-or-below the
059   * absolute threshold, while maintaining the ratio of speeds between wheels.
060   *
061   * @param attainableMaxSpeedMetersPerSecond The absolute max speed that a wheel can reach.
062   */
063  public void desaturate(double attainableMaxSpeedMetersPerSecond) {
064    double realMaxSpeed = Math.max(Math.abs(leftMetersPerSecond), Math.abs(rightMetersPerSecond));
065
066    if (realMaxSpeed > attainableMaxSpeedMetersPerSecond) {
067      leftMetersPerSecond = leftMetersPerSecond / realMaxSpeed * attainableMaxSpeedMetersPerSecond;
068      rightMetersPerSecond =
069          rightMetersPerSecond / realMaxSpeed * attainableMaxSpeedMetersPerSecond;
070    }
071  }
072
073  /**
074   * Renormalizes the wheel speeds if any either side is above the specified maximum.
075   *
076   * <p>Sometimes, after inverse kinematics, the requested speed from one or more wheels may be
077   * above the max attainable speed for the driving motor on that wheel. To fix this issue, one can
078   * reduce all the wheel speeds to make sure that all requested module speeds are at-or-below the
079   * absolute threshold, while maintaining the ratio of speeds between wheels.
080   *
081   * @param attainableMaxSpeed The absolute max speed that a wheel can reach.
082   */
083  public void desaturate(Measure<Velocity<Distance>> attainableMaxSpeed) {
084    desaturate(attainableMaxSpeed.in(MetersPerSecond));
085  }
086
087  /**
088   * Adds two DifferentialDriveWheelSpeeds and returns the sum.
089   *
090   * <p>For example, DifferentialDriveWheelSpeeds{1.0, 0.5} + DifferentialDriveWheelSpeeds{2.0, 1.5}
091   * = DifferentialDriveWheelSpeeds{3.0, 2.0}
092   *
093   * @param other The DifferentialDriveWheelSpeeds to add.
094   * @return The sum of the DifferentialDriveWheelSpeeds.
095   */
096  public DifferentialDriveWheelSpeeds plus(DifferentialDriveWheelSpeeds other) {
097    return new DifferentialDriveWheelSpeeds(
098        leftMetersPerSecond + other.leftMetersPerSecond,
099        rightMetersPerSecond + other.rightMetersPerSecond);
100  }
101
102  /**
103   * Subtracts the other DifferentialDriveWheelSpeeds from the current DifferentialDriveWheelSpeeds
104   * and returns the difference.
105   *
106   * <p>For example, DifferentialDriveWheelSpeeds{5.0, 4.0} - DifferentialDriveWheelSpeeds{1.0, 2.0}
107   * = DifferentialDriveWheelSpeeds{4.0, 2.0}
108   *
109   * @param other The DifferentialDriveWheelSpeeds to subtract.
110   * @return The difference between the two DifferentialDriveWheelSpeeds.
111   */
112  public DifferentialDriveWheelSpeeds minus(DifferentialDriveWheelSpeeds other) {
113    return new DifferentialDriveWheelSpeeds(
114        leftMetersPerSecond - other.leftMetersPerSecond,
115        rightMetersPerSecond - other.rightMetersPerSecond);
116  }
117
118  /**
119   * Returns the inverse of the current DifferentialDriveWheelSpeeds. This is equivalent to negating
120   * all components of the DifferentialDriveWheelSpeeds.
121   *
122   * @return The inverse of the current DifferentialDriveWheelSpeeds.
123   */
124  public DifferentialDriveWheelSpeeds unaryMinus() {
125    return new DifferentialDriveWheelSpeeds(-leftMetersPerSecond, -rightMetersPerSecond);
126  }
127
128  /**
129   * Multiplies the DifferentialDriveWheelSpeeds by a scalar and returns the new
130   * DifferentialDriveWheelSpeeds.
131   *
132   * <p>For example, DifferentialDriveWheelSpeeds{2.0, 2.5} * 2 = DifferentialDriveWheelSpeeds{4.0,
133   * 5.0}
134   *
135   * @param scalar The scalar to multiply by.
136   * @return The scaled DifferentialDriveWheelSpeeds.
137   */
138  public DifferentialDriveWheelSpeeds times(double scalar) {
139    return new DifferentialDriveWheelSpeeds(
140        leftMetersPerSecond * scalar, rightMetersPerSecond * scalar);
141  }
142
143  /**
144   * Divides the DifferentialDriveWheelSpeeds by a scalar and returns the new
145   * DifferentialDriveWheelSpeeds.
146   *
147   * <p>For example, DifferentialDriveWheelSpeeds{2.0, 2.5} / 2 = DifferentialDriveWheelSpeeds{1.0,
148   * 1.25}
149   *
150   * @param scalar The scalar to divide by.
151   * @return The scaled DifferentialDriveWheelSpeeds.
152   */
153  public DifferentialDriveWheelSpeeds div(double scalar) {
154    return new DifferentialDriveWheelSpeeds(
155        leftMetersPerSecond / scalar, rightMetersPerSecond / scalar);
156  }
157
158  @Override
159  public String toString() {
160    return String.format(
161        "DifferentialDriveWheelSpeeds(Left: %.2f m/s, Right: %.2f m/s)",
162        leftMetersPerSecond, rightMetersPerSecond);
163  }
164}