0.5.1
Loading...
Searching...
No Matches
ImuIntegrator.cpp
Go to the documentation of this file.
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#include "ImuIntegrator.hpp"
10
11#include <memory>
12#include <algorithm>
13#include <cstddef>
14
15#include <imgui.h>
16#include <imgui_internal.h>
17
20
21#include "NodeRegistry.hpp"
22#include <fmt/format.h>
24
27
28#include "util/Logger.hpp"
29#include "util/Eigen.hpp"
30
32 : Node(typeStatic())
33{
34 LOG_TRACE("{}: called", name);
35
36 _hasConfig = true;
37 _guiConfigDefaultWindowSize = { 422, 146 };
38
40 [](const Node* node, const InputPin& inputPin) {
41 const auto* imuIntegrator = static_cast<const ImuIntegrator*>(node); // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast)
42 return !inputPin.queue.empty() && imuIntegrator->_inertialIntegrator.hasInitialPosition();
43 });
45
47}
48
53
55{
56 return "ImuIntegrator";
57}
58
59std::string NAV::ImuIntegrator::type() const
60{
61 return typeStatic();
62}
63
65{
66 return "Data Processor";
67}
68
70{
71 if (ImGui::Checkbox(fmt::format("IMU Preintegration##{}", size_t(id)).c_str(), &_imuPreintegration))
72 {
74 }
75
77 {
78 if (ImGui::Checkbox(fmt::format("Reset every epoch##{}", size_t(id)).c_str(), &_resetPreintegratorEveryEpoch))
79 {
81 }
82 ImGui::SameLine();
83 gui::widgets::HelpMarker("Resetting the preintegrator every epoch makes it behave like a normal integrator");
84
85 if (InertialPreIntegratorGui(std::to_string(size_t(id)).c_str(), _inertialPreintegrator))
86 {
88 }
89 }
90 else
91 {
93 {
95 }
96 }
97}
98
99[[nodiscard]] json NAV::ImuIntegrator::save() const
100{
101 LOG_TRACE("{}: called", nameId());
102
103 return {
104 { "imuPreintegration", _imuPreintegration },
105 { "resetPreintegratorEveryEpoch", _resetPreintegratorEveryEpoch },
106 { "inertialIntegrator", _inertialIntegrator },
107 { "inertialPreintegrator", _inertialPreintegrator },
108 { "preferAccelerationOverDeltaMeasurements", _preferAccelerationOverDeltaMeasurements },
109 };
110}
111
113{
114 LOG_TRACE("{}: called", nameId());
115
116 if (j.contains("imuPreintegration")) { j.at("imuPreintegration").get_to(_imuPreintegration); }
117 if (j.contains("resetPreintegratorEveryEpoch")) { j.at("resetPreintegratorEveryEpoch").get_to(_resetPreintegratorEveryEpoch); }
118 if (j.contains("inertialIntegrator")) { j.at("inertialIntegrator").get_to(_inertialIntegrator); }
119 if (j.contains("inertialPreintegrator")) { j.at("inertialPreintegrator").get_to(_inertialPreintegrator); }
120 if (j.contains("preferAccelerationOverDeltaMeasurements")) { j.at("preferAccelerationOverDeltaMeasurements").get_to(_preferAccelerationOverDeltaMeasurements); }
121}
122
124{
125 LOG_TRACE("{}: called", nameId());
126
127 _inertialIntegrator.reset();
129 _lastImuObs.reset();
130 _lastPosVelAtt.reset();
131
132 LOG_DEBUG("ImuIntegrator initialized");
133
134 return true;
135}
136
138{
139 LOG_TRACE("{}: called", nameId());
140}
141
143{
144 auto nodeData = queue.extract_front();
145 if (nodeData->insTime.empty())
146 {
147 LOG_ERROR("{}: Can't set new imuObs__t0 because the observation has no time tag (insTime)", nameId());
148 return;
149 }
150
151 std::shared_ptr<NAV::PosVelAtt> integratedPosVelAtt = nullptr;
152
154 {
155 auto obs = std::static_pointer_cast<const ImuObs>(nodeData);
156 LOG_DATA("{}: recvImuObs at time [{}] (preintegration)", nameId(), obs->insTime.toYMDHMS(GPST));
157 // LOG_DATA("{}: p_accel = {}", nameId(), obs->p_acceleration.transpose());
158 // LOG_DATA("{}: p_gyro = {}", nameId(), obs->p_angularRate.transpose());
159
160 if (!_lastImuObs)
161 {
162 _lastImuObs = obs;
163 LOG_DATA("{}: Skipping as first epoch", nameId());
164 return;
165 }
166
167 auto dt = static_cast<double>((obs->insTime - _lastImuObs->insTime).count());
168 // LOG_DATA("{}: dt(imu) = {}", nameId(), dt);
169 if (dt <= 1e-9)
170 {
171 LOG_DATA("{}: Skipping as dt is negative or zero", nameId());
172 return;
173 }
176 .p_acceleration = _lastImuObs->p_acceleration,
177 .p_angularRate = _lastImuObs->p_angularRate },
179 };
181 .position = _lastPosVelAtt->e_position(),
182 .velocity = _lastPosVelAtt->e_velocity(),
183 .attitude = _lastPosVelAtt->e_Quat_b()
184 };
185
186 _inertialPreintegrator.addInertialMeasurement(meas, obs->imuPos, nameId());
187
188 auto pvaNew = _inertialPreintegrator.calcIntegratedState(pvaOld, InertialPreIntegrator::ImuState<double>{}, obs->imuPos, nameId());
189
190 integratedPosVelAtt = std::make_shared<PosVelAtt>();
191 integratedPosVelAtt->insTime = obs->insTime;
192 integratedPosVelAtt->setPosVelAtt_e(pvaNew.position, pvaNew.velocity, pvaNew.attitude);
193
194 _lastImuObs = obs;
195
197 {
198 _lastPosVelAtt = integratedPosVelAtt;
200 }
201 }
202 else
203 {
205 && NAV::NodeRegistry::NodeDataTypeAnyIsChildOf(inputPins.at(INPUT_PORT_INDEX_IMU_OBS).link.getConnectedPin()->dataIdentifier, { ImuObsWDelta::type() }))
206 {
207 auto obs = std::static_pointer_cast<const ImuObsWDelta>(nodeData);
208 LOG_DATA("{}: recvImuObsWDelta at time [{}]", nameId(), obs->insTime.toYMDHMS(GPST));
209
210 integratedPosVelAtt = _inertialIntegrator.calcInertialSolutionDelta(obs->insTime, obs->dtime, obs->dvel, obs->dtheta, obs->imuPos, nameId().c_str());
211 }
212 else
213 {
214 auto obs = std::static_pointer_cast<const ImuObs>(nodeData);
215 LOG_DATA("{}: recvImuObs at time [{}]", nameId(), obs->insTime.toYMDHMS(GPST));
216
217 integratedPosVelAtt = _inertialIntegrator.calcInertialSolution(obs->insTime, obs->p_acceleration, obs->p_angularRate, obs->imuPos, nameId().c_str());
218 }
219 }
220
221 if (integratedPosVelAtt)
222 {
223 LOG_DATA("{}: e_position = {}", nameId(), integratedPosVelAtt->e_position().transpose());
224 LOG_DATA("{}: e_velocity = {}", nameId(), integratedPosVelAtt->e_velocity().transpose());
225 LOG_DATA("{}: rollPitchYaw = {}", nameId(), rad2deg(integratedPosVelAtt->rollPitchYaw()).transpose());
227 }
228}
229
231{
232 auto posVelAtt = std::static_pointer_cast<const PosVelAtt>(queue.extract_front());
233 inputPins[INPUT_PORT_INDEX_POS_VEL_ATT_INIT].queueBlocked = true;
235
236 LOG_DATA("{}: recvPosVelAttInit at time [{}]", nameId(), posVelAtt->insTime.toYMDHMS(GPST));
237
238 _lastPosVelAtt = posVelAtt;
239 _inertialIntegrator.setInitialState(*posVelAtt, nameId().c_str());
240 LOG_DATA("{}: e_position = {}", nameId(), posVelAtt->e_position().transpose());
241 LOG_DATA("{}: e_velocity = {}", nameId(), posVelAtt->e_velocity().transpose());
242 LOG_DATA("{}: rollPitchYaw = {}", nameId(), rad2deg(posVelAtt->rollPitchYaw()).transpose());
243
245}
Holds all Constants.
Vector space operations.
Save/Load the Nodes.
nlohmann::json json
json namespace
Text Help Marker (?) with Tooltip.
Integrates ImuObs Data.
Inertial Measurement Preintegrator.
Utility class for logging to console and file.
#define LOG_DEBUG
Debug information. Should not be called on functions which receive observations (spamming)
Definition Logger.hpp:67
#define LOG_DATA
All output which occurs repeatedly every time observations are received.
Definition Logger.hpp:29
#define LOG_ERROR
Error occurred, which stops part of the program to work, but not everything.
Definition Logger.hpp:73
#define LOG_TRACE
Detailled info to trace the execution of the program. Should not be called on functions which receive...
Definition Logger.hpp:65
Simple Math functions.
Utility class which specifies available nodes.
static constexpr size_t INPUT_PORT_INDEX_POS_VEL_ATT_INIT
Flow (PosVelAtt)
std::shared_ptr< const PosVelAtt > _lastPosVelAtt
Last position, velocity and attitude.
void deinitialize() override
Deinitialize the node.
void recvObservation(InputPin::NodeDataQueue &queue, size_t pinIdx)
Receive Function.
std::shared_ptr< const ImuObs > _lastImuObs
Last IMU measuremnt.
bool _preferAccelerationOverDeltaMeasurements
Prefer the raw acceleration measurements over the deltaVel & deltaTheta values.
static std::string category()
String representation of the Class Category.
static std::string typeStatic()
String representation of the Class Type.
void restore(const json &j) override
Restores the node from a json object.
bool _imuPreintegration
Wether IMU preintegration should be used.
std::string type() const override
String representation of the Class Type.
ImuIntegrator()
Default constructor.
void guiConfig() override
ImGui config window which is shown on double click.
bool initialize() override
Initialize the node.
~ImuIntegrator() override
Destructor.
static constexpr size_t OUTPUT_PORT_INDEX_INERTIAL_NAV_SOL
Flow (InertialNavSol)
InertialPreIntegrator _inertialPreintegrator
Inertial Preintegrator.
void recvPosVelAttInit(InputPin::NodeDataQueue &queue, size_t pinIdx)
Receive Function for the PosVelAtt initial values.
json save() const override
Saves the node into a json object.
bool _resetPreintegratorEveryEpoch
Resetting the preintegrator every epoch makes it behave like a normal integrator.
InertialIntegrator _inertialIntegrator
Inertial Integrator.
static constexpr size_t INPUT_PORT_INDEX_IMU_OBS
Flow (ImuObs)
static std::string type()
Returns the type of the data class.
static std::string type()
Returns the type of the data class.
Definition ImuObs.hpp:33
GenericMeasurement< double > Measurement
Inertial measurements.
Input pins of nodes.
Definition Pin.hpp:491
TsDeque< std::shared_ptr< const NAV::NodeData > > NodeDataQueue
Node data queue type.
Definition Pin.hpp:707
ImVec2 _guiConfigDefaultWindowSize
Definition Node.hpp:522
Node(std::string name)
Constructor.
Definition Node.cpp:29
std::vector< InputPin > inputPins
List of input pins.
Definition Node.hpp:509
OutputPin * CreateOutputPin(const char *name, Pin::Type pinType, const std::vector< std::string > &dataIdentifier, OutputPin::PinData data=static_cast< void * >(nullptr), int idx=-1)
Create an Output Pin object.
Definition Node.cpp:278
std::string nameId() const
Node name and id.
Definition Node.cpp:323
std::string name
Name of the Node.
Definition Node.hpp:507
InputPin * CreateInputPin(const char *name, Pin::Type pinType, const std::vector< std::string > &dataIdentifier={}, InputPin::Callback callback=static_cast< InputPin::FlowFirableCallbackFunc >(nullptr), InputPin::FlowFirableCheckFunc firable=nullptr, int priority=0, int idx=-1)
Create an Input Pin object.
Definition Node.cpp:252
void invokeCallbacks(size_t portIndex, const std::shared_ptr< const NodeData > &data)
Calls all registered callbacks on the specified output port.
Definition Node.cpp:179
bool _hasConfig
Flag if the config window should be shown.
Definition Node.hpp:525
static std::string type()
Returns the type of the data class.
Definition PosVelAtt.hpp:29
auto extract_front()
Returns a copy of the first element in the container and removes it from the container.
Definition TsDeque.hpp:494
bool NodeDataTypeAnyIsChildOf(const std::vector< std::string > &childTypes, const std::vector< std::string > &parentTypes)
Checks if any of the provided child types is a child of any of the provided parent types.
void ApplyChanges()
Signals that there have been changes to the flow.
void HelpMarker(const char *desc, const char *symbol="(?)")
Text Help Marker, e.g. '(?)', with Tooltip.
@ GPST
GPS Time.
bool InertialPreIntegratorGui(const char *label, InertialPreIntegrator &integrator, float width)
Shows a GUI for advanced configuration of the InertialPreIntegrator.
bool InertialIntegratorGui(const char *label, InertialIntegrator &integrator, bool &preferAccelerationOverDeltaMeasurements, float width)
Shows a GUI for advanced configuration of the InertialIntegrator.
constexpr auto rad2deg(const T &rad)
Convert Radians to Degree.
Definition Units.hpp:39
Position, velocity and attitude state.
@ Flow
NodeData Trigger.
Definition Pin.hpp:52