7   Properties of Helm Behaviors


7.1 Brief Overview
7.2 Parameters Common to All IvP Behaviors
     7.2.1 A Summary of the Full Set of General Behavior Parameters
     7.2.2 The name Parameter
     7.2.3 The priority Parameter
     7.2.4 The post_mapping Parameter
     7.2.5 Altering Parameters Dynamically with the updates Parameter
     7.2.6 Limiting Behavior Duration with the duration Parameter
     7.2.7 The perpetual Parameter
     7.2.8 The post_mapping Parameter
     7.2.9 Detection of Stale Variables with the nostarve Parameter
7.3 Overloading the setParam() Function in New Behaviors
7.4 Behavior Functions Invoked by the Helm
     7.4.1 Helm-Invoked Immutable Functions
     7.4.2 Helm-Invoked Overloaded Functions
7.5 Local Behavior Utility Functions
     7.5.1 Summary of Implementor-Invoked Utility Functions
     7.5.2 The Information Buffer
     7.5.3 Requesting the Inclusion of a Variable in the Information Buffer
     7.5.4 Accessing Variable Information from the Information Buffer
7.6 Overloading the onRunState() and onIdleState() Functions
7.7 Dynamic Behavior Spawning
     7.7.1 Behavior Specifications Viewed as Templates
     7.7.2 Behavior Completion and Removal from the Helm
     7.7.3 Example Missions with Dynamic Behavior Spawning
     7.7.4 Examining the Helm's Life Event History


The objective of this section is to describe properties common to all IvP Helm behaviors, describe how to overload standard functions for 3rd party behaviors, and to provide a detailed simple example of a behavior. It builds on the discussion from Section 6. The focus in this section is an expansion of detail of Step 3 in Figure 6.1.

7.1   Brief Overview    [top]


Behaviors are implemented as C++ classes with the helm having one or more instances at runtime, each with a unique descriptor. The properties and implemented functions of a particular behavior are partly derived from the IvPBehavior superclass, shown in Figure 7.1. The is-a relationship of a derived class provides a form of code re-use as well as a common interface for constructing mission files with behaviors.

Figure 7.1: Behavior inheritance: Behaviors are derived from the IvPBehavior superclass. The native behaviors are the behaviors distributed with the helm. New behaviors also need to be a subclass of the IvPBehavior class to work with the helm. Certain virtual functions invoked by the helm may be optionally but typically overloaded in all new behaviors. Other private functions may be invoked within a behavior function as a way of facilitating common tasks involved in implementing a behavior.

The IvPBehavior class provides five virtual functions which are typically overloaded in a particular behavior implementation:

  • The setParam() function: parameter-value pairs are handled to configure a behavior's unique properties distinct from its superclass.
  • The onRunState() function: the meat of a behavior implementation, performed when the behavior has met its conditions for running, with the output being an objective function and a possibly empty set of variable-value pairs for posting to the MOOSDB.
  • The onIdleState() function: what the behavior does when it has not met its run conditions. It may involve updating internal state history, generation of variable-value pairs for posting to the MOOSDB, or absolutely nothing at all.
  • The onIdleToRunState() function: invoked once by the helm upon transitioning from the idle to running state (compared to the onRunState() function which is invoked on each helm iteration where the behavior has met its conditions).
  • The onRunToIdleState() function: invoked once by the helm upon transitioning from the running to idle state (compared to the onIdleState() function which is invoked on each helm iteration where the behavior has not met its conditions).

    This section discusses the properties of the IvPBehavior superclass that an author of a third-party behavior needs to be aware of in implementing new behaviors. It is also relevant material for users of the native behaviors as it details general properties.

7.2   Parameters Common to All IvP Behaviors    [top]


A behavior has a standard set of parameters defined at the IvPBehavior level as well as unique parameters defined at the subclass level. By configuring a behavior during mission planning, the setting of parameters is the primary venue for affecting the overall autonomy behavior in a vehicle. Parameters are set in the behavior file, but can also be dynamically altered once the mission has commenced. A parameter is set with a single line of the form:

     parameter = value

    The left-hand side, the parameter component, is case insensitive, while the value component is typically case sensitive. This was discussed in depth in Section 6.3. In this section, the parameters defined at the superclass level and available to all behaviors are exhaustively listed and discussed. Each behavior typically augments these parameters with new ones unique to the behavior, and in the next section the issue of implementing new parameters by overloading the setParam() function is addressed.

7.2.1   A Summary of the Full Set of General Behavior Parameters    [top]


The following parameters are defined for all behaviors at the superclass level. They are listed here for reference - certain related aspects are discussed in further detail in other sections.

Listing 7.1 - Configuration Parameters Common to All Behaviors.

