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}