INSTINCT Code Coverage Report


Directory: src/
File: Nodes/DataProvider/IMU/Simulators/ImuSimulator.hpp
Date: 2025-02-07 16:54:41
Exec Total Coverage
Lines: 2 2 100.0%
Functions: 0 0 -%
Branches: 2 4 50.0%

Line Branch Exec Source
1 // This file is part of INSTINCT, the INS Toolkit for Integrated
2 // Navigation Concepts and Training by the Institute of Navigation of
3 // the University of Stuttgart, Germany.
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
8
9 /// @file ImuSimulator.hpp
10 /// @brief Imu Observation Simulator
11 /// @author T. Topp (topp@ins.uni-stuttgart.de)
12 /// @author N. Stahl (Hiwi: Rose figure trajectory type)
13 /// @date 2023-07-18
14
15 #pragma once
16
17 #include "Nodes/DataProvider/IMU/Imu.hpp"
18
19 #include "util/Eigen.hpp"
20 #include "Navigation/Time/InsTime.hpp"
21 #include "Navigation/Gravity/Gravity.hpp"
22 #include "Navigation/Math/CubicSpline.hpp"
23 #include "internal/gui/widgets/TimeEdit.hpp"
24 #include "internal/gui/widgets/PositionInput.hpp"
25
26 #include "NodeData/General/CsvData.hpp"
27
28 #include <array>
29
30 namespace NAV
31 {
32 /// Imu Observation Simulator
33 class ImuSimulator : public Imu
34 {
35 public:
36 /// @brief Default constructor
37 ImuSimulator();
38 /// @brief Destructor
39 ~ImuSimulator() override;
40 /// @brief Copy constructor
41 ImuSimulator(const ImuSimulator&) = delete;
42 /// @brief Move constructor
43 ImuSimulator(ImuSimulator&&) = delete;
44 /// @brief Copy assignment operator
45 ImuSimulator& operator=(const ImuSimulator&) = delete;
46 /// @brief Move assignment operator
47 ImuSimulator& operator=(ImuSimulator&&) = delete;
48
49 /// @brief String representation of the Class Type
50 [[nodiscard]] static std::string typeStatic();
51
52 /// @brief String representation of the Class Type
53 [[nodiscard]] std::string type() const override;
54
55 /// @brief String representation of the Class Category
56 [[nodiscard]] static std::string category();
57
58 /// @brief ImGui config window which is shown on double click
59 /// @attention Don't forget to set _hasConfig to true in the constructor of the node
60 void guiConfig() override;
61
62 /// @brief Saves the node into a json object
63 [[nodiscard]] json save() const override;
64
65 /// @brief Restores the node from a json object
66 /// @param[in] j Json object with the node state
67 void restore(const json& j) override;
68
69 /// @brief Resets the node. Moves the read cursor to the start
70 bool resetNode() override;
71
72 private:
73 constexpr static size_t INPUT_PORT_INDEX_CSV = 0; ///< @brief Object (CsvData)
74 constexpr static size_t OUTPUT_PORT_INDEX_IMU_OBS = 0; ///< @brief Flow (ImuObs)
75 constexpr static size_t OUTPUT_PORT_INDEX_POS_VEL_ATT = 1; ///< @brief Flow (PosVelAtt)
76
77 /// @brief Initialize the node
78 bool initialize() override;
79
80 /// @brief Deinitialize the node
81 void deinitialize() override;
82
83 /// @brief Polls the next simulated data
84 /// @param[in] pinIdx Index of the pin the data is requested on
85 /// @param[in] peek Specifies if the data should be peeked or read
86 /// @return The simulated observation
87 [[nodiscard]] std::shared_ptr<const NodeData> pollImuObs(size_t pinIdx, bool peek);
88
89 /// @brief Polls the next simulated data
90 /// @param[in] pinIdx Index of the pin the data is requested on
91 /// @param[in] peek Specifies if the data should be peeked or read
92 /// @return The simulated observation
93 [[nodiscard]] std::shared_ptr<const NodeData> pollPosVelAtt(size_t pinIdx, bool peek);
94
95 /// @brief Checks the selected stop condition
96 /// @param[in] time Current simulation time
97 /// @param[in] lla_position Current position
98 /// @return True if it should be stopped
99 bool checkStopCondition(double time, const Eigen::Vector3d& lla_position);
100
101 // ###########################################################################################################
102
103 /// Types where the start time should be pulled from
104 enum class StartTimeSource : uint8_t
105 {
106 CustomTime, ///< Custom time selected by the user
107 CurrentComputerTime, ///< Gets the current computer time as start time
108 };
109
110 /// Source for the start time, selected in the GUI
111 StartTimeSource _startTimeSource = StartTimeSource::CustomTime;
112
113 /// Time Format to input the start time with
114 gui::widgets::TimeEditFormat _startTimeEditFormat;
115
116 /// Global starttime
117 InsTime _startTime{ 2000, 1, 1, 0, 0, 0 };
118
119 // ###########################################################################################################
120
121 /// Frequency to calculate the delta IMU values in [Hz]
122 double _imuInternalFrequency = 1000;
123 /// Frequency to sample the IMU with in [Hz]
124 double _imuFrequency = 100;
125 /// Frequency to sample the position with in [Hz]
126 double _gnssFrequency = 5;
127
128 // ###########################################################################################################
129
130 /// Types of Trajectories available for simulation
131 enum class TrajectoryType : uint8_t
132 {
133 Fixed, ///< Static position without movement
134 Linear, ///< Linear movement with constant velocity
135 Circular, ///< Circular path
136 Csv, ///< Get the input from the CsvData pin
137 RoseFigure, ///< Movement along a mathmatical rose figure
138 COUNT, ///< Amount of items in the enum
139 };
140 /// @brief Converts the enum to a string
141 /// @param[in] value Enum value to convert into text
142 /// @return String representation of the enum
143 static const char* to_string(TrajectoryType value);
144
145 /// Selected trajectory type in the GUI
146 TrajectoryType _trajectoryType = TrajectoryType::Fixed;
147
148 /// Start position in local navigation coordinates (latitude, longitude, altitude) [rad, rad, m]
149 ///
150 /// - Fixed, Linear: Start position
151 /// - Circular: Center of the circle
152 gui::widgets::PositionWithFrame _startPosition;
153
154 /// Orientation of the vehicle [roll, pitch, yaw] [rad]
155 Eigen::Vector3d _fixedTrajectoryStartOrientation = Eigen::Vector3d::Zero();
156
157 /// Start Velocity of the vehicle in local-navigation frame cooridnates in [m/s]
158 Eigen::Vector3d _n_linearTrajectoryStartVelocity = Eigen::Vector3d{ 1, 0, 0 };
159
160 /// Harmonic Oscillation Frequency on the circular trajectory [cycles/revolution]
161 int _circularHarmonicFrequency = 0;
162
163 /// Harmonic Oscillation Amplitude Factor of the circle radius [-]
164 double _circularHarmonicAmplitudeFactor = 0.1;
165
166 /// Possible directions for the circular trajectory
167 enum class Direction : uint8_t
168 {
169 CW, ///< Clockwise
170 CCW, ///< Counterclockwise
171 COUNT, ///< Amount of items in the enum
172 };
173 /// @brief Converts the enum to a string
174 /// @param[in] value Enum value to convert into text
175 /// @return String representation of the enum
176 static const char* to_string(Direction value);
177
178 /// In the GUI selected direction of the circular trajectory (used by circular and rose figure)
179 Direction _trajectoryDirection = Direction::CCW;
180
181 /// In the GUI selected origin angle of the circular trajectory in [rad]
182 double _trajectoryRotationAngle = 0.0;
183
184 /// Horizontal speed of the vehicle in the tangential plane in [m/s] (used by circular and rose figure)
185 double _trajectoryHorizontalSpeed = 10.0;
186
187 /// Vertical speed of the vehicle in the tangential plane in [m/s] (used by circular and rose figure)
188 double _trajectoryVerticalSpeed = 0.0;
189
190 /// In the GUI selected radius of the circular trajectory (used by circular and rose figure)
191 double _trajectoryRadius = 50.0;
192
193 /// In the GUI selected numerator of petals (2*k for even k, k for uneven k) of the rose figure
194 int _rosePetNum = 2;
195
196 /// In the GUI selected denominator of petals (2*k for even k, k for uneven k) of the rose figure
197 int _rosePetDenom = 1;
198
199 /// Maxmimum step length for the spline points for the rose figure [m]. Points will be spaced between [L/3 L]
200 double _roseStepLengthMax = 0.1;
201
202 /// Simulation duration needed for the rose figure
203 double _roseSimDuration = 0.0;
204
205 // ###########################################################################################################
206
207 /// Possible stop conditions for the simulation
208 enum StopCondition : uint8_t
209 {
210 Duration, ///< Time Duration
211 DistanceOrCirclesOrRoses, ///< Distance for Linear trajectory / Circle count for Circular / Count for rose figure trajectory
212 };
213
214 /// Condition which has to be met to stop the simulation
215 StopCondition _simulationStopCondition = StopCondition::Duration;
216
217 /// Duration to simulate in [s]
218 double _simulationDuration = 5 * 60;
219
220 /// Duration from the CSV file in [s]
221 double _csvDuration = 0;
222
223 /// Distance in [m] to the start position to stop the simulation
224 double _linearTrajectoryDistanceForStop = 100;
225
226 /// Amount of circles to simulate before stopping
227 double _circularTrajectoryCircleCountForStop = 1.0;
228
229 /// Amount of rose figures to simulate before stopping
230 double _roseTrajectoryCountForStop = 1.0;
231 // ###########################################################################################################
232
233 /// Gravitation model selected in the GUI
234 GravitationModel _gravitationModel = GravitationModel::EGM96;
235
236 /// Apply the coriolis acceleration to the measured accelerations
237 bool _coriolisAccelerationEnabled = true;
238
239 /// Apply the centrifugal acceleration to the measured accelerations
240 bool _centrifgalAccelerationEnabled = true;
241
242 /// Apply the Earth rotation rate to the measured angular rates
243 bool _angularRateEarthRotationEnabled = true;
244
245 /// Apply the transport rate to the measured angular rates
246 bool _angularRateTransportRateEnabled = true;
247
248 // ###########################################################################################################
249
250 /// @brief Get the Time from a CSV line
251 /// @param[in] line Line with data from the csv
252 /// @param[in] description Description of the data
253 /// @return InsTime or empty time if data not found
254 [[nodiscard]] InsTime getTimeFromCsvLine(const CsvData::CsvLine& line, const std::vector<std::string>& description) const;
255
256 /// @brief Get the Position from a CSV line
257 /// @param[in] line Line with data from the csv
258 /// @param[in] description Description of the data
259 /// @return Position in ECEF coordinates in [m] or NaN if data not found
260 [[nodiscard]] Eigen::Vector3d e_getPositionFromCsvLine(const CsvData::CsvLine& line, const std::vector<std::string>& description) const;
261
262 /// @brief Get the Attitude quaternion n_quat_b from a CSV line
263 /// @param[in] line Line with data from the csv
264 /// @param[in] description Description of the data
265 /// @return Attitude quaternion n_quat_b or NaN if data not found
266 static Eigen::Quaterniond n_getAttitudeQuaternionFromCsvLine_b(const CsvData::CsvLine& line, const std::vector<std::string>& description);
267
268 /// Assign a variable that holds the Spline information
269 struct
270 {
271 double sampleInterval = 0.03; ///< Spline sample interval
272 CubicSpline<long double> x; ///< ECEF X Position [m]
273 CubicSpline<long double> y; ///< ECEF Y Position [m]
274 CubicSpline<long double> z; ///< ECEF Z Position [m]
275 CubicSpline<long double> roll; ///< Roll angle [rad]
276 CubicSpline<long double> pitch; ///< Pitch angle [rad]
277 CubicSpline<long double> yaw; ///< Yaw angle [rad]
278 } _splines;
279
280 /// @brief Initializes the spline values
281 /// @return True if everything succeeded
282 bool initializeSplines();
283
284 /// Counter to calculate the internal IMU update time
285 uint64_t _imuInternalUpdateCnt = 0.0;
286 /// Counter to calculate the IMU update time
287 uint64_t _imuUpdateCnt = 0.0;
288 /// Counter to calculate the GNSS update time
289 uint64_t _gnssUpdateCnt = 0.0;
290
291 /// Update rate for the internal solution of linear movement in [Hz]
292 static constexpr double INTERNAL_LINEAR_UPDATE_FREQUENCY = 1000;
293
294 /// Last time the IMU message was calculated in [s]
295 double _imuLastUpdateTime = 0.0;
296 /// Last time the GNSS message was calculated in [s]
297 double _gnssLastUpdateTime = 0.0;
298 /// Last calculated position for the IMU in linear mode for iterative calculations as latitude, longitude, altitude [rad, rad, m]
299 Eigen::Vector3d _lla_imuLastLinearPosition = Eigen::Vector3d::Zero();
300 /// Last calculated position for the GNSS in linear mode for iterative calculations as latitude, longitude, altitude [rad, rad, m]
301 Eigen::Vector3d _lla_gnssLastLinearPosition = Eigen::Vector3d::Zero();
302 /// Last calculated acceleration measurement in platform coordinates [m/s²]
303
1/2
✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
120 Eigen::Vector3d _p_lastImuAccelerationMeas = Eigen::Vector3d::Ones() * std::nan("");
304 /// Last calculated angular rate measurement in platform coordinates [rad/s]
305
1/2
✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
120 Eigen::Vector3d _p_lastImuAngularRateMeas = Eigen::Vector3d::Ones() * std::nan("");
306
307 /// @brief Calculates the flight angles (roll, pitch, yaw)
308 /// @param[in] time Time in [s]
309 /// @return Roll, pitch, yaw in [rad]
310 [[nodiscard]] std::array<double, 3> calcFlightAngles(double time) const;
311
312 /// @brief Calculates the position in latLonAlt at the given time depending on the trajectoryType
313 /// @param[in] time Time in [s]
314 /// @return LatLonAlt in [rad, rad, m]
315 [[nodiscard]] Eigen::Vector3d lla_calcPosition(double time) const;
316
317 /// @brief Calculates the velocity in local-navigation frame coordinates at the given time depending on the trajectoryType
318 /// @param[in] time Time in [s]
319 /// @param[in] n_Quat_e Rotation quaternion from Earth frame to local-navigation frame
320 /// @return n_velocity in [rad, rad, m]
321 [[nodiscard]] Eigen::Vector3d n_calcVelocity(double time, const Eigen::Quaterniond& n_Quat_e) const;
322
323 /// @brief Calculates the acceleration in local-navigation frame coordinates at the given time depending on the trajectoryType
324 /// @param[in] time Time in [s]
325 /// @param[in] n_Quat_e Rotation quaternion from Earth frame to local-navigation frame
326 /// @param[in] lla_position Current position as latitude, longitude, altitude [rad, rad, m]
327 /// @param[in] n_velocity Velocity in local-navigation frame coordinates [m/s]
328 /// @return n_accel in [rad, rad, m]
329 [[nodiscard]] Eigen::Vector3d n_calcTrajectoryAccel(double time, const Eigen::Quaterniond& n_Quat_e,
330 const Eigen::Vector3d& lla_position, const Eigen::Vector3d& n_velocity) const;
331
332 /// @brief Calculates ω_nb_n, the turn rate of the body with respect to the navigation system expressed in NED coordinates
333 /// @param[in] time Time in [s]
334 /// @param[in] rollPitchYaw Gimbal angles (roll, pitch, yaw) [rad]
335 /// @param[in] n_Quat_b Rotation quaternion from body frame to the local-navigation frame
336 /// @return ω_nb_n [rad/s]
337 [[nodiscard]] Eigen::Vector3d n_calcOmega_nb(double time, const Eigen::Vector3d& rollPitchYaw, const Eigen::Quaterniond& n_Quat_b) const;
338 };
339
340 } // namespace NAV
341