name:The name of the behavior - should be unique between all behaviors. Due to the implementation of behavior templating, spawned behavior take on a new name by concatenating on the end of a base name. For this reason all configured behavior names could be regarded as base names. The check for uniqueness includes hypothetical extension. Thus the names loiter and loiter_two are not regarded as safe since the first could potentially grow into the latter with the contcatenation of _two. Logging and output sent to the helm console during operation will organize information by the behavior name.
priority:The priority weight of the produced objective function. The default value is 100. A behavior may also be implemented to determine its own priority weight depending on information about the world.
duration:The time in seconds that the behavior will remain running before declaring completion. If no duration value is provided, the behavior will never time-out. The clock starts ticking once the behavior satisfies its run conditions (becoming non-idle) the first time. Should the behavior switch between running and idle states, the clock keeps ticking even during the idle periods. See Section 7.2.6 for more detail.
duration_status:If the duration parameter is set, the remaining duration time, in seconds, can be posted by naming a duration_status variable. This variable will be update/posted only when the behavior is in the running state. See Section 7.2.6 for more detail.
duration_reset:This parameter takes a variable-pair such as MY_RESET=true. If the duration parameter is set, the duration clock is reset when the variable is posted to the MOOSDB with the specified value. Each time such a post is noted, the duration clock is reset. See Section 7.2.6 for more detail.
post_mapping:This parameter takes a comma-separated pair such as WPT_STAT, WAYPT_STATUS where the left-hand value is a variable normally posted by the behavior, and the right-hand value is an alternative variable name to be used. There is no error-checking to ensure that the left-hand value names a variable actually posted by the behavior. Transitive relationships are not respected. For example, if the two re-mappings are declared, FOO,BAR, and BAR,CAR, FOO will be posted as BAR, not CAR. To disable the normal posting of a variable FOO, use post_mapping = FOO,SILENT.
duration_idle_decay:If this parameter is false the duration clock is paused when the vehicle is in the idle state. The default value is true. See Section 7.2.6 for more detail.
condition:This parameter specifies a condition that must be met for the behavior to be active. Conditions are checked for each behavior at the beginning of each control loop iteration. Conditions are based on current MOOS variables, such as STATE = normal or (K < 4). More than one condition may be provided, as a convenience, treated collectively as a single conjunctive condition. The helm automatically subscribes for any condition variables. See Section 6.5.1 for more detail on run conditions.
runflag:This parameter specifies a variable and a value to be posted when the behavior has met all its conditions for being in the running state. It is only posted if the behavior, on the previous helm iteration, was not in the running state. It is an equal-separated pair such as TRANSITING=true. More than one flag may be provided. These can be used to satisfy or block the conditions of other behaviors.
idleflag:This parameter specifies a variable and a value to be posted when the behavior is in the idle state. See the Section 6.5.3 for more on run states. It is only posted if the behavior, on the previous helm iteration, was not in the idle state. It is an equal-separated pair such as WAITING=true. More than one flag may be provided. These can be used to satisfy or block the conditions of other behaviors.
activeflag:This parameter specifies a variable and a value to be posted when the behavior is in the active state. See the Section 6.5.3 for more on run states. It is only posted if the behavior, on the previous helm iteration, was not in the avtive state. It is an equal-separated pair such as TRANSITING=true. More than one flag may be provided. These can be used to satisfy or block the conditions of other behaviors.
inactiveflag:This parameter specifies a variable and a value to be posted when the behavior is not in the active state. See the Section 6.5.3 for more on run states. It is only posted if the behavior, on the previous helm iteration, was in the active state. It is a equal-separated pair such as OUT_OF_RANGE=true. More than one flag may be specified by the user in the behavior configuration. These can be used to satisfy or block the conditions of other behaviors.
endflag:This parameter specifies a variable and a value to be posted when the behavior has set the completed state variable to be true. The circumstances causing completion are unique to the individual behavior. However, if the behavior has a duration specified, the completed flag is set to true when the duration is exceeded. The value of this parameter is a equal-separated pair such as ARRIVED_HOME=true. Once the completed flag is set to true for a behavior, it remains inactive thereafter, regardless of future events, barring a complete helm restart.
updates:This parameter specifies a variable from which updates to behavior configuration parameters are read from after the behavior has been initially instantiated and configured at the helm startup time. Any parameter and value pair that would have been legal at startup time is legal at runtime. The syntax for this string is a #-separated list of parameter-value pairs: "param=value # param=value # ... # param=value". This is one of the primary hooks to the helm for mission control - the other being the behavior conditions described above. See Section 7.2.5 for more detail.
nostarve:The nostarve parameter allows a behavior to assert a maximum staleness for one or more MOOS variables, i.e., the time since the variable was last updated. The syntax for this parameter is a comma-separated pair "variable, ..., variable, value", where last component in the list is the time value given in seconds. See Section 7.2.9 for more detail.
perpetual:Setting the perpetual parameter to true allows the behavior to continue to run even after it has completed and posted its end flags. The parameter value is not case sensitive and the only two legal values are true and false. See Section 7.2.7 for more detail.
templating:The templating parameter may be used to turn a behavior specification into a template for spawning new behaviors dynamically after the helm has been launched. Instantiation requests are received via the updates parameter described in Section 7.7.

7.2.2   The name Parameter    [top]


