<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">%=====================================================================
\section{The StationKeep Behavior}
%=====================================================================
%\wikisec{grp=bhvsolo, file=BehaviorStationKeep,short=StationKeep Behavior}
\label{bhv_stationkeep}
%%\index{IvP Behaviors Implemented!\var{BHV\_StationKeep}}
%\index{StationKeep Behavior}

This behavior is designed to keep the vehicle at a given lat/lon or
x,y station-keep position by varying the speed to the station point as
a linear function of its distance to the point. The parameters allow
one to choose the two distances between which the speed varies
linearly, the range of linear speeds, and a default transit speed if
the vehicle is outside the outer radius.

\vspace{0.15in}
\begin{figure}[H]
  \centering 
  \includegraphics[width=0.78\textwidth]{figures/bhv_station.png}
  \caption{{\bf The station-keep behavior parameters:} The
    station-keep behavior can be configured to approach the outer
    station circle with a given transit speed, and will decrease its
    preference for speed linearly between the outer radius and inner
    radius. The preferred speed is zero when the vehicle is at or
    inside the inner radius.}
  \label{fig_bhv_station}
\end{figure}
\vspace{0.15in}

An alternative to this station keeping behavior is an active loiter
around a very tight polygon with the \var{Loiter} behavior. This
station keeping behavior conserves energy and aims to minimize
propulsor use. The behavior can be configured to station-keep at a
pre-set point, or wherever the vehicle happens to be when the behavior
transitions into an active state.

\pskip

The station-keep behavior was initially developed for use on an
autonomous kayak. It's worth pointing out that a vehicle's control
system, i.e., the front-seat driver described in Section
\ref{sec_backseat}, may have a native station-keeping mode, in which
case the activation of this behavior would be replaced by a message
from the backseat autonomy system to invoke the station-keeping mode.
It's also worth pointing out that most UUVs are positively buoyant and
will simply come to the surface if commanded with a zero-speed.


%=======================================================================
\subsection{Configuration Parameters}

\input{includes/bhv_all_properties}

\vspace{0.15in}
\begin{listing}{Configuration Parameters for the StationKeep Behavior}
\label{lst_bhv_station_keep}
\small
\renewcommand{\arraystretch}{1.15}
\begin{longtable}{rp{0.76\textwidth}} 

  {\bf Parameter} &amp; {\bf Description} \\  

  \bvar{center\_activate}: &amp; If true, station-keep at the vehicle's
  present position upon activation. Section
  \ref{sec_loiter_station_pt}. \\
  
  \bvar{hibernation\_radius}: &amp; A radius used for low-power, passive
  station-keeping. Section \ref{sec_loiter_lowpower}. \\

  \bvar{inner\_radius}: &amp; Distance to station-point within which the
  preferred speed is zero. Section \ref{sec_loiter_radii}. \\

  \bvar{outer\_radius}: &amp; Distance within which the preferred speed
  begins to decrease. Section \ref{sec_loiter_radii}. \\
  
  \bvar{outer\_speed}: &amp; Preferred speed at outer radius, decreasing
  toward inner radius. Section \ref{sec_loiter_radii}. \\
  
  \bvar{station\_pt}: &amp; An x,y pair given as a point in local
  coordinates. Section \ref{sec_loiter_station_pt}. \\
  
  \bvar{swing\_time}: &amp; Duration of drift of station circle with
  vehicle upon activation. Section \ref{sec_loiter_swing_time}. \\

  \bvar{transit\_speed}: &amp; Preferred speed beyond the outer radius. 
  Section \ref{sec_loiter_radii}. \\

  \bvar{visual\_hints}: &amp; Preferences for rendering visual artifacts
  produced by the behavior.  Section \ref{sec_loiter_vhints}. \\

\end{longtable}
\end{listing}
\normalsize

\vspace{0.15in}
\begin{listing}{Example Configuration Block}
\label{lst_bhv_station_keep_exmin}

