WPILibC++ 2023.4.3
DifferentialDrivePoseEstimator.h
Go to the documentation of this file.
1// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5#pragma once
6
7#include <wpi/SymbolExports.h>
8#include <wpi/array.h>
9
10#include "frc/EigenCore.h"
11#include "frc/geometry/Pose2d.h"
17#include "units/time.h"
18
19namespace frc {
20/**
21 * This class wraps Differential Drive Odometry to fuse latency-compensated
22 * vision measurements with differential drive encoder measurements. It will
23 * correct for noisy vision measurements and encoder drift. It is intended to be
24 * an easy drop-in for DifferentialDriveOdometry. In fact, if you never call
25 * AddVisionMeasurement(), and only call Update(), this will behave exactly the
26 * same as DifferentialDriveOdometry.
27 *
28 * Update() should be called every robot loop (if your robot loops are faster or
29 * slower than the default of 20 ms, then you should change the nominal delta
30 * time via the constructor).
31 *
32 * AddVisionMeasurement() can be called as infrequently as you want; if you
33 * never call it, then this class will behave like regular encoder odometry.
34 */
36 public:
37 /**
38 * Constructs a DifferentialDrivePoseEstimator with default standard
39 * deviations for the model and vision measurements.
40 *
41 * The default standard deviations of the model states are
42 * 0.02 meters for x, 0.02 meters for y, and 0.01 radians for heading.
43 * The default standard deviations of the vision measurements are
44 * 0.1 meters for x, 0.1 meters for y, and 0.1 radians for heading.
45 *
46 * @param kinematics A correctly-configured kinematics object for your
47 * drivetrain.
48 * @param gyroAngle The gyro angle of the robot.
49 * @param leftDistance The distance traveled by the left encoder.
50 * @param rightDistance The distance traveled by the right encoder.
51 * @param initialPose The estimated initial pose.
52 */
54 const Rotation2d& gyroAngle,
55 units::meter_t leftDistance,
56 units::meter_t rightDistance,
57 const Pose2d& initialPose);
58
59 /**
60 * Constructs a DifferentialDrivePoseEstimator.
61 *
62 * @param kinematics A correctly-configured kinematics object for your
63 * drivetrain.
64 * @param gyroAngle The gyro angle of the robot.
65 * @param leftDistance The distance traveled by the left encoder.
66 * @param rightDistance The distance traveled by the right encoder.
67 * @param initialPose The estimated initial pose.
68 * @param stateStdDevs Standard deviations of the pose estimate (x position in
69 * meters, y position in meters, and heading in radians). Increase these
70 * numbers to trust your state estimate less.
71 * @param visionMeasurementStdDevs Standard deviations of the vision pose
72 * measurement (x position in meters, y position in meters, and heading in
73 * radians). Increase these numbers to trust the vision pose measurement
74 * less.
75 */
77 DifferentialDriveKinematics& kinematics, const Rotation2d& gyroAngle,
78 units::meter_t leftDistance, units::meter_t rightDistance,
79 const Pose2d& initialPose, const wpi::array<double, 3>& stateStdDevs,
80 const wpi::array<double, 3>& visionMeasurementStdDevs);
81
82 /**
83 * Sets the pose estimator's trust in vision measurements. This might be used
84 * to change trust in vision measurements after the autonomous period, or to
85 * change trust as distance to a vision target increases.
86 *
87 * @param visionMeasurementStdDevs Standard deviations of the vision pose
88 * measurement (x position in meters, y position in meters, and heading in
89 * radians). Increase these numbers to trust the vision pose measurement
90 * less.
91 */
93 const wpi::array<double, 3>& visionMeasurementStdDevs);
94
95 /**
96 * Resets the robot's position on the field.
97 *
98 * @param gyroAngle The current gyro angle.
99 * @param leftDistance The distance traveled by the left encoder.
100 * @param rightDistance The distance traveled by the right encoder.
101 * @param pose The estimated pose of the robot on the field.
102 */
103 void ResetPosition(const Rotation2d& gyroAngle, units::meter_t leftDistance,
104 units::meter_t rightDistance, const Pose2d& pose);
105
106 /**
107 * Gets the estimated robot pose.
108 *
109 * @return The estimated robot pose.
110 */
112
113 /**
114 * Adds a vision measurement to the Kalman Filter. This will correct
115 * the odometry pose estimate while still accounting for measurement noise.
116 *
117 * This method can be called as infrequently as you want, as long as you are
118 * calling Update() every loop.
119 *
120 * To promote stability of the pose estimate and make it robust to bad vision
121 * data, we recommend only adding vision measurements that are already within
122 * one meter or so of the current pose estimate.
123 *
124 * @param visionRobotPose The pose of the robot as measured by the vision
125 * camera.
126 * @param timestamp The timestamp of the vision measurement in seconds. Note
127 * that if you don't use your own time source by calling UpdateWithTime(),
128 * then you must use a timestamp with an epoch since FPGA startup (i.e.,
129 * the epoch of this timestamp is the same epoch as
130 * frc::Timer::GetFPGATimestamp(). This means that you should use
131 * frc::Timer::GetFPGATimestamp() as your time source in this case.
132 */
133 void AddVisionMeasurement(const Pose2d& visionRobotPose,
134 units::second_t timestamp);
135
136 /**
137 * Adds a vision measurement to the Kalman Filter. This will correct
138 * the odometry pose estimate while still accounting for measurement noise.
139 *
140 * This method can be called as infrequently as you want, as long as you are
141 * calling Update() every loop.
142 *
143 * To promote stability of the pose estimate and make it robust to bad vision
144 * data, we recommend only adding vision measurements that are already within
145 * one meter or so of the current pose estimate.
146 *
147 * Note that the vision measurement standard deviations passed into this
148 * method will continue to apply to future measurements until a subsequent
149 * call to SetVisionMeasurementStdDevs() or this method.
150 *
151 * @param visionRobotPose The pose of the robot as measured by the vision
152 * camera.
153 * @param timestamp The timestamp of the vision measurement in seconds. Note
154 * that if you don't use your own time source by calling UpdateWithTime(),
155 * then you must use a timestamp with an epoch since FPGA startup (i.e.,
156 * the epoch of this timestamp is the same epoch as
157 * frc::Timer::GetFPGATimestamp(). This means that you should use
158 * frc::Timer::GetFPGATimestamp() as your time source in this case.
159 * @param visionMeasurementStdDevs Standard deviations of the vision pose
160 * measurement (x position in meters, y position in meters, and heading in
161 * radians). Increase these numbers to trust the vision pose measurement
162 * less.
163 */
165 const Pose2d& visionRobotPose, units::second_t timestamp,
166 const wpi::array<double, 3>& visionMeasurementStdDevs) {
167 SetVisionMeasurementStdDevs(visionMeasurementStdDevs);
168 AddVisionMeasurement(visionRobotPose, timestamp);
169 }
170
171 /**
172 * Updates the pose estimator with wheel encoder and gyro information. This
173 * should be called every loop.
174 *
175 * @param gyroAngle The current gyro angle.
176 * @param leftDistance The distance traveled by the left encoder.
177 * @param rightDistance The distance traveled by the right encoder.
178 *
179 * @return The estimated pose of the robot.
180 */
181 Pose2d Update(const Rotation2d& gyroAngle, units::meter_t leftDistance,
182 units::meter_t rightDistance);
183
184 /**
185 * Updates the pose estimator with wheel encoder and gyro information. This
186 * should be called every loop.
187 *
188 * @param currentTime The time at which this method was called.
189 * @param gyroAngle The current gyro angle.
190 * @param leftDistance The distance traveled by the left encoder.
191 * @param rightDistance The distance traveled by the right encoder.
192 *
193 * @return The estimated pose of the robot.
194 */
195 Pose2d UpdateWithTime(units::second_t currentTime,
196 const Rotation2d& gyroAngle,
197 units::meter_t leftDistance,
198 units::meter_t rightDistance);
199
200 private:
201 struct InterpolationRecord {
202 // The pose observed given the current sensor inputs and the previous pose.
203 Pose2d pose;
204
205 // The current gyro angle.
206 Rotation2d gyroAngle;
207
208 // The distance traveled by the left encoder.
209 units::meter_t leftDistance;
210
211 // The distance traveled by the right encoder.
212 units::meter_t rightDistance;
213
214 /**
215 * Checks equality between this InterpolationRecord and another object.
216 *
217 * @param other The other object.
218 * @return Whether the two objects are equal.
219 */
220 bool operator==(const InterpolationRecord& other) const = default;
221
222 /**
223 * Checks inequality between this InterpolationRecord and another object.
224 *
225 * @param other The other object.
226 * @return Whether the two objects are not equal.
227 */
228 bool operator!=(const InterpolationRecord& other) const = default;
229
230 /**
231 * Interpolates between two InterpolationRecords.
232 *
233 * @param endValue The end value for the interpolation.
234 * @param i The interpolant (fraction).
235 *
236 * @return The interpolated state.
237 */
238 InterpolationRecord Interpolate(DifferentialDriveKinematics& kinematics,
239 InterpolationRecord endValue,
240 double i) const;
241 };
242
243 static constexpr units::second_t kBufferDuration = 1.5_s;
244
245 DifferentialDriveKinematics& m_kinematics;
246 DifferentialDriveOdometry m_odometry;
248 Eigen::Matrix3d m_visionK = Eigen::Matrix3d::Zero();
249
250 TimeInterpolatableBuffer<InterpolationRecord> m_poseBuffer{
251 kBufferDuration, [this](const InterpolationRecord& start,
252 const InterpolationRecord& end, double t) {
253 return start.Interpolate(this->m_kinematics, end, t);
254 }};
255};
256
257} // namespace frc
#define WPILIB_DLLEXPORT
Definition: SymbolExports.h:36
Helper class that converts a chassis velocity (dx and dtheta components) to left and right wheel velo...
Definition: DifferentialDriveKinematics.h:25
Class for differential drive odometry.
Definition: DifferentialDriveOdometry.h:25
This class wraps Differential Drive Odometry to fuse latency-compensated vision measurements with dif...
Definition: DifferentialDrivePoseEstimator.h:35
void AddVisionMeasurement(const Pose2d &visionRobotPose, units::second_t timestamp)
Adds a vision measurement to the Kalman Filter.
Pose2d UpdateWithTime(units::second_t currentTime, const Rotation2d &gyroAngle, units::meter_t leftDistance, units::meter_t rightDistance)
Updates the pose estimator with wheel encoder and gyro information.
void SetVisionMeasurementStdDevs(const wpi::array< double, 3 > &visionMeasurementStdDevs)
Sets the pose estimator's trust in vision measurements.
Pose2d GetEstimatedPosition() const
Gets the estimated robot pose.
Pose2d Update(const Rotation2d &gyroAngle, units::meter_t leftDistance, units::meter_t rightDistance)
Updates the pose estimator with wheel encoder and gyro information.
void ResetPosition(const Rotation2d &gyroAngle, units::meter_t leftDistance, units::meter_t rightDistance, const Pose2d &pose)
Resets the robot's position on the field.
DifferentialDrivePoseEstimator(DifferentialDriveKinematics &kinematics, const Rotation2d &gyroAngle, units::meter_t leftDistance, units::meter_t rightDistance, const Pose2d &initialPose, const wpi::array< double, 3 > &stateStdDevs, const wpi::array< double, 3 > &visionMeasurementStdDevs)
Constructs a DifferentialDrivePoseEstimator.
void AddVisionMeasurement(const Pose2d &visionRobotPose, units::second_t timestamp, const wpi::array< double, 3 > &visionMeasurementStdDevs)
Adds a vision measurement to the Kalman Filter.
Definition: DifferentialDrivePoseEstimator.h:164
DifferentialDrivePoseEstimator(DifferentialDriveKinematics &kinematics, const Rotation2d &gyroAngle, units::meter_t leftDistance, units::meter_t rightDistance, const Pose2d &initialPose)
Constructs a DifferentialDrivePoseEstimator with default standard deviations for the model and vision...
Represents a 2D pose containing translational and rotational elements.
Definition: Pose2d.h:25
A rotation in a 2D coordinate frame represented by a point on the unit circle (cosine and sine).
Definition: Rotation2d.h:26
static EIGEN_DEPRECATED const end_t end
Definition: IndexedViewHelper.h:181
Definition: AprilTagFieldLayout.h:22
bool operator==(const Value &lhs, const Value &rhs)
constexpr bool operator!=(const UNIT_LIB_DEFAULT_TYPE lhs, const Units &rhs) noexcept
Definition: base.h:2716
constexpr empty_array_t empty_array
Definition: array.h:15