The name parameter is a mandatory parameter with no default value that assigns a name to the behavior instance. The name must be unique. The behavior name is case sensitive, so having the names "return_home" and "Return_Home" is acceptable (although not advisable).

    Due to the capability of behavior templating (Section 7.7) the policy of behavior uniqueness was expanded to include pairs of names where one name matches the beginning component of another. For example "return" and "return_home" are not allowed. This is due to way template spawning is implemented. The spawning process begins by setting the name of the newly spawned behavior. This is achieved by appending to the base name declared for the behavior template. By allowing, for example, "return" and "return_home", it leaves open the possiblity that the first behavior may spawn an instance with a name clash if it were spawned with a suffix directive of "_home".

    Behavior names have no relation to the behavior class name. For example an instance of the Waypoint behavior may be called "station-keep" (although not advisable). Furthermore, multiple instances of the same behavior may certainly co-exist so long as each instance has a unique name. If the helm is configured with one or more behaviors with non-unique names, the helm will come up in the "MALCONFIG" state. The terminal or appcasting output would look something like:

 ===================================================================
 pHelmIvP alpha                                             1/0(411)
 ===================================================================
 Configuration Warnings: 1
  [1 of 1]: Duplicate behavior name found: waypt_return

 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    !!                                             !!
    !!  The helm is in the MALCONFIG state due to  !!
    !!  unresolved configuration warnings.         !!
    !!                                             !!
    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

7.2.3   The priority Parameter    [top]


The priority parameter is a optional parameter with a default value of 100. It assigns a priority weight to be applied to an objective function produced by the behavior. Many behaviors interpret this priority to establish a range of priorities depending on the further evaluation of the situation by the behavior. For example, the collision avoidance behavior will treat the configured priority to be the maximum priority (when a contact is close) and will degrade the priority accordingly as the contact range is greater.

    The range of acceptable values is from zero to infinity. If a negative value is given for a behavior the helm will come up in the "MALCONFIG" state. The terminal or appcasting output would look something like:

 ===================================================================
 pHelmIvP alpha                                             1/0(21)
 ===================================================================
 Configuration Warnings: 1
  [1 of 1]: alpha.bhv: Line 61: pwt   = -1

 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    !!                                             !!
    !!  The helm is in the MALCONFIG state due to  !!
    !!  unresolved configuration warnings.         !!
    !!                                             !!
    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

7.2.4   The post_mapping Parameter    [top]


The post_mapping parameter is a optional parameter with no default value. It allows the user to configure a behavior to change the name of the variables otherwise posted by the behavior. For example, the Waypoint behavior by default publishes a variable WPT_INDEX indicating the index of the next point on its path. If there are multiple waypoint behaviors, or if you just don't like this variable, it may be change for example to SURVEY_INDEX with the following configuration:

    post_mapping=WPT_INDEX,SURVEY_INDEX

7.2.5   Altering Parameters Dynamically with the updates Parameter    [top]


The parameters of a behavior can be made to allow dynamic modifications - after the helm has been launched and executing the initial mission in the behavior file. The modifications come in a single MOOS variable specified by the parameter updates. For example, consider the simple waypoint behavior configuration below in Listing 7.2. The return point is the (0,0) point in local coordinates, and return speed is 2.0 meters/second. When the conditions are met, this is what will be executed.

Listing 7.2 - An example behavior configuration using the updates parameter.

  1  Behavior = BHV_Waypoint
  2  {
  3    name      = WAYPT_RETURN
  4    priority  = 100
  5    speed     = 2.0
  6    radius    = 8.0
  7    points    = 0,0
  8    updates   = RETURN_UPDATES
  9    condition = RETURN = true
 10    condition = DEPLOY = true
 11  }

    If, during the course of events, a different return point or speed is desired, this behavior can be altered dynamically by writing to the variable specified by the updates parameter, in this case the variable RETURN_UPDATES (line 8 in Listing 7.2). The syntax for this variable is of the form:

     parameter = value # parameter = value # ... # parameter = value

White space is ignored. The '#' character is treated as special for parsing the line into separate parameter-value pairs. It cannot be part of a parameter component or value component. For example, the return point and speed for this behavior could be altered by any other MOOS process that writes to the MOOS variable:

     RETURN_UPDATES = "points=50,50 # speed = 1.5"

    Each parameter-value pair is passed to the same parameter setting routines used by the behavior on initialization. The only difference is that an erroneous parameter-value pair will simply be ignored as opposed to halting the helm as done on startup. If a faulty parameter-value pair is encountered, a warning will be written to the variable BHV_WARNING. For example:

   BHV_WARNING = "Faulty update for behavior: WAYPT_RETURN. Bad parameter(s): speed."

Note that a check for parameter updates is made at the outset of helm iteration loop for a behavior (Figure 7.1) with the call checkUpdates(). Any updates received by the helm on the current iteration will be applied prior to behavior execution and in effect for the current iteration.

7.2.6   Limiting Behavior Duration with the duration Parameter    [top]


The duration parameter specifies a time period in seconds before a behavior times out and permanently enters the completed state (Figure 7.2). If left unspecified, there is no time limit to the behavior. By default, the duration clock begins ticking as soon as the helm is in drive. The duration clock remains ticking when or if the behavior subsequently enters the idle state. It even remains ticking if the helm temporarily parks. When a timeout occurs, end flags are posted. The behavior can be configured to post the time remaining before a timeout with the duration_status parameter. The forms for each are:

    duration        =  value (positive numerical)
    duration_status =  value (variable name)

