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}