YAMS
Yet Another Mechanism System
Loading...
Searching...
No Matches
LQRController.hpp
Go to the documentation of this file.
1// Copyright (c) 2026 Yet Another Software Suite
2// SPDX-License-Identifier: LGPL-3.0-or-later
3
4#pragma once
5
6#include <memory>
7#include <optional>
8#include <utility>
9#include <variant>
10#include <wpi/math/controller/LinearQuadraticRegulator.hpp>
11#include <wpi/math/estimator/KalmanFilter.hpp>
12#include <wpi/math/system/LinearSystem.hpp>
13#include <wpi/units/angle.hpp>
14#include <wpi/units/angular_velocity.hpp>
15#include <wpi/units/length.hpp>
16#include <wpi/units/time.hpp>
17#include <wpi/units/velocity.hpp>
18#include <wpi/units/voltage.hpp>
19
20#include "LQRConfig.hpp"
21
22namespace yams::math {
23
36 public:
42 explicit LQRController(LQRConfig config);
43
49 void UpdateConfig(LQRConfig config);
50
57 void Reset(wpi::units::radian_t angle, wpi::units::radians_per_second_t velocity);
58
65 void Reset(wpi::units::meter_t distance, wpi::units::meters_per_second_t velocity);
66
75 wpi::units::volt_t Calculate(wpi::units::radian_t measured, wpi::units::radian_t position,
76 wpi::units::radians_per_second_t velocity);
77
86 wpi::units::volt_t Calculate(wpi::units::meter_t measured, wpi::units::meter_t position,
87 wpi::units::meters_per_second_t velocity);
88
96 wpi::units::volt_t Calculate(wpi::units::radians_per_second_t measured,
97 wpi::units::radians_per_second_t velocity);
98
106 wpi::units::volt_t Calculate(wpi::units::meters_per_second_t measured,
107 wpi::units::meters_per_second_t velocity);
108
115
121 const std::optional<LQRConfig>& GetConfig() const;
122
123 private:
124 // wpi::math::LinearSystemLoop stores raw pointers to the LQR and Kalman filter passed to its
125 // constructor. These bundles heap-pin all three together so the pointers are never dangled.
126 struct FlywheelBundle {
127 wpi::math::LinearQuadraticRegulator<1, 1> controller;
128 wpi::math::KalmanFilter<1, 1, 1> observer;
129 LQRConfig::Loop1 loop;
130
131 FlywheelBundle(wpi::math::LinearSystem<1, 1, 1> plant,
132 wpi::math::LinearQuadraticRegulator<1, 1> ctrl,
133 wpi::math::KalmanFilter<1, 1, 1> obs, wpi::units::volt_t maxV,
134 wpi::units::second_t dt)
135 : controller{std::move(ctrl)},
136 observer{std::move(obs)},
137 loop{plant, controller, observer, maxV, dt} {}
138
139 FlywheelBundle(const FlywheelBundle&) = delete;
140 FlywheelBundle& operator=(const FlywheelBundle&) = delete;
141 FlywheelBundle(FlywheelBundle&&) = delete;
142 FlywheelBundle& operator=(FlywheelBundle&&) = delete;
143 };
144
145 struct ArmElevatorBundle {
146 wpi::math::LinearQuadraticRegulator<2, 1> controller;
147 wpi::math::KalmanFilter<2, 1, 1> observer;
148 LQRConfig::Loop2 loop;
149
150 ArmElevatorBundle(wpi::math::LinearSystem<2, 1, 1> plant,
151 wpi::math::LinearQuadraticRegulator<2, 1> ctrl,
152 wpi::math::KalmanFilter<2, 1, 1> obs, wpi::units::volt_t maxV,
153 wpi::units::second_t dt)
154 : controller{std::move(ctrl)},
155 observer{std::move(obs)},
156 loop{plant, controller, observer, maxV, dt} {}
157
158 ArmElevatorBundle(const ArmElevatorBundle&) = delete;
159 ArmElevatorBundle& operator=(const ArmElevatorBundle&) = delete;
160 ArmElevatorBundle(ArmElevatorBundle&&) = delete;
161 ArmElevatorBundle& operator=(ArmElevatorBundle&&) = delete;
162 };
163
164 static std::unique_ptr<FlywheelBundle> BuildFlywheel(const LQRConfig& cfg);
165 static std::unique_ptr<ArmElevatorBundle> BuildArmElevator(const LQRConfig& cfg);
166
167 std::optional<LQRConfig> m_config;
168 LQRConfig::LQRType m_type;
169 std::variant<std::unique_ptr<FlywheelBundle>, std::unique_ptr<ArmElevatorBundle>> m_bundle;
170 wpi::units::second_t m_period;
171};
172
173} // namespace yams::math
Definition LQRConfig.hpp:27
wpi::math::LinearSystemLoop< 2, 1, 1 > Loop2
Definition LQRConfig.hpp:39
LQRType
Definition LQRConfig.hpp:30
wpi::math::LinearSystemLoop< 1, 1, 1 > Loop1
Definition LQRConfig.hpp:37
Definition LQRController.hpp:35
wpi::units::volt_t Calculate(wpi::units::radian_t measured, wpi::units::radian_t position, wpi::units::radians_per_second_t velocity)
void UpdateConfig(LQRConfig config)
LQRConfig::LQRType GetType() const
void Reset(wpi::units::meter_t distance, wpi::units::meters_per_second_t velocity)
wpi::units::volt_t Calculate(wpi::units::radians_per_second_t measured, wpi::units::radians_per_second_t velocity)
wpi::units::volt_t Calculate(wpi::units::meters_per_second_t measured, wpi::units::meters_per_second_t velocity)
void Reset(wpi::units::radian_t angle, wpi::units::radians_per_second_t velocity)
wpi::units::volt_t Calculate(wpi::units::meter_t measured, wpi::units::meter_t position, wpi::units::meters_per_second_t velocity)
const std::optional< LQRConfig > & GetConfig() const
LQRController(LQRConfig config)
Definition DerivativeTimeFilter.hpp:10