54 return "PosVelAttInitializer";
73 if (ImGui::InputDouble(fmt::format(
"Initialization Duration Attitude##{}",
size_t(
id)).c_str(), &
_initDuration, 0.0, 0.0,
"%.3f s"))
91 if (ImGui::BeginTable(fmt::format(
"Initialized State##{}",
size_t(
id)).c_str(),
92 4, ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoHostExtendX, ImVec2(0.0F, 0.0F)))
94 ImGui::TableSetupColumn(
"");
95 ImGui::TableSetupColumn(
"");
96 ImGui::TableSetupColumn(
"Threshold");
97 ImGui::TableSetupColumn(
"Accuracy");
98 ImGui::TableHeadersRow();
104 ImGui::TableNextColumn();
105 ImGui::Text(
"Position");
106 ImGui::TableNextColumn();
108 ImGui::GetWindowDrawList()->AddCircleFilled(ImVec2(ImGui::GetCursorScreenPos().x + size / 1.2F,
109 ImGui::GetCursorScreenPos().y + size * 1.8F),
112 ? ImColor(0.0F, 255.0F, 0.0F)
113 : ImColor(255.0F, 0.0F, 0.0F));
114 ImGui::Selectable((
"##determinePosition" + std::to_string(
size_t(
id))).c_str(),
115 false, ImGuiSelectableFlags_Disabled, ImVec2(1.6F * size, 0.0F));
116 if (ImGui::IsItemHovered())
120 ImGui::TableNextColumn();
121 ImGui::SetNextItemWidth(-FLT_MIN);
122 if (
ImGui::DragDouble((
"##positionAccuracyThreshold" + std::to_string(
size_t(
id))).c_str(),
127 ImGui::TableNextColumn();
128 ImGui::GetWindowDrawList()->AddCircleFilled(ImVec2(ImGui::GetCursorScreenPos().x + size * 1.2F,
129 ImGui::GetCursorScreenPos().y + size * 1.8F),
132 ? ImColor(0.0F, 255.0F, 0.0F)
133 : ImColor(255.0F, 0.0F, 0.0F));
134 ImGui::Selectable((
"##lastPositionAccuracy.at(0)" + std::to_string(
size_t(
id))).c_str(),
135 false, ImGuiSelectableFlags_Disabled, ImVec2(2.0F * size, 0.0F));
136 if (ImGui::IsItemHovered())
141 ImGui::GetWindowDrawList()->AddCircleFilled(ImVec2(ImGui::GetCursorScreenPos().x + size * 1.2F,
142 ImGui::GetCursorScreenPos().y + size * 1.8F),
145 ? ImColor(0.0F, 255.0F, 0.0F)
146 : ImColor(255.0F, 0.0F, 0.0F));
147 ImGui::Selectable((
"##lastPositionAccuracy.at(1)" + std::to_string(
size_t(
id))).c_str(),
148 false, ImGuiSelectableFlags_Disabled, ImVec2(2.0F * size, 0.0F));
149 if (ImGui::IsItemHovered())
154 ImGui::GetWindowDrawList()->AddCircleFilled(ImVec2(ImGui::GetCursorScreenPos().x + size * 1.2F,
155 ImGui::GetCursorScreenPos().y + size * 1.8F),
158 ? ImColor(0.0F, 255.0F, 0.0F)
159 : ImColor(255.0F, 0.0F, 0.0F));
160 ImGui::Selectable((
"##lastPositionAccuracy.at(2)" + std::to_string(
size_t(
id))).c_str(),
161 false, ImGuiSelectableFlags_Disabled, ImVec2(2.0F * size, 0.0F));
162 if (ImGui::IsItemHovered())
171 ImGui::TableNextColumn();
172 ImGui::Text(
"Velocity");
173 ImGui::TableNextColumn();
174 ImGui::GetWindowDrawList()->AddCircleFilled(ImVec2(ImGui::GetCursorScreenPos().x + size / 1.2F,
175 ImGui::GetCursorScreenPos().y + size * 1.8F),
178 ? ImColor(0.0F, 255.0F, 0.0F)
179 : ImColor(255.0F, 0.0F, 0.0F));
180 ImGui::Selectable((
"##determineVelocity" + std::to_string(
size_t(
id))).c_str(),
181 false, ImGuiSelectableFlags_Disabled, ImVec2(1.6F * size, 0.0F));
182 if (ImGui::IsItemHovered())
185 ?
"Successfully Initialized"
186 :
"To be initialized");
188 ImGui::TableNextColumn();
189 ImGui::SetNextItemWidth(-FLT_MIN);
190 if (
ImGui::DragDouble((
"##velocityAccuracyThreshold" + std::to_string(
size_t(
id))).c_str(),
195 ImGui::TableNextColumn();
196 ImGui::GetWindowDrawList()->AddCircleFilled(ImVec2(ImGui::GetCursorScreenPos().x + size * 1.2F,
197 ImGui::GetCursorScreenPos().y + size * 1.8F),
200 ? ImColor(0.0F, 255.0F, 0.0F)
201 : ImColor(255.0F, 0.0F, 0.0F));
202 ImGui::Selectable((
"##lastVelocityAccuracy.at(0)" + std::to_string(
size_t(
id))).c_str(),
203 false, ImGuiSelectableFlags_Disabled, ImVec2(2.0F * size, 0.0F));
204 if (ImGui::IsItemHovered())
209 ImGui::GetWindowDrawList()->AddCircleFilled(ImVec2(ImGui::GetCursorScreenPos().x + size * 1.2F,
210 ImGui::GetCursorScreenPos().y + size * 1.8F),
213 ? ImColor(0.0F, 255.0F, 0.0F)
214 : ImColor(255.0F, 0.0F, 0.0F));
215 ImGui::Selectable((
"##lastVelocityAccuracy.at(1)" + std::to_string(
size_t(
id))).c_str(),
216 false, ImGuiSelectableFlags_Disabled, ImVec2(2.0F * size, 0.0F));
217 if (ImGui::IsItemHovered())
222 ImGui::GetWindowDrawList()->AddCircleFilled(ImVec2(ImGui::GetCursorScreenPos().x + size * 1.2F,
223 ImGui::GetCursorScreenPos().y + size * 1.8F),
226 ? ImColor(0.0F, 255.0F, 0.0F)
227 : ImColor(255.0F, 0.0F, 0.0F));
228 ImGui::Selectable((
"##lastVelocityAccuracy.at(2)" + std::to_string(
size_t(
id))).c_str(),
229 false, ImGuiSelectableFlags_Disabled, ImVec2(2.0F * size, 0.0F));
230 if (ImGui::IsItemHovered())
239 ImGui::TableNextColumn();
240 ImGui::Text(
"Attitude");
241 ImGui::TableNextColumn();
242 ImGui::GetWindowDrawList()->AddCircleFilled(ImVec2(ImGui::GetCursorScreenPos().x + size / 1.2F,
243 ImGui::GetCursorScreenPos().y + size * 1.4F),
246 ? ImColor(0.0F, 255.0F, 0.0F)
247 : ImColor(255.0F, 0.0F, 0.0F));
248 ImGui::Selectable((
"##determineAttitude" + std::to_string(
size_t(
id))).c_str(),
249 false, ImGuiSelectableFlags_Disabled, ImVec2(1.6F * size, 0.0F));
250 if (ImGui::IsItemHovered())
253 ?
"Successfully Initialized"
254 :
"To be initialized");
256 ImGui::TableNextColumn();
261 if (ImGui::Checkbox(fmt::format(
"Override Position##{}",
size_t(
id)).c_str(), &
_overridePosition))
291 1.0F, 0.0, 0.0,
"%.4f"))
297 1.0F, 0.0, 0.0,
"%.4f"))
303 1.0F, 0.0, 0.0,
"%.4f"))
311 if (ImGui::BeginTable((
"Overrides##" + std::to_string(
size_t(
id))).c_str(),
312 2, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoHostExtendX, ImVec2(0.0F, 0.0F)))
314 ImGui::TableNextColumn();
315 if (ImGui::Checkbox((
"Override Roll##" + std::to_string(
size_t(
id))).c_str(), &
_overrideRollPitchYaw.at(0)))
320 ImGui::TableNextColumn();
324 if (
ImGui::DragDouble((
"##overrideValuesRollPitchYaw.at(0)" + std::to_string(
size_t(
id))).c_str(),
331 ImGui::TableNextColumn();
332 if (ImGui::Checkbox((
"Override Pitch##" + std::to_string(
size_t(
id))).c_str(), &
_overrideRollPitchYaw.at(1)))
337 ImGui::TableNextColumn();
341 if (
ImGui::DragDouble((
"##overrideValuesRollPitchYaw.at(1)" + std::to_string(
size_t(
id))).c_str(),
348 ImGui::TableNextColumn();
349 if (ImGui::Checkbox((
"Override Yaw##" + std::to_string(
size_t(
id))).c_str(), &
_overrideRollPitchYaw.at(2)))
354 ImGui::TableNextColumn();
358 if (
ImGui::DragDouble((
"##overrideValuesRollPitchYaw.at(2)" + std::to_string(
size_t(
id))).c_str(),
371 ImGui::SetNextItemOpen(
true, ImGuiCond_FirstUseEver);
372 if (ImGui::TreeNode(fmt::format(
"Init Time##{}",
size_t(
id)).c_str()))
379 if (ImGui::Button(
"Reset"))
415 if (j.contains(
"initDuration"))
419 if (j.contains(
"attitudeMode"))
423 if (j.contains(
"positionAccuracyThreshold"))
427 if (j.contains(
"velocityAccuracyThreshold"))
431 if (j.contains(
"overridePosition"))
435 if (j.contains(
"overridePositionValues"))
439 if (j.contains(
"overrideVelocity"))
443 if (j.contains(
"overrideVelocityValues"))
447 if (j.contains(
"overrideRollPitchYaw"))
451 if (j.contains(
"overrideRollPitchYawValues"))
455 if (j.contains(
"initTime"))
459 if (j.contains(
"initTimeEditFormat"))
475 std::numeric_limits<double>::infinity(),
476 std::numeric_limits<double>::infinity() };
478 std::numeric_limits<double>::infinity(),
479 std::numeric_limits<double>::infinity() };
551 inputPin.queueBlocked =
true;
552 inputPin.queue.clear();
561 LOG_INFO(
"{}: Position initialized to Lat {:3.12f} [°], Lon {:3.12f} [°], Alt {:4.3f} [m]",
nameId(),
582 if (lla_position.z() < 0)
584 LOG_WARN(
"{}: Altitude has a value of {} which is below the ellipsoid height.",
nameId(), lla_position.z());
587 LOG_INFO(
"{}: Velocity initialized to v_N {:3.5f} [m/s], v_E {:3.5f} [m/s], v_D {:3.5f} [m/s]",
nameId(),
591 LOG_INFO(
"{}: Attitude initialized to Roll {:3.5f} [°], Pitch {:3.5f} [°], Yaw {:3.4f} [°]",
nameId(),
596 auto posVelAtt = std::make_shared<PosVelAtt>();
606 return connectedPin->noMoreDataAvailable.load();
611 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());
617 auto obs = std::static_pointer_cast<const ImuObs>(queue.
extract_front());
620 LOG_DATA(
"{}: receiveImuObs at time [{}]",
nameId(), obs->insTime.toYMDHMS());
625 const auto& imuPosition = obs->imuPos;
630 LOG_ERROR(
"No magnetometer data available. Please override the Yaw angle.");
633 Eigen::Vector3d mag_p = obs->p_magneticField ? obs->p_magneticField.value() : Eigen::Vector3d::Zero();
636 const Eigen::Vector3d b_mag = imuPosition.b_quat_p() * mag_p;
637 auto magneticHeading = -std::atan2(b_mag.y(), b_mag.x());
640 const Eigen::Vector3d b_accel = imuPosition.b_quat_p() * obs->p_acceleration * -1;
682 LOG_DATA(
"{}: receiveGnssObs at time [{}]",
nameId(), nodeData->insTime.toYMDHMS());
684 const auto* sourcePin =
inputPins.at(pinIdx).link.getConnectedPin();
700 receivePosObs(std::static_pointer_cast<const Pos>(nodeData));
713 LOG_DATA(
"{}: UBX_NAV_ATT: Roll {}, Pitch {}, Heading {} [deg]",
nameId(),
714 std::get<vendor::ublox::UbxNavAtt>(obs->data).roll * 1e-5,
715 std::get<vendor::ublox::UbxNavAtt>(obs->data).pitch * 1e-5,
716 std::get<vendor::ublox::UbxNavAtt>(obs->data).heading * 1e-5);
720 _lastPositionAccuracy.at(0) =
static_cast<float>(std::get<vendor::ublox::UbxNavPosecef>(obs->data).pAcc);
721 _lastPositionAccuracy.at(1) =
static_cast<float>(std::get<vendor::ublox::UbxNavPosecef>(obs->data).pAcc);
722 _lastPositionAccuracy.at(2) =
static_cast<float>(std::get<vendor::ublox::UbxNavPosecef>(obs->data).pAcc);
728 _e_initPosition = Eigen::Vector3d(std::get<vendor::ublox::UbxNavPosecef>(obs->data).ecefX * 1e-2,
729 std::get<vendor::ublox::UbxNavPosecef>(obs->data).ecefY * 1e-2,
730 std::get<vendor::ublox::UbxNavPosecef>(obs->data).ecefZ * 1e-2);
738 _lastPositionAccuracy.at(0) =
static_cast<float>(std::get<vendor::ublox::UbxNavPosllh>(obs->data).hAcc * 1e-1);
739 _lastPositionAccuracy.at(1) =
static_cast<float>(std::get<vendor::ublox::UbxNavPosllh>(obs->data).hAcc * 1e-1);
740 _lastPositionAccuracy.at(2) =
static_cast<float>(std::get<vendor::ublox::UbxNavPosllh>(obs->data).vAcc * 1e-1);
746 Eigen::Vector3d lla_position(
deg2rad(std::get<vendor::ublox::UbxNavPosllh>(obs->data).lat * 1e-7),
747 deg2rad(std::get<vendor::ublox::UbxNavPosllh>(obs->data).lon * 1e-7),
748 std::get<vendor::ublox::UbxNavPosllh>(obs->data).height * 1e-3);
758 _lastVelocityAccuracy.at(0) =
static_cast<float>(std::get<vendor::ublox::UbxNavVelned>(obs->data).sAcc);
759 _lastVelocityAccuracy.at(1) =
static_cast<float>(std::get<vendor::ublox::UbxNavVelned>(obs->data).sAcc);
760 _lastVelocityAccuracy.at(2) =
static_cast<float>(std::get<vendor::ublox::UbxNavVelned>(obs->data).sAcc);
766 _n_initVelocity = Eigen::Vector3d(std::get<vendor::ublox::UbxNavVelned>(obs->data).velN * 1e-2,
767 std::get<vendor::ublox::UbxNavVelned>(obs->data).velE * 1e-2,
768 std::get<vendor::ublox::UbxNavVelned>(obs->data).velD * 1e-2);
802 const Eigen::Vector3d rollPitchYaw = obs->rollPitchYaw();
852 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.
std::string nameId() const
Node name and id.
std::string name
Name of the Node.
void invokeCallbacks(size_t portIndex, const std::shared_ptr< const NodeData > &data)
Calls all registered callbacks on the specified output port.
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'.
OutputPin * CreateOutputPin(Node *node, 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.
bool DeleteInputPin(InputPin &pin)
Deletes the input pin. Invalidates the pin reference given.
InputPin * CreateInputPin(Node *node, 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.
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].