52 return "PosVelAttInitializer";
71 if (ImGui::InputDouble(fmt::format(
"Initialization Duration Attitude##{}",
size_t(
id)).c_str(), &
_initDuration, 0.0, 0.0,
"%.3f s"))
89 if (ImGui::BeginTable(fmt::format(
"Initialized State##{}",
size_t(
id)).c_str(),
90 4, ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoHostExtendX, ImVec2(0.0F, 0.0F)))
92 ImGui::TableSetupColumn(
"");
93 ImGui::TableSetupColumn(
"");
94 ImGui::TableSetupColumn(
"Threshold");
95 ImGui::TableSetupColumn(
"Accuracy");
96 ImGui::TableHeadersRow();
102 ImGui::TableNextColumn();
103 ImGui::Text(
"Position");
104 ImGui::TableNextColumn();
106 ImGui::GetWindowDrawList()->AddCircleFilled(ImVec2(ImGui::GetCursorScreenPos().x + size / 1.2F,
107 ImGui::GetCursorScreenPos().y + size * 1.8F),
110 ? ImColor(0.0F, 255.0F, 0.0F)
111 : ImColor(255.0F, 0.0F, 0.0F));
112 ImGui::Selectable((
"##determinePosition" + std::to_string(
size_t(
id))).c_str(),
113 false, ImGuiSelectableFlags_Disabled, ImVec2(1.6F * size, 0.0F));
114 if (ImGui::IsItemHovered())
118 ImGui::TableNextColumn();
119 ImGui::SetNextItemWidth(-FLT_MIN);
120 if (
ImGui::DragDouble((
"##positionAccuracyThreshold" + std::to_string(
size_t(
id))).c_str(),
125 ImGui::TableNextColumn();
126 ImGui::GetWindowDrawList()->AddCircleFilled(ImVec2(ImGui::GetCursorScreenPos().x + size * 1.2F,
127 ImGui::GetCursorScreenPos().y + size * 1.8F),
130 ? ImColor(0.0F, 255.0F, 0.0F)
131 : ImColor(255.0F, 0.0F, 0.0F));
132 ImGui::Selectable((
"##lastPositionAccuracy.at(0)" + std::to_string(
size_t(
id))).c_str(),
133 false, ImGuiSelectableFlags_Disabled, ImVec2(2.0F * size, 0.0F));
134 if (ImGui::IsItemHovered())
139 ImGui::GetWindowDrawList()->AddCircleFilled(ImVec2(ImGui::GetCursorScreenPos().x + size * 1.2F,
140 ImGui::GetCursorScreenPos().y + size * 1.8F),
143 ? ImColor(0.0F, 255.0F, 0.0F)
144 : ImColor(255.0F, 0.0F, 0.0F));
145 ImGui::Selectable((
"##lastPositionAccuracy.at(1)" + std::to_string(
size_t(
id))).c_str(),
146 false, ImGuiSelectableFlags_Disabled, ImVec2(2.0F * size, 0.0F));
147 if (ImGui::IsItemHovered())
152 ImGui::GetWindowDrawList()->AddCircleFilled(ImVec2(ImGui::GetCursorScreenPos().x + size * 1.2F,
153 ImGui::GetCursorScreenPos().y + size * 1.8F),
156 ? ImColor(0.0F, 255.0F, 0.0F)
157 : ImColor(255.0F, 0.0F, 0.0F));
158 ImGui::Selectable((
"##lastPositionAccuracy.at(2)" + std::to_string(
size_t(
id))).c_str(),
159 false, ImGuiSelectableFlags_Disabled, ImVec2(2.0F * size, 0.0F));
160 if (ImGui::IsItemHovered())
169 ImGui::TableNextColumn();
170 ImGui::Text(
"Velocity");
171 ImGui::TableNextColumn();
172 ImGui::GetWindowDrawList()->AddCircleFilled(ImVec2(ImGui::GetCursorScreenPos().x + size / 1.2F,
173 ImGui::GetCursorScreenPos().y + size * 1.8F),
176 ? ImColor(0.0F, 255.0F, 0.0F)
177 : ImColor(255.0F, 0.0F, 0.0F));
178 ImGui::Selectable((
"##determineVelocity" + std::to_string(
size_t(
id))).c_str(),
179 false, ImGuiSelectableFlags_Disabled, ImVec2(1.6F * size, 0.0F));
180 if (ImGui::IsItemHovered())
183 ?
"Successfully Initialized"
184 :
"To be initialized");
186 ImGui::TableNextColumn();
187 ImGui::SetNextItemWidth(-FLT_MIN);
188 if (
ImGui::DragDouble((
"##velocityAccuracyThreshold" + std::to_string(
size_t(
id))).c_str(),
193 ImGui::TableNextColumn();
194 ImGui::GetWindowDrawList()->AddCircleFilled(ImVec2(ImGui::GetCursorScreenPos().x + size * 1.2F,
195 ImGui::GetCursorScreenPos().y + size * 1.8F),
198 ? ImColor(0.0F, 255.0F, 0.0F)
199 : ImColor(255.0F, 0.0F, 0.0F));
200 ImGui::Selectable((
"##lastVelocityAccuracy.at(0)" + std::to_string(
size_t(
id))).c_str(),
201 false, ImGuiSelectableFlags_Disabled, ImVec2(2.0F * size, 0.0F));
202 if (ImGui::IsItemHovered())
207 ImGui::GetWindowDrawList()->AddCircleFilled(ImVec2(ImGui::GetCursorScreenPos().x + size * 1.2F,
208 ImGui::GetCursorScreenPos().y + size * 1.8F),
211 ? ImColor(0.0F, 255.0F, 0.0F)
212 : ImColor(255.0F, 0.0F, 0.0F));
213 ImGui::Selectable((
"##lastVelocityAccuracy.at(1)" + std::to_string(
size_t(
id))).c_str(),
214 false, ImGuiSelectableFlags_Disabled, ImVec2(2.0F * size, 0.0F));
215 if (ImGui::IsItemHovered())
220 ImGui::GetWindowDrawList()->AddCircleFilled(ImVec2(ImGui::GetCursorScreenPos().x + size * 1.2F,
221 ImGui::GetCursorScreenPos().y + size * 1.8F),
224 ? ImColor(0.0F, 255.0F, 0.0F)
225 : ImColor(255.0F, 0.0F, 0.0F));
226 ImGui::Selectable((
"##lastVelocityAccuracy.at(2)" + std::to_string(
size_t(
id))).c_str(),
227 false, ImGuiSelectableFlags_Disabled, ImVec2(2.0F * size, 0.0F));
228 if (ImGui::IsItemHovered())
237 ImGui::TableNextColumn();
238 ImGui::Text(
"Attitude");
239 ImGui::TableNextColumn();
240 ImGui::GetWindowDrawList()->AddCircleFilled(ImVec2(ImGui::GetCursorScreenPos().x + size / 1.2F,
241 ImGui::GetCursorScreenPos().y + size * 1.4F),
244 ? ImColor(0.0F, 255.0F, 0.0F)
245 : ImColor(255.0F, 0.0F, 0.0F));
246 ImGui::Selectable((
"##determineAttitude" + std::to_string(
size_t(
id))).c_str(),
247 false, ImGuiSelectableFlags_Disabled, ImVec2(1.6F * size, 0.0F));
248 if (ImGui::IsItemHovered())
251 ?
"Successfully Initialized"
252 :
"To be initialized");
254 ImGui::TableNextColumn();
259 if (ImGui::Checkbox(fmt::format(
"Override Position##{}",
size_t(
id)).c_str(), &
_overridePosition))
289 1.0F, 0.0, 0.0,
"%.4f"))
295 1.0F, 0.0, 0.0,
"%.4f"))
301 1.0F, 0.0, 0.0,
"%.4f"))
309 if (ImGui::BeginTable((
"Overrides##" + std::to_string(
size_t(
id))).c_str(),
310 2, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoHostExtendX, ImVec2(0.0F, 0.0F)))
312 ImGui::TableNextColumn();
313 if (ImGui::Checkbox((
"Override Roll##" + std::to_string(
size_t(
id))).c_str(), &
_overrideRollPitchYaw.at(0)))
318 ImGui::TableNextColumn();
322 if (
ImGui::DragDouble((
"##overrideValuesRollPitchYaw.at(0)" + std::to_string(
size_t(
id))).c_str(),
329 ImGui::TableNextColumn();
330 if (ImGui::Checkbox((
"Override Pitch##" + std::to_string(
size_t(
id))).c_str(), &
_overrideRollPitchYaw.at(1)))
335 ImGui::TableNextColumn();
339 if (
ImGui::DragDouble((
"##overrideValuesRollPitchYaw.at(1)" + std::to_string(
size_t(
id))).c_str(),
346 ImGui::TableNextColumn();
347 if (ImGui::Checkbox((
"Override Yaw##" + std::to_string(
size_t(
id))).c_str(), &
_overrideRollPitchYaw.at(2)))
352 ImGui::TableNextColumn();
356 if (
ImGui::DragDouble((
"##overrideValuesRollPitchYaw.at(2)" + std::to_string(
size_t(
id))).c_str(),
369 ImGui::SetNextItemOpen(
true, ImGuiCond_FirstUseEver);
370 if (ImGui::TreeNode(fmt::format(
"Init Time##{}",
size_t(
id)).c_str()))
377 if (ImGui::Button(
"Reset"))
413 if (j.contains(
"initDuration"))
417 if (j.contains(
"attitudeMode"))
421 if (j.contains(
"positionAccuracyThreshold"))
425 if (j.contains(
"velocityAccuracyThreshold"))
429 if (j.contains(
"overridePosition"))
433 if (j.contains(
"overridePositionValues"))
437 if (j.contains(
"overrideVelocity"))
441 if (j.contains(
"overrideVelocityValues"))
445 if (j.contains(
"overrideRollPitchYaw"))
449 if (j.contains(
"overrideRollPitchYawValues"))
453 if (j.contains(
"initTime"))
457 if (j.contains(
"initTimeEditFormat"))
473 std::numeric_limits<double>::infinity(),
474 std::numeric_limits<double>::infinity() };
476 std::numeric_limits<double>::infinity(),
477 std::numeric_limits<double>::infinity() };
549 inputPin.queueBlocked =
true;
550 inputPin.queue.clear();
559 LOG_INFO(
"{}: Position initialized to Lat {:3.12f} [°], Lon {:3.12f} [°], Alt {:4.3f} [m]",
nameId(),
580 if (lla_position.z() < 0)
582 LOG_WARN(
"{}: Altitude has a value of {} which is below the ellipsoid height.",
nameId(), lla_position.z());
585 LOG_INFO(
"{}: Velocity initialized to v_N {:3.5f} [m/s], v_E {:3.5f} [m/s], v_D {:3.5f} [m/s]",
nameId(),
589 LOG_INFO(
"{}: Attitude initialized to Roll {:3.5f} [°], Pitch {:3.5f} [°], Yaw {:3.4f} [°]",
nameId(),
594 auto posVelAtt = std::make_shared<PosVelAtt>();
604 return connectedPin->noMoreDataAvailable.load();
609 LOG_ERROR(
"{}: State Initialization failed. No more messages incoming to eventually receive a state. Please check which states got initialized and override the others.",
nameId());
615 auto obs = std::static_pointer_cast<const ImuObs>(queue.
extract_front());
618 LOG_DATA(
"{}: receiveImuObs at time [{}]",
nameId(), obs->insTime.toYMDHMS());
623 const auto& imuPosition = obs->imuPos;
628 LOG_ERROR(
"No magnetometer data available. Please override the Yaw angle.");
631 Eigen::Vector3d mag_p = obs->p_magneticField ? obs->p_magneticField.value() : Eigen::Vector3d::Zero();
634 const Eigen::Vector3d b_mag = imuPosition.b_quat_p() * mag_p;
635 auto magneticHeading = -std::atan2(b_mag.y(), b_mag.x());
638 const Eigen::Vector3d b_accel = imuPosition.b_quat_p() * obs->p_acceleration * -1;
680 LOG_DATA(
"{}: receiveGnssObs at time [{}]",
nameId(), nodeData->insTime.toYMDHMS());
682 const auto* sourcePin =
inputPins.at(pinIdx).link.getConnectedPin();
698 receivePosObs(std::static_pointer_cast<const Pos>(nodeData));
711 LOG_DATA(
"{}: UBX_NAV_ATT: Roll {}, Pitch {}, Heading {} [deg]",
nameId(),
712 std::get<vendor::ublox::UbxNavAtt>(obs->data).roll * 1e-5,
713 std::get<vendor::ublox::UbxNavAtt>(obs->data).pitch * 1e-5,
714 std::get<vendor::ublox::UbxNavAtt>(obs->data).heading * 1e-5);
718 _lastPositionAccuracy.at(0) =
static_cast<float>(std::get<vendor::ublox::UbxNavPosecef>(obs->data).pAcc);
719 _lastPositionAccuracy.at(1) =
static_cast<float>(std::get<vendor::ublox::UbxNavPosecef>(obs->data).pAcc);
720 _lastPositionAccuracy.at(2) =
static_cast<float>(std::get<vendor::ublox::UbxNavPosecef>(obs->data).pAcc);
726 _e_initPosition = Eigen::Vector3d(std::get<vendor::ublox::UbxNavPosecef>(obs->data).ecefX * 1e-2,
727 std::get<vendor::ublox::UbxNavPosecef>(obs->data).ecefY * 1e-2,
728 std::get<vendor::ublox::UbxNavPosecef>(obs->data).ecefZ * 1e-2);
736 _lastPositionAccuracy.at(0) =
static_cast<float>(std::get<vendor::ublox::UbxNavPosllh>(obs->data).hAcc * 1e-1);
737 _lastPositionAccuracy.at(1) =
static_cast<float>(std::get<vendor::ublox::UbxNavPosllh>(obs->data).hAcc * 1e-1);
738 _lastPositionAccuracy.at(2) =
static_cast<float>(std::get<vendor::ublox::UbxNavPosllh>(obs->data).vAcc * 1e-1);
744 Eigen::Vector3d lla_position(
deg2rad(std::get<vendor::ublox::UbxNavPosllh>(obs->data).lat * 1e-7),
745 deg2rad(std::get<vendor::ublox::UbxNavPosllh>(obs->data).lon * 1e-7),
746 std::get<vendor::ublox::UbxNavPosllh>(obs->data).height * 1e-3);
756 _lastVelocityAccuracy.at(0) =
static_cast<float>(std::get<vendor::ublox::UbxNavVelned>(obs->data).sAcc);
757 _lastVelocityAccuracy.at(1) =
static_cast<float>(std::get<vendor::ublox::UbxNavVelned>(obs->data).sAcc);
758 _lastVelocityAccuracy.at(2) =
static_cast<float>(std::get<vendor::ublox::UbxNavVelned>(obs->data).sAcc);
764 _n_initVelocity = Eigen::Vector3d(std::get<vendor::ublox::UbxNavVelned>(obs->data).velN * 1e-2,
765 std::get<vendor::ublox::UbxNavVelned>(obs->data).velE * 1e-2,
766 std::get<vendor::ublox::UbxNavVelned>(obs->data).velD * 1e-2);
800 const Eigen::Vector3d rollPitchYaw = obs->rollPitchYaw();
850 auto posVelAtt = std::make_shared<PosVelAtt>();
Transformation collection.
Combo representing an enumeration.
nlohmann::json json
json namespace
Text Help Marker (?) with Tooltip.
Inertial Navigation Helper Functions.
Utility class for logging to console and file.
#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.
#define LOG_ERROR
Error occurred, which stops part of the program to work, but not everything.
#define LOG_WARN
Error occurred, but a fallback option exists and program continues to work normally.
#define LOG_INFO
Info to the user on the state of the program.
#define LOG_TRACE
Detailled info to trace the execution of the program. Should not be called on functions which receive...
Utility class which specifies available nodes.
Position, Velocity, Attitude Initializer from GPS and IMU data.
Position, Velocity and Attitude Storage Class.
Keeps track of the current real/simulation time.
Type Definitions for Ublox messages.
static std::string type()
Returns the type of the data class.
The class is responsible for all time-related tasks.
ImVec2 _guiConfigDefaultWindowSize
std::vector< OutputPin > outputPins
List of output pins.
Node(std::string name)
Constructor.
std::vector< InputPin > inputPins
List of input pins.
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.
std::string nameId() const
Node name and id.
std::string name
Name of the Node.
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.
void invokeCallbacks(size_t portIndex, const std::shared_ptr< const NodeData > &data)
Calls all registered callbacks on the specified output port.
bool DeleteInputPin(size_t pinIndex)
Deletes the input pin. Invalidates the pin reference given.
bool _hasConfig
Flag if the config window should be shown.
std::shared_ptr< const NAV::NodeData >(Node::*)() PollDataFunc
FileReader/Simulator pollData function type for nodes with a single poll pin.
int _inputPinIdxGNSS
Index of the input pin for GNSS observations.
std::array< double, 3 > _overrideRollPitchYawValues
Values to override Roll, Pitch and Yaw with in [deg].
@ OFF
Do not override the values.
@ NED
Override with NED values.
@ ECEF
Override with ECEF values.
bool _overridePosition
Whether the GNSS values should be used or we want to override the values manually.
void receivePosObs(const std::shared_ptr< const Pos > &obs)
Receive Pos Observations.
void deinitialize() override
Deinitialize the node.
std::array< bool, 4 > _posVelAttInitialized
Whether the states are initialized (pos, vel, att, messages send)
gui::widgets::TimeEditFormat _initTimeEditFormat
Time Format to input the init time with.
std::array< double, 3 > _averagedAttitude
Averaged Attitude (roll, pitch, yaw) in [rad].
std::array< double, 3 > _lastPositionAccuracy
Last position accuracy in [cm] for XYZ or NED.
static constexpr size_t OUTPUT_PORT_INDEX_POS_VEL_ATT
Flow (PosVelAtt)
static std::string typeStatic()
String representation of the Class Type.
@ BOTH
Use IMU and GNSS Observations for attitude initialization.
@ IMU
Use IMU Observations for attitude initialization.
@ GNSS
Use GNSS Observations for attitude initialization.
Eigen::Vector3d _overrideVelocityValues
Values to override the Velocity in [m/s].
void receiveGnssObs(InputPin::NodeDataQueue &queue, size_t pinIdx)
Receive Gnss Observations.
AttitudeMode _attitudeMode
GUI option to pecify the initialization source for attitude.
Eigen::Vector3d _e_initPosition
Position in ECEF coordinates.
void receivePosVelObs(const std::shared_ptr< const PosVel > &obs)
Receive PosVel Observations.
std::string type() const override
String representation of the Class Type.
Eigen::Quaterniond _n_Quat_b_init
Initialized Quaternion body to navigation frame (roll, pitch, yaw)
void guiConfig() override
ImGui config window which is shown on double click.
void updatePins()
Add or removes input pins depending on the settings and modifies the output pin.
int _inputPinIdxIMU
Index of the input pin for IMU observations.
double _velocityAccuracyThreshold
Velocity Accuracy to achieve in [cm/s].
double _initDuration
Time in [s] to initialize the state.
void restore(const json &j) override
Restores the node from a json object.
~PosVelAttInitializer() override
Destructor.
PosVelAttInitializer()
Default constructor.
bool initialize() override
Initialize the node.
Eigen::Vector3d _n_initVelocity
Velocity in navigation coordinates.
std::array< bool, 3 > _overrideRollPitchYaw
Whether the IMU values should be used or we want to override the values manually.
std::shared_ptr< const NodeData > pollPVASolution()
Polls the PVA solution if all is set in the GUI.
json save() const override
Saves the node into a json object.
void finalizeInit()
Checks whether all Flags are set and writes logs messages.
InsTime _startTime
Start time of the averaging process.
InsTime _initTime
Initialization time.
double _positionAccuracyThreshold
Position Accuracy to achieve in [cm].
static std::string category()
String representation of the Class Category.
void receivePosVelAttObs(const std::shared_ptr< const PosVelAtt > &obs)
Receive PosVelAtt Observations.
void receiveImuObs(InputPin::NodeDataQueue &queue, size_t pinIdx)
Receive Imu Observations.
gui::widgets::PositionWithFrame _overridePositionValue
Values to override the Position in ECEF coordinates in [m].
double _countAveragedAttitude
Count of received attitude measurements.
VelocityOverride _overrideVelocity
Whether the GNSS values should be used or we want to override the values manually.
std::array< double, 3 > _lastVelocityAccuracy
Last velocity accuracy in [cm/s] for XYZ or NED.
void receiveUbloxObs(const std::shared_ptr< const UbloxObs > &obs)
Receive Ublox Observations.
static std::string type()
Returns the type of the data class.
static std::string type()
Returns the type of the data class.
static std::string type()
Returns the type of the data class.
static std::string type()
Returns the type of the data class.
auto extract_front()
Returns a copy of the first element in the container and removes it from the container.
static std::string type()
Returns the type of the data class.
static float windowFontRatio()
Ratio to multiply for GUI window elements.
bool DragDouble(const char *label, double *v, float v_speed, double v_min, double v_max, const char *format, ImGuiSliderFlags flags)
Shows a Drag GUI element for 'double'.
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.
Eigen::Vector3< typename Derived::Scalar > ecef2lla_WGS84(const Eigen::MatrixBase< Derived > &e_position)
Converts Earth-centered-Earth-fixed coordinates into latitude, longitude and altitude using WGS84.
Eigen::Quaternion< Scalar > n_Quat_e(const Scalar &latitude, const Scalar &longitude)
Quaternion for rotations from Earth-fixed to navigation frame.
Eigen::Vector3< typename Derived::Scalar > quat2eulerZYX(const Eigen::QuaternionBase< Derived > &q)
Converts the quaternion to Euler rotation angles with rotation sequence ZYX.
Eigen::Vector3< typename Derived::Scalar > lla2ecef_WGS84(const Eigen::MatrixBase< Derived > &lla_position)
Converts latitude, longitude and altitude into Earth-centered-Earth-fixed coordinates using WGS84.
Eigen::Quaternion< Scalar > n_Quat_b(Scalar roll, Scalar pitch, Scalar yaw)
Quaternion for rotations from body to navigation frame.
@ UBX_CLASS_NAV
Navigation Results Messages: Position, Speed, Time, Acceleration, Heading, DOP, SVs used.
UbxNavMessages
The available NAV Messages.
@ UBX_NAV_VELNED
Velocity Solution in NED (Length = 36; Type = Periodic/Polled)
@ UBX_NAV_ATT
Attitude Solution (Length = 32; Type = Periodic/Polled)
@ UBX_NAV_POSECEF
Position Solution in ECEF (Length = 20; Type = Periodic/Polled)
@ UBX_NAV_POSLLH
Geodetic Position Solution (Length = 28; Type = Periodic/Polled)
const char * to_string(gui::widgets::PositionWithFrame::ReferenceFrame refFrame)
Converts the enum to a string.
Derived::Scalar calcRollFromStaticAcceleration(const Eigen::MatrixBase< Derived > &b_accel)
Calculates the roll angle from a static acceleration measurement.
constexpr auto deg2rad(const T °)
Convert Degree to Radians.
Derived::Scalar calcPitchFromStaticAcceleration(const Eigen::MatrixBase< Derived > &b_accel)
Calculates the pitch angle from a static acceleration measurement.
constexpr auto rad2deg(const T &rad)
Convert Radians to Degree.
GPS week and time of week in GPS standard time [GPST].