264 lines
12 KiB
TeX
264 lines
12 KiB
TeX
% Project Drogheda — GNSS / Log Analysis findings (Helgen Beamer / Metropolis)
|
||
% Built from the helgen-beamer template. Compile: latexmk -xelatex <file>.tex
|
||
\documentclass[10pt,aspectratio=169]{beamer}
|
||
|
||
\usetheme[progressbar=frametitle, numbering=fraction, block=fill]{metropolis}
|
||
|
||
% ---------- Helgen official palette (Guia de Identidad v1.5, 2026) ----------
|
||
\definecolor{HelgenIndigo}{HTML}{2C3C5B}
|
||
\definecolor{HelgenCyan}{HTML}{51F3DA}
|
||
\definecolor{HelgenTeal}{HTML}{17A08C}
|
||
\definecolor{HelgenMist}{HTML}{EFF1F5}
|
||
|
||
\setbeamercolor{normal text}{fg=HelgenIndigo, bg=white}
|
||
\setbeamercolor{alerted text}{fg=HelgenTeal}
|
||
\setbeamercolor{frametitle}{bg=HelgenIndigo, fg=white}
|
||
\setbeamercolor{progress bar}{fg=HelgenCyan, bg=HelgenMist}
|
||
\setbeamercolor{title separator}{fg=HelgenCyan}
|
||
\setbeamercolor{block title}{bg=HelgenMist, fg=HelgenIndigo}
|
||
|
||
% ---------- Fonts: XeLaTeX + bundled brand fonts, clean fallback otherwise ----------
|
||
\usepackage{iftex}
|
||
\ifXeTeX
|
||
\usepackage{fontspec}
|
||
\IfFontExistsTF{League Spartan}{%
|
||
\newfontfamily\helgentitle{League Spartan}[BoldFont={* Bold}]
|
||
\setbeamerfont{title}{family=\helgentitle, series=\bfseries}
|
||
\setbeamerfont{frametitle}{family=\helgentitle, series=\bfseries}
|
||
\setbeamerfont{section title}{family=\helgentitle, series=\bfseries}
|
||
\setbeamerfont{standout}{family=\helgentitle, series=\bfseries}
|
||
}{}
|
||
\IfFontExistsTF{MADE Evolve Sans}{\setsansfont{MADE Evolve Sans}}{}
|
||
\else
|
||
\usepackage[T1]{fontenc}
|
||
\fi
|
||
\usepackage{booktabs}
|
||
\usepackage{tikz}
|
||
\usetikzlibrary{arrows.meta, positioning, shapes.misc, fit}
|
||
\usepackage{listings}
|
||
\lstset{
|
||
basicstyle=\ttfamily\scriptsize,
|
||
keywordstyle=\color{HelgenIndigo}\bfseries,
|
||
commentstyle=\color{gray},
|
||
stringstyle=\color{HelgenTeal},
|
||
showstringspaces=false, breaklines=true, frame=single,
|
||
framerule=0.2pt, rulecolor=\color{HelgenMist}
|
||
}
|
||
|
||
% Reusable block / arrow styles (Helgen palette)
|
||
\tikzset{
|
||
blk/.style={rounded rectangle, draw=HelgenIndigo, fill=HelgenMist, font=\scriptsize,
|
||
minimum height=8mm, inner xsep=2.4mm, align=center},
|
||
acc/.style={rounded rectangle, draw=HelgenTeal, fill=white, font=\scriptsize,
|
||
minimum height=8mm, inner xsep=2.4mm, align=center},
|
||
arr/.style={-{Stealth}, thick, HelgenTeal},
|
||
arrx/.style={-{Stealth}, thick, red!70!black, dashed},
|
||
}
|
||
|
||
% ---------- Footer ----------
|
||
\setbeamertemplate{frame footer}{%
|
||
\scriptsize\color{gray}\insertshortauthor\ · \insertshorttitle\ · Confidencial — Helgen Servicios Especializados}
|
||
|
||
% ---------- Metadata ----------
|
||
\title[Drogheda · GNSS/Logs]{Project Drogheda — GNSS \& Log Analysis}
|
||
\subtitle{HBOX RTK fleet: bench triage, healthy baseline, and observability}
|
||
\author[Helgen]{Helgen Technologies — CTO/CSO}
|
||
\date{20 June 2026}
|
||
\titlegraphic{}
|
||
|
||
\begin{document}
|
||
|
||
\maketitle
|
||
|
||
\begin{frame}{Agenda}
|
||
\tableofcontents
|
||
\end{frame}
|
||
|
||
% =====================================================================
|
||
\section{Context}
|
||
|
||
\begin{frame}{Where we are}
|
||
\begin{columns}[T]
|
||
\column{0.58\textwidth}
|
||
\begin{itemize}
|
||
\item HBOX RTK trackers on Hutchison Ports heavy equipment (ICAVE, Veracruz) — worked, then failed.
|
||
\item Three independent failure fronts, fixed in parallel:
|
||
\begin{itemize}\footnotesize
|
||
\item \textbf{Backend} (retranslator) — could drop the fleet / black-hole a unit
|
||
\item \textbf{Thermal} — PLA box in a sealed cabinet (heat trap)
|
||
\item \textbf{Prototype HW + observability} — hand-wired; logs untrustworthy
|
||
\end{itemize}
|
||
\item Field units pulled $\rightarrow$ bench triage in Querétaro (firmware v1, no thermal log).
|
||
\end{itemize}
|
||
\column{0.4\textwidth}
|
||
\begin{alertblock}{Invariant}
|
||
Corrections ride the \textbf{4G modem}, not the GNSS — recover the link by power-cycling the stack.
|
||
\end{alertblock}
|
||
\end{columns}
|
||
\end{frame}
|
||
|
||
\begin{frame}{The signal chain}
|
||
\centering
|
||
\begin{tikzpicture}[node distance=7mm and 13mm]
|
||
\node[blk] (f9p) {ZED-F9P\\(GNSS)};
|
||
\node[blk, right=of f9p] (mas) {4G NTRIP\\Master};
|
||
\node[blk, right=of mas] (ret) {retranslator\\(htracker)};
|
||
\node[blk, right=of ret] (wial) {Wialon};
|
||
\node[acc, above=10mm of mas] (cas) {NTRIP caster\\(rtk2go)};
|
||
\draw[arr] (f9p) -- node[above, font=\tiny]{UART2: GGA} (mas);
|
||
\draw[arr] (mas) -- node[above, font=\tiny]{UDP} (ret);
|
||
\draw[arr] (ret) -- (wial);
|
||
\draw[arr] (cas) -- node[right, font=\tiny]{RTCM in} (mas);
|
||
\end{tikzpicture}
|
||
\vfill
|
||
\footnotesize Corrections come \emph{down} from the caster over 4G; position goes \emph{out} by UDP to the retranslator. The GNSS receiver never talks to the network directly.
|
||
\end{frame}
|
||
|
||
% =====================================================================
|
||
\section{Backend (retranslator)}
|
||
|
||
\begin{frame}{Backend — hardened \& deployed to prod}
|
||
\begin{itemize}
|
||
\item \textbf{Head-of-line blocking removed:} a \texttt{WialonForwarder} thread pool does all Wialon TCP I/O \emph{off} the UDP receive loop — one slow upstream no longer drops the fleet.
|
||
\item \textbf{Anti-jump now time-aware + self-healing:} re-anchors after rejects, clears on disconnect — a unit is never permanently black-holed.
|
||
\item \textbf{Identity keyed by \texttt{cell\_id}} (CGNAT-safe), not \texttt{(ip,port)}.
|
||
\item Monitor gained a \textbf{backend-victim} KPI; logs ship to Grafana Loki. \alert{Live in production.}
|
||
\end{itemize}
|
||
\begin{alertblock}{Free triage}
|
||
ONLINE in htracker + OFFLINE in Wialon = \textbf{backend victim}, not a dead radio.
|
||
\end{alertblock}
|
||
\end{frame}
|
||
|
||
% =====================================================================
|
||
\section{GNSS log findings}
|
||
|
||
\begin{frame}{What we analyzed}
|
||
\begin{itemize}
|
||
\item \textbf{7 swap-matrix bench captures} (RTK board $\times$ NTRIP master) + one healthy baseline.
|
||
\item \textbf{Three views per unit:} u-blox \texttt{.ubx} (receiver), 4G-NTRIP console \texttt{.log}, server retranslator \texttt{tcpdump}.
|
||
\item Decoded the NTRIP-caster and ZED-F9P configuration files.
|
||
\item Built local tooling so this is repeatable (explorer + analyzer + dashboard).
|
||
\end{itemize}
|
||
\end{frame}
|
||
|
||
\begin{frame}{Headline: receivers are fine — RTK is not being achieved}
|
||
\begin{itemize}
|
||
\item Every board emits \textbf{valid NMEA} (6–12 sats, good HDOP). The ZED-F9P is \emph{not} the failure.
|
||
\item But \textbf{every epoch is SPS (quality 1)} — zero RTK (4/5). Centimetre position never delivered.
|
||
\item \textbf{Why:} free public \textbf{rtk2go} caster (no SLA) + F9P config saved to \textbf{RAM only} + indoor/bench sky.
|
||
\item The F9P message config itself is \textbf{correct} — GGA on UART2 @ 1\,Hz.
|
||
\end{itemize}
|
||
\end{frame}
|
||
|
||
\begin{frame}{Every unit is SPS — none reached RTK}
|
||
\centering
|
||
\includegraphics[width=0.88\textwidth]{fig/fig_fix_compare.pdf}\\[2mm]
|
||
\footnotesize Max GGA fix quality per capture (7 bench + baseline) — all flat at 1 (SPS); the RTK line (4) is never reached.
|
||
\end{frame}
|
||
|
||
\begin{frame}{Why: the corrections never settle}
|
||
\centering
|
||
\includegraphics[width=0.82\textwidth]{fig/fig_ntrip_delay.pdf}\\[2mm]
|
||
\footnotesize Even on a healthy unit the NTRIP correction delay sawtooths up to the 300\,s restart watchdog — the free rtk2go feed is intermittent.
|
||
\end{frame}
|
||
|
||
\begin{frame}{Healthy baseline — \texttt{RTK14\_440} (three views agree)}
|
||
\begin{columns}[T]
|
||
\column{0.56\textwidth}
|
||
\begin{itemize}\small
|
||
\item \textbf{Receiver:} 341 epochs, 100\% valid, 12 sats, HDOP 0.75 — SPS.
|
||
\item \textbf{Server:} 984 packets, steady 1\,Hz, \textbf{zero dropouts}, live in Wialon.
|
||
\item \textbf{Console:} ``registered'' only — no forwarding lines.
|
||
\end{itemize}
|
||
\column{0.4\textwidth}
|
||
\begin{alertblock}{The trap}
|
||
Healthy \textbf{delivery} $\neq$ \textbf{RTK}. Baseline = healthy SPS + reliable delivery.
|
||
\end{alertblock}
|
||
\end{columns}
|
||
\end{frame}
|
||
|
||
\begin{frame}{Baseline receiver — healthy geometry, stuck at SPS}
|
||
\centering
|
||
\includegraphics[width=0.93\textwidth]{fig/fig_baseline_gnss.pdf}\\[1mm]
|
||
\footnotesize \texttt{RTK14\_440} u-blox capture: 12 sats, HDOP 0.75, C/N0 $\sim$20 dB-Hz — but the fix never leaves 1 (SPS).
|
||
\end{frame}
|
||
|
||
\begin{frame}{Baseline delivery — healthy end-to-end}
|
||
\centering
|
||
\includegraphics[width=0.93\textwidth]{fig/fig_delivery.pdf}\\[1mm]
|
||
\footnotesize Server-side tcpdump: 984 datagrams, steady $\sim$1\,Hz, max gap 0.86\,s — the unit is genuinely reporting (live in Wialon).
|
||
\end{frame}
|
||
|
||
\begin{frame}{The console blind spot — and a retraction}
|
||
\begin{itemize}
|
||
\item The \emph{provably-healthy} unit logs the \textbf{same sparse console} as units that looked ``failed''.
|
||
\item $\Rightarrow$ the 4G-NTRIP console \textbf{cannot prove forwarding}. Absence of lines $\neq$ failure.
|
||
\item \alert{Retraction:} the earlier ``master-14 ingest fault'' is \textbf{withdrawn}.
|
||
\item Only \textbf{master 21} is a confirmed fault: modem won't register (\texttt{0xFFFFF} + 511 AT-parser errors).
|
||
\end{itemize}
|
||
\end{frame}
|
||
|
||
\begin{frame}{Per-master verdict}
|
||
\centering
|
||
\begin{tabular}{ll}
|
||
\toprule
|
||
\textbf{NTRIP master} & \textbf{Result} \\
|
||
\midrule
|
||
\#04 · \#17 · \#24 · \#25 & Healthy — registered + forwarding \\
|
||
\#14 & \alert{Indeterminate} — console can't confirm; baseline proves it forwards \\
|
||
\#21 & \alert{Failed} — modem won't register (\texttt{0xFFFFF} + 511 AT errors) \\
|
||
\bottomrule
|
||
\end{tabular}
|
||
\vfill
|
||
\footnotesize Confirm a unit only from a \texttt{.ubx} (fix), the Blackpill, or a server delivery capture — never the console alone.
|
||
\end{frame}
|
||
|
||
\begin{frame}{Heat — not implicated (by these logs)}
|
||
\begin{itemize}
|
||
\item Room-temperature bench captures, \textbf{no thermal channel} (firmware v1).
|
||
\item The hard faults reproduce \textbf{cold} $\Rightarrow$ heat is \emph{not} the cause of what we see here.
|
||
\item The \textbf{field} thermal hypothesis stays open — needs a thermocouple cabinet soak and/or v2 MCU-temp logging.
|
||
\end{itemize}
|
||
\end{frame}
|
||
|
||
% =====================================================================
|
||
\section{Changes \& tooling}
|
||
|
||
\begin{frame}{Observability — the real fix}
|
||
\begin{itemize}
|
||
\item The Blackpill watchdog already computes fix, packets, state, battery, MCU temp.
|
||
\item \textbf{v2.1 logging spec:} replace the self-overwriting ANSI dashboard with a \textbf{structured, timestamped, parseable} stream (+ decoded reset cause).
|
||
\item \textbf{\texttt{hbox-log-tools}} repo: in-browser Log Explorer (parse + plot + compare to baseline, offline), batch analyzer, dashboard, manual.
|
||
\end{itemize}
|
||
\end{frame}
|
||
|
||
\begin{frame}[fragile]{The new per-unit log line (v2.1)}
|
||
\begin{lstlisting}
|
||
BOOT,32,fw=2.1,reset=POR
|
||
COLS,ms,state,link,fix,sat,rx,rate,vbat,v5v,veh,ign,tc,tmax,der,rec,limp,nmea_age
|
||
TLM,190000,RUN,OK,4,12,340,1HZ,5.01,1,1,48,49,0,0,0,310
|
||
EVT,490000,RUN,DEGR,RTK lost -> recycle 4G/NTRIP
|
||
\end{lstlisting}
|
||
\footnotesize Fix + packets + state + reset cause $\Rightarrow$ per-unit health is unambiguous from the unit's own log — no server tcpdump needed.
|
||
\end{frame}
|
||
|
||
% =====================================================================
|
||
\section{Next steps}
|
||
|
||
\begin{frame}{Next steps}
|
||
\begin{enumerate}
|
||
\item Save the F9P config to \textbf{FLASH} + verify (RAM-only is a power-cycle risk); check the simpleRTK2B Pro \texttt{XBEE$\leftrightarrow$UART2} switch.
|
||
\item Move corrections off rtk2go $\rightarrow$ a \textbf{dedicated caster} (HelgenSRV) with uptime.
|
||
\item \textbf{Open-sky RTK retest} with a verified caster $\rightarrow$ confirm fix $\geq 4$.
|
||
\item Connect the \textbf{Blackpill} with v2.1 logging; modem-triage master 21; thermal soak.
|
||
\end{enumerate}
|
||
\end{frame}
|
||
|
||
\begin{frame}[standout]
|
||
The radios work.\\
|
||
We deliver \textbf{SPS} reliably — \textbf{not RTK}.\\[2mm]
|
||
{\normalsize The blockers are \textbf{corrections} and \textbf{observability} — both now addressed.}
|
||
\end{frame}
|
||
|
||
\end{document}
|