\begin{fileverb}
Behavior = BHV_StationKeep
{
  // General Behavior Parameters
  // ---------------------------
  name         = station-keep          // example
  pwt          = 100                   // default
  condition    = MODE==SKEEPING        // example
  inactiveflag = STATIONING = false    // example
  activeflag   = STATIONING = true     // example


  // Parameters specific to this behavior
  // ------------------------------------
     center_activate = false   // default
  hibernation_radius = -1      // default
        inner_radius = 4       // default
        outer_radius = 15      // default
        outer_speed  = 1.2     // default
      transit_speed  = 2.5     // default
          station_pt = 0,0     // default
          swing_time = 0       // default

        visual_hints = vertex_size  = 1           // default
        visual_hints = edge_color   = light_blue  // default
        visual_hints = edge_size    = 1           // default
        visual_hints = label_color  = white       // default
        visual_hints = vertex_color = red         // default
}
\end{fileverb}
\end{listing}

%=======================================================================
\subsection{The \bvar{station\_pt} and \bvar{center\_activate} Parameters}
\label{sec_loiter_station_pt}

The station-keep point is set in one of two ways: either with a
pre-specified fixed position, or with the vehicle's current position
when the vehicle transitions into the running state. To set a fixed
station-keep position:

\prevbhv
\begin{verbatim}
  station_pt = 100,250 
\end{verbatim}
\postverb

\noindent
To configure the behavior to station-keep at the vehicle's current
position when it enters the running state:

\prevbhv
\begin{verbatim}
  center_activate = true  // "true" is case insensitive
\end{verbatim}
\postverb

%=======================================================================
\subsection{The \bvar{swing\_time} Parameter}
\label{sec_loiter_swing_time}

At the outset of station-keeping via \bvar{center\_activate}, the
vehicle typically is moving at some speed. Despite the fact that
station-keeping is immediately active and typically results in a
desired speed of zero if no other behaviors are active, the vehicle
will continue some distance before coming to a near or complete stop
in the water, thus "over-shooting" the station-keep point.  This often
means that the station-keep behavior will immediately turn the vehicle
around to come back to the station-keep point. This can be countered
by setting the behavior's \bvar{swing\_time} parameter, the amount of
time after initial center-activation that the station-keep point is
allowed to drift with the current position of the vehicle before
becoming fixed. The format is:

\prevbhv
\begin{verbatim}
  swing_time = &lt;time-duration&gt;   // default is 0 seconds
\end{verbatim}
\postverb

\noindent
The time duration is given in seconds and should be in the range [0,
  60]. If found to be outside this range it it simply clipped to the
boundary value.

\pskip

If the behavior enters the running state, but center-activation is not
set to true, and no pre-specified fixed position is given, the
behavior will not produce an objective function. It will remain in the
running state, but not the active state. (Section \ref{sec_run_states}
discusses run states.) In this situation, a warning will be posted via
the helm appcast structure and by posting to the \mvar{BHV\_WARNING} 
variable. In both cases the warning will read: \var{"STATION\_POINT\_NOT\_SET"}.

%=======================================================================
\subsection{The \bvar{inner\_radius}, \bvar{outer\_radius}, and \bvar{outer\_speed} Parameters}
\label{sec_loiter_radii}

The \bvar{inner\_radius} and \bvar{outer\_radius} parameters affect
the preferred speed of the behavior as it relates to the vehicle's
current range to the station point. The preferred speed at the outer
radius is given by the parameter \bvar{outer\_speed}. The preferred
speed decreases linearly to zero as the vehicle approaches the inner
radius.  The default values for the inner and outer radii are 4 and 15
respectively. If configured with values such that the inner is greater
than the outer, this will not trigger an error, but the two radii
parameters will be collapsed to the value of the inner radius on the
first iteration of the behavior. The \bvar{transit\_speed} parameter
indicates the desired speed when the vehicle is outside the
\bvar{outer\_radius}. The default value for \bvar{transit\_speed} is
2.5 meters per second. If the \bvar{outer\_speed} is set higher than
the \bvar{transit\_speed} the \bvar{transit\_speed} will automatically
be raised to the \var{outer\_speed}.


%=======================================================================
\subsection{Passive Low-Energy Station Keeping Mode}
\label{sec_loiter_lowpower}

The station-keep behavior can be configured to operate in a
"passive" mode.  This mode differs from the default mode primarily
in the way it acts after it reaches the inner-radius, i.e., the point
at which the behavior regards the vehicle to be on-station and outputs
a preferred speed of zero. In the normal mode, the behavior will begin
to output a preferred heading and non-zero speed as soon as the
vehicle slips beyond the inner-radius. In the passive mode, the
behavior will let the vehicle drift or otherwise move to a distance
specified by the \bvar{hibernation\_radius} before it resumes
outputting a preferred heading and non-zero speed. The idea is shown
in Figure \ref{fig_station_passive}.
\pskip

