blob: 8235f13b0eb70ddd2e28ffc577366e5d5f8df130 [file] [log] [blame]
James Kuszmaul313e9ce2024-02-11 17:47:33 -08001#ifndef Y2024_LOCALIZER_LOCALIZER_H_
2#define Y2024_LOCALIZER_LOCALIZER_H_
3
4#include <array>
5#include <map>
6
7#include "aos/network/message_bridge_client_generated.h"
8#include "aos/network/message_bridge_server_generated.h"
9#include "frc971/constants/constants_sender_lib.h"
10#include "frc971/control_loops/drivetrain/hybrid_ekf.h"
11#include "frc971/control_loops/drivetrain/improved_down_estimator.h"
12#include "frc971/control_loops/drivetrain/localization/localizer_output_generated.h"
13#include "frc971/control_loops/drivetrain/localization/utils.h"
14#include "frc971/imu_reader/imu_watcher.h"
15#include "frc971/vision/target_map_generated.h"
16#include "y2024/constants/constants_generated.h"
17#include "y2024/localizer/status_generated.h"
18#include "y2024/localizer/visualization_static.h"
19
20namespace y2024::localizer {
21
22class Localizer {
23 public:
24 static constexpr size_t kNumCameras = 4;
25 using Pose = frc971::control_loops::Pose;
26 typedef Eigen::Matrix<double, 4, 4> Transform;
27 typedef frc971::control_loops::drivetrain::HybridEkf<double> HybridEkf;
28 typedef HybridEkf::State State;
29 typedef HybridEkf::Output Output;
30 typedef HybridEkf::Input Input;
31 typedef HybridEkf::StateIdx StateIdx;
32 Localizer(aos::EventLoop *event_loop);
33
34 private:
35 class Corrector : public HybridEkf::ExpectedObservationFunctor {
36 public:
37 // Indices used for each of the members of the output vector for this
38 // Corrector.
39 enum OutputIdx {
40 kHeading = 0,
41 kDistance = 1,
42 kSkew = 2,
43 };
44 Corrector(const State &state_at_capture, const Transform &H_field_target,
45 const Transform &H_robot_camera,
46 const Transform &H_camera_target);
47
48 using HMatrix = Eigen::Matrix<double, Localizer::HybridEkf::kNOutputs,
49 Localizer::HybridEkf::kNStates>;
50
51 Output H(const State &, const Input &) final;
52 HMatrix DHDX(const State &) final { return H_; }
53 const Eigen::Vector3d &observed() const { return observed_; }
54 const Eigen::Vector3d &expected() const { return expected_; }
55 const Pose &expected_robot_pose() const { return expected_robot_pose_; }
56 const Pose &expected_camera_pose() const { return expected_camera_; }
57 const Pose &observed_camera_pose() const { return observed_camera_; }
58
59 static Eigen::Vector3d HeadingDistanceSkew(const Pose &relative_pose);
60
61 static Corrector CalculateHeadingDistanceSkewH(
62 const State &state_at_capture, const Transform &H_field_target,
63 const Transform &H_robot_camera, const Transform &H_camera_target);
64
65 static void PopulateMeasurement(const Eigen::Vector3d &vector,
66 MeasurementStatic *builder) {
67 builder->set_heading(vector(kHeading));
68 builder->set_distance(vector(kDistance));
69 builder->set_skew(vector(kSkew));
70 }
71
72 private:
73 Corrector(const Pose &expected_robot_pose, const Pose &observed_camera,
74 const Pose &expected_camera, const Eigen::Vector3d &expected,
75 const Eigen::Vector3d &observed, const HMatrix &H)
76 : expected_robot_pose_(expected_robot_pose),
77 observed_camera_(observed_camera),
78 expected_camera_(expected_camera),
79 expected_(expected),
80 observed_(observed),
81 H_(H) {}
82 // For debugging.
83 const Pose expected_robot_pose_;
84 const Pose observed_camera_;
85 const Pose expected_camera_;
86 // Actually used.
87 const Eigen::Vector3d expected_;
88 const Eigen::Vector3d observed_;
89 const HMatrix H_;
90 };
91
92 struct CameraState {
93 aos::Sender<VisualizationStatic> debug_sender;
94 Transform extrinsics = Transform::Zero();
95 aos::util::ArrayErrorCounter<RejectionReason, RejectionCount>
96 rejection_counter;
97 size_t total_candidate_targets = 0;
98 size_t total_accepted_targets = 0;
99 };
100
101 static std::array<CameraState, kNumCameras> MakeCameras(
102 const Constants &constants, aos::EventLoop *event_loop);
103 void HandleTarget(int camera_index,
104 const aos::monotonic_clock::time_point capture_time,
105 const frc971::vision::TargetPoseFbs &target,
106 TargetEstimateDebugStatic *debug_builder);
107 void HandleImu(aos::monotonic_clock::time_point sample_time_pico,
108 aos::monotonic_clock::time_point sample_time_pi,
109 std::optional<Eigen::Vector2d> encoders, Eigen::Vector3d gyro,
110 Eigen::Vector3d accel);
111 void RejectImage(int camera_index, RejectionReason reason,
112 TargetEstimateDebugStatic *builder);
113
114 void SendOutput();
115 static flatbuffers::Offset<frc971::control_loops::drivetrain::LocalizerState>
116 PopulateState(const State &X_hat, flatbuffers::FlatBufferBuilder *fbb);
117 flatbuffers::Offset<ImuStatus> PopulateImu(
118 flatbuffers::FlatBufferBuilder *fbb) const;
119 void SendStatus();
120 static flatbuffers::Offset<CumulativeStatistics> StatisticsForCamera(
121 const CameraState &camera, flatbuffers::FlatBufferBuilder *fbb);
122 static void StatisticsForCamera(const CameraState &camera,
123 CumulativeStatisticsStatic *builder);
124
125 bool UseAprilTag(uint64_t target_id);
126
127 aos::EventLoop *const event_loop_;
128 frc971::constants::ConstantsFetcher<Constants> constants_fetcher_;
129 const frc971::control_loops::drivetrain::DrivetrainConfig<double> dt_config_;
130 std::array<CameraState, kNumCameras> cameras_;
131 const std::array<Transform, kNumCameras> camera_extrinsics_;
132 const std::map<uint64_t, Transform> target_poses_;
133
134 frc971::control_loops::drivetrain::DrivetrainUkf down_estimator_;
135 HybridEkf ekf_;
136 HybridEkf::ExpectedObservationAllocator<Corrector> observations_;
137
138 frc971::controls::ImuWatcher imu_watcher_;
139 frc971::control_loops::drivetrain::LocalizationUtils utils_;
140
141 aos::Sender<Status> status_sender_;
142 aos::Sender<frc971::controls::LocalizerOutput> output_sender_;
143 aos::monotonic_clock::time_point t_ = aos::monotonic_clock::min_time;
144 size_t clock_resets_ = 0;
145
146 size_t total_candidate_targets_ = 0;
147 size_t total_accepted_targets_ = 0;
148
149 // For the status message.
150 std::optional<Eigen::Vector2d> last_encoder_readings_;
151
152 aos::Fetcher<aos::message_bridge::ServerStatistics>
153 server_statistics_fetcher_;
154 aos::Fetcher<aos::message_bridge::ClientStatistics>
155 client_statistics_fetcher_;
156};
157} // namespace y2024::localizer
158#endif // Y2024_LOCALIZER_LOCALIZER_H_