WPILibC++ 2027.0.0-alpha-4
Loading...
Searching...
No Matches
SimpleMotorFeedforward.hpp
Go to the documentation of this file.
1// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5#pragma once
6
7#include <gcem.hpp>
8
10#include "wpi/units/angle.hpp"
11#include "wpi/units/length.hpp"
12#include "wpi/units/time.hpp"
13#include "wpi/units/voltage.hpp"
15
16namespace wpi::math {
17
18/**
19 * A helper class that computes feedforward voltages for a simple
20 * permanent-magnet DC motor.
21 */
22template <class Distance>
23 requires wpi::units::length_unit<Distance> || wpi::units::angle_unit<Distance>
25 public:
26 using Velocity =
27 wpi::units::compound_unit<Distance,
28 wpi::units::inverse<wpi::units::seconds>>;
30 wpi::units::compound_unit<Velocity,
31 wpi::units::inverse<wpi::units::seconds>>;
32 using kv_unit = wpi::units::compound_unit<wpi::units::volts,
33 wpi::units::inverse<Velocity>>;
34 using ka_unit = wpi::units::compound_unit<wpi::units::volts,
35 wpi::units::inverse<Acceleration>>;
36
37 /**
38 * Creates a new SimpleMotorFeedforward with the specified gains.
39 *
40 * @param kS The static gain, in volts.
41 * @param kV The velocity gain, in volt seconds per distance.
42 * @param kA The acceleration gain, in volt seconds² per distance.
43 * @param dt The period in seconds.
44 * @throws IllegalArgumentException for kv &lt; zero.
45 * @throws IllegalArgumentException for ka &lt; zero.
46 * @throws IllegalArgumentException for period &le; zero.
47 */
49 wpi::units::volt_t kS, wpi::units::unit_t<kv_unit> kV,
50 wpi::units::unit_t<ka_unit> kA = wpi::units::unit_t<ka_unit>(0),
51 wpi::units::second_t dt = 20_ms)
52 : kS(kS), kV(kV), kA(kA), m_dt(dt) {
53 if (kV.value() < 0) {
54 wpi::math::MathSharedStore::ReportError(
55 "kV must be a non-negative number, got {}!", kV.value());
56 this->kV = wpi::units::unit_t<kv_unit>{0};
58 }
59 if (kA.value() < 0) {
60 wpi::math::MathSharedStore::ReportError(
61 "kA must be a non-negative number, got {}!", kA.value());
62 this->kA = wpi::units::unit_t<ka_unit>{0};
64 }
65 if (dt <= 0_ms) {
67 "period must be a positive number, got {}!", dt.value());
68 this->m_dt = 20_ms;
69 wpi::math::MathSharedStore::ReportWarning("period defaulted to 20 ms.");
70 }
71 }
72
73 /**
74 * Calculates the feedforward from the gains and velocity setpoint assuming
75 * discrete control. Use this method when the velocity setpoint does not
76 * change.
77 *
78 * @param velocity The velocity setpoint.
79 * @return The computed feedforward, in volts.
80 */
81 constexpr wpi::units::volt_t Calculate(
82 wpi::units::unit_t<Velocity> velocity) const {
83 return Calculate(velocity, velocity);
84 }
85
86 /**
87 * Calculates the feedforward from the gains and setpoints assuming discrete
88 * control.
89 *
90 * <p>Note this method is inaccurate when the velocity crosses 0.
91 *
92 * @param currentVelocity The current velocity setpoint.
93 * @param nextVelocity The next velocity setpoint.
94 * @return The computed feedforward, in volts.
95 */
96 constexpr wpi::units::volt_t Calculate(
97 wpi::units::unit_t<Velocity> currentVelocity,
98 wpi::units::unit_t<Velocity> nextVelocity) const {
99 // See wpimath/algorithms.md#Simple_motor_feedforward for derivation
100 if (kA < decltype(kA)(1e-9)) {
101 return kS * wpi::util::sgn(nextVelocity) + kV * nextVelocity;
102 } else {
103 double A = -kV.value() / kA.value();
104 double B = 1.0 / kA.value();
105 double A_d = gcem::exp(A * m_dt.value());
106 double B_d = A > -1e-9 ? B * m_dt.value() : 1.0 / A * (A_d - 1.0) * B;
107 return kS * wpi::util::sgn(currentVelocity) +
108 wpi::units::volt_t{
109 1.0 / B_d *
110 (nextVelocity.value() - A_d * currentVelocity.value())};
111 }
112 }
113
114 // Rearranging the main equation from the calculate() method yields the
115 // formulas for the methods below:
116
117 /**
118 * Calculates the maximum achievable velocity given a maximum voltage supply
119 * and an acceleration. Useful for ensuring that velocity and
120 * acceleration constraints for a trapezoidal profile are simultaneously
121 * achievable - enter the acceleration constraint, and this will give you
122 * a simultaneously-achievable velocity constraint.
123 *
124 * @param maxVoltage The maximum voltage that can be supplied to the motor.
125 * @param acceleration The acceleration of the motor.
126 * @return The maximum possible velocity at the given acceleration.
127 */
128 constexpr wpi::units::unit_t<Velocity> MaxAchievableVelocity(
129 wpi::units::volt_t maxVoltage,
130 wpi::units::unit_t<Acceleration> acceleration) const {
131 // Assume max velocity is positive
132 return (maxVoltage - kS - kA * acceleration) / kV;
133 }
134
135 /**
136 * Calculates the minimum achievable velocity given a maximum voltage supply
137 * and an acceleration. Useful for ensuring that velocity and
138 * acceleration constraints for a trapezoidal profile are simultaneously
139 * achievable - enter the acceleration constraint, and this will give you
140 * a simultaneously-achievable velocity constraint.
141 *
142 * @param maxVoltage The maximum voltage that can be supplied to the motor.
143 * @param acceleration The acceleration of the motor.
144 * @return The minimum possible velocity at the given acceleration.
145 */
146 constexpr wpi::units::unit_t<Velocity> MinAchievableVelocity(
147 wpi::units::volt_t maxVoltage,
148 wpi::units::unit_t<Acceleration> acceleration) const {
149 // Assume min velocity is positive, ks flips sign
150 return (-maxVoltage + kS - kA * acceleration) / kV;
151 }
152
153 /**
154 * Calculates the maximum achievable acceleration given a maximum voltage
155 * supply and a velocity. Useful for ensuring that velocity and
156 * acceleration constraints for a trapezoidal profile are simultaneously
157 * achievable - enter the velocity constraint, and this will give you
158 * a simultaneously-achievable acceleration constraint.
159 *
160 * @param maxVoltage The maximum voltage that can be supplied to the motor.
161 * @param velocity The velocity of the motor.
162 * @return The maximum possible acceleration at the given velocity.
163 */
164 constexpr wpi::units::unit_t<Acceleration> MaxAchievableAcceleration(
165 wpi::units::volt_t maxVoltage,
166 wpi::units::unit_t<Velocity> velocity) const {
167 return (maxVoltage - kS * wpi::util::sgn(velocity) - kV * velocity) / kA;
168 }
169
170 /**
171 * Calculates the minimum achievable acceleration given a maximum voltage
172 * supply and a velocity. Useful for ensuring that velocity and
173 * acceleration constraints for a trapezoidal profile are simultaneously
174 * achievable - enter the velocity constraint, and this will give you
175 * a simultaneously-achievable acceleration constraint.
176 *
177 * @param maxVoltage The maximum voltage that can be supplied to the motor.
178 * @param velocity The velocity of the motor.
179 * @return The minimum possible acceleration at the given velocity.
180 */
181 constexpr wpi::units::unit_t<Acceleration> MinAchievableAcceleration(
182 wpi::units::volt_t maxVoltage,
183 wpi::units::unit_t<Velocity> velocity) const {
184 return MaxAchievableAcceleration(-maxVoltage, velocity);
185 }
186
187 /**
188 * Sets the static gain.
189 *
190 * @param kS The static gain.
191 */
192 constexpr void SetKs(wpi::units::volt_t kS) { this->kS = kS; }
193
194 /**
195 * Sets the velocity gain.
196 *
197 * @param kV The velocity gain.
198 */
199 constexpr void SetKv(wpi::units::unit_t<kv_unit> kV) { this->kV = kV; }
200
201 /**
202 * Sets the acceleration gain.
203 *
204 * @param kA The acceleration gain.
205 */
206 constexpr void SetKa(wpi::units::unit_t<ka_unit> kA) { this->kA = kA; }
207
208 /**
209 * Returns the static gain.
210 *
211 * @return The static gain.
212 */
213 constexpr wpi::units::volt_t GetKs() const { return kS; }
214
215 /**
216 * Returns the velocity gain.
217 *
218 * @return The velocity gain.
219 */
220 constexpr wpi::units::unit_t<kv_unit> GetKv() const { return kV; }
221
222 /**
223 * Returns the acceleration gain.
224 *
225 * @return The acceleration gain.
226 */
227 constexpr wpi::units::unit_t<ka_unit> GetKa() const { return kA; }
228
229 /**
230 * Returns the period.
231 *
232 * @return The period.
233 */
234 constexpr wpi::units::second_t GetDt() const { return m_dt; }
235
236 private:
237 /** The static gain. */
238 wpi::units::volt_t kS;
239
240 /** The velocity gain. */
241 wpi::units::unit_t<kv_unit> kV;
242
243 /** The acceleration gain. */
244 wpi::units::unit_t<ka_unit> kA;
245
246 /** The period. */
247 wpi::units::second_t m_dt;
248};
249
250} // namespace wpi::math
251
static void ReportError(const S &format, Args &&... args)
Definition MathShared.hpp:48
static void ReportWarning(const S &format, Args &&... args)
Definition MathShared.hpp:57
wpi::units::compound_unit< wpi::units::volts, wpi::units::inverse< Acceleration > > ka_unit
Definition SimpleMotorFeedforward.hpp:34
constexpr void SetKa(wpi::units::unit_t< ka_unit > kA)
Sets the acceleration gain.
Definition SimpleMotorFeedforward.hpp:206
constexpr wpi::units::volt_t Calculate(wpi::units::unit_t< Velocity > currentVelocity, wpi::units::unit_t< Velocity > nextVelocity) const
Calculates the feedforward from the gains and setpoints assuming discrete control.
Definition SimpleMotorFeedforward.hpp:96
constexpr SimpleMotorFeedforward(wpi::units::volt_t kS, wpi::units::unit_t< kv_unit > kV, wpi::units::unit_t< ka_unit > kA=wpi::units::unit_t< ka_unit >(0), wpi::units::second_t dt=20_ms)
Creates a new SimpleMotorFeedforward with the specified gains.
Definition SimpleMotorFeedforward.hpp:48
constexpr wpi::units::unit_t< Acceleration > MaxAchievableAcceleration(wpi::units::volt_t maxVoltage, wpi::units::unit_t< Velocity > velocity) const
Calculates the maximum achievable acceleration given a maximum voltage supply and a velocity.
Definition SimpleMotorFeedforward.hpp:164
wpi::units::compound_unit< wpi::units::volts, wpi::units::inverse< Velocity > > kv_unit
Definition SimpleMotorFeedforward.hpp:32
constexpr wpi::units::volt_t Calculate(wpi::units::unit_t< Velocity > velocity) const
Calculates the feedforward from the gains and velocity setpoint assuming discrete control.
Definition SimpleMotorFeedforward.hpp:81
constexpr wpi::units::second_t GetDt() const
Returns the period.
Definition SimpleMotorFeedforward.hpp:234
constexpr wpi::units::volt_t GetKs() const
Returns the static gain.
Definition SimpleMotorFeedforward.hpp:213
constexpr wpi::units::unit_t< Velocity > MaxAchievableVelocity(wpi::units::volt_t maxVoltage, wpi::units::unit_t< Acceleration > acceleration) const
Calculates the maximum achievable velocity given a maximum voltage supply and an acceleration.
Definition SimpleMotorFeedforward.hpp:128
constexpr wpi::units::unit_t< Acceleration > MinAchievableAcceleration(wpi::units::volt_t maxVoltage, wpi::units::unit_t< Velocity > velocity) const
Calculates the minimum achievable acceleration given a maximum voltage supply and a velocity.
Definition SimpleMotorFeedforward.hpp:181
constexpr wpi::units::unit_t< kv_unit > GetKv() const
Returns the velocity gain.
Definition SimpleMotorFeedforward.hpp:220
wpi::units::compound_unit< Velocity, wpi::units::inverse< wpi::units::seconds > > Acceleration
Definition SimpleMotorFeedforward.hpp:29
constexpr void SetKv(wpi::units::unit_t< kv_unit > kV)
Sets the velocity gain.
Definition SimpleMotorFeedforward.hpp:199
wpi::units::compound_unit< Distance, wpi::units::inverse< wpi::units::seconds > > Velocity
Definition SimpleMotorFeedforward.hpp:26
constexpr wpi::units::unit_t< ka_unit > GetKa() const
Returns the acceleration gain.
Definition SimpleMotorFeedforward.hpp:227
constexpr wpi::units::unit_t< Velocity > MinAchievableVelocity(wpi::units::volt_t maxVoltage, wpi::units::unit_t< Acceleration > acceleration) const
Calculates the minimum achievable velocity given a maximum voltage supply and an acceleration.
Definition SimpleMotorFeedforward.hpp:146
constexpr void SetKs(wpi::units::volt_t kS)
Sets the static gain.
Definition SimpleMotorFeedforward.hpp:192
constexpr return_t< T > exp(const T x) noexcept
Compile-time exponential function.
Definition exp.hpp:130
Definition LinearSystem.hpp:20
constexpr int sgn(T val)
Definition MathExtras.hpp:766