Skyward boardcore
Loading...
Searching...
No Matches
AirBrakesInterpPID.cpp
Go to the documentation of this file.
1/* Copyright (c) 2021-2022 Skyward Experimental Rocketry
2 * Authors: Vincenzo Santomarco, Alberto Nidasio, Emilio Corigliano
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#include "AirBrakesInterpPID.h"
24
25#include <logger/Logger.h>
26#include <utils/Constants.h>
27
28#include <limits>
29
31#include "utils/Debug.h"
32
33namespace Boardcore
34{
35
37 std::function<TimedTrajectoryPoint()> getCurrentPosition,
38 const TrajectorySet& trajectoryOpenSet,
39 const TrajectorySet& trajectoryCloseSet,
40 const AirBrakesInterpPIDConfig& configInterp,
41 std::function<void(float)> setActuator)
42 : getCurrentPosition(std::move(getCurrentPosition)),
43 setActuator(std::move(setActuator)), trajectoryOpenSet(trajectoryOpenSet),
44 trajectoryCloseSet(trajectoryCloseSet), configInterp(configInterp)
45{
46}
47
48bool AirBrakesInterpPID::init() { return true; }
49
50void AirBrakesInterpPID::begin(float currentMass)
51{
52 if (running)
53 return;
54
55 // Choose the best trajectories depending on the mass and the delta mass
56 if (configInterp.DM == 0)
57 {
58 // Compatibility in case the mass information is not provided
59 choosenOpenTrajectory = &trajectoryOpenSet.trajectories[0];
60 choosenCloseTrajectory = &trajectoryCloseSet.trajectories[0];
61 }
62 else
63 {
64 int index =
65 round((currentMass - configInterp.INITIAL_MASS) / configInterp.DM);
66
67 // Bound the index in order to have an indexable element
68 index = std::max(index, 0);
69 uint32_t boundedIndex = std::min(static_cast<uint32_t>(index),
70 trajectoryOpenSet.length() - 1);
71
72 choosenOpenTrajectory = &trajectoryOpenSet.trajectories[boundedIndex];
73 choosenCloseTrajectory = &trajectoryCloseSet.trajectories[boundedIndex];
74 }
75
77}
78
79void AirBrakesInterpPID::step()
80{
81 auto currentPosition = getCurrentPosition();
82
83 // Do nothing if we have no new data
84 if (lastPosition.timestamp >= currentPosition.timestamp)
85 return;
86
87 lastPosition = currentPosition;
88
89 // Interpolation + PID
90 float percentage = controlInterp(currentPosition);
91
92 // Filtering
93 if (currentPosition.z < configInterp.ABK_CRITICAL_ALTITUDE)
94 {
95 // Compute the actual value filtered
96 percentage =
97 lastPercentage + (percentage - lastPercentage) * filterCoeff;
98 }
99 else
100 {
101 // If the height is beyond the target one, the algorithm tries to brake
102 // as much as possible
103 percentage = 1;
104 }
105
106 // If the altitude is lower than the minimum one, the filter is kept at the
107 // same value, to avoid misleading filtering actions
108 if (currentPosition.z < configInterp.FILTER_MINIMUM_ALTITUDE)
109 {
110 filterCoeff = configInterp.STARTING_FILTER_VALUE;
111 }
112 else
113 {
114 filterCoeff =
115 configInterp.STARTING_FILTER_VALUE -
116 (currentPosition.z - configInterp.FILTER_MINIMUM_ALTITUDE) *
117 ((configInterp.STARTING_FILTER_VALUE) /
118 (configInterp.FILTER_MAXIMUM_ALTITUDE -
119 configInterp.FILTER_MINIMUM_ALTITUDE));
120 }
121
122 lastPercentage = percentage;
123 setActuator(percentage);
124}
125
126float AirBrakesInterpPID::controlInterp(TrajectoryPoint currentPosition)
127{
128 // we take the index of the current point of the trajectory and we look
129 // ahead of N points
130 int index_z =
131 floor((currentPosition.z / configInterp.DZ)) + configInterp.N_FORWARD;
132
133 index_z = std::max(index_z, 0);
134
135 // for safety we check whether the index exceeds the maximum index of the
136 // trajectory sets
137 index_z = std::min(index_z, std::min(choosenCloseTrajectory->trjSize - 1,
138 choosenOpenTrajectory->trjSize - 1));
139
140 Boardcore::TrajectoryPoint trjPointClosed =
141 choosenCloseTrajectory->points[index_z];
142 Boardcore::TrajectoryPoint trjPointOpen =
143 choosenOpenTrajectory->points[index_z];
144
145 // TRACE("z: %+.3f, curr: %+.3f, clos: %+.3f, open: %+.3f\n",
146 // currentPosition.z, currentPosition.vz, trjPointClosed.vz,
147 // trjPointOpen.vz);
148
149 if (currentPosition.vz <= trjPointClosed.vz)
150 {
151 return 0;
152 }
153 else if (currentPosition.vz >= trjPointOpen.vz)
154 {
155 return 1;
156 }
157 else
158 {
159 float detectedPosition = (currentPosition.vz - trjPointClosed.vz) /
160 (trjPointOpen.vz - trjPointClosed.vz);
161
162 float dt = 1 / configInterp.ARB_FREQ;
163
164 float ref = configInterp.PID_REF;
165 float error = detectedPosition - ref;
166 float prevError = lastPercentage - ref;
167
168 if (saturation == false)
169 integralError += error * dt;
170
171 float kp = configInterp.KP;
172 float ki = configInterp.KI;
173 float kd = configInterp.KD;
174
175 float percentage =
176 kp * error + kd * prevError / dt + ki * integralError + ref;
177
178 if (percentage < 0)
179 {
180 percentage = 0;
181 saturation = true;
182 }
183 else if (percentage > 1)
184 {
185 percentage = 1;
186 saturation = true;
187 }
188 else
189 saturation = false;
190
191 return percentage;
192 }
193}
194} // namespace Boardcore
AirBrakesInterpPID(std::function< TimedTrajectoryPoint()> getCurrentPosition, const TrajectorySet &trajectoryOpenSet, const TrajectorySet &trajectoryCloseSet, const AirBrakesInterpPIDConfig &configInterp, std::function< void(float)> setActuator)
bool init() override
Initializes the Algorithm object, must be called as soon as the object is created.
void begin()
Starts the execution of the algorithm and set the running flag to true.
Definition Algorithm.h:42
std::atomic< bool > running
Definition Algorithm.h:68
Trajectory point with timestamp and velocity module.
TrajectoryPoint * points
Definition Trajectory.h:34
float vz
Vertical velocity [m/s].
uint32_t length() const
Driver for the VN100S IMU.
Definition WIZ5500.h:339