blob: accb0c1055c339feac9eb762aa2cd55853411de3 [file] [log] [blame]
James Kuszmaul04a343c2023-02-20 16:38:22 -08001#ifndef Y2023_LOCALIZER_LOCALIZER_H_
2#define Y2023_LOCALIZER_LOCALIZER_H_
3
4#include <array>
5#include <map>
6
7#include "frc971/constants/constants_sender_lib.h"
8#include "frc971/control_loops/drivetrain/hybrid_ekf.h"
9#include "frc971/control_loops/drivetrain/improved_down_estimator.h"
10#include "frc971/control_loops/drivetrain/localization/localizer_output_generated.h"
11#include "frc971/control_loops/drivetrain/localization/utils.h"
12#include "frc971/imu_reader/imu_watcher.h"
13#include "frc971/vision/target_map_generated.h"
14#include "y2023/constants/constants_generated.h"
15#include "y2023/localizer/status_generated.h"
16#include "y2023/localizer/visualization_generated.h"
17
18namespace y2023::localizer {
19
20class Localizer {
21 public:
22 static constexpr size_t kNumCameras = 4;
23 typedef Eigen::Matrix<double, 4, 4> Transform;
24 typedef frc971::control_loops::drivetrain::HybridEkf<double> HybridEkf;
25 typedef HybridEkf::State State;
26 typedef HybridEkf::Output Output;
27 typedef HybridEkf::Input Input;
28 typedef HybridEkf::StateIdx StateIdx;
29 Localizer(aos::EventLoop *event_loop,
30 const frc971::control_loops::drivetrain::DrivetrainConfig<double>
31 dt_config);
32
33 private:
34 class Corrector : public HybridEkf::ExpectedObservationFunctor {
35 public:
36 // Indices used for each of the members of the output vector for this
37 // Corrector.
38 enum OutputIdx {
39 kX = 0,
40 kY = 1,
41 kTheta = 2,
42 };
43 Corrector(const State &state_at_capture, const Eigen::Vector3d &Z)
44 : state_at_capture_(state_at_capture), Z_(Z) {
45 H_.setZero();
46 H_(kX, StateIdx::kX) = 1;
47 H_(kY, StateIdx::kY) = 1;
48 H_(kTheta, StateIdx::kTheta) = 1;
49 }
50 Output H(const State &, const Input &) final;
51 Eigen::Matrix<double, HybridEkf::kNOutputs, HybridEkf::kNStates> DHDX(
52 const State &) final {
53 return H_;
54 }
55
56 private:
57 Eigen::Matrix<double, HybridEkf::kNOutputs, HybridEkf::kNStates> H_;
58 const State state_at_capture_;
59 const Eigen::Vector3d &Z_;
60 };
61
62 struct CameraState {
63 aos::Sender<Visualization> debug_sender;
64 Transform extrinsics = Transform::Zero();
65 aos::util::ArrayErrorCounter<RejectionReason, RejectionCount>
66 rejection_counter;
67 size_t total_candidate_targets = 0;
68 size_t total_accepted_targets = 0;
69 };
70
71 static std::array<CameraState, kNumCameras> MakeCameras(
72 const Constants &constants, aos::EventLoop *event_loop);
73 flatbuffers::Offset<TargetEstimateDebug> HandleTarget(
74 int camera_index, const aos::monotonic_clock::time_point capture_time,
75 const frc971::vision::TargetPoseFbs &target,
76 flatbuffers::FlatBufferBuilder *debug_fbb);
77 void HandleImu(aos::monotonic_clock::time_point sample_time_pico,
78 aos::monotonic_clock::time_point sample_time_pi,
79 std::optional<Eigen::Vector2d> encoders, Eigen::Vector3d gyro,
80 Eigen::Vector3d accel);
81 flatbuffers::Offset<TargetEstimateDebug> RejectImage(
82 int camera_index, RejectionReason reason,
83 TargetEstimateDebug::Builder *builder);
84
85 void SendOutput();
James Kuszmaule600d172023-03-12 10:19:44 -070086 static flatbuffers::Offset<frc971::control_loops::drivetrain::LocalizerState>
87 PopulateState(const State &X_hat, flatbuffers::FlatBufferBuilder *fbb);
James Kuszmaul04a343c2023-02-20 16:38:22 -080088 flatbuffers::Offset<ImuStatus> PopulateImu(
89 flatbuffers::FlatBufferBuilder *fbb) const;
90 void SendStatus();
James Kuszmaulfb894572023-02-23 17:25:06 -080091 static flatbuffers::Offset<CumulativeStatistics> StatisticsForCamera(
92 const CameraState &camera, flatbuffers::FlatBufferBuilder *fbb);
James Kuszmaul04a343c2023-02-20 16:38:22 -080093
94 aos::EventLoop *const event_loop_;
95 const frc971::control_loops::drivetrain::DrivetrainConfig<double> dt_config_;
96 frc971::constants::ConstantsFetcher<Constants> constants_fetcher_;
97 std::array<CameraState, kNumCameras> cameras_;
98 const std::array<Transform, kNumCameras> camera_extrinsics_;
99 const std::map<uint64_t, Transform> target_poses_;
100
101 frc971::control_loops::drivetrain::DrivetrainUkf down_estimator_;
102 HybridEkf ekf_;
103 HybridEkf::ExpectedObservationAllocator<Corrector> observations_;
104
105 frc971::controls::ImuWatcher imu_watcher_;
106 frc971::control_loops::drivetrain::LocalizationUtils utils_;
107
108 aos::Sender<Status> status_sender_;
109 aos::Sender<frc971::controls::LocalizerOutput> output_sender_;
110 aos::monotonic_clock::time_point t_ = aos::monotonic_clock::min_time;
111 size_t clock_resets_ = 0;
112
113 size_t total_candidate_targets_ = 0;
114 size_t total_accepted_targets_ = 0;
115
116 // For the status message.
117 std::optional<Eigen::Vector2d> last_encoder_readings_;
118};
James Kuszmaul04a343c2023-02-20 16:38:22 -0800119} // namespace y2023::localizer
120#endif // Y2023_LOCALIZER_LOCALIZER_H_