Note that the duration status variable will only be published/updated when the behavior is in the running state. The duration status is rounded to the nearest integer until less than ten seconds remain, after which the time is posted out to two decimal places. The behavior can be configured to have the duration clock pause when it is in the idle state with the following:

    duration_idle_decay = false   // The default is true 

Configured in the above manner, a behavior's duration clock will remain paused until it's conditions are met. The behavior may also be configured to allow for the duration clock to be reset upon the writing of a MOOS variable with a particular value. For example:

    duration_reset = BRAVO_TIMER_RESET=true

The behavior checks for and notes that the variable-value pair holds true and the duration clock is then reset to the original duration value. The behavior also marks the time at which the variable-value pair was noted to have held true. Thus there is no need to "un-set" the variable-value pair, e.g., setting BRAVO_TIMER_RESET=false, to allow the duration clock to resume its count-down.

7.2.7   The perpetual Parameter    [top]


When a behavior enters the completed state, it by default remains in that state with no chance to change. When the perpetual parameter is set to true, a behavior that is declared to be complete does not actually enter the complete state but performs all the other activity normally associated with completion, such as the posting of end flags. See Section 6.5.4 for more detail on posting flags to the MOOSDB from the helm. The default value for perpetual is false. The form for this parameter is:

    perpetual  =  value

The value component is case insensitive, and the only legal values are either true or false. A behavior using the duration parameter with perpetual set to true will post its end flags upon time out, but will reset its clock and begin the count-down once more the next time its run conditions are met, i.e., enters the running state. Typically when a behavior is used in this way, it also posts an endflag that would put itself in the idle state, waiting for an external event.

7.2.8   The post_mapping Parameter    [top]


This parameter takes a comma-separated pair where the left-hand value is a variable normally posted by the behavior, and the right-hand value is an alternative variable name to be used. For example, the Waypoint behavior normally posts the variable WPT_STAT when it is running. This can be changed with:

  post_mapping = WPT_STAT, WAYPT_STATUS 

    Note there is no error-checking to ensure that the left-hand value names a variable actually posted by the behavior. Transitive relationships are not respected. For example, if the two re-mappings are declared, FOO,BAR, and BAR,CAR, FOO will be posted as BAR, not CAR. To disable the normal posting of a variable FOO, use:

  post_mapping = FOO, SILENT

7.2.9   Detection of Stale Variables with the nostarve Parameter    [top]


A behavior utilizing a variable generated by a MOOS process outside the helm, may require the variable to be sufficiently up-to-date. The staleness of a variable is the time since it was last written to by any process. The nostarve parameter allows the mission writer to set a staleness threshold. The form for this parameters is:

    nostarve  =  variable_1, ..., variable_n, duration

The value of this parameter is a comma-separated list such as nostarve = NAV_X, NAV_Y, 5.0. The variable components name MOOS variables and the duration component, the last entry in the list, represents the tolerated staleness in seconds. If staleness is detected, a behavior failure condition is triggered which will trigger the helm to post all-stop values and relinquish to manual control.

7.3   Overloading the setParam() Function in New Behaviors    [top]


The setParam() function is a virtual function defined in the IvPBehavior class, with parameters implemented in the superclass (Section 7.2) handled in the superclass version of this function:

     bool IvPBehavior::setParam(string parameter, string value);

The setParam() function should return true if the parameter is recognized and the value is in an acceptable form. In the rare case that a new behavior has no additional parameters, leaving this function undefined in the subclass is appropriate. The example below in Listing 7.3 gives an example for a fictional behavior BHV_YourBehavior having a single parameter period.

Listing 7.3 - Example setParam() implementation for fictional BHV_YourBehavior.

   1  bool BHV_YourBehavior::setParam(string param, string value) 
   2  {
   3    if(param == "period") {
   4      double time_value = atof(value.c_str());
   5      if((time_value < 0) || (!isNumber(value)))
   6        return(false);
   7      m_period = time_value;
   8      return(true);
   9    }
  10    return(false);
  11  }

Since the period parameter refers to a time period, a check is made on line 4 that the value component indeed is not a negative number. The atof() function on line 6, which converts an ASCII string to a floating point value, returns zero when passed a non-numerical string, therefore the isNumber() function is also used to ensure the string represented by value represents a numerical value. The isNumber() function is part of the IvP utility library. A behavior implementation of this function without sufficient syntax or semantic checking simply runs the risk that faulty parameters are not detected at the time of helm launch, or during dynamic updates. Solid checking in this function will reduce debugging headaches down the road.

7.4   Behavior Functions Invoked by the Helm    [top]


The IvPBehavior superclass implements a number of functions invoked by the helm on each iteration. Two of these functions are overloadable as described previously - the onRunState() and onIdleState() functions. The basic flow of calls to a behavior from the helm are shown in Figure 7.2. These are discussed in more detail later in the section, but the idea is to execute certain behavior functions based on the activity state, which may be one of the four states depicted.

