56 .averagedMeasurement =
false,
58 .p_acceleration = Eigen::Vector3d::Zero(),
59 .p_angularRate = Eigen::Vector3d::Zero(),
81 _states.back().position -= lla_positionError;
82 _states.back().velocity -= n_velocityError;
85 _states.back().attitude = Eigen::Quaterniond(n_Dcm_b).normalized();
110 _states.back().position -= e_positionError;
111 _states.back().velocity -= e_velocityError;
114 _states.back().attitude = Eigen::Quaterniond(e_Dcm_b).normalized();
119 if (
_states.empty()) {
return {}; }
150 if (
_states.empty()) {
return {}; }
152 return _states.back().m.p_acceleration +
_states.back().p_biasAcceleration;
157 if (
_states.empty()) {
return {}; }
159 return _states.back().m.p_angularRate +
_states.back().p_biasAngularRate;
167 if (
_states.back().epoch == epoch)
169 LOG_DATA(
"{}: Updating existing state", nameId);
172 _states.back().m.p_acceleration = p_acceleration;
173 _states.back().m.p_angularRate = p_angularRate;
179 LOG_DATA(
"{}: Adding as new state", nameId);
182 .position =
_states.back().position,
183 .velocity =
_states.back().velocity,
184 .attitude =
_states.back().attitude,
188 .p_acceleration = p_acceleration,
189 .p_angularRate = p_angularRate,
199 Eigen::Vector3d p_acceleration = Eigen::Vector3d::Zero();
200 Eigen::Vector3d p_angularRate = Eigen::Vector3d::Zero();
204 p_acceleration = p_deltaVelocity / deltaTime;
205 p_angularRate = p_deltaTheta / deltaTime;
207 else if (std::abs(dt) > 0.0)
210 p_acceleration = p_deltaVelocity / dt;
211 p_angularRate = p_deltaTheta / dt;
215 _states.back().m.averagedMeasurement =
true;
222 auto posVelAtt = std::make_shared<PosVelAtt>();
223 posVelAtt->insTime =
_states.back().epoch;
227 posVelAtt->setPosVelAtt_n(
_states.back().position,
_states.back().velocity,
_states.back().attitude);
230 posVelAtt->setPosVelAtt_e(
_states.back().position,
_states.back().velocity,
_states.back().attitude);
238 const Eigen::Vector3d& p_acceleration,
const Eigen::Vector3d& p_angularRate,
239 const ImuPos& imuPos,
const char* nameId)
242 if (
_states.back().epoch.empty()) {
_states.back().epoch = obsTime; }
244 auto dt =
static_cast<double>((obsTime -
_states.back().epoch).count());
245 addMeasurement(obsTime, dt, p_acceleration, p_angularRate, nameId);
246 if (std::abs(dt) < 1e-8)
248 LOG_DATA(
"{}: Returning state [{}], as no time difference between measurement.", nameId,
_states.back().epoch.toYMDHMS(
GPST));
256 const Eigen::Vector3d& p_deltaVelocity,
const Eigen::Vector3d& p_deltaTheta,
257 const ImuPos& imuPos,
const char* nameId)
260 if (
_states.back().epoch.empty()) {
_states.back().epoch = obsTime; }
262 auto dt =
static_cast<double>((obsTime -
_states.back().epoch).count());
264 if (std::abs(dt) < 1e-8)
266 LOG_DATA(
"{}: Returning state [{}], as no time difference between measurement.", nameId,
_states.back().epoch.toYMDHMS(
GPST));
278 LOG_DATA(
"{}: Calculating inertial solution from buffer. States t0 = [{}], t1 = [{}]",
283 auto posVelAtt = std::make_shared<PosVelAtt>();
284 posVelAtt->insTime =
_states.back().epoch;
288 posVelAtt->setPosVelAtt_n(y.segment<3>(0), y.segment<3>(3), Eigen::Quaterniond(y.segment<4>(6)));
291 posVelAtt->setPosVelAtt_e(y.segment<3>(0), y.segment<3>(3), Eigen::Quaterniond(y.segment<4>(6)));
298 _states.back().position = posVelAtt->lla_position();
299 _states.back().velocity = posVelAtt->n_velocity();
300 _states.back().attitude = posVelAtt->n_Quat_b();
303 _states.back().position = posVelAtt->e_position();
304 _states.back().velocity = posVelAtt->e_velocity();
305 _states.back().attitude = posVelAtt->e_Quat_b();
335 bool changed =
false;
340 ImGui::Combo(fmt::format(
"Integration Frame##{}", label).c_str(), &integrationFrame,
"ECEF\0NED\0\0"))
365 ImGui::SetItemDefaultFocus();
372 changed |= ImGui::Checkbox(fmt::format(
"Prefer raw measurements over delta##{}", label).c_str(), &preferAccelerationOverDeltaMeasurements);
374 if (preferAccelerationOverDeltaMeasurements)
378 gui::widgets::HelpMarker(
"Some IMUs operate at higher rates than their output rate. (e.g. internal rate 800Hz and output rate is 100Hz)\n"
379 "- Such IMUs often output averaged accelerations between the current and last output.\n"
380 "- If the connected IMU (e.g. a VectorNavSensor node) is such as sensor, please check this.\n"
381 "- If delta measurements are used, this is automatically true");
384 ImGui::SetNextItemOpen(
false, ImGuiCond_FirstUseEver);
385 if (ImGui::TreeNode(fmt::format(
"Compensation models##{}", label).c_str()))
387 ImGui::TextUnformatted(
"Acceleration compensation");
408 ImGui::TextUnformatted(
"Angular rate compensation");
446 if (j.contains(
"integrationFrame")) { j.at(
"integrationFrame").get_to(data.
_integrationFrame); }
447 if (j.contains(
"lockIntegrationFrame")) { j.at(
"lockIntegrationFrame").get_to(data.
_lockIntegrationFrame); }
448 if (j.contains(
"integrationAlgorithm"))
462 return "Runge-Kutta 1st order (explicit) / (Forward) Euler method";
464 return "Runge-Kutta 2nd order (explicit)";
466 return "Heun's method (2nd order) (explicit)";
468 return "Runge-Kutta 3rd order (explicit) / Simpson's rule";
470 return "Heun's method (3nd order) (explicit)";
472 return "Runge-Kutta 4th order (explicit)";
474 return "Runge-Kutta 3rd order (explicit) / Simpson's rule (multistep)";
476 return "Runge-Kutta 4th order (explicit) (multistep)";
#define INS_ASSERT_USER_ERROR(_EXP, _MSG)
Assert function with message.
Functions concerning the ellipsoid model.
nlohmann::json json
json namespace
Text Help Marker (?) with Tooltip.
Inertial Navigation Helper Functions.
Inertial Measurement Integrator.
#define LOG_DEBUG
Debug information. Should not be called on functions which receive observations (spamming)
#define LOG_DATA
All output which occurs repeatedly every time observations are received.
IntegrationAlgorithm _integrationAlgorithm
Integration algorithm used for the update.
void applyStateErrors_e(const Eigen::Vector3d &e_positionError, const Eigen::Vector3d &e_velocityError, const Eigen::Vector3d &e_attitudeError_b)
Apply the errors to the latest state.
std::optional< Eigen::Vector3d > p_calcCurrentAcceleration() const
Calculate the current acceleration, if measurements area available.
bool hasInitialPosition() const
Checks if an initial position is set.
Eigen::Vector3d _p_lastBiasAcceleration
Initial values for the acceleration bias [m/s^2].
std::shared_ptr< PosVelAtt > calcInertialSolution(const InsTime &obsTime, const Eigen::Vector3d &p_acceleration, const Eigen::Vector3d &p_angularRate, const ImuPos &imuPos, const char *nameId)
Calculates the inertial navigation solution.
std::optional< Eigen::Vector3d > p_calcCurrentAngularRate() const
Calculate the current angular rate, if measurements area available.
void addState(const PosVelAtt &state, const char *nameId)
Pushes the state to the list of states.
void applyStateErrors_n(const Eigen::Vector3d &lla_positionError, const Eigen::Vector3d &n_velocityError, const Eigen::Vector3d &n_attitudeError_b)
Apply the errors to the latest state.
IntegrationAlgorithm
Available Integration Algorithms.
@ SingleStepRungeKutta4
Runge-Kutta 4th order (explicit)
@ MultiStepRK4
Multistep Runge-Kutta 4th order (explicit) (taking 2 old epochs into account)
@ SingleStepHeun2
Heun's method (2nd order) (explicit)
@ COUNT
Amount of available integration algorithms.
@ MultiStepRK3
Multistep Runge-Kutta 3rd order (explicit) / Simpson's rule (taking 2 old epochs into account)
@ SingleStepRungeKutta3
Runge-Kutta 3rd order (explicit) / Simpson's rule.
@ SingleStepRungeKutta2
Runge-Kutta 2nd order (explicit) / Explicit midpoint method.
@ SingleStepHeun3
Heun's method (3nd order) (explicit)
@ SingleStepRungeKutta1
Runge-Kutta 1st order (explicit) / (Forward) Euler method.
bool _accelerationsAreAveragedMeasurements
If true, then the measurements are accumulated values over the last epoch. (always true when using de...
void setTotalSensorBiases(const Eigen::Vector3d &p_biasAcceleration, const Eigen::Vector3d &p_biasAngularRate)
Sets the sensor biases total values.
const Eigen::Vector3d & p_getLastAccelerationBias() const
Return the last acceleration bias in platform frame coordinates in [m/s^2].
void setBufferSizes()
Resizes the measurement and state buffers depending on the integration algorithm.
std::shared_ptr< PosVelAtt > calcInertialSolutionFromMeasurementBuffer(const ImuPos &imuPos, const char *nameId)
Calculates the inertial navigation solution.
void addMeasurement(const InsTime &epoch, double dt, const Eigen::Vector3d &p_acceleration, const Eigen::Vector3d &p_angularRate, const char *nameId)
Adds the measurement to the tracking buffer.
InertialIntegrator()=default
Default Constructor.
std::shared_ptr< PosVelAtt > calcInertialSolutionDelta(const InsTime &obsTime, double deltaTime, const Eigen::Vector3d &p_deltaVelocity, const Eigen::Vector3d &p_deltaTheta, const ImuPos &imuPos, const char *nameId)
Calculates the inertial navigation solution.
bool areAccelerationsAveragedMeasurements() const
Wether the measurements are accumulated values over the last epoch. (always true when using delta mea...
std::optional< std::reference_wrapper< const State > > getLatestState() const
Get the latest state if it exists.
void addDeltaMeasurement(const InsTime &epoch, double dt, double deltaTime, const Eigen::Vector3d &p_deltaVelocity, const Eigen::Vector3d &p_deltaTheta, const char *nameId)
Adds the measurement to the tracking buffer.
IntegrationFrame
Available Integration Frames.
@ NED
Local North-East-Down frame.
@ ECEF
Earth-Centered Earth-Fixed frame.
void setInitialState(const PosVelAtt &state, const char *nameId)
Sets the initial state.
void reset()
Clears all internal data.
IntegrationFrame _integrationFrame
Frame to integrate the observations in.
PosVelAttDerivativeConstants _posVelAttDerivativeConstants
Settings for the models to use.
IntegrationFrame getIntegrationFrame() const
Returns the selected integration frame.
Eigen::Vector3d _p_lastBiasAngularRate
Initial values for the angular rate bias [rad/s].
ScrollingBuffer< State > _states
List of states. Length depends on algorithm used.
bool _lockIntegrationFrame
Wether to lock the integration frame.
std::shared_ptr< PosVelAtt > lastStateAsPosVelAtt() const
Returns the last state as PosVelAtt.
const Eigen::Vector3d & p_getLastAngularRateBias() const
Return the last angular rate bias in platform frame coordinates in [rad/s].
void applySensorBiasesIncrements(const Eigen::Vector3d &p_deltaBiasAcceleration, const Eigen::Vector3d &p_deltaBiasAngularRate)
Sets the sensor biases increment.
GenericState< double > State
Inertial state and measurements.
const PosVelAttDerivativeConstants & getConstants() const
Returns the selected compensation models.
The class is responsible for all time-related tasks.
constexpr InsTime_YMDHMS toYMDHMS(TimeSystem timesys=UTC, int digits=-1) const
Converts this time object into a different format.
InsTime insTime
Time at which the message was received.
Position, Velocity and Attitude Storage Class.
const Eigen::Quaterniond & n_Quat_b() const
Returns the Quaternion from body to navigation frame (NED)
const Eigen::Quaterniond & e_Quat_b() const
Returns the Quaternion from body to Earth-fixed frame.
const Eigen::Vector3d & n_velocity() const
Returns the velocity in [m/s], in navigation coordinates.
const Eigen::Vector3d & e_velocity() const
Returns the velocity in [m/s], in earth coordinates.
const Eigen::Vector3d & e_position() const
Returns the coordinates in [m].
const Eigen::Vector3d & lla_position() const
Returns the latitude 𝜙, longitude λ and altitude (height above ground) in [rad, rad,...
static float windowFontRatio()
Ratio to multiply for GUI window elements.
Eigen::Matrix< typename Derived::Scalar, 3, 3 > skewSymmetricMatrix(const Eigen::MatrixBase< Derived > &a)
Calculates the skew symmetric matrix of the given vector. This is needed to perform the cross product...
void to_json(json &j, const Node &node)
Converts the provided node into a json object.
const char * to_string(gui::widgets::PositionWithFrame::ReferenceFrame refFrame)
Converts the enum to a string.
bool InertialIntegratorGui(const char *label, InertialIntegrator &integrator, bool &preferAccelerationOverDeltaMeasurements, float width)
Shows a GUI for advanced configuration of the InertialIntegrator.
bool ComboGravitationModel(const char *label, GravitationModel &gravitationModel)
Shows a ComboBox to select the gravitation model.
void from_json(const json &j, Node &node)
Converts the provided json object into a node object.
Values needed to calculate the PosVelAttDerivative for the local-navigation frame.
bool centrifgalAccelerationCompensationEnabled
Apply the centrifugal acceleration compensation to the measured accelerations.
bool angularRateEarthRotationCompensationEnabled
Apply the Earth rotation rate compensation to the measured angular rates.
bool angularRateTransportRateCompensationEnabled
Apply the transport rate compensation to the measured angular rates.
GravitationModel gravitationModel
Gravity Model to use.
bool coriolisAccelerationCompensationEnabled
Apply the Coriolis acceleration compensation to the measured accelerations.