<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">\documentclass[onecolumn,letterpaper,11pt]{article}

%===================================================================
\input{common_latex/common_latex_packages}
\input{common_latex/common_latex_definitions}
\input{common_latex/common_latex_help_format}
%===================================================================

\begin{document}

\begin{labcover}
\labtitle{pNodeReporter: Summarizing a Node's Position and Status}
\vspace{0.1in}
\labdate{Feb 2025}
\vspace{0.1in}
\labauth{Michael Benjamin, mikerb@mit.edu}
\labauth{Department of Mechanical Engineering}
\labauth{MIT, Cambridge MA 02139}
\labsrc{project-pavlab/appdocs/app\_pnreporter} 
\labtoc{small}
\end{labcover}

\wikidoc{file=IvPTools.PNodeReporter}
\wikidoc{bugz=pNodeNodeReporter}
\wikidoc{auth=mikerb@mit.edu}

%===================================================================
\section{Overview}
%===================================================================
\label{sec_util_pnr}
%\index{pNodeReporter}

The \app{pNodeReporter} app runs on each vehicle (real or simulated)
and generates node reports for sharing between vehicles, depicted in
Figure \ref{pnr_topology}.  They can be regarded as a proxy for AIS
reports. The app serves one primary function - it repeatedly gathers
local platform information and navigation data and creates an AIS like
report in the form of the MOOS variable
\mvar{NODE\_REPORT\_LOCAL}. The \mvar{NODE\_REPORT} messages are
communicated between the vehicles and the shore or shipside command
and control through an inter-MOOSDB communications process such as
\app{pShare} or via acoustic modem.  Since a node or platform may both
generate and receive reports, the locally generated reports are
labeled with the \var{\_LOCAL} suffix and transmitted to the outside
communities without the suffix. This is to ensure that processes
running locally may easily distinguish between locally generated and
externally generated reports.

\vspace{0.15in}
\begin{figure}[H]
  \centering 
  \includegraphics[width=0.78\textwidth]{figures/pnreporter_topology.png}
  \caption{{\bf Typical \vvar{pNodeReporter} usage:} The
    \vvar{pNodeReporter} application is typically used with
    \vvar{pShare} or acoustic modems to share node summaries between
    vehicles and to a shoreside command-and-control GUI.}
  \label{pnr_topology}
\end{figure}


\vspace{0.1in}
\noindent
To generate the local report, \app{pNodeReporter} registers for the
local \var{NAV\_*} vehicle navigation data and creates a report in the
form of a single string posted to the variable
\mvar{NODE\_REPORT\_LOCAL}. An example of this variable is given in
below in Section \ref{sec_pnr_nrep}. The \app{pMarineViewer} and
\app{pHelmIvP} applications are two modules that consume and parse the
incoming \mvar{NODE\_REPORT} messages.

\vspace{0.1in}
\noindent
The \app{pNodeReporter} utility may also publish a second report, the
\mvar{PLATFORM\_REPORT}. While the \mvar{NODE\_REPORT} summary consists of
an immutable set of data fields described later in this section, the 
\mvar{PLATFORM\_REPORT} consists of data fields configured by the user
and may therefore vary widely across applications. The user may also
configure the frequency in which components of the \mvar{PLATFORM\_REPORT}
are posted within the report.

%===================================================================
\section{Using pNodeReporter}
%===================================================================

%===================================================================
\subsection{Overview Node Report Components}
\label{sec_pnr_nrep}

The primary output of \app{pNodeReporter} is the node report string.
It is a comma-separated list of key-value pairs. The order of the
pairs is not significant. The following is an example report:

\prevgreen
\begin{verbatim}
NODE_REPORT_LOCAL = "NAME=alpha,TYPE=UUV,TIME=1252348077.59,X=51.71,Y=-35.50,
                    LAT=43.824981,LON=-70.329755,SPD=2.00,HDG=118.85,YAW=118.84754,
                    DEP=4.63,LENGTH=3.8,MODE=MODE@ACTIVE:LOITERING"
\end{verbatim}
\postverb

\noindent
The \var{TIME} reflects the Coordinated Universal Time as indicated by
the system clock running on the machine where the MOOSDB is
running. Speed is given in meters per second, heading is in degrees in
the range $[0, 360)$, depth is in meters, and the local x-y
  coordinates are also in meters. The source of information for these
  fields is the \msvar{NAV\_*} navigation MOOS variables such as
  \mvar{NAV\_SPEED}. The report also contains several components
  describing characteristics of the physical platform, and the state
  of the IvP Helm, described next.

\vspace{0.1in}
\noindent
If desired, \app{pNodeReporter} may be configured to use a different
variable than \mvar{NODE\_REPORT\_LOCAL} for its node reports, by
setting the configuration parameter \pvar{node\_report\_output} to
\var{MY\_REPORT} for example.  Most applications that subscribe to
node reports, subscribe to two variables, \mvar{NODE\_REPORT\_LOCAL}
and \mvar{NODE\_REPORT}. This is because node reports are meant to be
bridged to other MOOS communities (typically with \app{pShare} but not
necessarily). A node report should be broadcast only from the
community that generated the report. In practice, to ensure that node
reports that arrive in one community are not then sent out to other
communities, the node reports generated locally have the \var{\_LOCAL}
suffix, and when they are sent to other communities they are sent to
arrive with the new variable name, minus the suffix.

%===================================================================
\subsection{Helm Characteristics}
\label{sec_pnr_helm}

The node report contains one field regarding the current mode of the
helm, \var{MODE}. Typically the \app{pNodeReporter} and \app{pHelmIvP}
applications are running on the same platform, connected to the same
MOOSDB. When the helm is running, but disengaged, i.e., in manual
override mode, the \var{MODE} field in the node report simply reads
\var{"MODE=DISENGAGED"}. When or if the helm is detected to be not
running, the field reads \var{"MODE=NOHELM-SECS"}, where \var{SECS} is
the number of seconds since the last time \var{pNodeReporter} detected
the presence of the helm, or \var{"MODE=NOHELM-EVER"} if no helm
presence has ever been detected since \app{pNodeReporter} has been
launched. 

\vspace{0.1in}
\noindent
How does \app{pNodeReporter} know about the health or status of the
helm? It subscribes to two MOOS variables published by the helm,
\mvar{IVPHELM\_STATE} and \mvar{IVPHELM\_SUMMARY}. These are described
more fully in helm documentation, but below are typical example values:

\prevgreen
\begin{verbatim}
  IVPHELM_STATE   = "DRIVE"

  IVPHELM_SUMMARY = "iter=72,ofnum=1,warnings=0,time=127349406.22,solve_time=0.00,
                     create_time=0.00,loop_time=0.00,var=course:209.0,var=speed:1.2,
                     halted=false,running_bhvs=none,modes=MODE@ACTIVE:LOITERING,
                     active_bhvs=loiter$17.8$100.00$9$0.04$0/0,completed_bhvs=none
                     idle_bhvs=waypt_return$17.8$0/0:station-keep$17.8$n/a
\end{verbatim}
\postverb

\noindent
The \mvar{IVPHELM\_STATE} variable is published on each iteration of
the \app{pHelmIvP} process regardless of whether the helm is in manual
override (\var{"PARK"}) mode or not, and regardless of whether the
value of this variable has changed between iterations. It is
considered the "heartbeat" of the helm. This is the variable monitored
by \app{pNodeReporter} to determine whether a \var{"NOHELM"} message
is warranted. By default, a period of five seconds is used as a
threshold for triggering a \var{"NOHELM"} warning. This value may be
changed by setting the \pvar{nohelm\_threshold} configuration
parameter.

\vspace{0.1in}
\noindent
When the helm is indeed engaged, i.e., not in manual override mode,
the value of \mvar{IVPHELM\_STATE} posting simply reads \var{"DRIVE"},
but the helm further publishes the \mvar{IVPHELM\_SUMMARY} variable
similar to the above example. If the user has chosen to configure the
helm using hierarchical mode declarations (as described in helm
documentation), the \mvar{IVPHELM\_SUMMARY} posting will include a
component such as \var{"modes=MODE@ACTIVE:LOITERING"} as above. This
value is then included in the node report by \app{pNodeReporter}. If
the helm is not configured with hierarchical mode declarations, the
node report simply reports \var{"MODE=DRIVE"}.

%===================================================================
\subsection{Custom Rider Augmentation of the Node Report}
\label{sec_pnr_rider}

A node report typically is limited to the components shown in the
Section \ref{sec_pnr_nrep}, e.g., vehicle heading, speed, and
position.  These components are derived from the MOOS variables
\mvar{NAV\_HEADING}, \mvar{NAV\_SPEED}, \mvar{NAV\_LAT} and
\mvar{NAV\_LONG}.

\vspace{0.1in}
\noindent
A {rider} is a custom augmentation of the node report, resulting in
additional param=value pairs in the outgoing node report. There are
{\em static} riders, configured in the mission file, and {\em dynamic}
riders with values filled in at run time, where the source is a named
MOOS variable, configured in the mission file.

%-------------------------------------------------------------------
\subsubsection{Static Riders}
\label{sec_pnr_rider_stat}

A {\em static} rider is set in the mission file, typically for values that
are known prior to launch time, and do not change during the course
of the mission. Post Release 24.8, this is possible with the
\pvar{platform\_aspect} configuration parameter: For example:

\vspace{0.1in}
\begin{fileverb}
  platform_aspect = ID=439                                   
  platform_aspect = FUEL_TYPE=diesel
\end{fileverb}
\vspace{0.1in}

\noindent
This will result in the string \var{"ID=439,FUEL\_TYPE=diesel"} added
to all outgoing node reports.

\vspace{0.1in}
\noindent
Of course the following is possible too: 

\vspace{0.1in}
\begin{fileverb}
  platform_aspect = ID=$(ID)                    
\end{fileverb}
\vspace{0.1in}

\noindent
In this case presumably the \var{\$(ID)} macro is filled in at launch
time with a utility like \app{nsplug}.

\vspace{0.1in}
\noindent
Note: if two \pvar{platform\_aspect} configurations are made with the
same lefthand component, the second line will overwrite the first, and
there will be no warning.

%-------------------------------------------------------------------
\subsubsection{Dynamic Riders}
\label{sec_pnr_rider_dyn}

\vspace{0.1in}
\noindent
A {\em dynamic} rider is a param=value component where the value
changes dynamically at run time.  For example, if there are MOOS
variables \mvar{ENGINE\_TEMP}, or \mvar{FUEL\_LEVEL}, a user may wish
to include these in a node report. The last part of the node report
may look like \var{ETMP=145.32,FUEL=84.5}.

\vspace{0.1in}
\noindent
Post Release 24.8, this can be done with the \pvar{rider} configuration
parameter. Each rider contains (a) a MOOS variable, (b) the field name
in the node report, (c) the frequency at which it is include in node reports,
and (d) the precision, if the value is numerical. Continuing with the above
two examples, the configuration would like:

\vspace{0.1in}
\begin{fileverb}
  rider = var=ENGINE_TEMP, rfld=ETMP, policy=always, prec=2
  rider = var=FUEL_LEVEL, rfld=FUEL, policy=always, prec=1
\end{fileverb}
\vspace{0.1in}

\noindent
The \var{var} component names the MOOS variable to watch. The \var{rfld}
component names the "rider field", i.e., the field in the node report.
The policy component indicates how often it should be included in the
node report. If set to {\em always}, it will be in every report. If set to
{\em updated}, it will be include in reports only when the value
changes. If set to {\em 15}, it will be included only once every 15
seconds. If set to {\em updated+15}, it will be included immediately if the
value is updated, or otherwise once every 15 seconds. The \var{prec} component
names the precision if the value is numerical. A value of say 3, will be
posted with three digits after the decimal.

%===================================================================
\subsection{Enabling Sparse Node Report Intervals}
\label{sec_pnr_extrap}

By default, a node report is generated on each iteration of
\app{pNodeReporter}.  In certain situations a reduction in the
frequency may be appropriate. Each node report contributes both to the
local alog file size, and consumes inter-vehicle communications
bandwidth. If the vehicle is traversing a long straight leg, with
little to no deviation in heading or speed, the vehicle position can
be inferred by extrapolation. The node report frequency can perhaps be
reduced from say 4Hz, to 0.5Hz.

\vspace{0.1in}
\noindent
Extrapolation is used in two parts:

\begin{packed_itemize}
\item The sender of reports, \app{pNodeReporter}, extrapolates from
  the last posted report, for the time since the last posted report,
  and compares the difference. If the difference between the extrapolated
  position and the actual current position exceeds a configured threshold,
  then a node report with the current position is posted. 
\item The receiver of reports, e.g., other vehicles, or
  \app{pMarineViewer}, or similar, use extrapolation from the last
  received node report to update local vehicle position state.
\end{packed_itemize}

\vspace{0.1in}
\noindent
The following configuration parameters may be used to reduce the frequency
of node reports:

\vspace{0.1in}
\noindent
The \pvar{extrap\_enabled} parameter must set to \var{true} to enable
reduced posting frequency through extrapolation. By default it is set to
\var{false}.

\vspace{0.1in}
\noindent
The \pvar{extrap\_pos\_thresh} parameter is a value given in
meters. The current vehicle position is compared against the position
extrapolated from the last reported position assuming the heading in
the last reported position, and the time since the last reported
position. If the distance between these two positions is greater than
this threshold, a node report is generated regardless of other
configuration parameters.

\vspace{0.1in}
\noindent
The \pvar{extrap\_hdg\_thresh} parameter is a value given in
degrees. The current vehicle heading is compared to the heading in the
most recently posted node report. If the difference in heading exceeds
the threshold, then a node report is generated regardless of other
configuration parameters.

\vspace{0.1in}
\noindent
The \pvar{extrap\_max\_gap} parameter is a value given in seconds. The
current time is compared to the time of the most recently posted node
report. If the difference in time exceeds the threshold, then a node
report is generated regardless of other configuration parameters.

\vspace{0.1in}
\noindent
The default values for these configuration parameters are: 

\vspace{0.1in}
\begin{fileverb}
  extrap_enabled    = false
  extrap_pos_thresh = 0.25    // meters
  extrap_hdg_thresh = 1       // degrees
  extrap_max_gap    = 5       // seconds
\end{fileverb}
\vspace{0.1in}


%===================================================================
\subsection{Platform Characteristics}
\label{sec_pnr_plat}

The node report contains four fields regarding the platform
characteristics, \var{NAME}, \var{TYPE}, \var{LENGTH}, and
\var{BEAM}. The name of the platform is equivalent to the name of the
MOOS community within which \app{pNodeReporter} is running. The MOOS
community is declared as a global MOOS parameter (outside any given
process' configuration block) in the \var{.moos} mission file. The
\var{TYPE}, \var{LENGTH}, and \var{BEAM} parameters are set in the
\app{pNodeReporter} configuration block.

\vspace{0.1in}
\noindent
Example:

\prevblue
\begin{verbatim}
  platform_length = 16              // meters
  platform_beam   = 15              // meters
  platform_type   = kayak
  platform_color  = dodger_blue
\end{verbatim}
\postverb

\vspace{0.1in}
\noindent
If the platform type is known, but no information about the platform
length is known, certain rough default values may be used if the
platform type matches one of the following: \var{"kayak}" maps to 4
meters, \var{"mokai"} maps to 4 meters, \var{"uuv"} maps to 4 meters,
\var{"auv"} maps to 4 meters, \var{"ship"} maps to 18 meters,
\var{"glider"} maps to 3 meters.

%===================================================================
\subsection{Dealing with Local versus Global Coordinates}
\label{sec_pnr_crossfill}

A primary component of the node report is the current position of the
vehicle. The \app{pNodeReporter} application subscribes for the
following MOOS variables to garner this information:
\var{NAV\_X}, \var{NAV\_Y} in local coordinates, and the pair
\var{NAV\_LAT}, \var{NAV\_LONG} in global coordinates. These two pairs
should be consistent, but what if they are not? And what if
\var{pNodeReporter} is receiving mail for one pair but not the other?
Four distinct policy choices are supported, set in the configuration
parameter \pvar{crossfill\_policy}:

\begin{packed_itemize}
\item The default policy: node reports include exactly what is
  given. If \mvar{NAV\_X} and \mvar{NAV\_Y} are being received only,
  then there will be no entry in the node report for global
  coordinates, and vice versa. If both pairs are being received, then
  both pairs are reported. No attempt is made to check or ensure that
  they are consistent.  This is the default policy, equivalent to the
  configuration \pvar{crossfill\_policy}\psvar{=literal}.

\item If one of the two pairs is not being received,
  \app{pNodeReporter} will fill in the missing pair from the
  other. This policy can be chosen with the configuration
  \pvar{cross\_fill\_policy}\psvar{=fill-empty}.

\item If \mvar{NAV\_LAT} and \mvar{NAV\_LONG} are being received,
  \app{pNodeReporter} will use these in its report, {\em and} convert
  the global coordinates to local coordinates, and use these converted
  coordinates in its report, essentially disregarding \mvar{NAV\_X} and
  \mvar{NAV\_Y} if they are also being received. This policy can be
  chosen with the configuration \pvar{cross\_fill\_policy}\psvar{=global}.
  This is available in the next release after Release 19.8.x.

\item If one of the two pairs has been received more recently, the
  older pair is updated by converting from the other pair. The older
  pair may also be in a state where it has never been received.  This
  policy can be chosen with the configuration
  \pvar{cross\_fill\_policy}\psvar{=fill-latest}.
\end{packed_itemize}

\vspace{0.1in}
\noindent
An additional configuration param, \pvar{coord\_global\_policy},
accepts a Boolean value, by default \var{false}. When it is set to
true, it will mask out the x/y portion of the node report, leaving
only the lat/lon portion. The manner in which the lat/lon is set is
determined by the \pvar{crossfill\_policy} configuration parameter.


%===================================================================
\subsection{Processing Alternate Navigation Solutions}
\label{sec_pnr_altnav}

Under normal circumstances, node reports are generated reflecting the
current navigation solution as defined by the incoming \var{NAV\_*}
variables. The \app{pNodeReporter} application can handle the case
where the vehicle also publishes an alternate navigation solution, as
defined by a sister set of incoming MOOS variables separate from the
\var{NAV\_*} variables. In this case \app{pNodeReporter} will monitor
both sets of variables and may generate {\em two} node reports on each
iteration. The following two configuration parameters are needed to
activate this capability:

\prevblue
\begin{verbatim}
  alt_nav_prefix = &lt;prefix&gt;      // example: NAV_GT_
  alt_nav_name   = &lt;node-name&gt;   // example: _GT
  alt_nav_group  = &lt;group-name&gt;  // example: ground_truth (Post R.19.8.x)
\end{verbatim}
\postverb

\noindent
The configuration parameter, \pvar{alt\_nav\_prefix}, names a prefix
for the alternate incoming navigation variables. For example,
\pvar{alt\_nav\_prefix}\psvar{=NAV\_GT\_} would result in
\app{pNodeReporter} subscribing for \mvar{NAV\_GT\_X},
\mvar{NAV\_GT\_Y} and so on. A separate vehicle state would be
maintained internally based on this alternate set of navigation
information and a second node report would be generated.
The \pvar{alt\_nav\_group} allows the alt nav node report to have
a different group name than the baseline node report. If not specified,
the group names will match. This feature was introduced after
Release 19.8.x.

\vspace{0.1in}
\noindent
A second node report would be published under the same MOOS variable,
\mvar{NODE\_REPORT\_LOCAL}, but the \var{NAME} component of the report
would be distinct based on the value provided in the
\pvar{alt\_nav\_name} parameter. If a name is provided that does not
begin with an underscore character, that name is used. If the name
does begin with an underscore, the name used in the report is the
otherwise configured name of the vehicle plus the suffix.

%===================================================================
\subsection{Publishing Node Reports in JSON Format}
\label{sec_pnr_json}

Post Release 24.8, node reports may optionally be published in JSON
format. Either (a) the \mvar{NODE\_REPORT\_LOCAL} message can be made
in JSON format, or (b) a second MOOS variable can be specified to be
additionally published in JSON format. The deserialization function,
converting node report strings into a C++ record, will auto-detect the
format. All apps in MOOS-IvP ingesting node reports use this function.

\vspace{0.1in}
\noindent
To publish \mvar{NODE\_REPORT\_LOCAL} in JSON format, simply use:

\vspace{0.1in}
\begin{fileverb}
  json_report = true
\end{fileverb}
\vspace{0.1in}

\noindent
If the value of the argument is any string other than \var{true}, or
\var{false}, case insensitive, the value is interpreted to mean a MOOS
variable to which a second node report will be published in JSON format.
For example, consider the below configuration:

\vspace{0.1in}
\begin{fileverb}
  json_report = NODE_REPORT_JSON
\end{fileverb}
\vspace{0.1in}

\noindent
Both the comma-separated-pair (CSP) format, and JSON format will be published:

\vspace{0.1in}
\begin{consoleverb}
NODE_REPORT_JSON = {"NAME":"abe","SPD":1.9,"HDG":190.45,"DEP":0,"LAT":43.82472523,
    "LON":-70.33059595,"TYPE":"kayak","COLOR":"yellow",
    "MODE":"MODE@ACTIVE:LOITERING","ALLSTOP":"clear",
    "INDEX":113,"YAW":-1.753119,"TIME":17398343683.8,"LENGTH":4}

NODE_REPORT_LOCAL = NAME=abe,SPD=1.9,HDG=190.45,DEP=0,LAT=43.82472523,
    LON=-70.33059595,TYPE=kayak,COLOR=yellow,
    MODE=MODE@ACTIVE:LOITERING,ALLSTOP=clear,
    INDEX=113,YAW=-1.753119,TIME=17398343683.8,LENGTH=4
\end{consoleverb}
\vspace{0.1in}

%===================================================================
\section{The Optional Blackout Interval Option}
%===================================================================
\label{sec_pnr_blackout}

Under normal circumstances, the \app{pNodeReporter} application will
post a node report once per iteration, the gap between postings being
determined solely by the \pvar{app\_tick} parameter (Figure
\ref{pnr_gap_one}). However, there are times when it is desirable to
add an artificial delay between postings. Node reports are typically
only useful as information sent to another node, or to a shoreside
computer rendering fielded vehicles, and there are often dropped node
report messages due to the uncertain nature of communications in the
field, whether it be acoustic communications, WiFi, or satellite link.

\vspace{0.1in}
\noindent
Applications receiving node reports usually implement provisions that
take dropped messages into account. A collision-avoidance or
formation-following behavior, or a contact manager, may extrapolate a
contact position from its last received position and trajectory.  A
shoreside command-and-control GUI such as \app{pMarineViewer} may
render an interpolation of vehicle positions between node reports. To
test the robustness of applications needing to deal with dropped
messages, a way of simulating the dropped messages is desired. One way
is to add this to the simulation version of whatever communications
medium is being used. For example, there is an acoustic communications
simulator where the dropping of messages may be simulated, where the
probability of a drop may even be tied to the range between
vehicles. Another way is to simply simulate the dropped message at the
source, by adding delay to the posting of reports by
\app{pNodeReporter}.

\vspace{0.1in}
\noindent
By setting the \pvar{blackout\_interval} parameter, \app{pNodeReporter}
may be configured to ensure that a node report is not posted until
{\em at least} the duration specified by this parameter has elapsed, 
as shown in Figure \ref{pnr_gap_two}.


\vspace{0.15in}
\begin{figure}[H]
  \centering 
  \includegraphics[width=0.8\textwidth]{figures/pnr_interval1.png}
  \caption{{\bf Normal schedule of node report postings}: The
    \vvar{pNodeReporter} application will post node reports once per
    application iteration. The duration of time between postings is
    directly tied to the frequency at which \vvar{pNodeReporter} is
    configured to run, as set by the standard MOOS \vvar{AppTick}
    parameter.}
\label{pnr_gap_one}
\end{figure}
\vspace{0.15in}

\vspace{0.15in}
\begin{figure}[H]
  \centering 
  \includegraphics[width=0.8\textwidth]{figures/pnr_interval2.png}
  \caption{{\bf The optional blackout interval parameter:} The
    schedule of node report postings may be altered by the setting the
    \vvar{BLACKOUT\_INTERVAL} parameter. Reports will not be posted
    until at least the time specified by the blackout interval has
    elapsed since the previous posting.}
\label{pnr_gap_two}
\end{figure}

\vspace{0.1in}
\noindent
An element of unpredictability may be added by specifying a value for
the \pvar{blackout\_variance} parameter. This parameter is given in
seconds and defines an interval $[-t, t]$ from which a value is chosen
with uniform probability, to be added to the duration of the blackout
interval. This variation is re-calculated after each interval
determination. The idea is depicted in Figure \ref{pnr_gap_three}.

\vspace{0.15in}
\begin{figure}[H]
  \centering 
  \includegraphics[width=0.8\textwidth]{figures/pnr_interval3.png}
  \caption{{\bf Blackout intervals with varying duration:} The
    duration of a blackout interval may be configured to vary randomly
    within a user-specified range, specified in the
    \pvar{blackout\_variance} parameter.}
\label{pnr_gap_three}
\end{figure}

\vspace{0.1in}
\noindent
Message dropping is typically tied semi-predictably to characteristics
of the environment, such as range between nodes, water temperature or
platform depth, an so on. This method of simulating dropped messages
captures none of that. It is however simple and allows for easily
proceeding with the testing of applications that need to deal with the
dropped messages.

%===================================================================
\section{Configuration Parameters for pNodeReporter}
%===================================================================

The following parameters are defined for \app{pNodeReporter}. A
more detailed description is provided in other parts of this
section. Parameters having default values are indicated so in
parentheses.

\vspace{0.15in}
\begin{listing}{Configuration Parameters for pNodeReporter}
\label{lst_pmv_params}
\renewcommand{\arraystretch}{1.1}
\begin{longtable}{rp{0.76\textwidth}} 

  \pvar{alt\_nav\_prefix}: &amp; Source for processing alternate nav
  reports.  Section \ref{sec_pnr_altnav}. \\

  \pvar{alt\_nav\_group}: &amp; Group associated with node reports
  generated for alternate nav node reports. Introduced after
  Release 19.8.x. Section \ref{sec_pnr_altnav}. \\

  \pvar{alt\_nav\_name}: &amp; Node name in posting alternate nav
   reports. Section \ref{sec_pnr_altnav}. \\

  \pvar{blackout\_interval}: &amp; Minimum duration, in seconds, between
  reports (0). Section \ref{sec_pnr_blackout}. \\

  \pvar{blackout\_variance}: &amp; Variance in uniformly random blackout
  duration. Legal values: any non-negative value. The default is
  zero. Section \ref{sec_pnr_blackout}. \\

  \pvar{coord\_policy\_global}: &amp; If true (default is false), then only
  lat/lon coordinates are published in the node report; no local
  x/y coordinates.  Section \ref{sec_pnr_crossfill}. \\

  \pvar{crossfill\_policy}: &amp; Policy for handling local versus
  global nav reports (\var{"literal"}).  Section
  \ref{sec_pnr_crossfill}. \\

  \pvar{extrap\_enabled}: &amp; If \var{true} (the default is
  \var{false}), then a node report is not generated on every
  iteration, but can instead be held back for some time, assuming the
  consumers of the node reports are capable of extrapolating the
  vehicle position. This can reduce network traffic and log file size,
  but must be used with care and when sure that consumers are capable
  of extrapolation.  Section \ref{sec_pnr_extrap}. \\

  \pvar{extrap\_hdg\_thresh}: &amp; If extrapolation is enabled, this
  parameter, in degrees, determines a threshold for posting a new node
  report. If the vehicle heading has changed by degrees set here, a
  new node report must be posted. The default is 1 degree. Section
  \ref{sec_pnr_extrap}. \\

  \pvar{extrap\_max\_gap}: &amp; If extrapolation is enabled, this
  parameter, in seconds, determines a threshold for posting a new node
  report. If node report has not been published in the time set here,
  a new node report must be posted. The default is 5 seconds. Section
  \ref{sec_pnr_extrap}. \\

  \pvar{extrap\_pos\_thresh}: &amp; If extrapolation is enabled, this
  parameter, in meters, determines a threshold for posting a new node
  report. If the vehicle position has changed by this distance, a new
  node report must be posted. The default is \var{0.25}
  meters. Section \ref{sec_pnr_extrap}. \\

  \pvar{json\_report}: &amp; If \var{true}, the node report will be
  published in JSON format. If set to something other than true, e.g.,
  \mvar{FOOBAR}, a second node report will be published, in JSON
  format, to \mvar{FOOBAR}, and the normal node report in CSP format
  will be published as normal.  Section \ref{sec_pnr_json}. \\

  \pvar{node\_report\_output}: &amp; MOOS variable used for the node
  report (\mvar{NODE\_REPORT\_LOCAL}). Section \ref{sec_pnr_nrep}. \\

  \pvar{nav\_grace\_period}: &amp; A duration, in seconds, before a run
  warning is posted due to mission navigation information, e.g,
  \mvar{NAV\_LAT} or \mvar{NAV\_LONG}. \\

  \pvar{nohelm\_threshold}: &amp; Seconds after which a quiet helm is
  reported as AWOL. Legal values: any non-negative value. The default
  is 5 seconds. Section \ref{sec_pnr_helm}. \\

  \pvar{platform\_aspect}: &amp; A custom param=value pair to be include
  in all node reports. Section \ref{sec_pnr_rider_stat}. \\

  \pvar{platform\_beam}: &amp; The reported beam length (from side-to-side
  at the widest point) of the platform in meters. Legal values: any
  non-negative value. The default is zero. Section
  \ref{sec_pnr_plat}. \\

  \pvar{platform\_length}: &amp; The reported length of the platform in
  meters. Legal values: any non-negative value. The default is
  zero. Section \ref{sec_pnr_plat}. \\

  \pvar{plat\_report\_output}: &amp; The Platform report MOOS
  variable. Legal values: conventions for MOOS variable names. The
  default is \mvar{PLATFORM\_REPORT\_LOCAL}. Section
  \ref{sec_pnr_prep}. \\

  \pvar{plat\_report\_input}: &amp; A component of the optional platform
  report. Section \ref{sec_pnr_prep}. \\

  \pvar{platform\_color}: &amp; A hint on how to render the vehicle in a
  GUI application like \app{pMarineViewer} or \app{alogview}.
  Introduced in Release 16.5. Section \ref{sec_pnr_plat}. \\

  \pvar{platform\_type}: &amp; The reported type of the platform. Legal
  values: any string. The default is \var{"unknown"}. Section
  \ref{sec_pnr_plat}. \\

  \pvar{paused}: &amp; If true, posting of reports is suspended.
  The default is \var{"false"}. With release 15.3. \\

  \pvar{rider}: &amp; A custom augmentation of the node report can be configured,
  by registering for one or more MOOS variables and reformatting the output
  and tagging onto (riding) the end of a node report. Post 24.8. See
  Section \ref{sec_pnr_rider_dyn}. \\

\end{longtable}
\end{listing}

%===================================================================
\subsection*{An Example MOOS Configuration Block}

An example MOOS configuration block is provided in Listing
\ref{lst_pnr_econfig} below.  To see an example MOOS configuration
block from the console, enter the following:

\begin{consoleverb}
 $ pNodeReporter --example or -e
\end{consoleverb}

\noindent
This will show the output shown in Listing \ref{lst_pnr_econfig} below.

\vspace{0.2in}
\begin{listing}{Example configuration of pNodeReporter}
\label{lst_pnr_econfig}
\footnotesize
\begin{verbatim}
   1  =============================================================== 
   2  pNodeReporter Example MOOS Configuration                        
   3  =============================================================== 
   4  Blue lines: Default configuration                        
   5                                                                  
   6  ProcessConfig = pNodeReporter                                   
   7  {                                                               
   8    AppTick   = 4                                                 
   9    CommsTick = 4                                                 
  10                                                                  
  11    // Configure key aspects of the node                          
  12    platform_type      = glider   // or {uuv,auv,ship,kayak}   
  13    platform_length    = 8        // meters.  Range [0,inf)    
  14                                                                  
  15    // Configure optional blackout functionality                  
  16    blackout_interval  = 0        // seconds. Range [0,inf)    
  17                                                                  
  18     // Configure the optional platform report summary            
  19    plat_report_input  = COMPASS_HEADING, gap=1                   
  20    plat_report_input  = GPS_SAT, gap=5                           
  21    plat_report_input  = WIFI_QUALITY, gap=1                      
  22    plat_report_output = PLATFORM_REPORT_LOCAL                    
  23                                                                  
  24    // Configure the MOOS variable containg the node report       
  25    node_report_output = NODE_REPORT_LOCAL                        
  26                                                                  
  27    // Threshold for conveying an absense of the helm             
  28    nohelm_threshold   = 5        // seconds                   
  39                                                                  
  30    // Policy for filling in missing lat/lon from x/y or v.versa  
  31    // Valid policies: [literal], fill-empty, use-latest, global
  32    crossfill_policy   = literal
  33                                                                  
  34    // Configure monitor/reporting of dual nav solution           
  35    alt_nav_prefix     = NAV_GT                                   
  36    alt_nav_name       = _GT                                      
  37  }                                                        
\end{verbatim}
\end{listing}
\normalsize

%===================================================================
\section{Publications and Subscriptions for pNodeReporter}
%===================================================================
%\index{pNodeReporter!Publications and Subscriptions}
%\index{Publications and Subscriptions!pNodeReporter}
\label{sec_pnr_interface}

The interface for \app{pNodeReporter}, in terms of publications and 
subscriptions, is described below. This same information may also be
obtained from the terminal with:

\begin{consoleverb}
 $ pNodeReporter --interface or -i
\end{consoleverb}

%===================================================================
\subsection{Variables Published by pNodeReporter}
\label{sec_pnr_pubs}

The primary output of pNodeReporter to the MOOSDB is the node
report and the optional platform report:

\begin{packed_itemize}[2]
\item \mvar{APPCAST}: Contains an appcast report identical to the
  terminal output. Appcasts are posted only after an appcast request
  is received from an appcast viewing utility.

\item \mvar{NODE\_REPORT\_LOCAL}: Primary summary of the node's
  navigation and helm status. Section \ref{sec_pnr_nrep}.

\item \mvar{PLATFORM\_REPORT\_LOCAL}: Optional summary of certain
  platform characteristics. Section \ref{sec_pnr_plat}.
\end{packed_itemize}

%===================================================================
\subsection{Variables Subscribed for by pNodeReporter}
\label{sec_pnr_subs}

Variables subscribed for by \app{pNodeReporter} are summarized below.
A more detailed description of each variable follows. In addition to
these variables, any MOOS variable that the user requests to be
included in the optional \mvar{PLATFORM\_REPORT} will also be
automatically subscribed for.

\begin{packed_itemize}[1]
\item \mvar{APPCAST\_REQ}: A request to generate and post a new
  apppcast report, with reporting criteria, and expiration.

\item \mvar{IVPHELM\_STATE}: A indicator of the helm state produced by
  \app{pHelmIvP}, e.g., \var{"PARK"}, \var{"DRIVE"} \var{"DISABLED"},
  or \var{"STANDBY"}.

\item \mvar{IVPHELM\_ALLSTOP}: A indicator of the helm allstop produced by
  \app{pHelmIvP}, e.g., \var{"clear"}, or a reason why the vehicle is
  at zero speed.

\item \mvar{IVPHELM\_SUMMARY}: A summary report produced by the IvP
  Helm (pHelmIvP).
 
\item \mvar{NAV\_X}: The ownship vehicle position on the $x$ axis of
  local coordinates.

\item \mvar{NAV\_Y}: The ownship vehicle position on the $y$ axis of
  local coordinates. 

\item \mvar{NAV\_LAT}: The ownship vehicle position on the $y$ axis of
  global coordinates. 

\item \mvar{NAV\_LONG}: The ownship vehicle position on the $x$ axis
  of global coordinates.

\item \mvar{NAV\_HEADING}: The ownship vehicle heading in degrees. 
  
\item \mvar{NAV\_YAW}: The ownship vehicle yaw in radians. 
     
\item \mvar{NAV\_SPEED}: The ownship vehicle speed in meters per second. 

\item \mvar{NAV\_DEPTH}: The ownship vehicle depth in meters. 
 
\item \mvar{PNR\_PAUSE}: Allows the paused state to be set or
  toggled. Acceptable values are \var{"true"} \var{"false"}
  \var{"toggle"}. With release 15.3.
 
\end{packed_itemize}

\noindent
If \app{pNodeReporter} is configured to handle a second navigation
solution as described in Section \ref{sec_pnr_altnav}, the
corresponding additional variables described in that section will also
be automatically subscribed for.

%===================================================================
\subsection{Command Line Usage of pNodeReporter}
\label{sec_pnr_cmdline}
%\index{Command Line Usage!pNodeReporter}
%\index{pNodeReporter!Command Line Usage}
%\index{Configuration Parameters!pNodeReporter}
%\index{pNodeReporter!Configuration Parameters}

The \var{pNodeReporter} application is typically launched as a part
of a batch of processes by pAntler, but may also be launched from the
command line by the user. The basic command line usage for the
\var{pNodeReporter} application is the following:

\vspace{0.1in}
\begin{listing}{Command line usage for the \app{pNodeReporter} application}
\label{pnr_usage}
\footnotesize
\begin{verbatim}
  1  Usage: pNodeReporter file.moos [OPTIONS]               
  2                                                            
  3  Options:                                                  
  4    --alias=&lt;ProcessName&gt;                                   
  5        Launch pNodeReporter with the given process name    
  6        rather than pNodeReporter.                          
  7    --example, -e                                           
  8        Display example MOOS configuration block.           
  9    --help, -h                                              
 10        Display this help message.                          
 11    --version,-v                                            
 12        Display the release version of pNodeReporter.      
\end{verbatim}
\end{listing}
\normalsize

%===================================================================
\section{The Optional Platform Report Feature}
%===================================================================
\label{sec_pnr_prep}

The \app{pNodeReporter} application allows for the optional reporting
of another user-specified list of information. This report is made by
posting the \mvar{PLATFORM\_REPORT\_LOCAL} variable. An alternative
variable name may be used by setting the \mvar{PLAT\_REPORT\_SUMMARY}
configuration parameter. This report may be configured by specifying
one or more components in the \app{pNodeReporter} configuration
block, of the following form:

\prevblue
\begin{verbatim}
   plat_report_input = &lt;variable&gt;, gap=&lt;duration&gt;, alias=&lt;variable&gt;
\end{verbatim}
\postverb

\noindent
If no component is specified, then no platform report will be
posted. The \var{&lt;variable&gt;} element specifies the name of a MOOS
variable.  This variable will be automatically subscribed for by
\app{pNodeReporter} and included in (not necessarily all) postings of
the platform report. If the variable \msvar{BODY\_TEMP} is specified, a
component of the report may contain \msvar{"BODY\_TEMP=98.6"}. An alias
for a MOOS variable may be specified. For example, \var{alias=T}, for
the \msvar{BODY\_TEMP} component would result in \var{"T=98.6"} in the
platform report instead.

\vspace{0.1in}
\noindent
How often is the platform report posted? Certainly it will not be
posted any more often than the \pvar{apptick} parameter allows, but it
may be posted far more infrequently depending on the user
configuration and how often the values of its components are changing.
The platform report is posted only when one or more of its components
requires a re-posting. A component requires a re-posting only if (a)
its value has changed, {\em and} (b) the time specified by its gap
setting has elapsed since the last platform report that included that
component. When a \mvar{PLATFORM\_REPORT\_LOCAL} posting is made, only
components that required a posting will be included in the report.

\vspace{0.1in}
\noindent
The wide variation in configurations of the platform report allow for
reporting information about the node that may be very specific to the
platform, not suitable for a general-purpose node report. As an
example, consider a situation where a shoreside application is running
to monitor the platform's battery level and whether or not the payload
compartment has suffered a breach, i.e., the presence of water is
detected inside. A platform report could be configured as follows:

\prevblue
\begin{verbatim}
   plat_report_input = ACME_BATT_LEVEL, gap=300, alias=BATTERY_LEVEL
   plat_report_input = PAYLOAD_BREACH
\end{verbatim}
\postverb

\noindent
This would result in an initial posting of:

\prevgreen
\begin{verbatim}
   PLATFORM_REPORT_LOCAL = "platform=alpha,utc_time=1273510720.99,BATTERY_LEVEL=97.3,
                           PAYLOAD_BREACH=false"             
\end{verbatim}
\postverb

\noindent
In this case, the platform uses batteries made by the ACME Battery
Company and the interface to the battery monitor happens to publish
its value in the variable \msvar{ACME\_BATT\_LEVEL}, and the software on
the shoreside that monitors all vehicles in the field accepts the
generic variable \msvar{BATTERY\_LEVEL}, so the alias is used. It is
also known that the ACME battery monitor output tends to fluctuate a
percentage point or two on each posting, so the platform report is
configured to include a battery level component no more than once
every five minutes, (\var{gap=300}). The MOOS process monitoring the
indication of a payload breach is known to have few false alarms and
to publish its findings in the variable \msvar{PAYLOAD\_BREACH}. Unlike
the battery level which has frequent minor fluctuations and degrades
slowly, the detection of a payload breach amounts to the flipping of a
Boolean value and needs to be conveyed to the shoreside as quickly as
possible.  Setting \var{gap=0}, the default, ensures that a platform
report is posted on the very next iteration of \app{pNodeReporter},
presumably to be read by a MOOS process controlling the platform's
outgoing communication mechanism.

%===================================================================
\section{An Example Platform Report Configuration Block for pNodeReporter}
%===================================================================
%\index{pNodeReporter}
%\index{pNodeReporter!Configuration Parameters}
%\index{Configuration Parameters!pNodeReporter}

Listing \ref{lst_pnr_econfig_platrpt} below shows an example
configuration block for \app{pNodeReporter} where an extensive
platform report is configured to report information about the
autonomous kayak platform to support a ``kayak dashboard'' display
running on a shoreside computer. Most of the components in the
platform report are specific to the autonomous kayak platform, which
is precisely why this information is included in the platform report,
and not the node report.

\vspace{0.1in}
\begin{listing}{An example pNodeReporter configuration block}
\label{lst_pnr_econfig_platrpt}
\footnotesize
\begin{verbatim}
  1  //------------------------------------------------------------------
  2  // pNodeReporter config block
  3  
  4  ProcessConfig = pNodeReporter
  5  {
  6    AppTick	 = 2
  7    CommsTick = 2
  8   
  9    platform_type       = KAYAK   
 10    platform_length     = 3.5     // Units in meters
 11    nohelm_thresh       = 5       // The default
 12    blackout_interval   = 0       // The default
 13    blackout_variance   = 0       // The default
 14
 15    node_report_output  = NODE_REPORT_LOCAL        // The default
 16    plat_report_output  = PLATFORM_REPORT_LOCAL    // The default
 17
 18    plat_report_input = COMPASS_PITCH, gap=1
 19    plat_report_input = COMPASS_HEADING, gap=1
 20    plat_report_input = COMPASS_ROLL, gap=1
 21    plat_report_input = DB_UPTIME, gap=1
 22    plat_report_input = COMPASS_TEMPERATURE, gap=1, alias=COMPASS_TEMP
 23    plat_report_input = GPS_MAGNETIC_DECLINATION, gap=10, alias=MAG_DECL
 24    plat_report_input = GPS_SAT, gap=5
 25    plat_report_input = DESIRED_RUDDER, gap=0.5
 26    plat_report_input = DESIRED_HEADING, gap=0.5
 27    plat_report_input = DESIRED_THRUST, gap=0.5
 28    plat_report_input = GPS_SPEED, gap=0.5
 29    plat_report_input = DESIRED_SPEED, gap=0.5
 30    plat_report_input = WIFI_QUALITY, gap=0.5
 31    plat_report_input = WIFI_QUALITY, gap=1.0
 32    plat_report_input = MOOS_MANUAL_OVERRIDE, gap=1.0
 33  }
\end{verbatim}
\end{listing}
\normalsize

%===================================================================
\section{Measuring the Odometry Extent Per Mission Hash}
%===================================================================
\label{sec_pnr_mhash}

A new feature, {\em after} Release 22.8, is introduced to enable
\app{pNodeReporter} to post useful information to be logged with the
vehicle alog file. This coincides with the introduction of a {\em
  mission hash}. The mission hash is published by the shoreside and
shared to all vehicles and logged. It has the form:

\vspace{0.1in}
\begin{fileverb}
MISSION_HASH = mhash=221119-1255K-NEAR-MILK,utc=1668880538.69 
\end{fileverb}
\vspace{0.1in}

\noindent
The posting contains both the hash itself, \var{221119-1255K-NEAR-MILK},
and the UTC timestamp when the hash was created on the shoreside. The
first part of the hash reflects the time and date, \var{241119-1255},
Nov 19th, 2024, 12:55.  The second part of the hash is comprised of
randomly configured words that are easier to remember. The final
two-word part of the hash can be used as an alias in some
applications.

\vspace{0.1in}
\noindent
The shoreside generates the hash, and it cannot be ruled out that the
shoreside generates multiple hashes for a single vehicle alog file.
This can happen for example if the shoreside app, e.g.,
\app{pMarineViewer}, generating the mission hash, is re-started during
the vehicle deployment. In this case the vehicle alog file may have
multiple mission hashes, leading to confusion. This is where
\app{pNodeReporter} can help.

\vspace{0.1in}
\noindent
\app{pNodeReporter} will register for \mvar{MISSION\_HASH} and use an
odometer to track the maximum vehicle extent associated with this
hash. The {\em extent} is the maximum distance from the odometer
starting point, i.e., the farthest linear distance from the starting
point at any time in the mission. The node reporter will publish to
\mvar{PNR\_MHASH} whenever this maximum extent has reached a new max
value. If the \mvar{MISSION\_HASH} value should change mid-mission,
the \mvar{PNR\_MHASH} value will also change.


\vspace{0.1in}
\noindent
If the mission hash changes mid-mission, we may see a set of alog entries
from \app{pMarineViewer} along the lines of:

\vspace{0.1in}
\begin{fileverb}
14.853   PNR_MHASH  mhash=221119-1412M-GOLD-EPIC,ext=2.6
15.874   PNR_MHASH  mhash=221119-1412M-GOLD-EPIC,ext=3.9
16.897   PNR_MHASH  mhash=221119-1412M-GOLD-EPIC,ext=5.4
22.538   PNR_MHASH  mhash=221119-1412M-GOLD-EPIC,ext=6.9
23.560   PNR_MHASH  mhash=221119-1412M-GOLD-EPIC,ext=8.3
24.587   PNR_MHASH  mhash=221119-1412M-GOLD-EPIC,ext=9.5
26.119   PNR_MHASH  mhash=221119-1412M-GOLD-EPIC,ext=10.6
177.068  PNR_MHASH  mhash=221119-1413E-MAIN-KHAN,ext=12.1
178.093  PNR_MHASH  mhash=221119-1413E-MAIN-KHAN,ext=13.5
179.117  PNR_MHASH  mhash=221119-1413E-MAIN-KHAN,ext=14.9
180.129  PNR_MHASH  mhash=221119-1413E-MAIN-KHAN,ext=16.3
181.159  PNR_MHASH  mhash=221119-1413E-MAIN-KHAN,ext=17.8
182.172  PNR_MHASH  mhash=221119-1413E-MAIN-KHAN,ext=19.2
183.207  PNR_MHASH  mhash=221119-1413E-MAIN-KHAN,ext=20.4
184.228  PNR_MHASH  mhash=221119-1413E-MAIN-KHAN,ext=21.8
218.643  PNR_MHASH  mhash=221119-1413E-MAIN-KHAN,ext=23.2
219.682  PNR_MHASH  mhash=221119-1413E-MAIN-KHAN,ext=24.3
220.693  PNR_MHASH  mhash=221119-1413E-MAIN-KHAN,ext=25.4
222.219  PNR_MHASH  mhash=221119-1413E-MAIN-KHAN,ext=26.9
223.762  PNR_MHASH  mhash=221119-1413E-MAIN-KHAN,ext=28.3
225.317  PNR_MHASH  mhash=221119-1413E-MAIN-KHAN,ext=29.8
226.876  PNR_MHASH  mhash=221119-1413E-MAIN-KHAN,ext=31.1
\end{fileverb}
\vspace{0.1in}

\noindent
In this case the mission hash was changed sometime between the offset
times of $26.119$ and $177.068$. When \app{pNodeReporter} noticed that
the max extent distance accumulated while the mission hash was
\var{"MAIN-KHAN"} had exceeded 10.6, a new \mvar{PNR\_MHASH} posting was
made.

\vspace{0.1in}
\noindent
In a nutshell, if there was unfortunately more than one mission
hash received by a vehicle and logged in a single alog file, this
information can help determine which mission hash was the "real"
one. It should always be the hash associated with the final posting
to \mvar{PNR\_MHASH}. And this information can be obtained using a few
\app{aloggrep} switches:

\vspace{0.1in}
\begin{consoleverb}
  $ aloggrep file.alog --final --no_report PNR_MHASH
  226.876  PNR_MHASH    pNodeReporter   mhash=221119-1413E-MAIN-KHAN,ext=31.1
\end{consoleverb}
\vspace{0.1in}

\noindent
Or, to isolate the hash itself:

\vspace{0.1in}
\begin{consoleverb}
  $ aloggrep file.alog --final --format=val --subpat=mhash PNR_MHASH
  221119-1413E-MAIN-KHAN
\end{consoleverb}
\vspace{0.1in}

\noindent
The latter example is essentially the whole point of this feature: to
enable \app{aloggrep} to determine the most likely single mission hash
for a give alog file, even if multiple hashes exist. This tool can
then be used as a component of other scripts that are performing post-mission
log file archiving tasks.


\end{document}

</pre></body></html>