Figure 7.2: Behavior function-calls by the helm: The helm invokes a sequence of functions on each behavior on each iteration of the helm. The sequence of calls is dependent on what the behavior returns, and reflects the behaviors activity state. Certain functions are immutable and can not be overloaded by a behavior author. Two key functions, onRunState() and onIdleState() can be indeed overloaded as the usual hook for an author to provide the implementation of a behavior. The postFlags() function is also immutable, but the parameters (flags) are provided in the helm configuration (*.bhv) file.

    An idle behavior is one that has not met its conditions for running. A completed behavior is one that has reached its objectives or exceeded its duration. A running behavior is one that has not yet completed, has met its run conditions, but may still opt not to produce any output. An active behavior is one that is running and is producing output in the form of an objective function.

    The types of functions defined at the superclass level fall into one of the three categories below, only the first two of which are shown in Figure 7.2:

  • Helm-invoked immutable functions - functions invoked by the helm on each iteration that the author of a new behavior may not re-implement.
  • Helm-invoked overloadable functions - functions invoked by the helm that an author of a new behavior typically re-implements of overloads.
  • User-invoked functions - functions invoked within a behavior implementation.

    The user-invoked functions are utilities for common operations typically invoked within the implementation of the onRunState() and onIdleState() functions written by the behavior author.

7.4.1   Helm-Invoked Immutable Functions    [top]


These functions, implemented in the IvPBehavior superclass, are called by the helm but are not defined as virtual functions which means that attempts to overload them in a new behavior implementation will be ignored. See Figure 7.2 regarding the sequence of these function calls.

  • void checkUpdates(): This function is called first on each iteration to handle requested dynamic changes in the behavior configuration. This needs to be the very first function applied to a behavior on the helm iteration so any requested changes to the behavior parameters may be applied on the present iteration. See Section 7.2.5 for more on dynamic behavior configuration with the updates parameter.
  • bool isComplete(): This function simply returns a Boolean indicating whether the behavior was put into the complete state during a prior iteration.
  • bool isRunnable(): Determines if a behavior is in the running state or not. Within this function call four things are checked: (a) if the duration is set, the duration time remaining is checked for timeout, (b) variables that are monitored for staleness are checked against (Section 7.2.9). (c) the run conditions must be met. (d) the behavior's decision domain (IvP domain) is a proper subset of the helm's configured IvP domain. See Section 6.5.1 for more detail on run conditions.
  • void postFlags(string flag_type): This function will post flags depending on whether the value of flag_type is set to "idleflags", "runflags", "activeflags", "inactiveflags", or "endflags". Although this function is immutable, not overloadable by subclass implementations, its effect is indeed mutable since the flags are specified in the mission configuration *.bhv file. See Section 6.5.4 for more detail on posting flags to the MOOSDB from the helm.

7.4.2   Helm-Invoked Overloaded Functions    [top]


These are functions called by the helm. They are defined as virtual functions so that a behavior author may overload them. Typically the bulk of writing a new behavior resides in implementing these three functions.

  • IvPFunction* onRunState(): This function is called by the helm when deemed to be in the running state (Figure 7.2). The bulk of the work in implementing a new behavior is in this function implementation, and is the subject of Section 7.6.
  • void onIdleState(): This function is called by the helm when deemed to be in the idle state (Figure 7.2). Many behaviors are implemented with this function left undefined, but it is a useful hook to have in many cases.
  • bool setParam(string, string): This function is called by the helm when the behavior is first instantiated with the set of parameter and parameter values provided in the behavior file. It is also called by the helm within the checkUpdates() function to apply parameter updates dynamically.

7.5   Local Behavior Utility Functions    [top]


The bulk of the work done in implementing a new behavior is in the implementation of the onIdleState() and onRunState() functions. The utility functions described below are designed to aid in that implementation and are generally "protected" functions, that is callable only from within the code of another function in the behavior, such as the onRunState() and onIdleState() functions, and not invoked by the helm.

7.5.1   Summary of Implementor-Invoked Utility Functions    [top]


