PhotonVision C++ v2027.0.0-alpha-2
Loading...
Searching...
No Matches
PhotonPoseEstimator.h
Go to the documentation of this file.
1/*
2 * MIT License
3 *
4 * Copyright (c) PhotonVision
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25#pragma once
26
27#include <optional>
28#include <span>
29
30#include <wpi/apriltag/AprilTagFieldLayout.hpp>
31#include <wpi/math/geometry/Pose3d.hpp>
32#include <wpi/math/geometry/Rotation3d.hpp>
33#include <wpi/math/geometry/Transform3d.hpp>
34#include <wpi/math/interpolation/TimeInterpolatableBuffer.hpp>
35#include <wpi/util/SmallVector.hpp>
36
37#include "photon/PhotonCamera.h"
40
41namespace photon {
53
58
60 /** The estimated pose */
61 wpi::math::Pose3d estimatedPose;
62 /** The estimated time the frame used to derive the robot pose was taken, in
63 * the same timebase as the RoboRIO FPGA Timestamp */
64 wpi::units::second_t timestamp;
65
66 /** A list of the targets used to compute this pose */
67 wpi::util::SmallVector<PhotonTrackedTarget, 10> targetsUsed;
68
69 /** The strategy actually used to produce this pose */
71
72 EstimatedRobotPose(wpi::math::Pose3d pose_, wpi::units::second_t time_,
73 std::span<const PhotonTrackedTarget> targets,
74 PoseStrategy strategy_)
75 : estimatedPose(pose_),
76 timestamp(time_),
77 targetsUsed(targets.data(), targets.data() + targets.size()),
78 strategy(strategy_) {}
79};
80
81/**
82 * The PhotonPoseEstimator class filters or combines readings from all the
83 * fiducials visible at a given timestamp on the field to produce a single robot
84 * in field pose, using the strategy set below. Example usage can be found in
85 * our apriltagExample example project.
86 */
88 public:
89 /**
90 * Create a new PhotonPoseEstimator.
91 *
92 * @param aprilTags A AprilTagFieldLayout linking AprilTag IDs to Pose3ds with
93 * respect to the FIRST field.
94 * @param robotToCamera Transform3d from the center of the robot to the camera
95 * mount positions (ie, robot ➔ camera).
96 */
97 explicit PhotonPoseEstimator(wpi::apriltag::AprilTagFieldLayout aprilTags,
98 wpi::math::Transform3d robotToCamera);
99
100 /**
101 * Get the AprilTagFieldLayout being used by the PositionEstimator.
102 *
103 * @return the AprilTagFieldLayout
104 */
105 wpi::apriltag::AprilTagFieldLayout GetFieldLayout() const {
106 return aprilTags;
107 }
108
109 /**
110 * @return The current transform from the center of the robot to the camera
111 * mount position.
112 */
113 inline wpi::math::Transform3d GetRobotToCameraTransform() {
114 return m_robotToCamera;
115 }
116
117 /**
118 * Useful for pan and tilt mechanisms, or cameras on turrets
119 *
120 * @param robotToCamera The current transform from the center of the robot to
121 * the camera mount position.
122 */
123 inline void SetRobotToCameraTransform(wpi::math::Transform3d robotToCamera) {
124 m_robotToCamera = robotToCamera;
125 }
126
127 /**
128 * Add robot heading data to the buffer. Must be called periodically for the
129 * PNP_DISTANCE_TRIG_SOLVE strategy.
130 *
131 * @param timestamp Timestamp of the robot heading data.
132 * @param heading Field-relative heading at the given timestamp. Standard
133 * WPILIB field coordinates.
134 */
135 inline void AddHeadingData(wpi::units::second_t timestamp,
136 wpi::math::Rotation2d heading) {
137 this->headingBuffer.AddSample(timestamp, heading);
138 }
139
140 /**
141 * Add robot heading data to the buffer. Must be called periodically for the
142 * PNP_DISTANCE_TRIG_SOLVE strategy.
143 *
144 * @param timestamp Timestamp of the robot heading data.
145 * @param heading Field-relative heading at the given timestamp. Standard
146 * WPILIB coordinates.
147 */
148 inline void AddHeadingData(wpi::units::second_t timestamp,
149 wpi::math::Rotation3d heading) {
150 AddHeadingData(timestamp, heading.ToRotation2d());
151 }
152
153 /**
154 * Clears all heading data in the buffer, and adds a new seed. Useful for
155 * preventing estimates from utilizing heading data provided prior to a pose
156 * or rotation reset.
157 *
158 * @param timestamp Timestamp of the robot heading data.
159 * @param heading Field-relative robot heading at given timestamp. Standard
160 * WPILIB field coordinates.
161 */
162 inline void ResetHeadingData(wpi::units::second_t timestamp,
163 wpi::math::Rotation2d heading) {
164 headingBuffer.Clear();
165 AddHeadingData(timestamp, heading);
166 }
167
168 /**
169 * Clears all heading data in the buffer, and adds a new seed. Useful for
170 * preventing estimates from utilizing heading data provided prior to a pose
171 * or rotation reset.
172 *
173 * @param timestamp Timestamp of the robot heading data.
174 * @param heading Field-relative robot heading at given timestamp. Standard
175 * WPILIB field coordinates.
176 */
177 inline void ResetHeadingData(wpi::units::second_t timestamp,
178 wpi::math::Rotation3d heading) {
179 ResetHeadingData(timestamp, heading.ToRotation2d());
180 }
181
182 /**
183 * Return the estimated position of the robot with the lowest position
184 * ambiguity from a List of pipeline results.
185 *
186 * @param cameraResult A pipeline result from the camera.
187 * @return An EstimatedRobotPose with an estimated pose, timestamp, and
188 * targets used to create the estimate, or std::nullopt if there's no targets.
189 */
190 std::optional<EstimatedRobotPose> EstimateLowestAmbiguityPose(
191 PhotonPipelineResult cameraResult);
192
193 /**
194 * Return the estimated position of the robot using the target with the lowest
195 * delta height difference between the estimated and actual height of the
196 * camera.
197 *
198 * @param cameraResult A pipeline result from the camera.
199 * @return An EstimatedRobotPose with an estimated pose, timestamp and
200 * targets used to create the estimate, or std::nullopt if there's no targets.
201 */
202 std::optional<EstimatedRobotPose> EstimateClosestToCameraHeightPose(
203 PhotonPipelineResult cameraResult);
204
205 /**
206 * Return the estimated position of the robot using the target with the lowest
207 * delta in the vector magnitude between it and the reference pose.
208 *
209 * @param cameraResult A pipeline result from the camera.
210 * @param referencePose reference pose to check vector magnitude difference
211 * against.
212 * @return An EstimatedRobotPose with an estimated pose, timestamp, and
213 * targets used to create the estimate, or std::nullopt if there's no targets.
214 */
215 std::optional<EstimatedRobotPose> EstimateClosestToReferencePose(
216 PhotonPipelineResult cameraResult, wpi::math::Pose3d referencePose);
217
218 /**
219 * Return the estimated position of the robot by using all visible tags to
220 * compute a single pose estimate on coprocessor. This option needs to be
221 * enabled on the PhotonVision web UI as well.
222 *
223 * @param cameraResult A pipeline result from the camera.
224 * @return An EstimatedRobotPose with an estimated pose, timestamp, and
225 * targets used to create the estimate or std::nullopt if there's no targets,
226 * no multi-tag results, or multi-tag is disabled in the web UI.
227 */
228 std::optional<EstimatedRobotPose> EstimateCoprocMultiTagPose(
229 PhotonPipelineResult cameraResult);
230
231 /**
232 * Return the estimated position of the robot by using all visible tags to
233 * compute a single pose estimate on the RoboRIO. This can take a lot of time
234 * due to the RIO's weak computing power.
235 *
236 * @param cameraResult A pipeline result from the camera.
237 * @param cameraMatrix Camera intrinsics from camera calibration data.
238 * @param distCoeffs Distortion coefficients from camera calibration data.
239 * @return An EstimatedRobotPose with an estimated pose, timestamp, and
240 * targets used to create the estimate, or std::nullopt if there's less than 2
241 * targets visible or SolvePnP fails.
242 */
243 std::optional<EstimatedRobotPose> EstimateRioMultiTagPose(
246
247 /**
248 * Return the estimated position of the robot by using distance data from best
249 * visible tag to compute a Pose. This runs on the RoboRIO in order to access
250 * the robot's yaw heading, and MUST have AddHeadingData called every frame so
251 * heading data is up-to-date.
252 *
253 * <p>Yields a Pose2d in estimatedRobotPose (0 for z, roll, pitch)
254 *
255 * <p>https://www.chiefdelphi.com/t/frc-6328-mechanical-advantage-2025-build-thread/477314/98
256 *
257 * @param cameraResult A pipeline result from the camera.
258 * @return An EstimatedRobotPose with an estimated pose, timestamp, and
259 * targets used to create the estimate, or std::nullopt if there's no targets
260 * or heading data.
261 */
262 std::optional<EstimatedRobotPose> EstimatePnpDistanceTrigSolvePose(
263 PhotonPipelineResult cameraResult);
264
265 /**
266 * Return the average of the best target poses using ambiguity as weight.
267 * @param cameraResult A pipeline result from the camera.
268 * @return An EstimatedRobotPose with an estimated pose, timestamp, and
269 * targets used to create the estimate, or std::nullopt if there's no targets.
270 */
271 std::optional<EstimatedRobotPose> EstimateAverageBestTargetsPose(
272 PhotonPipelineResult cameraResult);
273
274 /**
275 * Return the estimated position of the robot by solving a constrained version
276 * of the Perspective-n-Point problem with the robot's drivebase flat on the
277 * floor. This computation takes place on the RoboRIO, and typically takes not
278 * more than 2ms. See
279 * photon::VisionEstimation::EstimateRobotPoseConstrainedSolvePNP for tuning
280 * handles this strategy exposes. Internally, the cost function is a
281 * sum-squared of pixel reprojection error + (optionally) heading error *
282 * heading scale factor. This strategy needs addHeadingData called every frame
283 * so heading data is up-to-date.
284 *
285 * @param cameraResult A pipeline result from the camera.
286 * @param cameraMatrix Camera intrinsics from camera calibration data.
287 * @param distCoeffs Distortion coefficients from camera calibration data.
288 * @param seedPose An initial guess at robot pose, refined via optimization.
289 * Better guesses will converge faster. Can come from any pose source, but
290 * some battle-tested sources are estimateCoprocMultiTagPose, or
291 * estimateLowestAmbiguityPose if MultiTag results aren't available.
292 * @param headingFree If true, heading is completely free to vary. If false,
293 * heading excursions from the provided heading measurement will be penalized
294 * @param headingScaleFactor If headingFree is false, this weights the cost of
295 * changing our robot heading estimate against the tag corner reprojection
296 * error cost.
297 * @return An EstimatedRobotPose with an estimated pose, timestamp, and
298 * targets used to create the estimate, or std::nullopt if there's no targets
299 * or heading data, or if the solver fails to solve the problem.
300 */
301 std::optional<EstimatedRobotPose> EstimateConstrainedSolvepnpPose(
302 photon::PhotonPipelineResult cameraResult,
305 wpi::math::Pose3d seedPose, bool headingFree, double headingScaleFactor);
306
307 private:
308 wpi::apriltag::AprilTagFieldLayout aprilTags;
309
310 wpi::math::Transform3d m_robotToCamera;
311
312 wpi::math::TimeInterpolatableBuffer<wpi::math::Rotation2d> headingBuffer;
313
314 inline static int InstanceCount = 1;
315};
316
317} // namespace photon
Eigen::Matrix< double, 8, 1 > DistortionMatrix
Definition PhotonCamera.h:200
Eigen::Matrix< double, 3, 3 > CameraMatrix
Definition PhotonCamera.h:199
Represents a pipeline result from a PhotonCamera.
Definition PhotonPipelineResult.h:34
The PhotonPoseEstimator class filters or combines readings from all the fiducials visible at a given ...
Definition PhotonPoseEstimator.h:87
std::optional< EstimatedRobotPose > EstimateAverageBestTargetsPose(PhotonPipelineResult cameraResult)
Return the average of the best target poses using ambiguity as weight.
void SetRobotToCameraTransform(wpi::math::Transform3d robotToCamera)
Useful for pan and tilt mechanisms, or cameras on turrets.
Definition PhotonPoseEstimator.h:123
std::optional< EstimatedRobotPose > EstimateClosestToCameraHeightPose(PhotonPipelineResult cameraResult)
Return the estimated position of the robot using the target with the lowest delta height difference b...
PhotonPoseEstimator(wpi::apriltag::AprilTagFieldLayout aprilTags, wpi::math::Transform3d robotToCamera)
Create a new PhotonPoseEstimator.
std::optional< EstimatedRobotPose > EstimateLowestAmbiguityPose(PhotonPipelineResult cameraResult)
Return the estimated position of the robot with the lowest position ambiguity from a List of pipeline...
wpi::apriltag::AprilTagFieldLayout GetFieldLayout() const
Get the AprilTagFieldLayout being used by the PositionEstimator.
Definition PhotonPoseEstimator.h:105
std::optional< EstimatedRobotPose > EstimateCoprocMultiTagPose(PhotonPipelineResult cameraResult)
Return the estimated position of the robot by using all visible tags to compute a single pose estimat...
void ResetHeadingData(wpi::units::second_t timestamp, wpi::math::Rotation3d heading)
Clears all heading data in the buffer, and adds a new seed.
Definition PhotonPoseEstimator.h:177
std::optional< EstimatedRobotPose > EstimateConstrainedSolvepnpPose(photon::PhotonPipelineResult cameraResult, photon::PhotonCamera::CameraMatrix cameraMatrix, photon::PhotonCamera::DistortionMatrix distCoeffs, wpi::math::Pose3d seedPose, bool headingFree, double headingScaleFactor)
Return the estimated position of the robot by solving a constrained version of the Perspective-n-Poin...
std::optional< EstimatedRobotPose > EstimatePnpDistanceTrigSolvePose(PhotonPipelineResult cameraResult)
Return the estimated position of the robot by using distance data from best visible tag to compute a ...
wpi::math::Transform3d GetRobotToCameraTransform()
Definition PhotonPoseEstimator.h:113
std::optional< EstimatedRobotPose > EstimateRioMultiTagPose(PhotonPipelineResult cameraResult, PhotonCamera::CameraMatrix camMat, PhotonCamera::DistortionMatrix distCoeffs)
Return the estimated position of the robot by using all visible tags to compute a single pose estimat...
void AddHeadingData(wpi::units::second_t timestamp, wpi::math::Rotation2d heading)
Add robot heading data to the buffer.
Definition PhotonPoseEstimator.h:135
void ResetHeadingData(wpi::units::second_t timestamp, wpi::math::Rotation2d heading)
Clears all heading data in the buffer, and adds a new seed.
Definition PhotonPoseEstimator.h:162
std::optional< EstimatedRobotPose > EstimateClosestToReferencePose(PhotonPipelineResult cameraResult, wpi::math::Pose3d referencePose)
Return the estimated position of the robot using the target with the lowest delta in the vector magni...
void AddHeadingData(wpi::units::second_t timestamp, wpi::math::Rotation3d heading)
Add robot heading data to the buffer.
Definition PhotonPoseEstimator.h:148
Definition VisionEstimation.h:30
PoseStrategy
Definition PhotonPoseEstimator.h:42
@ CONSTRAINED_SOLVEPNP
Definition PhotonPoseEstimator.h:50
@ LOWEST_AMBIGUITY
Definition PhotonPoseEstimator.h:43
@ AVERAGE_BEST_TARGETS
Definition PhotonPoseEstimator.h:47
@ PNP_DISTANCE_TRIG_SOLVE
Definition PhotonPoseEstimator.h:51
@ MULTI_TAG_PNP_ON_RIO
Definition PhotonPoseEstimator.h:49
@ CLOSEST_TO_CAMERA_HEIGHT
Definition PhotonPoseEstimator.h:44
@ CLOSEST_TO_LAST_POSE
Definition PhotonPoseEstimator.h:46
@ MULTI_TAG_PNP_ON_COPROCESSOR
Definition PhotonPoseEstimator.h:48
@ CLOSEST_TO_REFERENCE_POSE
Definition PhotonPoseEstimator.h:45
Definition PhotonPoseEstimator.h:54
bool headingFree
Definition PhotonPoseEstimator.h:55
double headingScalingFactor
Definition PhotonPoseEstimator.h:56
Definition PhotonPoseEstimator.h:59
wpi::math::Pose3d estimatedPose
The estimated pose.
Definition PhotonPoseEstimator.h:61
EstimatedRobotPose(wpi::math::Pose3d pose_, wpi::units::second_t time_, std::span< const PhotonTrackedTarget > targets, PoseStrategy strategy_)
Definition PhotonPoseEstimator.h:72
wpi::units::second_t timestamp
The estimated time the frame used to derive the robot pose was taken, in the same timebase as the Rob...
Definition PhotonPoseEstimator.h:64
wpi::util::SmallVector< PhotonTrackedTarget, 10 > targetsUsed
A list of the targets used to compute this pose.
Definition PhotonPoseEstimator.h:67
PoseStrategy strategy
The strategy actually used to produce this pose.
Definition PhotonPoseEstimator.h:70