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.Meters;
008
009import edu.wpi.first.math.MathSharedStore;
010import edu.wpi.first.math.MathUsageId;
011import edu.wpi.first.math.geometry.Pose2d;
012import edu.wpi.first.math.geometry.Rotation2d;
013import edu.wpi.first.units.measure.Distance;
014
015/**
016 * Class for differential drive odometry. Odometry allows you to track the robot's position on the
017 * field over the course of a match using readings from 2 encoders and a gyroscope.
018 *
019 * <p>Teams can use odometry during the autonomous period for complex tasks like path following.
020 * Furthermore, odometry can be used for latency compensation when using computer-vision systems.
021 *
022 * <p>It is important that you reset your encoders to zero before using this class. Any subsequent
023 * pose resets also require the encoders to be reset to zero.
024 */
025public class DifferentialDriveOdometry extends Odometry<DifferentialDriveWheelPositions> {
026  /**
027   * Constructs a DifferentialDriveOdometry object.
028   *
029   * @param gyroAngle The angle reported by the gyroscope.
030   * @param leftDistanceMeters The distance traveled by the left encoder.
031   * @param rightDistanceMeters The distance traveled by the right encoder.
032   * @param initialPoseMeters The starting position of the robot on the field.
033   */
034  public DifferentialDriveOdometry(
035      Rotation2d gyroAngle,
036      double leftDistanceMeters,
037      double rightDistanceMeters,
038      Pose2d initialPoseMeters) {
039    super(
040        new DifferentialDriveKinematics(1),
041        gyroAngle,
042        new DifferentialDriveWheelPositions(leftDistanceMeters, rightDistanceMeters),
043        initialPoseMeters);
044    MathSharedStore.reportUsage(MathUsageId.kOdometry_DifferentialDrive, 1);
045  }
046
047  /**
048   * Constructs a DifferentialDriveOdometry object.
049   *
050   * @param gyroAngle The angle reported by the gyroscope.
051   * @param leftDistance The distance traveled by the left encoder.
052   * @param rightDistance The distance traveled by the right encoder.
053   * @param initialPoseMeters The starting position of the robot on the field.
054   */
055  public DifferentialDriveOdometry(
056      Rotation2d gyroAngle,
057      Distance leftDistance,
058      Distance rightDistance,
059      Pose2d initialPoseMeters) {
060    this(gyroAngle, leftDistance.in(Meters), rightDistance.in(Meters), initialPoseMeters);
061  }
062
063  /**
064   * Constructs a DifferentialDriveOdometry object.
065   *
066   * @param gyroAngle The angle reported by the gyroscope.
067   * @param leftDistanceMeters The distance traveled by the left encoder.
068   * @param rightDistanceMeters The distance traveled by the right encoder.
069   */
070  public DifferentialDriveOdometry(
071      Rotation2d gyroAngle, double leftDistanceMeters, double rightDistanceMeters) {
072    this(gyroAngle, leftDistanceMeters, rightDistanceMeters, Pose2d.kZero);
073  }
074
075  /**
076   * Constructs a DifferentialDriveOdometry object.
077   *
078   * @param gyroAngle The angle reported by the gyroscope.
079   * @param leftDistance The distance traveled by the left encoder.
080   * @param rightDistance The distance traveled by the right encoder.
081   */
082  public DifferentialDriveOdometry(
083      Rotation2d gyroAngle, Distance leftDistance, Distance rightDistance) {
084    this(gyroAngle, leftDistance, rightDistance, Pose2d.kZero);
085  }
086
087  /**
088   * Resets the robot's position on the field.
089   *
090   * <p>The gyroscope angle does not need to be reset here on the user's robot code. The library
091   * automatically takes care of offsetting the gyro angle.
092   *
093   * @param gyroAngle The angle reported by the gyroscope.
094   * @param leftDistanceMeters The distance traveled by the left encoder.
095   * @param rightDistanceMeters The distance traveled by the right encoder.
096   * @param poseMeters The position on the field that your robot is at.
097   */
098  public void resetPosition(
099      Rotation2d gyroAngle,
100      double leftDistanceMeters,
101      double rightDistanceMeters,
102      Pose2d poseMeters) {
103    super.resetPosition(
104        gyroAngle,
105        new DifferentialDriveWheelPositions(leftDistanceMeters, rightDistanceMeters),
106        poseMeters);
107  }
108
109  /**
110   * Resets the robot's position on the field.
111   *
112   * <p>The gyroscope angle does not need to be reset here on the user's robot code. The library
113   * automatically takes care of offsetting the gyro angle.
114   *
115   * @param gyroAngle The angle reported by the gyroscope.
116   * @param leftDistance The distance traveled by the left encoder.
117   * @param rightDistance The distance traveled by the right encoder.
118   * @param poseMeters The position on the field that your robot is at.
119   */
120  public void resetPosition(
121      Rotation2d gyroAngle, Distance leftDistance, Distance rightDistance, Pose2d poseMeters) {
122    resetPosition(gyroAngle, leftDistance.in(Meters), rightDistance.in(Meters), poseMeters);
123  }
124
125  /**
126   * Updates the robot position on the field using distance measurements from encoders. This method
127   * is more numerically accurate than using velocities to integrate the pose and is also
128   * advantageous for teams that are using lower CPR encoders.
129   *
130   * @param gyroAngle The angle reported by the gyroscope.
131   * @param leftDistanceMeters The distance traveled by the left encoder.
132   * @param rightDistanceMeters The distance traveled by the right encoder.
133   * @return The new pose of the robot.
134   */
135  public Pose2d update(
136      Rotation2d gyroAngle, double leftDistanceMeters, double rightDistanceMeters) {
137    return super.update(
138        gyroAngle, new DifferentialDriveWheelPositions(leftDistanceMeters, rightDistanceMeters));
139  }
140}