The following is summary of utility functions implemented at the IvPBehavior superclass level.

  • void setComplete(): The notion of what it means for a behavior to be "complete" is largely an issue specific to an individual behavior. When or if this state is reached, a call to setComplete() can be made and end flags will be posted, and the behavior will be permanently put into the completed state unless the perpetual parameter is set to true. See Section 6.5.3 for more on behavior run states.
  • void addInfoVars(string var_names): The helm will register for variables from the MOOSDB on a need-only basis, and a behavior is obligated to inform the helm that certain variables are needed on its behalf. A call to the addInfoVars() function can be made from anywhere with a behavior implementation to declare needed variables. This can be one call per variable, or the string argument can be a comma-separated list of variables. The most common point of invoking this function is within a behavior's constructor since needed variables are typically known at the point of instantiation. More on this issue in Section 7.5.3.
  • double getBufferDoubleVal(string varname, bool& result): Query the info_buffer for the latest (double) value for a given variable named by the string argument. The bool argument indicates whether the queried variable was found in the buffer. More on this in Section 7.5.2.
  • double getBufferStringVal(string varname, bool& result): Query the info_buffer for the latest (string) value for a given variable named by the string argument. The bool argument indicates whether the queried variable was found in the buffer. More on this in Section 7.5.2.
  • double getBufferCurrTime(): Query the info_buffer for the current buffer local time, equivalent to the duration in seconds since the helm was launched. More on this in Section 7.5.2.
  • vector<double> getBufferDoubleVector(string var, bool& result): Query the info_buffer for all changes to the variable (of type double) named by the string argument, since the last iteration. The bool argument indicates whether the queried variable was found in the buffer. More on this in Section 7.5.2.
  • vector<string> getBufferStringVector(string var, bool& result): Query the info_buffer for all changes to the variable (of type string) named by the string argument, since the last iteration. The bool argument indicates whether the queried variable was found in the buffer. More on this in Section 7.5.2.
  • void postMessage(string varname, string value, string key): The helm can post messages (variable-value pairs) to the MOOSDB at the end of the helm iteration. Behaviors can request such postings via a call to the postMessage() function where the first argument is the variable name, and the second is the variable value. The optional key parameter is used in conjunction with the duplication filter and by default is the empty string. See Section 5.8 for more on the duplication filter.
  • void postMessage(string varname, double value, string key): Same as above except used when the posted variable is of type double rather than string. The optional key parameter is used in conjunction with the duplication filter and by default is the empty string. See Section 5.8 for more on the duplication filter.
  • void postBoolMessage(string varname, bool value, string key): Same as above, except used when the posted variable is a bool rather than string. The optional key parameter is used in conjunction with the duplication filter and by default is the empty string. See Section 5.8 for more on the duplication filter.
  • void postIntMessage(string varname, double value, string key): Same as postMessage(string, double) above except the numerical output is rounded to the nearest integer. This, combined with the helm's use of the duplication filter, can reduce the number of posts to the MOOSDB. The optional key parameter is used in conjunction with the duplication filter and by default is the empty string. See Section 5.8 for more on the duplication filter.
  • void postWMessage(string warning_msg): Identical to the postMessage() function except the variable name is automatically set to BHV_WARNING. Provided as a matter of convenience to the caller and for uniformity in monitoring warnings.
  • void postEMessage(string error_msg): Similar to the postWMessage() function except the variable name is BHV_ERROR. This call is for more serious problems noted by the behavior. It also results in an internal state_ok bit being flipped which results in the helm posting all-stop values to the actuators.
  • void postRepeatableMessage(string varname, string value): A convenience function. A posting of postRepeatableMessage("FOO", "bar") is equivalent to postMessage("FOO", "bar", "repeatable").
  • void postRepeatableMessage(string varname, double value): A convenience function. A posting of postRepeatableMessage("FOO", 100) is equivalent to postMessage("FOO", 100, "repeatable").

7.5.2   The Information Buffer    [top]


Behaviors do not have direct access to the MOOSDB - they don't read mail, and they don't post changes directly, but rather through the helm as an intermediary. The information buffer, or info_buffer, is a data structure maintained by the helm to reflect a subset of the information in the MOOSDB and made available to each behavior. This topic is hidden from a user configuring existing behaviors and can be safely skipped, but is an important issue for a behavior author implementing a new behavior. The info_buffer is a data structure shared by all behaviors, each behavior having an pointer to a single instance of the InfoBuffer class. This data structure is maintained by the helm, primarily by reading mail from the MOOSDB and reflecting the change onto the buffer on each helm iteration, before the helm requests input from each behavior. Each behavior therefore has the exact same snapshot of a subset of the MOOSDB. A behavior author needs to know two things - how to ensure that certain variables show up in the buffer, and how to access that information from within the behavior. These two issues are discussed next.

7.5.3   Requesting the Inclusion of a Variable in the Information Buffer    [top]


A variable can be specifically requested for inclusion in the info_buffer by invoking the following function:

    void  IvPBehavior::addInfoVars(string varnames)

The string argument is either a single MOOS variable or a comma-separated list of variables. Duplicate requests are simply ignored. Typically such calls are invoked in a behavior's constructor, but may be done dynamically at any point after the helm is running. The helm will simply register with the MOOSDB for the requested variable at the end of the current iteration. Certain variables are registered for automatically on behalf of the behavior. All variables referenced in run conditions will be registered and accessible in the buffer. Variables named in the updates and nostarve parameters will also be automatically registered.

7.5.4   Accessing Variable Information from the Information Buffer    [top]


A variable value can be queried from the buffer with one of the following two function calls, depending on whether the variable is of type double or string.

    string  IvPBehavior::getBufferStringVal(string varname, bool& result)
    double  IvPBehavior::getBufferDoubleVal(string varname, bool& result)

The first string argument is the variable name, and the second argument is a reference to a Boolean variable which, upon the function return, will indicate whether the queried variable was found in the buffer. A duration value indicating the elapsed time since the variable was last changed in the buffer can be obtained from the following function call:

    double  IvPBehavior::getBufferTimeVal(string varname);

The string argument is the variable name. The returned value should be exactly zero if this variable was updated by new mail received by the helm at the beginning of the current iteration. If the variable name is not found in the buffer, the return value is -1. The ``current'' buffer time, equivalent to the cumulative time in seconds since the helm was launched, can be retrieved with the following function call:

    double  IvPBehavior::getBufferCurrTime()

