blob: 0aa4456179c712aeaae1ad3c3e30194785b61e47 [file] [log] [blame]
James Kuszmaul1798c072022-02-13 15:32:11 -08001#include "y2022/control_loops/drivetrain/localizer.h"
2
3namespace y2022 {
4namespace control_loops {
5namespace drivetrain {
6
7Localizer::Localizer(
8 aos::EventLoop *event_loop,
9 const frc971::control_loops::drivetrain::DrivetrainConfig<double>
10 &dt_config)
11 : event_loop_(event_loop),
12 dt_config_(dt_config),
13 ekf_(dt_config),
James Kuszmaul2971b5a2023-01-29 15:49:32 -080014 observations_(&ekf_),
James Kuszmaul1798c072022-02-13 15:32:11 -080015 localizer_output_fetcher_(
16 event_loop_->MakeFetcher<frc971::controls::LocalizerOutput>(
17 "/localizer")),
James Kuszmaulc76c19b2022-03-16 22:41:44 -070018 joystick_state_fetcher_(
19 event_loop_->MakeFetcher<aos::JoystickState>("/aos")),
James Kuszmaul1798c072022-02-13 15:32:11 -080020 clock_offset_fetcher_(
21 event_loop_->MakeFetcher<aos::message_bridge::ServerStatistics>(
22 "/aos")) {
23 ekf_.set_ignore_accel(true);
24
25 event_loop->OnRun([this, event_loop]() {
26 ekf_.ResetInitialState(event_loop->monotonic_now(),
27 HybridEkf::State::Zero(), ekf_.P());
28 });
29
30 target_selector_.set_has_target(false);
31}
32
33void Localizer::Reset(
34 aos::monotonic_clock::time_point t,
35 const frc971::control_loops::drivetrain::HybridEkf<double>::State &state) {
36 // Go through and clear out all of the fetchers so that we don't get behind.
37 localizer_output_fetcher_.Fetch();
38 ekf_.ResetInitialState(t, state.cast<float>(), ekf_.P());
39}
40
41void Localizer::Update(const Eigen::Matrix<double, 2, 1> &U,
42 aos::monotonic_clock::time_point now,
43 double left_encoder, double right_encoder,
44 double gyro_rate, const Eigen::Vector3d &accel) {
45 ekf_.UpdateEncodersAndGyro(left_encoder, right_encoder, gyro_rate,
46 U.cast<float>(), accel.cast<float>(), now);
James Kuszmaulc76c19b2022-03-16 22:41:44 -070047 joystick_state_fetcher_.Fetch();
48 if (joystick_state_fetcher_.get() != nullptr &&
49 joystick_state_fetcher_->autonomous()) {
50 // TODO(james): This is an inelegant way to avoid having the localizer mess
51 // up splines. Do better.
James Kuszmaul2971b5a2023-01-29 15:49:32 -080052 // return;
James Kuszmaulc76c19b2022-03-16 22:41:44 -070053 }
James Kuszmaul1798c072022-02-13 15:32:11 -080054 if (localizer_output_fetcher_.Fetch()) {
55 clock_offset_fetcher_.Fetch();
56 bool message_bridge_connected = true;
57 std::chrono::nanoseconds monotonic_offset{0};
58 if (clock_offset_fetcher_.get() != nullptr) {
59 for (const auto connection : *clock_offset_fetcher_->connections()) {
60 if (connection->has_node() && connection->node()->has_name() &&
61 connection->node()->name()->string_view() == "imu") {
62 if (connection->has_monotonic_offset()) {
63 monotonic_offset =
64 std::chrono::nanoseconds(connection->monotonic_offset());
65 } else {
66 // If we don't have a monotonic offset, that means we aren't
67 // connected, in which case we should break the loop but shouldn't
68 // populate the offset.
69 message_bridge_connected = false;
70 }
71 break;
72 }
73 }
74 }
75 if (!message_bridge_connected) {
76 return;
77 }
78 aos::monotonic_clock::time_point capture_time(
79 std::chrono::nanoseconds(
80 localizer_output_fetcher_->monotonic_timestamp_ns()) -
81 monotonic_offset);
82 // TODO: Finish implementing simple x/y/theta updater with state_at_capture.
83 // TODO: Implement turret/camera processing logic on pi side.
James Kuszmaulba59dc92022-03-12 10:46:54 -080084 std::optional<State> state_at_capture =
James Kuszmaul1798c072022-02-13 15:32:11 -080085 ekf_.LastStateBeforeTime(capture_time);
James Kuszmaulba59dc92022-03-12 10:46:54 -080086 if (!state_at_capture.has_value()) {
87 state_at_capture = ekf_.OldestState();
88 if (!state_at_capture.has_value()) {
89 return;
90 }
91 }
92
James Kuszmaul1798c072022-02-13 15:32:11 -080093 const Eigen::Vector3f Z{
94 static_cast<float>(localizer_output_fetcher_->x()),
95 static_cast<float>(localizer_output_fetcher_->y()),
96 static_cast<float>(localizer_output_fetcher_->theta())};
97 Eigen::Matrix3f R = Eigen::Matrix3f::Zero();
98 R.diagonal() << 0.01, 0.01, 1e-4;
99 const Input U_correct = ekf_.MostRecentInput();
James Kuszmaul2971b5a2023-01-29 15:49:32 -0800100 observations_.CorrectKnownH(Eigen::Vector3f::Zero(), &U_correct,
101 Corrector(state_at_capture.value(), Z), R, now);
James Kuszmaul1798c072022-02-13 15:32:11 -0800102 }
103}
104
105} // namespace drivetrain
106} // namespace control_loops
107} // namespace y2022