\vspace{0.15in}
\begin{figure}[H]
  \centering 
  \includegraphics[width=0.78\textwidth]{figures/bhv_station_passive.png}
  \caption{{\bf Passive station-keeping:} The station-keep behavior
    can be configured in the "passive" mode. The vehicle will move
    toward the station point until it reaches the \bvar{inner\_radius}
    or until progress ceases. It will then drift until its distance to
    the station point is beyond the \bvar{hibernation\_radius}. At
    this point it will re-engage to reach the station-point and may
    trigger another behavior to dive.}
  \label{fig_station_passive}
\end{figure}
\vspace{0.1in}

This mode was built with UUVs in mind. Most UUVs are deployed having a
positive buoyancy (battery dies - vehicle floats to the surface). They
need to be moving at some speed to maintain a depth. Furthermore, it
may not be safe to assume that a UUV can effectively execute a desired
heading when it is operating on the surface. For these reasons, when
operating in the passive mode, this behavior will publish a variable
indicating whether it is in the mode of drifting or attempting to make
progress toward the station point. The status is published in the
variable \mvar{PSKEEP\_MODE}, short for "passive station-keeping
mode". This variable will be set to \var{"SEEKING\_STATION"} when
outputting a non-zero speed preference, and presumably moving toward
the station-point. The variable will be set to \var{"HIBERNATING"}
otherwise. This opens the option of configuring the helm with the
ConstantDepth behavior to work in conjunction with the StationKeep
behavior by conditioning the ConstantDepth behavior to be running only
when \msvar{PSKEEP\_MODE="SEEKING\_STATION"}. The idea is shown in Figure
\ref{fig_station_mode}.

\vspace{0.15in}
\begin{figure}[H]
  \centering 
  \includegraphics[width=0.92\textwidth]{figures/bhv_station_mode.png}
  \caption{{\bf Passive station-keeping with depth coordination:} The
    passive mode can be coordinated with the ConstantDepth behavior to
    dive each time the StationKeep behavior enters the
    \vvar{"SEEKING\_STATION"} mode.  This ensures that a UUV needing
    to be at depth to have reliable heading control will indeed be at
    depth when it needs to be.}
\label{fig_station_mode}
\end{figure}
\vspace{0.15in}

\pskip

This behavior mode is regarded as "low-power" due to the presumably
long periods of drifting before resuming actively seeking the station
point. A couple of safeguards are designed to ensure that when the
behavior is in the \var{"STATION\_SEEKING"} mode, that it does not get
hung or stuck in this mode for much longer than intended or
needed. How could one become stuck in this mode? Two ways - by either
reaching an equilibrium at-speed, (and perhaps at-depth) state where
the vehicle is neither progressing toward or way from the
\bvar{inner\_radius}, or by repeatedly "missing" the
\bvar{inner\_radius} by heading right past it. 

\pskip 

Both cases can be guarded against and detected by monitoring the
history of vehicle speed in the direction of the station-point. If
this speed becomes zero, an equilibrium state is assumed, and if it
becomes negative, it is assumed that the vehicle missed the inner
radius circle entirely. In short, the StationKeep behavior exits the
\var{"STATION\_SEEKING"} mode and enters the \var{"HIBERNATING"} mode
when it detects the vehicle speed toward the station-point reach
zero. To calculate this vehicle speed, a ten-second history of range
to the station-point is kept by the behavior. A zero speed, or
"stale-progress" criteria is declared simply if the range to the
station-point for the most recent measure in the history is not less
than the range of ten seconds ago in the history list. The behavior
will transition into the \var{"HIBERNATING"} mode if either the
inner-radius or stale-progress criteria are met.

\pskip 

It is also possible that when the StationKeep behavior enters the
\var{"SEEKING\_STATION"} mode from the \var{"HIBERNATING"} mode, that
the vehicle initially begins to open its range to the station-point
before it begins to close range. This would be expected, for example,
if the vehicle were pointed away from the station-point when the
behavior first entered the \var{"SEEKING\_STATION"} mode. In this case
it's quite possible that the behavior would correctly, but
unwantingly, infer that the stale-progress criteria has been met.  For
this reason, the stale-progress criteria is not applied until an
"initial-progress" criteria is met after entering the
\var{"SEEKING\_STATION"} mode. The same ten second history is used to
detect when the vehicle begins to make initial progress, i.e., closing
range, toward the station-point.