The buffer time is a local variable of the info_buffer data structure. It is updated once at the beginning of the helm OnNewMail() loop prior to processing all new updates to the buffer from the MOOS mail stack, or at the beginning of the Iterate() loop if no mail is processed on the current iteration. Thus the time-stamp returned by the above call should be exactly the same for successive calls by all behaviors within a helm iteration.

    The values returned by getBufferStringVal() and getBufferDoubleVal() represent the latest value of the variable in the MOOSDB at the point in time when the helm began its iteration and processed its mail stack. The value may have changed several times in the MOOSDB between iterations, and this information may be of use to a behavior. This is particularly true when a variable is being posted in pieces, or a sequence of delta changes to a data structure. In any event, this information can be recovered with the following two function calls:

    vector<string>  IvPBehavior::getBufferStringVector(string varname, bool& result)
    vector<double>  IvPBehavior::getBufferDoubleVector(string varname, bool& result)

They return all values updated to the buffer for a given variable since the last iteration in a vector of strings or doubles respectively. The latest change is located at the highest index of the vector. An empty vector is returned if no changes were received at the outset of the current iteration.

7.6   Overloading the onRunState() and onIdleState() Functions    [top]


The onRunState() function is declared as a virtual function in the IvPBehavior superclass intended to be overloaded by the behavior author to accomplish the primary work of the behavior. The primary behavior output is the objective function. This is what drives the vehicle. The objective function is an instance of the class IvPFunction, and a behavior generates an instance and returns a pointer to the object in the following function:

    IvPFunction* onRunState()

This function is called automatically by the helm on the current iteration if the behavior is deemed to be in the running state, as depicted in Figure 7.2. The invocation of onRunState() does not necessarily mean an objective function is returned. The behavior may opt not to for whatever reason, in which case it returns a null pointer. However, if it does generate a function, the behavior is said to be in the active state. The steps comprising the typical implementation of the onRunState() implementation can be summarized as follows:

  • Get information from the info_buffer, and update any internal behavior state.
  • Generate any messages to be posted to the MOOSDB.
  • Produce an objective function if warranted.
  • Return.

    The same steps hold for the onIdleState() function except for producing an objective function. The first two steps have been discussed in detail. Accessing the info_buffer was described in Sections 7.5.2 - 7.5.4. The functions for posting messages to the MOOSDB from within a behavior were discussed in Section 7.5.1. Further issues regarding the posting of messages were covered in Section 6.5.4 The remaining issue to discuss is how objective functions are generated. This is covered in the IvPBuild Toolbox documentation.

7.7   Dynamic Behavior Spawning    [top]


In certain scenarios it may not be practical or possible to know in advance all the behaviors needed to accomplish mission objectives. For example, if the helm uses a certain kind of behavior to deal with another vehicle in its operation area, for collision avoidance or trailing etc., the identities or number of such vehicles may not be known when the mission planner is configuring the helm's behavior file. One way to circumvent this problem is to design a collision avoidance behavior, for example, to handle all known contacts. However, this has a couple drawbacks. It would entail a degree of multi-objective optimization be implemented within the behavior to produce an objective function that was comprehensive across all contacts. This would likely be much more computationally expensive than simply generating an objective function for each contact. It also may be advantageous to have different types of collision avoidance behaviors for different contact types or collision avoidance protocols. In any event, the helm support for dynamic behavior spawning gives behavior architects and mission planners another potentially powerful option for implementing an autonomy system.

7.7.1   Behavior Specifications Viewed as Templates    [top]


The templating parameter may be used to turn an otherwise static behavior specification into a template for spawning new behaviors dynamically after the helm has been launched. Instantiation requests are received via the updates parameter described in Section 7.2.5. Updates received through this variable are normally used to change behavior parameters dynamically, but they can be further used to request the spawning of a new behavior by including the following component:

    name = <new-behavior-name>

If the <new-behavior-name> is not the name of the behavior given in the behavior specification, and if it is not the name of a behavior already presently instantiated by the helm, the helm interprets this as a request to spawn a new behavior, if templating is enabled. Templating is enabled by including the following component in the behavior specification:

    templating = <templating-mode>

The <templating-mode> may be set to either "disallowed" (the default), "clone", or "spawn". In the "clone" mode, the helm will instantiate a behavior immediately upon helm startup. In the "spawn" mode, the helm will not instantiate a behavior until it receives a request to do so via the updates parameter as described above. An example of a behavior configured to allow dynamic spawning is given in Listing 34.1, taken from the Berta example mission.

    For a behavior configured with templating enabled in the "spawn" mode, the helm will not spawn a behavior at the helm startup time. However, internally it will indeed spawn such a behavior, check that it can be found and built as configured, and then destroy it immediately. This means that the behavior configuration found in the .bhv configuration file must not have an invalid configuration. It is preferable to know at helm launch time that a behavior is misconfigured, rather than waiting for the spawning event to occur perhaps hours into a mission and being surprised that a critical behavior, such as collision avoidance, failed to be spawned.

7.7.2   Behavior Completion and Removal from the Helm    [top]


All behaviors, whether statically spawned upon helm startup, or dynamically spawned during the mission, are capable of dying and being removed from the helm. Death and removal are part of the consequences of a behavior entering the completed state. Behavior run states were discussed in Section 6.5.3. A completed behavior configured with perpetual=true will not die upon completion. Once a behavior dies, its name is removed from the helm's internal registry of currently-spawned behaviors and a new behavior by the same name may be spawned at a future time.

7.7.3   Example Missions with Dynamic Behavior Spawning    [top]


