WPILibC++ 2023.4.3
ArmFeedforward.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 <wpi/MathExtras.h>
8#include <wpi/SymbolExports.h>
9
10#include "units/angle.h"
12#include "units/math.h"
13#include "units/voltage.h"
14
15namespace frc {
16/**
17 * A helper class that computes feedforward outputs for a simple arm (modeled as
18 * a motor acting against the force of gravity on a beam suspended at an angle).
19 */
21 public:
22 using Angle = units::radians;
23 using Velocity = units::radians_per_second;
24 using Acceleration = units::compound_unit<units::radians_per_second,
26 using kv_unit =
27 units::compound_unit<units::volts,
29 using ka_unit =
31
32 constexpr ArmFeedforward() = default;
33
34 /**
35 * Creates a new ArmFeedforward with the specified gains.
36 *
37 * @param kS The static gain, in volts.
38 * @param kG The gravity gain, in volts.
39 * @param kV The velocity gain, in volt seconds per radian.
40 * @param kA The acceleration gain, in volt secondsĀ² per radian.
41 */
42 constexpr ArmFeedforward(
43 units::volt_t kS, units::volt_t kG, units::unit_t<kv_unit> kV,
45 : kS(kS), kG(kG), kV(kV), kA(kA) {}
46
47 /**
48 * Calculates the feedforward from the gains and setpoints.
49 *
50 * @param angle The angle setpoint, in radians. This angle should be
51 * measured from the horizontal (i.e. if the provided
52 * angle is 0, the arm should be parallel to the floor).
53 * If your encoder does not follow this convention, an
54 * offset should be added.
55 * @param velocity The velocity setpoint, in radians per second.
56 * @param acceleration The acceleration setpoint, in radians per secondĀ².
57 * @return The computed feedforward, in volts.
58 */
59 units::volt_t Calculate(units::unit_t<Angle> angle,
61 units::unit_t<Acceleration> acceleration =
63 return kS * wpi::sgn(velocity) + kG * units::math::cos(angle) +
64 kV * velocity + kA * acceleration;
65 }
66
67 // Rearranging the main equation from the calculate() method yields the
68 // formulas for the methods below:
69
70 /**
71 * Calculates the maximum achievable velocity given a maximum voltage supply,
72 * a position, and an acceleration. Useful for ensuring that velocity and
73 * acceleration constraints for a trapezoidal profile are simultaneously
74 * achievable - enter the acceleration constraint, and this will give you
75 * a simultaneously-achievable velocity constraint.
76 *
77 * @param maxVoltage The maximum voltage that can be supplied to the arm.
78 * @param angle The angle of the arm. This angle should be measured
79 * from the horizontal (i.e. if the provided angle is 0,
80 * the arm should be parallel to the floor). If your
81 * encoder does not follow this convention, an offset
82 * should be added.
83 * @param acceleration The acceleration of the arm.
84 * @return The maximum possible velocity at the given acceleration and angle.
85 */
87 units::volt_t maxVoltage, units::unit_t<Angle> angle,
88 units::unit_t<Acceleration> acceleration) {
89 // Assume max velocity is positive
90 return (maxVoltage - kS - kG * units::math::cos(angle) -
91 kA * acceleration) /
92 kV;
93 }
94
95 /**
96 * Calculates the minimum achievable velocity given a maximum voltage supply,
97 * a position, and an acceleration. Useful for ensuring that velocity and
98 * acceleration constraints for a trapezoidal profile are simultaneously
99 * achievable - enter the acceleration constraint, and this will give you
100 * a simultaneously-achievable velocity constraint.
101 *
102 * @param maxVoltage The maximum voltage that can be supplied to the arm.
103 * @param angle The angle of the arm. This angle should be measured
104 * from the horizontal (i.e. if the provided angle is 0,
105 * the arm should be parallel to the floor). If your
106 * encoder does not follow this convention, an offset
107 * should be added.
108 * @param acceleration The acceleration of the arm.
109 * @return The minimum possible velocity at the given acceleration and angle.
110 */
112 units::volt_t maxVoltage, units::unit_t<Angle> angle,
113 units::unit_t<Acceleration> acceleration) {
114 // Assume min velocity is negative, ks flips sign
115 return (-maxVoltage + kS - kG * units::math::cos(angle) -
116 kA * acceleration) /
117 kV;
118 }
119
120 /**
121 * Calculates the maximum achievable acceleration given a maximum voltage
122 * supply, a position, and a velocity. Useful for ensuring that velocity and
123 * acceleration constraints for a trapezoidal profile are simultaneously
124 * achievable - enter the velocity constraint, and this will give you
125 * a simultaneously-achievable acceleration constraint.
126 *
127 * @param maxVoltage The maximum voltage that can be supplied to the arm.
128 * @param angle The angle of the arm. This angle should be measured
129 * from the horizontal (i.e. if the provided angle is 0,
130 * the arm should be parallel to the floor). If your
131 * encoder does not follow this convention, an offset
132 * should be added.
133 * @param velocity The velocity of the arm.
134 * @return The maximum possible acceleration at the given velocity and angle.
135 */
137 units::volt_t maxVoltage, units::unit_t<Angle> angle,
138 units::unit_t<Velocity> velocity) {
139 return (maxVoltage - kS * wpi::sgn(velocity) -
140 kG * units::math::cos(angle) - kV * velocity) /
141 kA;
142 }
143
144 /**
145 * Calculates the minimum achievable acceleration given a maximum voltage
146 * supply, a position, and a velocity. Useful for ensuring that velocity and
147 * acceleration constraints for a trapezoidal profile are simultaneously
148 * achievable - enter the velocity constraint, and this will give you
149 * a simultaneously-achievable acceleration constraint.
150 *
151 * @param maxVoltage The maximum voltage that can be supplied to the arm.
152 * @param angle The angle of the arm. This angle should be measured
153 * from the horizontal (i.e. if the provided angle is 0,
154 * the arm should be parallel to the floor). If your
155 * encoder does not follow this convention, an offset
156 * should be added.
157 * @param velocity The velocity of the arm.
158 * @return The minimum possible acceleration at the given velocity and angle.
159 */
161 units::volt_t maxVoltage, units::unit_t<Angle> angle,
162 units::unit_t<Velocity> velocity) {
163 return MaxAchievableAcceleration(-maxVoltage, angle, velocity);
164 }
165
166 units::volt_t kS{0};
167 units::volt_t kG{0};
170};
171} // namespace frc
#define WPILIB_DLLEXPORT
Definition: SymbolExports.h:36
A helper class that computes feedforward outputs for a simple arm (modeled as a motor acting against ...
Definition: ArmFeedforward.h:20
units::unit_t< Velocity > MaxAchievableVelocity(units::volt_t maxVoltage, units::unit_t< Angle > angle, units::unit_t< Acceleration > acceleration)
Calculates the maximum achievable velocity given a maximum voltage supply, a position,...
Definition: ArmFeedforward.h:86
units::radians_per_second Velocity
Definition: ArmFeedforward.h:23
units::volt_t Calculate(units::unit_t< Angle > angle, units::unit_t< Velocity > velocity, units::unit_t< Acceleration > acceleration=units::unit_t< Acceleration >(0)) const
Calculates the feedforward from the gains and setpoints.
Definition: ArmFeedforward.h:59
units::unit_t< Acceleration > MaxAchievableAcceleration(units::volt_t maxVoltage, units::unit_t< Angle > angle, units::unit_t< Velocity > velocity)
Calculates the maximum achievable acceleration given a maximum voltage supply, a position,...
Definition: ArmFeedforward.h:136
units::compound_unit< units::volts, units::inverse< Acceleration > > ka_unit
Definition: ArmFeedforward.h:30
units::compound_unit< units::radians_per_second, units::inverse< units::second > > Acceleration
Definition: ArmFeedforward.h:25
units::radians Angle
Definition: ArmFeedforward.h:22
units::unit_t< Acceleration > MinAchievableAcceleration(units::volt_t maxVoltage, units::unit_t< Angle > angle, units::unit_t< Velocity > velocity)
Calculates the minimum achievable acceleration given a maximum voltage supply, a position,...
Definition: ArmFeedforward.h:160
units::unit_t< Velocity > MinAchievableVelocity(units::volt_t maxVoltage, units::unit_t< Angle > angle, units::unit_t< Acceleration > acceleration)
Calculates the minimum achievable velocity given a maximum voltage supply, a position,...
Definition: ArmFeedforward.h:111
constexpr ArmFeedforward()=default
units::compound_unit< units::volts, units::inverse< units::radians_per_second > > kv_unit
Definition: ArmFeedforward.h:28
constexpr ArmFeedforward(units::volt_t kS, units::volt_t kG, units::unit_t< kv_unit > kV, units::unit_t< ka_unit > kA=units::unit_t< ka_unit >(0))
Creates a new ArmFeedforward with the specified gains.
Definition: ArmFeedforward.h:42
typename units::detail::inverse_impl< U >::type inverse
represents the inverse unit type of class U.
Definition: base.h:1134
dimensionless::scalar_t cos(const AngleUnit angle) noexcept
Compute cosine.
Definition: math.h:61
typename units::detail::compound_impl< U, Us... >::type compound_unit
Represents a unit type made up from other units.
Definition: base.h:1434
Definition: AprilTagFieldLayout.h:22
constexpr int sgn(T val)
Definition: MathExtras.h:936