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