blob: 5190544663b1b399fe004cb0821cbe28ac02253f [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
Maxwell Henderson85d81872023-04-07 18:21:59 -07007#include "aos/network/message_bridge_client_generated.h"
8#include "aos/network/message_bridge_server_generated.h"
James Kuszmaul04a343c2023-02-20 16:38:22 -08009#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 "y2023/constants/constants_generated.h"
17#include "y2023/localizer/status_generated.h"
18#include "y2023/localizer/visualization_generated.h"
19
20namespace y2023::localizer {
21
22class Localizer {
23 public:
24 static constexpr size_t kNumCameras = 4;
25 typedef Eigen::Matrix<double, 4, 4> Transform;
26 typedef frc971::control_loops::drivetrain::HybridEkf<double> HybridEkf;
27 typedef HybridEkf::State State;
28 typedef HybridEkf::Output Output;
29 typedef HybridEkf::Input Input;
30 typedef HybridEkf::StateIdx StateIdx;
31 Localizer(aos::EventLoop *event_loop,
32 const frc971::control_loops::drivetrain::DrivetrainConfig<double>
33 dt_config);
34
35 private:
36 class Corrector : public HybridEkf::ExpectedObservationFunctor {
37 public:
38 // Indices used for each of the members of the output vector for this
39 // Corrector.
40 enum OutputIdx {
41 kX = 0,
42 kY = 1,
43 kTheta = 2,
44 };
45 Corrector(const State &state_at_capture, const Eigen::Vector3d &Z)
46 : state_at_capture_(state_at_capture), Z_(Z) {
47 H_.setZero();
48 H_(kX, StateIdx::kX) = 1;
49 H_(kY, StateIdx::kY) = 1;
50 H_(kTheta, StateIdx::kTheta) = 1;
51 }
52 Output H(const State &, const Input &) final;
53 Eigen::Matrix<double, HybridEkf::kNOutputs, HybridEkf::kNStates> DHDX(
54 const State &) final {
55 return H_;
56 }
57
58 private:
59 Eigen::Matrix<double, HybridEkf::kNOutputs, HybridEkf::kNStates> H_;
60 const State state_at_capture_;
61 const Eigen::Vector3d &Z_;
62 };
63
64 struct CameraState {
65 aos::Sender<Visualization> debug_sender;
66 Transform extrinsics = Transform::Zero();
67 aos::util::ArrayErrorCounter<RejectionReason, RejectionCount>
68 rejection_counter;
69 size_t total_candidate_targets = 0;
70 size_t total_accepted_targets = 0;
71 };
72
73 static std::array<CameraState, kNumCameras> MakeCameras(
74 const Constants &constants, aos::EventLoop *event_loop);
75 flatbuffers::Offset<TargetEstimateDebug> HandleTarget(
76 int camera_index, const aos::monotonic_clock::time_point capture_time,
77 const frc971::vision::TargetPoseFbs &target,
78 flatbuffers::FlatBufferBuilder *debug_fbb);
79 void HandleImu(aos::monotonic_clock::time_point sample_time_pico,
80 aos::monotonic_clock::time_point sample_time_pi,
81 std::optional<Eigen::Vector2d> encoders, Eigen::Vector3d gyro,
82 Eigen::Vector3d accel);
83 flatbuffers::Offset<TargetEstimateDebug> RejectImage(
84 int camera_index, RejectionReason reason,
85 TargetEstimateDebug::Builder *builder);
86
87 void SendOutput();
James Kuszmaule600d172023-03-12 10:19:44 -070088 static flatbuffers::Offset<frc971::control_loops::drivetrain::LocalizerState>
89 PopulateState(const State &X_hat, flatbuffers::FlatBufferBuilder *fbb);
James Kuszmaul04a343c2023-02-20 16:38:22 -080090 flatbuffers::Offset<ImuStatus> PopulateImu(
91 flatbuffers::FlatBufferBuilder *fbb) const;
92 void SendStatus();
James Kuszmaulfb894572023-02-23 17:25:06 -080093 static flatbuffers::Offset<CumulativeStatistics> StatisticsForCamera(
94 const CameraState &camera, flatbuffers::FlatBufferBuilder *fbb);
James Kuszmaul04a343c2023-02-20 16:38:22 -080095
James Kuszmaul4fe845a2023-03-26 12:57:30 -070096 bool UseAprilTag(uint64_t target_id);
97
James Kuszmaul04a343c2023-02-20 16:38:22 -080098 aos::EventLoop *const event_loop_;
99 const frc971::control_loops::drivetrain::DrivetrainConfig<double> dt_config_;
100 frc971::constants::ConstantsFetcher<Constants> constants_fetcher_;
101 std::array<CameraState, kNumCameras> cameras_;
102 const std::array<Transform, kNumCameras> camera_extrinsics_;
103 const std::map<uint64_t, Transform> target_poses_;
104
105 frc971::control_loops::drivetrain::DrivetrainUkf down_estimator_;
106 HybridEkf ekf_;
107 HybridEkf::ExpectedObservationAllocator<Corrector> observations_;
108
109 frc971::controls::ImuWatcher imu_watcher_;
110 frc971::control_loops::drivetrain::LocalizationUtils utils_;
111
112 aos::Sender<Status> status_sender_;
113 aos::Sender<frc971::controls::LocalizerOutput> output_sender_;
114 aos::monotonic_clock::time_point t_ = aos::monotonic_clock::min_time;
115 size_t clock_resets_ = 0;
116
117 size_t total_candidate_targets_ = 0;
118 size_t total_accepted_targets_ = 0;
119
120 // For the status message.
121 std::optional<Eigen::Vector2d> last_encoder_readings_;
Maxwell Henderson85d81872023-04-07 18:21:59 -0700122
123 aos::Fetcher<aos::message_bridge::ServerStatistics>
124 server_statistics_fetcher_;
125 aos::Fetcher<aos::message_bridge::ClientStatistics>
126 client_statistics_fetcher_;
James Kuszmaul04a343c2023-02-20 16:38:22 -0800127};
James Kuszmaul04a343c2023-02-20 16:38:22 -0800128} // namespace y2023::localizer
129#endif // Y2023_LOCALIZER_LOCALIZER_H_