69 [[maybe_unused]]
const std::string& nameId,
72 LOG_DATA(
"{}: Calculating observation estimates:", nameId);
74 for (
auto& [satSigId, observation] : observations.
signals)
79 for (
size_t r = 0; r < observation.recvObs.size(); r++)
81 auto& recvObs = observation.recvObs.at(r);
82 [[maybe_unused]]
auto recv =
static_cast<ReceiverType
>(r);
84 const Antenna& antenna = _antenna.at(r);
86 Eigen::Vector3d hen_delta(0.0, 0.0, antenna.hen_delta(0));
87 Eigen::Vector3d e_recvPosAPC;
88 Eigen::Vector3d lla_recvPosAPC;
91 std::string antennaType;
92 if (antenna.autoDetermine && receiver.
gnssObs->receiverInfo)
94 antennaType = receiver.
gnssObs->receiverInfo->get().antennaType;
96 else if (!antenna.autoDetermine)
98 antennaType = antenna.name;
109 lla_recvPosAPC.z() += hen_delta.z();
112 double rho_r_s = (recvObs.e_satPos() - e_recvPosAPC).norm();
113 recvObs.terms.rho_r_s = rho_r_s;
116 recvObs.satElevation(), recvObs.satAzimuth(), _troposphereModels);
117 recvObs.terms.tropoZenithDelay = tropo_r_s;
119 double dpsr_T_r_s = tropo_r_s.ZHD * tropo_r_s.zhdMappingFactor + tropo_r_s.ZWD * tropo_r_s.zwdMappingFactor;
120 recvObs.terms.dpsr_T_r_s = dpsr_T_r_s;
123 freq, observation.freqNum(), lla_recvPosAPC, recvObs.satElevation(), recvObs.satAzimuth(),
124 _ionosphereModel, &ionosphericCorrections);
125 recvObs.terms.dpsr_I_r_s = dpsr_I_r_s;
128 recvObs.terms.dpsr_ie_r_s = dpsr_ie_r_s;
135 double cn0 = recvObs.gnssObsData().CN0.value_or(1.0);
137 for (
auto& [obsType, obsData] : recvObs.obs)
139 LOG_DATA(
"{}: [{}][{:11}][{:5}] Observation estimate", nameId, satSigId, obsType, recv);
143 obsData.estimate = rho_r_s
153 obsData.measVar = _gnssMeasurementErrorModel.
psrMeasErrorVar(satSys, recvObs.satElevation(), cn0);
154 LOG_DATA(
"{}: [{}][{:11}][{:5}] {:.4f} [m] Geometrical range", nameId, satSigId, obsType, recv, rho_r_s);
155 LOG_DATA(
"{}: [{}][{:11}][{:5}] + {:.4f} [m] Sagnac correction", nameId, satSigId, obsType, recv, dpsr_ie_r_s);
156 if (dpsr_T_r_s != 0.0) {
LOG_DATA(
"{}: [{}][{:11}][{:5}] + {:.4f} [m] Tropospheric delay", nameId, satSigId, obsType, recv, dpsr_T_r_s); }
157 if (dpsr_I_r_s != 0.0) {
LOG_DATA(
"{}: [{}][{:11}][{:5}] + {:.4f} [m] Ionospheric delay", nameId, satSigId, obsType, recv, dpsr_I_r_s); }
159 if (obsDiff ==
NoDifference) {
LOG_DATA(
"{}: [{}][{:11}][{:5}] - {:.4f} [m] Satellite clock bias", nameId, satSigId, obsType, recv,
InsConst<>::C * recvObs.satClock().bias); }
163 LOG_DATA(
"{}: [{}][{:11}][{:5}] = {:.4f} [m] Pseudorange estimate", nameId, satSigId, obsType, recv, obsData.estimate);
164 LOG_DATA(
"{}: [{}][{:11}][{:5}] {:.4e} [m] Difference to measurement", nameId, satSigId, obsType, recv, obsData.measurement - obsData.estimate);
167 obsData.estimate = rho_r_s
177 obsData.measVar = _gnssMeasurementErrorModel.
carrierMeasErrorVar(satSys, recvObs.satElevation(), cn0);
178 LOG_DATA(
"{}: [{}][{:11}][{:5}] {:.4f} [m] Geometrical range", nameId, satSigId, obsType, recv, rho_r_s);
179 LOG_DATA(
"{}: [{}][{:11}][{:5}] + {:.4f} [m] Sagnac correction", nameId, satSigId, obsType, recv, dpsr_ie_r_s);
180 if (dpsr_T_r_s != 0.0) {
LOG_DATA(
"{}: [{}][{:11}][{:5}] + {:.4f} [m] Tropospheric delay", nameId, satSigId, obsType, recv, dpsr_T_r_s); }
181 if (dpsr_I_r_s != 0.0) {
LOG_DATA(
"{}: [{}][{:11}][{:5}] - {:.4f} [m] Ionospheric delay", nameId, satSigId, obsType, recv, dpsr_I_r_s); }
183 if (obsDiff ==
NoDifference) {
LOG_DATA(
"{}: [{}][{:11}][{:5}] - {:.4f} [m] Satellite clock bias", nameId, satSigId, obsType, recv,
InsConst<>::C * recvObs.satClock().bias); }
186 LOG_DATA(
"{}: [{}][{:11}][{:5}] = {:.4f} [m] Carrier-phase estimate", nameId, satSigId, obsType, recv, obsData.estimate);
187 LOG_DATA(
"{}: [{}][{:11}][{:5}] {:.4e} [m] Difference to measurement", nameId, satSigId, obsType, recv, obsData.measurement - obsData.estimate);
190 obsData.estimate = recvObs.e_pLOS().dot(recvObs.e_satVel() - receiver.
e_vel)
196 obsData.measVar = _gnssMeasurementErrorModel.
psrRateMeasErrorVar(freq, observation.freqNum(), recvObs.satElevation(), cn0);
197 LOG_DATA(
"{}: [{}][{:11}][{:5}] {:.4f} [m/s] ", nameId, satSigId, obsType, recv, recvObs.e_pLOS().dot(recvObs.e_satVel() - receiver.
e_vel));
198 LOG_DATA(
"{}: [{}][{:11}][{:5}] - {:.4f} [m/s] Sagnac rate correction", nameId, satSigId, obsType, recv,
calcSagnacRateCorrection(e_recvPosAPC, recvObs.e_satPos(), receiver.
e_vel, recvObs.e_satVel()));
200 if (obsDiff ==
NoDifference) {
LOG_DATA(
"{}: [{}][{:11}][{:5}] - {:.4f} [m/s] Satellite clock drift", nameId, satSigId, obsType, recv,
InsConst<>::C * recvObs.satClock().drift); }
202 LOG_DATA(
"{}: [{}][{:11}][{:5}] = {:.4f} [m/s] Doppler estimate", nameId, satSigId, obsType, recv, obsData.estimate);
203 LOG_DATA(
"{}: [{}][{:11}][{:5}] {:.4e} [m/s] Difference to measurement", nameId, satSigId, obsType, recv, obsData.measurement - obsData.estimate);
208 LOG_DATA(
"{}: [{}][{:11}][{:5}] Observation error variance", nameId, satSigId, obsType, recv);
209 LOG_DATA(
"{}: [{}][{:11}][{:5}] {:.4g} [{}] Measurement error variance", nameId, satSigId, obsType, recv, obsData.measVar,
216 obsData.measVar += observation.navData()->calcSatellitePositionVariance()
219 LOG_DATA(
"{}: [{}][{:11}][{:5}] + {:.4f} [m^2] Satellite position variance", nameId, satSigId, obsType, recv, observation.navData()->calcSatellitePositionVariance());
220 if (dpsr_I_r_s != 0.0) {
LOG_DATA(
"{}: [{}][{:11}][{:5}] + {:.4f} [m^2] Ionosphere variance", nameId, satSigId, obsType, recv,
ionoErrorVar(dpsr_I_r_s, freq, observation.freqNum())); }
221 if (dpsr_T_r_s != 0.0) {
LOG_DATA(
"{}: [{}][{:11}][{:5}] + {:.4f} [m^2] Troposphere variance", nameId, satSigId, obsType, recv,
tropoErrorVar(dpsr_T_r_s, recvObs.satElevation())); }
226 LOG_DATA(
"{}: [{}][{:11}][{:5}] + {:.4f} [m^2] Code bias variance", nameId, satSigId, obsType, recv, _gnssMeasurementErrorModel.
codeBiasErrorVar());
231 LOG_DATA(
"{}: [{}][{:11}][{:5}] + {:.4f} [m^2] Inter-frequency bias variance", nameId, satSigId, obsType, recv,
243 obsData.measVar += recvClockVariance;
244 LOG_DATA(
"{}: [{}][{:11}][{:5}] + {:.4f} [m^2] Receiver clock bias variance", nameId, satSigId, obsType, recv, recvClockVariance);
251 obsData.measVar += recvClockVariance;
252 LOG_DATA(
"{}: [{}][{:11}][{:5}] + {:.4f} [m^2/s^2] Receiver clock drift variance", nameId, satSigId, obsType, recv, recvClockVariance);
255 LOG_DATA(
"{}: [{}][{:11}][{:5}] = {:.4g} [{}] Observation error variance", nameId, satSigId, obsType, recv, obsData.measVar,
268 bool changed =
false;
270 ImGui::SetNextItemOpen(
true, ImGuiCond_FirstUseEver);
271 if (ImGui::TreeNode(fmt::format(
"Compensation models##{}",
id).c_str()))
273 ImGui::SetNextItemWidth(itemWidth - ImGui::GetStyle().IndentSpacing);
279 if (
ComboTroposphereModel(fmt::format(
"Troposphere Model##{}",
id).c_str(), _troposphereModels, itemWidth - ImGui::GetStyle().IndentSpacing))
286 ImGui::SetNextItemOpen(
true, ImGuiCond_FirstUseEver);
287 if (ImGui::TreeNode(fmt::format(
"GNSS Measurement Error##{}",
id).c_str()))
289 if (_gnssMeasurementErrorModel.
ShowGuiWidgets(
id, itemWidth - ImGui::GetStyle().IndentSpacing))
291 LOG_DEBUG(
"{}: GNSS Measurement Error Model changed.",
id);
297 if (ImGui::TreeNode(fmt::format(
"Antenna settings##{}",
id).c_str()))
299 for (
size_t i = 0; i < ReceiverType::ReceiverType_COUNT; ++i)
301 if (ReceiverType::ReceiverType_COUNT > 1)
303 ImGui::SetNextItemOpen(
true, ImGuiCond_FirstUseEver);
304 if (!ImGui::TreeNode(fmt::format(
"{}",
static_cast<ReceiverType
>(i)).c_str())) {
continue; }
307 if (ImGui::Checkbox(fmt::format(
"Correct Phase-center offset##antenna {} {}",
id, i).c_str(), &_antenna.at(i).enabled))
309 LOG_DEBUG(
"{}: Antenna {} enabled: {}",
id, i, _antenna.at(i).enabled);
313 if (!_antenna.at(i).enabled) { ImGui::BeginDisabled(); }
314 if (ImGui::Checkbox(fmt::format(
"Auto determine##antenna {} {}",
id, i).c_str(), &_antenna.at(i).autoDetermine))
316 LOG_DEBUG(
"{}: Antenna {} auto: {}",
id, i, _antenna.at(i).autoDetermine);
319 if (_antenna.at(i).autoDetermine) { ImGui::BeginDisabled(); }
320 ImGui::SetNextItemWidth(itemWidth - (1.0F +
static_cast<float>(ReceiverType::ReceiverType_COUNT > 1)) * ImGui::GetStyle().IndentSpacing);
322 if (ImGui::BeginCombo(fmt::format(
"Type##Combo {} {}",
id, i).c_str(), _antenna.at(i).name.c_str()))
324 ImGui::PushFont(Application::MonoFont());
325 if (ImGui::Selectable(fmt::format(
"##Selectable {} {}",
id, i).c_str(), _antenna.at(i).name.empty()))
327 _antenna.at(i).name =
"";
332 const bool is_selected = (_antenna.at(i).name == iter);
333 if (ImGui::Selectable(iter.c_str(), is_selected))
335 _antenna.at(i).name = iter;
337 if (is_selected) { ImGui::SetItemDefaultFocus(); }
342 if (_antenna.at(i).autoDetermine) { ImGui::EndDisabled(); }
343 if (!_antenna.at(i).enabled) { ImGui::EndDisabled(); }
345 gui::widgets::HelpMarker(
"Used for lookup in ANTEX file.");
347 ImGui::SetNextItemWidth(itemWidth - (1.0F +
static_cast<float>(ReceiverType::ReceiverType_COUNT > 1)) * ImGui::GetStyle().IndentSpacing);
348 if (ImGui::InputDouble3(fmt::format(
"Delta H/E/N [m]##{} {}",
id, i).c_str(), _antenna.at(i).hen_delta.data(),
"%.3f"))
350 LOG_DEBUG(
"{}: Antenna {} delta: {}",
id, i, _antenna.at(i).hen_delta.transpose());
354 gui::widgets::HelpMarker(
"- Antenna height: Height of the antenna reference point (ARP) above the marker\n"
355 "- Horizontal eccentricity of ARP relative to the marker (east/north)");
357 if (ReceiverType::ReceiverType_COUNT > 1) { ImGui::TreePop(); }