13#include <imgui_internal.h>
65 std::mt19937_64 gen(
static_cast<uint64_t
>(std::chrono::system_clock::now().time_since_epoch().count()));
66 std::uniform_int_distribution<uint64_t> dist(0, std::numeric_limits<uint64_t>::max() / 2);
104 return "Data Processor";
109 if (
outputPins.front().dataIdentifier.size() != 1
112 ImGui::TextUnformatted(
"Please connect the input pin to show the options");
119 auto inputDoubleWithUnit = [&](
const char* title,
double& data,
auto& unit,
const char* combo_items_separated_by_zeros,
const char* format) {
121 &data, unit, combo_items_separated_by_zeros, 0.0, 0.0,
122 format, ImGuiInputTextFlags_CharsScientific))
130 auto inputVector3WithUnit = [&](
const char* title, Eigen::Vector3d& data,
auto& unit,
const char* combo_items_separated_by_zeros,
const char* format) {
132 data.data(), unit, combo_items_separated_by_zeros,
133 format, ImGuiInputTextFlags_CharsScientific))
142 float currentCursorX = ImGui::GetCursorPosX();
143 if (ImGui::Checkbox(fmt::format(
"##rng.useSeed {} {}", title,
size_t(
id)).c_str(), &rng.useSeed))
145 LOG_DEBUG(
"{}: {} rng.useSeed changed to {}",
nameId(), title, rng.useSeed);
148 if (ImGui::IsItemHovered()) { ImGui::SetTooltip(
"Use seed?"); }
152 ImGui::BeginDisabled();
154 ImGui::SetNextItemWidth(itemWidth - (ImGui::GetCursorPosX() - currentCursorX));
155 if (
ImGui::SliderULong(fmt::format(
"{} Seed##{}", title,
size_t(
id)).c_str(), &rng.seed, 0, std::numeric_limits<uint64_t>::max() / 2,
"%lu"))
162 ImGui::EndDisabled();
166 auto noiseGuiInput = [&]<
typename T>(
const char* title, T& data,
auto& unit,
const char* combo_items_separated_by_zeros,
const char* format,
RandomNumberGenerator& rng) {
167 if constexpr (std::is_same_v<T, double>) { inputDoubleWithUnit(title, data, unit, combo_items_separated_by_zeros, format); }
168 else if constexpr (std::is_same_v<T, Eigen::Vector3d>) { inputVector3WithUnit(title, data, unit, combo_items_separated_by_zeros, format); }
170 rngInput(title, rng);
176 ImGui::TextUnformatted(
"Offsets:");
205 ImGui::TextUnformatted(
"Measurement noise:");
216 ?
"Standard deviation"
230 ?
"Standard deviation"
248 ImGui::TextUnformatted(
"Random walk noise:");
253 ImGui::TextUnformatted(
"Integrated Random walk noise:");
262 ImGui::TextUnformatted(
"Ambiguities:");
265 ImGui::SetNextItemWidth((itemWidth - ImGui::GetStyle().ItemInnerSpacing.x) / 2.0F);
273 ImGui::SetCursorPosX(ImGui::GetCursorPosX() - ImGui::GetStyle().ItemSpacing.x + ImGui::GetStyle().ItemInnerSpacing.x);
274 ImGui::SetNextItemWidth((itemWidth - ImGui::GetStyle().ItemInnerSpacing.x) / 2.0F);
285 ImGui::TextUnformatted(
"Cycle-slip:");
301 ImGui::SetNextItemWidth(itemWidth);
302 if (ImGui::DragInt(fmt::format(
"Ambiguity Range to slip to##{}",
size_t(
id)).c_str(), &
_gui_cycleSlipRange,
303 1.0F, 1, std::numeric_limits<int>::max(),
"+/- %d"))
311 ImGui::SetNextItemWidth(itemWidth);
319 ImGui::SetNextItemWidth(itemWidth);
327 ImGui::SetNextItemOpen(
true, ImGuiCond_FirstUseEver);
328 if (ImGui::TreeNode(fmt::format(
"Simulated Ambiguities and Cycle-slips##{}",
size_t(
id)).c_str()))
333 std::set<InsTime> ambiguityTimes;
334 for (
int i = 0; i < nAmb; i++)
336 const auto& ambVec = std::next(
_ambiguities.begin(), i)->second;
337 for (
const auto& amb : ambVec)
339 ambiguityTimes.insert(amb.first);
342 if (ambiguityTimes.size() < 64 - 1)
344 ImGui::PushFont(Application::MonoFont());
346 if (ImGui::BeginTable(fmt::format(
"Ambiguities##{}",
size_t(
id)).c_str(),
static_cast<int>(ambiguityTimes.size() + 1),
347 ImGuiTableFlags_Borders | ImGuiTableFlags_NoHostExtendX | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY,
350 ImGui::TableSetupColumn(
"");
351 for (
const auto& time : ambiguityTimes)
353 auto t = time.toYMDHMS(
GPST);
354 t.sec = std::round(t.sec * 1e2) / 1e2;
357 ImGui::TableSetupScrollFreeze(1, 1);
358 ImGui::TableHeadersRow();
360 for (
int i = 0; i < nAmb; i++)
362 ImGui::TableNextRow();
363 ImGui::TableNextColumn();
364 const auto& ambiguities = std::next(
_ambiguities.begin(), i);
366 ImGui::TextUnformatted(fmt::format(
"{}", ambiguities->first).c_str());
367 ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ImGui::GetColorU32(ImGui::GetStyle().Colors[ImGuiCol_TableHeaderBg]));
369 for (
const auto& time : ambiguityTimes)
371 ImGui::TableNextColumn();
372 auto iter = std::ranges::find_if(ambiguities->second, [&time](
const auto& timeAndAmb) {
373 return timeAndAmb.first == time;
375 if (iter != ambiguities->second.end())
379 return cycleSlip.
time == time && cycleSlip.
satSigId == ambiguities->first;
381 if (cycleIter !=
_cycleSlips.end()) { color = ImColor(240, 128, 128); }
382 else if (ambiguities->second.back().first == time) { color = ImGui::GetStyle().Colors[ImGuiCol_Text]; }
383 else { color = ImGui::GetStyle().Colors[ImGuiCol_TextDisabled]; }
384 ImGui::TextColored(color,
"%s%s",
385 fmt::format(
"{}", iter->second).c_str(),
386 cycleIter !=
_cycleSlips.end() && cycleIter->LLI ?
" (LLI)" :
"");
387 if (ImGui::IsItemHovered() && cycleIter !=
_cycleSlips.end()) { ImGui::SetTooltip(
"Cycle-slip"); }
389 else if (time < ambiguities->second.front().first)
391 ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ImColor(70, 70, 70));
402 ImGui::TextColored(ImColor(255, 0, 0),
"More than 64 timestamps for ambiguities, which cannot be displayed in a table");
488 if (j.contains(
"imuGyroscopeBiasUnit")) { j.at(
"imuGyroscopeBiasUnit").get_to(
_imuGyroscopeBiasUnit); }
489 if (j.contains(
"imuGyroscopeBias_p")) { j.at(
"imuGyroscopeBias_p").get_to(
_imuGyroscopeBias_p); }
491 if (j.contains(
"imuAccelerometerNoise")) { j.at(
"imuAccelerometerNoise").get_to(
_imuAccelerometerNoise); }
492 if (j.contains(
"imuAccelerometerRng")) { j.at(
"imuAccelerometerRng").get_to(
_imuAccelerometerRng); }
493 if (j.contains(
"imuGyroscopeNoiseUnit")) { j.at(
"imuGyroscopeNoiseUnit").get_to(
_imuGyroscopeNoiseUnit); }
494 if (j.contains(
"imuGyroscopeNoise")) { j.at(
"imuGyroscopeNoise").get_to(
_imuGyroscopeNoise); }
495 if (j.contains(
"imuGyroscopeRng")) { j.at(
"imuGyroscopeRng").get_to(
_imuGyroscopeRng); }
498 if (j.contains(
"imuAccelerometerRW")) { j.at(
"imuAccelerometerRW").get_to(
_imuAccelerometerRW); }
499 if (j.contains(
"imuAccelerometerRWRng")) { j.at(
"imuAccelerometerRWRng").get_to(
_imuAccelerometerRWRng); }
500 if (j.contains(
"imuGyroscopeRWUnit")) { j.at(
"imuGyroscopeRWUnit").get_to(
_imuGyroscopeRWUnit); }
501 if (j.contains(
"imuGyroscopeRW")) { j.at(
"imuGyroscopeRW").get_to(
_imuGyroscopeRW); }
502 if (j.contains(
"imuGyroscopeRWRng")) { j.at(
"imuGyroscopeRWRng").get_to(
_imuGyroscopeRWRng); }
504 if (j.contains(
"imuAccelerometerIRW")) { j.at(
"imuAccelerometerIRW").get_to(
_imuAccelerometerIRW); }
506 if (j.contains(
"imuGyroscopeIRWUnit")) { j.at(
"imuGyroscopeIRWUnit").get_to(
_imuGyroscopeIRWUnit); }
507 if (j.contains(
"imuGyroscopeIRW")) { j.at(
"imuGyroscopeIRW").get_to(
_imuGyroscopeIRW); }
508 if (j.contains(
"imuGyroscopeIRWRng")) { j.at(
"imuGyroscopeIRWRng").get_to(
_imuGyroscopeIRWRng); }
510 if (j.contains(
"positionBiasUnit")) { j.at(
"positionBiasUnit").get_to(
_positionBiasUnit); }
511 if (j.contains(
"positionBias")) { j.at(
"positionBias").get_to(
_positionBias); }
512 if (j.contains(
"velocityBiasUnit")) { j.at(
"velocityBiasUnit").get_to(
_velocityBiasUnit); }
513 if (j.contains(
"velocityBias")) { j.at(
"velocityBias").get_to(
_velocityBias); }
514 if (j.contains(
"attitudeBiasUnit")) { j.at(
"attitudeBiasUnit").get_to(
_attitudeBiasUnit); }
515 if (j.contains(
"attitudeBias")) { j.at(
"attitudeBias").get_to(
_attitudeBias); }
516 if (j.contains(
"positionNoiseUnit")) { j.at(
"positionNoiseUnit").get_to(
_positionNoiseUnit); }
517 if (j.contains(
"positionNoise")) { j.at(
"positionNoise").get_to(
_positionNoise); }
518 if (j.contains(
"positionRng")) { j.at(
"positionRng").get_to(
_positionRng); }
519 if (j.contains(
"velocityNoiseUnit")) { j.at(
"velocityNoiseUnit").get_to(
_velocityNoiseUnit); }
520 if (j.contains(
"velocityNoise")) { j.at(
"velocityNoise").get_to(
_velocityNoise); }
521 if (j.contains(
"velocityRng")) { j.at(
"velocityRng").get_to(
_velocityRng); }
522 if (j.contains(
"attitudeNoiseUnit")) { j.at(
"attitudeNoiseUnit").get_to(
_attitudeNoiseUnit); }
523 if (j.contains(
"attitudeNoise")) { j.at(
"attitudeNoise").get_to(
_attitudeNoise); }
524 if (j.contains(
"attitudeRng")) { j.at(
"attitudeRng").get_to(
_attitudeRng); }
528 if (j.contains(
"pseudorangeRng")) { j.at(
"pseudorangeRng").get_to(
_pseudorangeRng); }
531 if (j.contains(
"carrierPhaseRng")) { j.at(
"carrierPhaseRng").get_to(
_carrierPhaseRng); }
533 if (j.contains(
"dopplerNoise")) { j.at(
"dopplerNoise").get_to(
_gui_dopplerNoise); }
534 if (j.contains(
"dopplerRng")) { j.at(
"dopplerRng").get_to(
_dopplerRng); }
536 if (j.contains(
"ambiguityRng")) { j.at(
"ambiguityRng").get_to(
_ambiguityRng); }
542 if (j.contains(
"cycleSlipRng")) { j.at(
"cycleSlipRng").get_to(
_cycleSlipRng); }
543 if (j.contains(
"filterFreq"))
546 j.at(
"filterFreq").get_to(value);
549 if (j.contains(
"filterCode")) { j.at(
"filterCode").get_to(
_filterCode); }
601 auto previousOutputPinDataIdentifier =
outputPins.front().dataIdentifier;
605 if (previousOutputPinDataIdentifier !=
outputPins.front().dataIdentifier)
610 if (
auto* endPin = link.getConnectedPin())
612 if (!
outputPins.front().canCreateLink(*endPin))
621 if (
outputPins.front().dataIdentifier != previousOutputPinDataIdentifier)
625 if (
auto* connectedPin = link.getConnectedPin())
627 outputPins.front().recreateLink(*connectedPin);
654 LOG_DATA(
"{}: accelerometerBias_p = {} [m/s^2]",
nameId(), accelerometerBias_p.transpose());
658 LOG_DATA(
"{}: gyroscopeBias_p = {} [rad/s]",
nameId(), gyroscopeBias_p.transpose());
664 LOG_DATA(
"{}: accelerometerNoiseStd = {} [m/s^2/sqrt(s)]",
nameId(), accelerometerNoiseStd.transpose());
668 LOG_DATA(
"{}: gyroscopeNoiseStd = {} [rad/s/sqrt(s)]",
nameId(), gyroscopeNoiseStd.transpose());
674 receiveImuObsWDelta(std::make_shared<ImuObsSimulated>(*std::static_pointer_cast<const ImuObsSimulated>(obs)),
677 accelerometerNoiseStd,
683 receiveImuObsWDelta(std::make_shared<ImuObsWDelta>(*std::static_pointer_cast<const ImuObsWDelta>(obs)),
686 accelerometerNoiseStd,
692 receiveImuObs(std::make_shared<ImuObs>(*std::static_pointer_cast<const ImuObs>(obs)),
695 accelerometerNoiseStd,
719 const Eigen::Vector3d& accelerometerBias_p,
720 const Eigen::Vector3d& gyroscopeBias_p,
721 const Eigen::Vector3d& accelerometerNoiseStd,
722 const Eigen::Vector3d& gyroscopeNoiseStd)
729 LOG_DATA(
"{}: accelerometerRWStd = {} [m/s^2/sqrt(s)]",
nameId(), accelerometerRWStd.transpose());
740 LOG_DATA(
"{}: accelerometerIRWStd = {} [m/s^3/sqrt(s)]",
nameId(), accelerometerIRWStd.transpose());
755 LOG_DATA(
"{}: gyroscopeRWStd = {} [rad/s/sqrt(s)]",
nameId(), gyroscopeRWStd.transpose());
766 LOG_DATA(
"{}: gyroscopeIRWStd = {} [rad/s^2/sqrt(s)]",
nameId(), gyroscopeIRWStd.transpose());
782 imuObs->p_acceleration += accelerometerBias_p
786 imuObs->p_angularRate += gyroscopeBias_p
791 imuObs->p_acceleration += Eigen::Vector3d{
_imuAccelerometerRng.getRand_normalDist(0.0, accelerometerNoiseStd(0)),
795 imuObs->p_angularRate += Eigen::Vector3d{
_imuGyroscopeRng.getRand_normalDist(0.0, gyroscopeNoiseStd(0)),
805 const Eigen::Vector3d& accelerometerBias_p,
806 const Eigen::Vector3d& gyroscopeBias_p,
807 const Eigen::Vector3d& accelerometerNoiseStd,
808 const Eigen::Vector3d& gyroscopeNoiseStd)
810 receiveImuObs(imuObsWDelta, accelerometerBias_p, gyroscopeBias_p, accelerometerNoiseStd, gyroscopeNoiseStd);
812 double imuObsWDeltaAverageWindow =
_dt != 0.0 ?
_dt / imuObsWDelta->dtime : 1.0;
818 imuObsWDelta->dvel += Eigen::Vector3d{
_imuAccelerometerRng.getRand_normalDist(0.0, accelerometerNoiseStd(0) / std::sqrt(imuObsWDeltaAverageWindow)),
819 _imuAccelerometerRng.getRand_normalDist(0.0, accelerometerNoiseStd(1) / std::sqrt(imuObsWDeltaAverageWindow)),
820 _imuAccelerometerRng.getRand_normalDist(0.0, accelerometerNoiseStd(2) / std::sqrt(imuObsWDeltaAverageWindow)) }
821 * imuObsWDelta->dtime / std::sqrt(
_dt);
822 imuObsWDelta->dtheta += Eigen::Vector3d{
_imuGyroscopeRng.getRand_normalDist(0.0, gyroscopeNoiseStd(0) / std::sqrt(imuObsWDeltaAverageWindow)),
823 _imuGyroscopeRng.getRand_normalDist(0.0, gyroscopeNoiseStd(1) / std::sqrt(imuObsWDeltaAverageWindow)),
824 _imuGyroscopeRng.getRand_normalDist(0.0, gyroscopeNoiseStd(2) / std::sqrt(imuObsWDeltaAverageWindow)) }
825 * imuObsWDelta->dtime / std::sqrt(
_dt);
834 Eigen::Vector3d lla_positionBias = Eigen::Vector3d::Zero();
840 if (!e_positionBias.isZero())
847 LOG_DATA(
"{}: lla_positionBias = {} [rad, rad, m]",
nameId(), lla_positionBias.transpose());
850 Eigen::Vector3d n_velocityBias = Eigen::Vector3d::Zero();
857 LOG_DATA(
"{}: n_velocityBias = {} [m/s]",
nameId(), n_velocityBias.transpose());
860 Eigen::Vector3d attitudeBias = Eigen::Vector3d::Zero();
870 LOG_DATA(
"{}: attitudeBias = {} [rad]",
nameId(), attitudeBias.transpose());
875 Eigen::Vector3d lla_positionNoiseStd = Eigen::Vector3d::Zero();
876 Eigen::Vector3d NED_pos_variance = Eigen::Vector3d::Zero();
882 if (!e_positionNoiseStd.isZero())
884 lla_positionNoiseStd =
trafo::ecef2lla_WGS84(pos->e_position() + e_positionNoiseStd) - pos->lla_position();
892 if (!e_positionNoiseStd.isZero())
894 lla_positionNoiseStd =
trafo::ecef2lla_WGS84(pos->e_position() + e_positionNoiseStd) - pos->lla_position();
900 LOG_DATA(
"{}: lla_positionNoiseStd = {} [rad, rad, m]",
nameId(), lla_positionNoiseStd.transpose());
904 pos->setPositionAndCov_n(pos->lla_position()
906 + Eigen::Vector3d{ _positionRng.getRand_normalDist(0.0, lla_positionNoiseStd(0)),
907 _positionRng.getRand_normalDist(0.0, lla_positionNoiseStd(1)),
908 _positionRng.getRand_normalDist(0.0, lla_positionNoiseStd(2)) },
909 NED_pos_variance.asDiagonal().toDenseMatrix());
917 Eigen::Vector3d lla_positionBias = Eigen::Vector3d::Zero();
923 if (!e_positionBias.isZero())
925 lla_positionBias =
trafo::ecef2lla_WGS84(posVel->e_position() + e_positionBias) - posVel->lla_position();
930 LOG_DATA(
"{}: lla_positionBias = {} [rad, rad, m]",
nameId(), lla_positionBias.transpose());
933 Eigen::Vector3d n_velocityBias = Eigen::Vector3d::Zero();
940 LOG_DATA(
"{}: n_velocityBias = {} [m/s]",
nameId(), n_velocityBias.transpose());
945 Eigen::Vector3d lla_positionNoiseStd = Eigen::Vector3d::Zero();
946 Eigen::Vector3d NED_pos_variance = Eigen::Vector3d::Zero();
947 Eigen::Vector3d NED_velocity_variance = Eigen::Vector3d::Zero();
953 if (!e_positionNoiseStd.isZero())
955 lla_positionNoiseStd =
trafo::ecef2lla_WGS84(posVel->e_position() + e_positionNoiseStd) - posVel->lla_position();
963 if (!e_positionNoiseStd.isZero())
965 lla_positionNoiseStd =
trafo::ecef2lla_WGS84(posVel->e_position() + e_positionNoiseStd) - posVel->lla_position();
971 LOG_DATA(
"{}: lla_positionNoiseStd = {} [rad, rad, m]",
nameId(), lla_positionNoiseStd.transpose());
974 Eigen::Vector3d n_velocityNoiseStd = Eigen::Vector3d::Zero();
986 LOG_DATA(
"{}: n_velocityNoiseStd = {} [m/s]",
nameId(), n_velocityNoiseStd.transpose());
990 Eigen::Matrix<double, 6, 6> cov_n = Eigen::Matrix<double, 6, 6>::Zero();
991 cov_n.block<3, 3>(0, 0).diagonal() = NED_pos_variance;
992 cov_n.block<3, 3>(3, 3).diagonal() = NED_velocity_variance;
994 posVel->setPosVelAndCov_n(posVel->lla_position()
996 + Eigen::Vector3d{ _positionRng.getRand_normalDist(0.0, lla_positionNoiseStd(0)),
997 _positionRng.getRand_normalDist(0.0, lla_positionNoiseStd(1)),
998 _positionRng.getRand_normalDist(0.0, lla_positionNoiseStd(2)) },
1001 + Eigen::Vector3d{ _velocityRng.getRand_normalDist(0.0, n_velocityNoiseStd(0)),
1002 _velocityRng.getRand_normalDist(0.0, n_velocityNoiseStd(1)),
1003 _velocityRng.getRand_normalDist(0.0, n_velocityNoiseStd(2)) },
1012 Eigen::Vector3d lla_positionBias = Eigen::Vector3d::Zero();
1018 if (!e_positionBias.isZero())
1020 lla_positionBias =
trafo::ecef2lla_WGS84(posVelAtt->e_position() + e_positionBias) - posVelAtt->lla_position();
1025 LOG_DATA(
"{}: lla_positionBias = {} [rad, rad, m]",
nameId(), lla_positionBias.transpose());
1028 Eigen::Vector3d n_velocityBias = Eigen::Vector3d::Zero();
1035 LOG_DATA(
"{}: n_velocityBias = {} [m/s]",
nameId(), n_velocityBias.transpose());
1038 Eigen::Vector3d attitudeBias = Eigen::Vector3d::Zero();
1048 LOG_DATA(
"{}: attitudeBias = {} [rad]",
nameId(), attitudeBias.transpose());
1053 Eigen::Vector3d lla_positionNoiseStd = Eigen::Vector3d::Zero();
1054 Eigen::Vector3d NED_pos_variance = Eigen::Vector3d::Zero();
1055 Eigen::Vector3d NED_velocity_variance = Eigen::Vector3d::Zero();
1056 Eigen::Vector3d RPY_attitude_variance = Eigen::Vector3d::Zero();
1062 if (!e_positionNoiseStd.isZero())
1064 lla_positionNoiseStd =
trafo::ecef2lla_WGS84(posVelAtt->e_position() + e_positionNoiseStd) - posVelAtt->lla_position();
1072 if (!e_positionNoiseStd.isZero())
1074 lla_positionNoiseStd =
trafo::ecef2lla_WGS84(posVelAtt->e_position() + e_positionNoiseStd) - posVelAtt->lla_position();
1080 LOG_DATA(
"{}: lla_positionNoiseStd = {} [rad, rad, m]",
nameId(), lla_positionNoiseStd.transpose());
1083 Eigen::Vector3d n_velocityNoiseStd = Eigen::Vector3d::Zero();
1095 LOG_DATA(
"{}: n_velocityNoiseStd = {} [m/s]",
nameId(), n_velocityNoiseStd.transpose());
1098 Eigen::Vector3d attitudeNoiseStd = Eigen::Vector3d::Zero();
1118 LOG_DATA(
"{}: attitudeNoiseStd = {} [rad]",
nameId(), attitudeNoiseStd.transpose());
1122 Eigen::Matrix<double, 9, 9> cov_n = Eigen::Matrix<double, 9, 9>::Zero();
1123 cov_n.block<3, 3>(0, 0).diagonal() = NED_pos_variance;
1124 cov_n.block<3, 3>(3, 3).diagonal() = NED_velocity_variance;
1125 cov_n.block<3, 3>(6, 6).diagonal() = RPY_attitude_variance;
1127 Eigen::Matrix<double, 10, 9> J = Eigen::Matrix<double, 10, 9>::Zero();
1128 J.topLeftCorner<6, 6>().setIdentity();
1131 posVelAtt->setPosVelAttAndCov_n(posVelAtt->lla_position()
1133 + Eigen::Vector3d{ _positionRng.getRand_normalDist(0.0, lla_positionNoiseStd(0)),
1134 _positionRng.getRand_normalDist(0.0, lla_positionNoiseStd(1)),
1135 _positionRng.getRand_normalDist(0.0, lla_positionNoiseStd(2)) },
1136 posVelAtt->n_velocity()
1138 + Eigen::Vector3d{ _velocityRng.getRand_normalDist(0.0, n_velocityNoiseStd(0)),
1139 _velocityRng.getRand_normalDist(0.0, n_velocityNoiseStd(1)),
1140 _velocityRng.getRand_normalDist(0.0, n_velocityNoiseStd(2)) },
1143 + Eigen::Vector3d{ _attitudeRng.getRand_normalDist(0.0, attitudeNoiseStd(0)),
1144 _attitudeRng.getRand_normalDist(0.0, attitudeNoiseStd(1)),
1145 _attitudeRng.getRand_normalDist(0.0, attitudeNoiseStd(2)) }),
1146 J * cov_n * J.transpose());
1153 LOG_DATA(
"{}: [{}] Simulating error on GnssObs",
nameId(), gnssObs->insTime.toYMDHMS(
GPST));
1154 double pseudorangeNoise{};
1161 double carrierPhaseNoise{};
1168 double dopplerNoise{};
1176 double dtCycleSlipSeconds{};
1189 auto dtCycleSlip = std::chrono::nanoseconds(
static_cast<int64_t
>(dtCycleSlipSeconds * 1e9));
1191 double cycleSlipDetectionProbability{};
1207 for (
auto& obs : gnssObs->data)
1216 for (
auto& obs : gnssObs->data)
1218 if (obs.pseudorange) { obs.pseudorange.value().value +=
_pseudorangeRng.getRand_normalDist(0.0, pseudorangeNoise); }
1219 if (obs.doppler) { obs.doppler.value() +=
rangeRate2doppler(
_dopplerRng.getRand_normalDist(0.0, dopplerNoise), obs.satSigId.freq(), 0); }
1221 if (obs.carrierPhase)
1224 auto lambda =
InsConst::C / obs.satSigId.freq().getFrequency(0);
1225 obs.carrierPhase.value().value +=
_carrierPhaseRng.getRand_normalDist(0.0, carrierPhaseNoise) / lambda;
1235 double probabilityCycleSlip =
_dt / (dtCycleSlipSeconds *
static_cast<double>(nObs)) * 2.0;
1236 if (
_cycleSlipRng.getRand_uniformRealDist(0.0, 1.0) <= probabilityCycleSlip
1237 || (gnssObs->insTime >=
_cycleSlipWindowStartTime + dtCycleSlip - std::chrono::nanoseconds(
static_cast<int64_t
>((
_dt + 0.001) * 1e9))))
1239 int newAmbiguity = 0;
1244 auto signAmbiguity =
_cycleSlipRng.getRand_uniformIntDist(0, 1) == 0.0 ? 1 : -1;
1248 newAmbiguity = oldAmbiguity + signAmbiguity * deltaAmbiguity;
1263 _ambiguities[obs.satSigId].emplace_back(gnssObs->insTime, newAmbiguity);
1265 if (
_cycleSlipRng.getRand_uniformRealDist(0.0, 1.0) <= cycleSlipDetectionProbability)
1267 obs.carrierPhase.value().LLI = 1;
1269 _cycleSlips.push_back(
CycleSlipInfo{ .time = gnssObs->insTime, .satSigId = obs.satSigId, .LLI = obs.carrierPhase.value().LLI != 0 });
1270 LOG_DEBUG(
"{}: [{}] Simulating cycle-slip for satellite [{}] with LLI {}",
nameId(), gnssObs->insTime.toYMDHMS(
GPST),
1271 obs.satSigId, obs.carrierPhase.value().LLI);
1282 obs.carrierPhase.value().value +=
_ambiguities.at(obs.satSigId).back().second;
Transformation collection.
Adds errors (biases and noise) to measurements.
nlohmann::json json
json namespace
Text Help Marker (?) with Tooltip.
Data storage class for simulated IMU observations.
Data storage class for one VectorNavImu observation.
#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_TRACE
Detailled info to trace the execution of the program. Should not be called on functions which receive...
Utility class which specifies available nodes.
Utility functions for working with std::strings.
Frequency _filterFreq
Frequencies used for calculation (GUI filter)
std::shared_ptr< PosVel > receivePosVel(const std::shared_ptr< PosVel > &posVel)
Callback when receiving an PosVelObs.
RandomNumberGenerator _imuAccelerometerRng
Random number generator for the accelerometer noise.
int _gui_cycleSlipRange
Ambiguity limits cycle-slip.
RandomNumberGenerator _carrierPhaseRng
Random number generator for the carrier-phase noise.
Units::ImuAccelerometerUnits _imuAccelerometerBiasUnit
Selected unit for the accelerometer bias in the GUI.
std::shared_ptr< ImuObs > receiveImuObs(const std::shared_ptr< ImuObs > &imuObs, const Eigen::Vector3d &accelerometerBias_p, const Eigen::Vector3d &gyroscopeBias_p, const Eigen::Vector3d &accelerometerNoiseStd, const Eigen::Vector3d &gyroscopeNoiseStd)
Callback when receiving an ImuObs.
VelocityBiasUnits _velocityBiasUnit
Selected unit for the velocity bias in the GUI.
std::array< int, 2 > _gui_ambiguityLimits
Ambiguity limits.
CarrierPhaseNoiseUnits _gui_carrierPhaseNoiseUnit
Selected unit for the carrier-phase noise in the GUI.
RandomNumberGenerator _imuGyroscopeRng
Random number generator for the gyroscope noise.
RandomNumberGenerator _imuAccelerometerIRWRng
Random number generator for the accelerometer IRW noise.
Units::ImuGyroscopeIRWUnits _imuGyroscopeIRWUnit
Selected unit for the accelerometer IRW noise in the GUI.
RandomNumberGenerator _imuGyroscopeRWRng
Random number generator for the accelerometer RW noise.
RandomNumberGenerator _imuAccelerometerRWRng
Random number generator for the accelerometer RW noise.
~ErrorModel() override
Destructor.
PositionNoiseUnits _positionNoiseUnit
Selected unit for the position noise in the GUI.
Eigen::Vector3d _positionNoise
Noise of the position (Unit as selected)
Units::ImuGyroscopeUnits _imuGyroscopeBiasUnit
Selected unit for the gyroscope bias in the GUI.
static std::string typeStatic()
String representation of the Class Type.
Eigen::Vector3d _imuAccelerometerNoise
Noise of the accelerometer (Unit as selected)
static constexpr size_t OUTPUT_PORT_INDEX_FLOW
Flow.
VelocityNoiseUnits _velocityNoiseUnit
Selected unit for the velocity noise in the GUI.
void restore(const json &j) override
Restores the node from a json object.
void afterDeleteLink(OutputPin &startPin, InputPin &endPin) override
Called when a link was deleted.
Eigen::Vector3d _integratedRandomWalkGyroscope
3D array which allow to accumulate IRW for gyro
Units::ImuAccelerometerNoiseUnits _imuAccelerometerNoiseUnit
Selected unit for the accelerometer noise in the GUI.
std::shared_ptr< GnssObs > receiveGnssObs(const std::shared_ptr< GnssObs > &gnssObs)
Callback when receiving an GnssObs.
RandomNumberGenerator _attitudeRng
Random number generator for the attitude noise.
AttitudeBiasUnits _attitudeBiasUnit
Selected unit for the attitude bias in the GUI.
@ rad
[rad] (Standard deviation)
@ deg
[deg] (Standard deviation)
json save() const override
Saves the node into a json object.
std::string type() const override
String representation of the Class Type.
RandomNumberGenerator _imuGyroscopeIRWRng
Random number generator for the accelerometer RW noise.
Eigen::Vector3d _velocityBias
Bias of the velocity (Unit as selected)
InsTime _lastObservationTime
Last observation time.
RandomNumberGenerator _cycleSlipRng
Random number generator for the cycle-slip.
double _gui_cycleSlipDetectionProbability
The chance to detect a cycle slip and set the Loss-of-Lock indicator.
Eigen::Vector3d _integratedRandomWalkGyroscope_velocity
3D array which allow to accumulate IRW veloctiy noise for gyro
CycleSlipDetectionProbabilityUnits _gui_cycleSlipDetectionProbabilityUnit
Selected unit for the cycle-slip detection probability in the GUI.
Eigen::Vector3d _velocityNoise
Noise of the velocity (Unit as selected)
std::shared_ptr< Pos > receivePos(const std::shared_ptr< Pos > &pos)
Callback when receiving an PosObs.
CycleSlipFrequencyUnits _gui_cycleSlipFrequencyUnit
Selected unit for the cycle-slip frequency in the GUI.
Eigen::Vector3d _imuAccelerometerRW
RW noise of the accelerometer (Unit as selected)
double _gui_pseudorangeNoise
Noise of the pseudorange (Unit as selected)
double _gui_carrierPhaseNoise
Noise of the carrier-phase (Unit as selected)
double _dt
Time interval of the messages [s].
RandomNumberGenerator _pseudorangeRng
Random number generator for the pseudorange noise.
Eigen::Vector3d _integratedRandomWalkAccelerometer
3D array which allow to accumulate IRW for accelerometer
std::shared_ptr< PosVelAtt > receivePosVelAtt(const std::shared_ptr< PosVelAtt > &posVelAtt)
Callback when receiving an PosVelAttObs.
Units::ImuGyroscopeNoiseUnits _imuGyroscopeRWUnit
Selected unit for the accelerometer RW noise in the GUI.
@ meter2
NED [m^2 m^2 m^2] (Variance)
@ meter
NED [m m m] (Standard deviation)
DopplerNoiseUnits _gui_dopplerNoiseUnit
Selected unit for the range-rate noise in the GUI.
RandomNumberGenerator _ambiguityRng
Random number generator for the ambiguity.
@ m_s
[m/s] (Standard deviation)
Eigen::Vector3d _imuAccelerometerBias_p
Bias of the accelerometer in platform coordinates (Unit as selected)
RandomNumberGenerator _positionRng
Random number generator for the position noise.
Eigen::Vector3d _imuGyroscopeBias_p
Bias of the gyroscope in platform coordinates (Unit as selected)
Code _filterCode
Codes used for calculation (GUI filter)
double _gui_dopplerNoise
Noise of the range-rate (Unit as selected)
void receiveObs(InputPin::NodeDataQueue &queue, size_t pinIdx)
Callback when receiving data on a port.
Units::ImuAccelerometerNoiseUnits _imuAccelerometerRWUnit
Selected unit for the accelerometer RW noise in the GUI.
Eigen::Vector3d _imuGyroscopeNoise
Noise of the gyroscope (Unit as selected)
static std::string category()
String representation of the Class Category.
Eigen::Vector3d _positionBias
Bias of the position (Unit as selected)
void afterCreateLink(OutputPin &startPin, InputPin &endPin) override
Called when a new link was established.
@ meter
[m] (Standard deviation)
Eigen::Vector3d _imuGyroscopeIRW
RW noise of the accelerometer (Unit as selected)
@ meter
[m] (Standard deviation)
Units::ImuAccelerometerIRWUnits _imuAccelerometerIRWUnit
Selected unit for the accelerometer IRW noise in the GUI.
Eigen::Vector3d _randomWalkGyroscope
3D array which allow to accumulate RW noise for gyro
Eigen::Vector3d _attitudeBias
Bias of the attitude (Unit as selected)
void guiConfig() override
ImGui config window which is shown on double click.
Eigen::Vector3d _imuAccelerometerIRW
IRW noise of the accelerometer (Unit as selected)
PositionBiasUnits _positionBiasUnit
Selected unit for the position bias in the GUI.
Eigen::Vector3d _imuGyroscopeRW
RW noise of the accelerometer (Unit as selected)
AttitudeNoiseUnits _attitudeNoiseUnit
Selected unit for the attitude noise in the GUI.
ErrorModel()
Default constructor.
Eigen::Vector3d _randomWalkAccelerometer
3D array which allow to accumulate RW noise for accelerometer
@ m_s
[m/s] (Standard deviation)
@ m2_s2
[m^2/s^2] (Variance)
Eigen::Vector3d _integratedRandomWalkAccelerometer_velocity
3D array which allow to accumulate IRW veloctiy noise for accelerometer
InsTime _cycleSlipWindowStartTime
The time frame which is considered for a cycle slip.
double _gui_cycleSlipFrequency
The cycle-slip frequency (Unit as selected)
std::shared_ptr< ImuObsWDelta > receiveImuObsWDelta(const std::shared_ptr< ImuObsWDelta > &imuObs, const Eigen::Vector3d &accelerometerBias_p, const Eigen::Vector3d &gyroscopeBias_p, const Eigen::Vector3d &accelerometerNoiseStd, const Eigen::Vector3d &gyroscopeNoiseStd)
Callback when receiving an ImuObsWDelta.
RandomNumberGenerator _velocityRng
Random number generator for the velocity noise.
std::vector< CycleSlipInfo > _cycleSlips
List of produced cycle-slips.
RandomNumberGenerator _dopplerRng
Random number generator for the range-rate noise.
Units::ImuGyroscopeNoiseUnits _imuGyroscopeNoiseUnit
Selected unit for the gyroscope noise in the GUI.
Eigen::Vector3d _attitudeNoise
Noise of the attitude (Unit as selected)
std::map< SatSigId, std::vector< std::pair< InsTime, int > > > _ambiguities
Ambiguity map.
bool resetNode() override
Resets the node. It is guaranteed that the node is initialized when this is called.
PseudorangeNoiseUnits _gui_pseudorangeNoiseUnit
Selected unit for the pseudorange noise in the GUI.
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 constexpr double C
Speed of light [m/s].
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.
ax::NodeEditor::NodeId id
Unique Id of the Node.
bool _hasConfig
Flag if the config window should be shown.
Node * parentNode
Reference to the parent node.
ax::NodeEditor::PinId id
Unique Id of the Pin.
std::vector< std::string > dataIdentifier
One or multiple Data Identifiers (Unique name which is used for data flows)
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.
Manages a thread which calls a specified function at a specified interval.
auto extract_front()
Returns a copy of the first element in the container and removes it from the container.
static float windowFontRatio()
Ratio to multiply for GUI window elements.
static float monoFontRatio()
Ratio to multiply for log output GUI elements.
bool InputIntL(const char *label, int *v, int v_min, int v_max, int step, int step_fast, ImGuiInputTextFlags flags)
Shows a value limited InputText GUI element for 'int'.
bool SliderULong(const char *label, uint64_t *v, uint64_t v_min, uint64_t v_max, const char *format, ImGuiSliderFlags flags)
Shows a Slider GUI element for 'uint64'.
constexpr int32_t SECONDS_PER_DAY
Seconds / Day.
constexpr int32_t SECONDS_PER_HOUR
Seconds / Hour.
constexpr int32_t SECONDS_PER_MINUTE
Seconds / Minute.
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.
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.
static std::string replaceAll_copy(std::string str, const std::string &from, const std::string &to, CaseSensitivity cs)
Replaces all occurrence of a search pattern with another sequence.
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 > e_Quat_n(const Scalar &latitude, const Scalar &longitude)
Quaternion for rotations from navigation to Earth-fixed frame.
Eigen::Matrix< typename Derived::Scalar, 4, 3 > covRPY2quatJacobian(const Eigen::QuaternionBase< Derived > &n_quat_b)
Calculates the Jacobian to convert an attitude represented in Euler angels (roll, pitch,...
Eigen::Quaternion< Scalar > n_Quat_b(Scalar roll, Scalar pitch, Scalar yaw)
Quaternion for rotations from body to navigation frame.
Frequency_
Enumerate for GNSS frequencies.
bool ShowFrequencySelector(const char *label, Frequency &frequency, bool singleSelect)
Shows a ComboBox to select GNSS frequencies.
bool ShowCodeSelector(const char *label, Code &code, const Frequency &filterFreq, bool singleSelect)
Shows a ComboBox to select signal codes.
double convertUnit(const double &value, Units::PositionUncertaintyUnits unit)
Converts the value depending on the unit provided.
constexpr auto deg2rad(const T °)
Convert Degree to Radians.
std::string MakeComboItems()
Units separated by '\0' and terminated by double '\0'.
const std::vector< std::string > supportedDataIdentifier
List of supported data identifiers.
double rangeRate2doppler(double rangeRate, Frequency freq, int8_t num)
Transforms a range-rate into a doppler-shift.
InsTime time
Time of the cycle-slip.
SatSigId satSigId
Satellite Signal identifier.