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