%=======================================================================
\subsection{Station Keeping On Demand}

A common, and perhaps recommended configuration, is to have one
station-keep behavior defined for a given helm configuration and have
it set to be usable in one of three ways: (a) station-keep at a
default pre-specified position, (b) station-keep at a specified
position dynamically provided, or (c) station-keep at the vehicle's
present position when activated.  The behavior would be configured as
follows:

\prevbhv
\begin{verbatim}
    station_pt      = 100,200 // The default station-keep point 
    center_activate = false
    updates         = STATION_UPDATES
    condition       = STATION_REQUEST = true 
\end{verbatim}
\postverb

\noindent
Then, to use the station-keep behavior in the above three ways, the
following three pairs of postings, i.e., pokes, to the MOOSDB would be
used. See Section \ref{sec_updates} for more on the \bvar{updates}
parameter defined for all behaviors - by utilizing this dynamic
configuration hook, the one behavior configuration above can be used
in these different manners.  The first pair would result in the
behavior keeping station at its pre-arranged point of (100,200):

\prevgreen
\begin{verbatim}
    STATION_REQUEST = true
    STATION_UPDATES = center_activate=false
\end{verbatim}
\postverb

\noindent
The second line above dynamically configures the behavior parameter
\bvar{center\_activate} to be false to ensure that the point
given by the original \bvar{station\_pt} parameter is used. Even though
the \bvar{center\_activate} parameter is initially set to false,
the above usage sets it to false anyway, to be safe, and in case
it has been dynamically set to true in a prior usage.

\pskip

In the second case below, again the \bvar{center\_activate} parameter
is dynamically set to false for the same reasons. In this case
the \bvar{station\_point} parameter is also dynamically configured with 
a given point:

\prevgreen
\begin{verbatim}
    STATION_REQUEST = true
    STATION_UPDATES = station_pt=45,-150 # center_activate=false
\end{verbatim}
\postverb

\noindent
In the last case, below, the behavior is activated and configured to 
station-keep at the vehicle's present position when activated. There
is no need to tinker with the \bvar{station\_pt} parameter since this
parameter is ignored when \bvar{center\_activate} is true:

\prevgreen
\begin{verbatim}
    STATION_REQUEST = true
    STATION_UPDATES = center_activate=true
\end{verbatim}
\postverb

\noindent
It's worth noting that above variable-value pairs that trigger the
StationKeep behavior could have come from a variety of sources. They
could be endflags from another behavior. They could have come from a
poke using \app{uPokeDB}, \app{uTimerScript}, \app{pMarineViewer} or
any third party command and control interface.

%low power because
% a. vehicle can power off thrusters and come to surface
% b. progress to station-point ceases when speed ceases or innner_radius 


%=======================================================================
\subsection{The \bvar{visual\_hints} Parameter}
\label{sec_loiter_vhints}

Although the primary output of the StationKeep behavior is an IvP
Function, a number of visual properties are also published for
convenience in mission monitoring.  This includes (a) the
\bvar{inner\_radius}, (b) the \bvar{outer\_radius}, and (c) the
\bvar{hibernation\_radius} if used.  These visual artifacts have
default properties in size and color that may be altered to the user's
preferences. These preferences are configurable through the
\bvar{visual\_hints} parameter. Each parameter below is used in the
following way by example:

\vspace{0.1in}
\begin{fileverb}
 visual_hint = vertex_size=3, edge_size=2
 visual_hint = vertex_color=khaki
\end{fileverb}
\vspace{0.1in}


\begin{packed_itemize}[1]
\item \bvar{edge\_color}: The color of edges rendered in the loiter
  polygon. The default is "white".
\item \bvar{edge\_size}: The width of edges rendered in the
  loiter polygon. The default is 1.
\item \bvar{label\_color}: The color of labels rendered with the
  innner and outer radii. The default is "gray50".
\item \bvar{vertex\_color}: The color of vertices rendered in the
  loiter polygon. The default is "dodger\_blue".
\item \bvar{vertex\_size}: The size of vertices rendered in the
  loiter polygon. The default is 1.
\end{packed_itemize}

\noindent
Rendering of vertices may be shut off with a size of zero, and labels
may be shut off with the special color "invisible". For a list of
legal colors, see Appendix \ref{app:colormap}.






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