Skyward boardcore
Loading...
Searching...
No Matches
Follower.cpp
Go to the documentation of this file.
1/* Copyright (c) 2024 Skyward Experimental Rocketry
2 * Authors: Emilio Corigliano, Niccolò Betto, Federico Lolli
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 "Follower.h"
24
27
28#include <Eigen/Dense>
29#include <cmath>
30#include <iostream>
31
32using namespace miosix;
33
34namespace Boardcore
35{
36
43float minimizeRotation(float angle)
44{
45 if (angle > 180)
46 angle -= 360;
47 else if (angle < -180)
48 angle += 360;
49
50 return angle;
51}
52
53Follower::Follower(std::chrono::milliseconds updPeriod)
54 : updatePeriod{updPeriod}, targetAngles({0, 0, 0})
55{
56}
57
59{
60 Lock<FastMutex> lock(followerMutex);
61 antennaCoordinates = {gpsData.latitude, gpsData.longitude};
63 antennaCoordinatesSet = true;
64}
65
67{
68 Lock<FastMutex> lock(followerMutex);
69 rocketNASOrigin = {gpsData.latitude, gpsData.longitude, gpsData.height};
71 rocketCoordinatesSet = true;
72}
73
75{
76 Lock<FastMutex> lock(followerMutex);
77 firstAntennaAttitudeSet = true;
78 lastAntennaAttitude = attitudeData;
79}
80
81VN300Data Follower::getLastAntennaAttitude()
82{
83 Lock<FastMutex> lock(followerMutex);
84 return lastAntennaAttitude;
85}
86
88{
89 Lock<FastMutex> lock(followerMutex);
90 lastRocketNasState = nasState;
91 lastRocketNasStateSet = true;
92}
93
94NASState Follower::getLastRocketNasState()
95{
96 Lock<FastMutex> lock(followerMutex);
97 return lastRocketNasState;
98}
99
101{
102 miosix::Lock<miosix::FastMutex> lock(followerMutex);
103 return state;
104}
105
106void Follower::setState(const FollowerState& newState)
107{
108 miosix::Lock<miosix::FastMutex> lock(followerMutex);
109 state = newState;
110}
111
113{
114 miosix::Lock<miosix::FastMutex> lock(followerMutex);
115 return targetAngles;
116}
117
118bool Follower::setMaxGain(float yawGainNew, float pitchGainNew)
119{
120 Lock<FastMutex> lock(followerMutex);
121
122 // In case of negative or over the limit values, do not set the gains
123 if (yawGainNew < 0 || yawGainNew > YAW_GAIN_LIMIT || pitchGainNew < 0 ||
124 pitchGainNew > PITCH_GAIN_LIMIT)
125 return false;
126
127 yawGain = yawGainNew;
128 pitchGain = pitchGainNew;
129 return true;
130}
131
133{
134 Lock<FastMutex> lock(followerMutex);
135 if (!antennaCoordinatesSet || !rocketCoordinatesSet)
136 {
137 LOG_ERR(logger, "Antenna or rocket coordinates not set");
138 return false;
139 }
140 return true;
141}
142
143void Follower::step()
144{
145 AntennaAngles diffAngles;
146 VN300Data vn300;
147 NASState lastRocketNas;
148 NEDCoords rocketPosition;
149
150 // Read the data for the step computation
151 {
152 Lock<FastMutex> lock(followerMutex);
153
154 if (!firstAntennaAttitudeSet)
155 {
156 LOG_ERR(logger, "Antenna attitude not set\n");
157 return;
158 }
159 // TODO: See if needed to check the NAS or rather point to the NAS
160 // origin if missing
161
162 lastRocketNas = lastRocketNasState;
163 vn300 = lastAntennaAttitude;
164
165 // Local variable checks and updates
166 // Getting the position of the rocket wrt the antennas in NED frame
167 rocketPosition = {lastRocketNas.n, lastRocketNas.e, lastRocketNas.d};
168
169 // Calculate the antenna target angles from the NED rocket coordinates
170 targetAngles = rocketPositionToAntennaAngles(rocketPosition);
171
172 // Calculate the amount to move from the current position
173 diffAngles = {targetAngles.timestamp, targetAngles.yaw - vn300.yaw,
174 targetAngles.pitch - vn300.pitch};
175
176 // Rotate in the shortest direction
177 diffAngles.yaw = std::min(yawGain, YAW_GAIN_LIMIT) *
178 minimizeRotation(diffAngles.yaw);
179 diffAngles.pitch = std::min(pitchGain, PITCH_GAIN_LIMIT) *
180 minimizeRotation(diffAngles.pitch);
181 }
182
183 // Calculate angular velocity for moving the antennas toward position
184 float horizontalSpeed =
185 std::abs((diffAngles.yaw) /
186 (360 * (static_cast<float>(updatePeriod.count()) / 1000)));
187 TRACE("[Follower] horizontalSpeed is: %f\n", horizontalSpeed);
188 float verticalSpeed =
189 std::abs((diffAngles.pitch) /
190 (360 * (static_cast<float>(updatePeriod.count()) / 1000)));
191 TRACE("[Follower] Vertical speed is: %f\n", horizontalSpeed);
192
193 // Update the state of the follower
194 FollowerState newState;
195 newState.timestamp = TimestampTimer::getTimestamp();
196 newState.yaw = diffAngles.yaw;
197 newState.pitch = diffAngles.pitch;
198 newState.horizontalSpeed = horizontalSpeed;
199 newState.verticalSpeed = verticalSpeed;
200
201 // Write the new state for the follower
202 {
203 Lock<FastMutex> lockWrite(followerMutex);
204 state = newState;
205 }
206
207#ifndef NDEBUG
208 std::cout << "[FOLLOWER] STEPPER " << "Angles: [" << newState.yaw << ", "
209 << newState.pitch << "] " << "Speed: ["
210 << newState.horizontalSpeed << ", " << newState.verticalSpeed
211 << "] VN300 measure: [" << vn300.yaw << ", " << vn300.pitch
212 << "]\n";
213#endif
214}
215
216Eigen::Vector2f Follower::getAntennaCoordinates()
217{
218 Lock<FastMutex> lock(followerMutex);
219 return Eigen::Vector2f{antennaCoordinates};
220}
221
222Eigen::Vector3f Follower::getRocketNASOrigin()
223{
224 Lock<FastMutex> lock(followerMutex);
225 return Eigen::Vector3f{rocketNASOrigin};
226}
227
228AntennaAngles Follower::rocketPositionToAntennaAngles(
229 const NEDCoords& rocketNed)
230{
231 // Antenna Coordinates
232 Eigen::Vector2f antennaCoord = antennaCoordinates;
233
234 // Rocket coordinates, w/out altitude
235 Eigen::Vector2f rocketCoord = rocketNASOrigin.head<2>();
236
237 antennaRocketDistance = Aeroutils::geodetic2NED(rocketCoord, antennaCoord);
238
239 // NED coordinates of the rocket in the NED antenna frame
240 NEDCoords ned = {rocketNed.n + antennaRocketDistance.x(),
241 rocketNed.e + antennaRocketDistance.y(), rocketNed.d};
242
243 AntennaAngles angles;
244 angles.timestamp = TimestampTimer::getTimestamp();
245
246 // Calculate the horizontal angle relative to the NED frame
247 // std::atan2 outputs angles in radians, convert to degrees
248 angles.yaw = std::atan2(ned.e, ned.n) / EIGEN_PI * 180;
249
250 float distance = std::sqrt(ned.n * ned.n + ned.e * ned.e);
251 // Calculate the vertical angle relative to the NED frame
252 angles.pitch = std::atan2(-ned.d, distance) / EIGEN_PI * 180;
253
254 return angles;
255}
256
257} // namespace Boardcore
#define TRACE(...)
Definition Debug.h:58
#define LOG_ERR(logger,...)
FollowerState getState()
Synchronized getter for the State of the follower algorithm.
Definition Follower.cpp:100
AntennaAngles getTargetAngles()
Getter for the target antenna position computed by the algorithm.
Definition Follower.cpp:112
bool setMaxGain(float yawGainNew, float pitchGainNew)
Set the maximum gain for the yaw and pitch.
Definition Follower.cpp:118
Follower(std::chrono::milliseconds updatePeriod)
Constructor of the follower class.
Definition Follower.cpp:53
void setLastRocketNasState(const NASState &nasState)
Setter for the NAS state of the rocket.
Definition Follower.cpp:87
bool init() override
Check that both the antenna and rocket coordinates have been set.
Definition Follower.cpp:132
void setLastAntennaAttitude(const VN300Data &attitudeData)
Setter for the attitude of the antenna.
Definition Follower.cpp:74
void setRocketNASOrigin(const GPSData &gpsData)
Setter for the GPS coordinates of the rocket's NAS origin reference.
Definition Follower.cpp:66
void setAntennaCoordinates(const GPSData &gpsData)
Setter for the GPS coordinates of the antenna.
Definition Follower.cpp:58
LoggerResult log(const T &t)
Call this function to log a class.
Definition Logger.h:224
static Logger & getInstance()
Definition Singleton.h:52
float verticalSpeed(float p, float dpDt, float pRef, float tRef)
Definition AeroUtils.cpp:69
Vector2f geodetic2NED(const Vector2f &target, const Vector2f &origin)
Definition AeroUtils.cpp:74
uint64_t getTimestamp()
Returns the current timer value in microseconds.
This file includes all the types the logdecoder script will decode.
float minimizeRotation(float angle)
Minimize rotation angle.
Definition Follower.cpp:43
A structure for storing angles relative to the NED frame.
float pitch
position, positive UP [deg]
State of the Follower algorithm, with the angles and speeds.
Structure to handle GPS data.
Definition SensorData.h:291
A structure for logging the ARP system coordinates set in the Follower.
A structure for logging the Rocket coordinates set in the Follower.
Data class for VN300.
Definition VN300Data.h:51