Two example missions are provided that demonstrate the workings of dynamic behavior spawning, The Echo mission in Section 32, and the Berta mission in Section 34. The Echo mission involves a single vehicle with its helm configured to spawn dynamic behaviors of the type BHV_BearingLine. These behaviors do nothing more than post a viewable line segment to the MOOSDB between ownship and a point in the operation area. The interesting thing about this example is that the mission is configured with an event script (via uTimerScript) to automatically cue the spawning of 5000 behaviors over about one hour. Each behavior has a random duration of less than a minute, so behaviors are spawning and dying quite rapidly with visual confirmation via the viewable line segments.

    The second example mission, the Berta mission, involves two vehicles that are loitering near one another. Periodically their loiter assignments are randomly altered (again through uTimerScript). The change in loiter locations repeatedly puts them on an unpredictable and random near-collision course and each vehicle needs to spawn a collision avoidance behavior. The interesting thing about this scenario is that the behavior, the BHV_AvoidCollision behavior, is an actual behavior of common use, unlike the BHV_BearingLine behavior used in the Echo mission. This example also uses the pBasicContactMgr to coordinate the receiving of contact reports with helm behavior spawning.

7.7.4   Examining the Helm's Life Event History    [top]


Behavior spawning, and behavior completion and removal from the helm, are two types of life events the helm takes note of and posts in the MOOS variable IVPHELM_LIFE_EVENT. A third type of life event occurs when a behavior spawning is aborted due to either a syntax error or a name collision. Monitoring life events at run time is possible by scoping on the variable IVPHELM_LIFE_EVENT with either uXMS or uMS. A better method is available via the uHelmScope application. It automatically registers for the IVPHELM_LIFE_EVENT variable and will generate a formatted report like that shown in Listing 7.4. In the post-mission analysis phase, the aloghelm application may be used to examine the life event history and will generate the same formatted report from a given alog file.

Listing 7.4 - A Life Event History generated with either the uHelmScope or aloghelm utilities.

  1        ***************************************************
  2        *        Summary of Behavior Life Events          *
  3        ***************************************************
  4  
  5  Time    Iter  Event  Behavior      Behavior Type       Spawning Seed             
  6  ------  ----  -----  ------------  ------------------  ----------------------------
  7   47.84     1  spawn  loiter        BHV_Loiter          helm startup                
  8   47.84     1  spawn  waypt_return  BHV_Waypoint        helm startup                
  9   47.84     1  spawn  station-keep  BHV_StationKeep     helm startup                
 10  101.79   218  spawn  avd_henry     BHV_AvoidCollision  name=avd_henry#contact=henry
 11  161.20   423  death  avd_henry     BHV_AvoidCollision                              
 12  297.07   969  spawn  avd_henry     BHV_AvoidCollision  name=avd_henry#contact=henry
 13  351.80  1159  death  avd_henry     BHV_AvoidCollision                              
 14  461.37  1599  spawn  avd_henry     BHV_AvoidCollision  name=avd_henry#contact=henry
 15  516.51  1795  death  avd_henry     BHV_AvoidCollision                              
 16  644.94  2311  spawn  avd_henry     BHV_AvoidCollision  name=avd_henry#contact=henry
 17  704.31  2517  death  avd_henry     BHV_AvoidCollision                              
 18  730.02  2620  abort                BHV_AvoidCollision  name=avd_henry#foo=bar  
 19  825.17  3002  spawn  avd_henry     BHV_AvoidCollision  name=avd_henry#contact=henry

    The life event history shown in Listing 7.4 was taken from the Berta example mission, the "gilda" vehicle, described in Section 34. The time-stamp reported in column one is the elapsed time between the event and the time of the helm's startup. The first three events, in lines 6-8, reflect the three static behaviors spawned when the helm was launched, in first iteration of the helm. The collision avoidance behavior was spawned each time (lines 9, 11, 13 etc.) the vehicle "henry" came within sufficiently close range. Each time the "henry" vehicle passed and opened range to a sufficient amount, the collision avoidance behavior completed and died (lines 10, 12, 14, etc.). Line 17 shows an example of an aborted spawning. This was brought about purposely by poking the MOOSDB with the Spawning Seed shown for that line. Since the collision avoidance parameter does not have a parameter "foo", the spawning failed.

    Accessing the life event history via uHelmScope may be done by launching the scope with the vehicle's mission file, and hitting the 'L' key to toggle into the life event history mode. Or one may launch the scope directly into this mode via:

  uHelmScope --life targ_gilda.moos}

The same summary may also be accessed after mission completion via the log files:

  aloghelm --life gilda.alog

Note that perhaps not all life events will be displayed when using uHelmScope, depending on when it is launched relative to pHelmIvP. When uHelmScope connects to the MOOSDB it will only receive the latest and all following posts to the variable IVPHELM_LIFE_EVENT. If uHelmScope connects after pHelmIvP is launched and put into drive, it may have missed older postings. The initial spawning events do not occur in the helm until the helm enters the DRIVE state. (See Section 5.2 about helm state). In the example in Listing 7.4, the helm apparently was in the PARK state for about 48 seconds before it was put into drive and began to execute its first iteration. The full event history should always be accessible via the log file however.


Page built from LaTeX source using the texwiki program.