Skip to content

Keywords

Note

  • This section mainly uses TethysL syntax for illustration, but the conceptual model of the language applies regardless of the particular syntax (XML or TethysL).
  • In general, the documentation structure for language constructs, keywords, grammar description, etc., is still being worked out.
  • For the notation used in various parts to this documentation, see Notation.

aggregate

todo: expand/review

The aggregate keyword starts one of the two possible top-level constructs in a mission script (the other one being a mission). The definition of an aggregate can also be embedded within a mission or other aggregate.

Examples:

aggregate AbortDrift {
  """
  Limit drifting period without receiving any acoustic signals.
  """

  arguments {
    AcousticTimeout = 96 hour
      """
      Drifting for longer than this period without receiving any acoustic
      signals will trigger the abort.
      """
  }

  run in parallel

  syslog info "Insert acoustic timeout set to " + AcousticTimeout~hour + "."

  behavior Guidance:AbortDrift {
    run in sequence
    set acousticTimeout = AcousticTimeout
  }

  behavior Guidance:Execute {
    run in sequence
    set command = "stop"
  }
}

Syntax: The general structure of an aggregate is:

aggregate ⟨id⟩ {
  ⟨testCode⟩?
  ⟨description⟩?
  ⟨defineArgs⟩?
  ⟨defineOutput⟩?
  ⟨runMode⟩?
  ⟨endRunGroup⟩?
  ⟨preemptive⟩?
  ⟨maTypeChoice⟩*
}

arguments

todo: expand/review

Starts a block where the arguments of a mission or aggregate are defined.

mission example {
  """
  Mission description.
  """

  arguments {
    MissionTimeout = 2 hour
      """
      Maximum duration of mission.
      """

    NeedCommsTime = 60 minute
      """
      How often to surface for communications.
      """

    ...
  }
  ...
}

assign

todo: expand/review

assign is one of the possible "statements" in the body of a mission or aggregate.

Examples:

mission example {
  arguments {
    MissionTimeout = 90 minute
      """
      Maximum duration of mission
      """
    ...
  }

  insert Insert/NeedComms id="NeedComms"

  assign in sequence NeedComms:DiveInterval = MissionTimeout
  ...

With a block of assignments:

mission example {
  ...
  insert Insert/StandardEnvelopes

  assign in sequence {
    StandardEnvelopes:MinAltitude = MinAltitude
    StandardEnvelopes:MaxDepth = MaxDepth
    StandardEnvelopes:MinOffshore = MinOffshore
  }
  ...

Syntax: As shown, assign has two main forms, one form with a single assignment, whose general form is:

assign  id = "str" ⟧?  ⟨runMode⟩  ⟨id⟩ = ⟨expression⟩

and one other form with a block of assignments:

assign  id = "str" ⟧?  ⟨runMode⟩ {
   ⟨id⟩ = ⟨expression⟩ ⟧+
}

This form is an extension in TethysL to capture multiple assignments with the same ⟨runMode⟩.


behavior

todo: expand/review

This keyword is used to invoke a particular LRAUV behavior.

Examples:

mission example {
  ...
  behavior Guidance:Point {
    run in parallel
    set heading = -135 degree
  }
  ...
}

break

todo: expand/review

Allows to terminate a behavior execution according to a given condition.

behavior Some:Behavior {
  run in parallel

  break if ( ⟨condition⟩ )

  set xyz = -135 degree
}

call

todo: expand/review

Calls an inserted mission or aggregate.

mission CallExample {
  arguments {
    someTime = 5 minute
  }

  insert _examples/defineBlock {
    redefineArg foo = someTime
  }

  call refId="defineBlock"

  call id="StartingMission" priorityHere=true refId="defineBlock"
    """
    A description of this call.
    """
}

The elements of a call construct are:

  • id: Optional. ...
  • priorityHere: Optional. ...
  • refId: Required. Indicates the mission or aggregate to call.
  • description: Optional. ...

called

todo: expand/review

This is a boolean expression that evaluates to true only when ...

Example:

mission CalledExample {
  ...
  aggregate GPSFIX {
    run when ( called )

    behavior Guidance:GoToSurface {
      run in progression
    }
    ...
  }
}

customUri

todo: expand/review

mission TestMission {
  arguments {
    MassDeadband = customUri "VerticalControl.massDeadband"
  }

  syslog "Rudder limit = " + customUri "HorizontalControl.rudLimit" ~ degree
}

destination

todo: expand/review

See sendData.


elapsed

todo: expand/review


elapsed_

todo: expand/review

Similar to elapsed, elapsed_ returns the elapsed time since the start of the mission item that contains the elapsed_ element.

In the following example:

mission TestMission {
  ...
  aggregate Test {
    ...
    output {
      elapsed = 0 second
    }
    run in sequence
    ...
    assign in parallel elapsed = elapsed_
    ...
that item would be the assign, which starts running in parallel as soon as the surrounding aggregate, aggregate Test, starts running in sequence.


insert

todo: expand/review

Similar to an import statement in various programming languages, this construct imports the aggregate or mission defined in another script at the location of the insert element.

The basic forms of this statement are:

  • insert ⟨filename⟩
  • insert ⟨filename⟩ { ⟨body⟩ }

where:

  • ⟨filename⟩:

    • Can refer to a TethysL or XML script, that is, with .tl or .xml file extension
    • The inserted script must exist and be valid
  • ⟨body⟩

    • One or more of: redefineArg ⟨identifier⟩ = ⟨expression⟩
      where:
      • ⟨identifier⟩ is an argument in the inserted file
      • ⟨expression⟩ is valid and with compatible units
mission example {
  ...

  insert Insert/Science

  ...

  insert Transport/transit {
    redefineArg MissionTimeout = 90 minute
    redefineArg Latitude = 36.8049 degree
    redefineArg Longitude = -121.8108 degree
    redefineArg MinOffshore = 750 meter
  }
  ...
}

Syntax: The general structure of an insert construct is:

insert  id = "str" ⟧?  ⟨filename⟩ ⟨block⟩?

⟨block⟩ = {
  ⟨description⟩?
   redefineArg ⟨identifier⟩ = ⟨expression⟩ ⟧+
}

isNaN

todo: expand/review


macro

TethysL includes syntax extensions that can significantly help capture similar constructs in a mission script with a concise, readable, and less error-prone syntax compared to the traditional XML based language. More details in this section.


mission

todo: expand/review

The mission keyword starts one of the two possible top-level constructs in a mission script (the other one being an aggregate).

Examples:

mission transit_1km {
  """
  Vehicle transits to the 1km waypoint.
  """

  insert Transport/transit {
    redefineArg MissionTimeout = 90 minute

    redefineArg NeedCommsTime = 40 minute

    redefineArg Latitude = 36.8156 degree

    redefineArg Longitude = -121.806 degree

    redefineArg MinOffshore = 300 meter
  }
}

Syntax: The general structure of a mission is:

mission ⟨id⟩ {
  ⟨testCode⟩?
  ⟨description⟩?
  ⟨defineArgs⟩?
  ⟨defineOutput⟩?
  ⟨endRunGroup⟩?
  ⟨maTypeChoice⟩*
}

Not

todo: expand/review


output

todo: expand/review

Starts a block defining the output parameters of a mission or aggregate.

mission example {
  ...
  arguments {
    ...
  }

  output {
    DoingComms = false
      """
      The mission sets this to true *before* the vehicle surfaces for comms.
      """

    StartFromSurface = true
      """
      The mission sets this to true *after* the vehicle surfaces for comms.
      """
  }
  ...
}

outputArg

todo: expand/review

Sets the value for an output parameter from a behavior output. See behavior.


preemptive

todo: expand/review

See aggregate.


priorityHere

todo: expand/review

See call.


readData

todo: expand/review

Examples:

readData {
  Universal:sea_water_salinity
  Universal:sea_water_temperature
}
readData strategy="MinError"  {
  while ( EnabledNeilBrown or EnabledSeabird )
  Universal:sea_water_temperature
  Universal:sea_water_salinity
}
readData  {
  while ( not ( Drifting ) and Universal:depth >= ScienceOnDepth )

  Universal:sea_water_temperature
  Universal:sea_water_salinity
  Universal:mass_concentration_of_chlorophyll_in_sea_water
  Universal:mass_concentration_of_oxygen_in_sea_water
}

Syntax: The general structure of a readData construct is:

readData  id = "str" ⟧?   strategy = "str" ⟧? {
  ⟨description⟩?
  ⟨while_⟩?
  ⟨endRunGroup⟩?
  ⟨intPerChoice⟩?
  ⟨idExpression⟩+
}

readDatum

todo: expand/review

Examples:

readDatum {
  Universal:latitude_fix
}
readDatum id="Read_GPS" {
  timeout duration=P5M
  Universal:time_fix
}
readDatum {
  timeout duration=P10S
  Science:ESPComponent.sample_number
}
readDatum {
  timeout duration=CANONSamplerTimeout {
    syslog important "Timed out sampling with CANONSampler."
  }
  Science:CANONSampler.sample_number
}

Syntax: The general structure of a readDatum construct is:

readDatum  id = "str" ⟧?  ⟨repeatGetsChoice⟩? {
  ⟨description⟩?
  ⟨endRunGroup⟩?
  ⟨idExpression⟩
}

redefineArg

todo: expand/review

See insert.


repeat

todo: expand/review

See readDatum.


run

todo: expand/review

Determines under which condition or execution mode to run the relevant construct.

Examples:

behavior Trigger:PeakDetectVsDepth {
  run in sequence
  outputArg out1 = deepBound
}
mission example {
  ...
  aggregate SurfaceOps {
    run in parallel
    ...
  }
}
mission example {
  ...
  behavior Guidance:Waypoint {
    run in sequence
    set latitude = 36.82 degree
  }
}
mission example {
  ...
  aggregate Loop {
    run in sequence repeat=72
    ...
  }
  ...
}
mission example {
  ...
  aggregate NeedComms {
    run when ( Universal:platform_pitch_angle > 0 degree and
               elapsed ( Universal:time_fix ) > 120 minute )

    ...
  }
  ...
}

sendData

todo: expand/review

sendData service=express (
  Control:HorizontalControl.latitudeCmd ~ degree,
  Control:HorizontalControl.longitudeCmd ~ degree
)

service

todo: expand/review

See syslog.


set

todo: expand/review

Allows to set the value for a behavior setting. See behavior.


syslog

todo: expand/review

Examples:

syslog "hello world"
syslog info "SkipComms = " + SkipComms~bool
syslog important service=express "newTime = " + newTime ~ second
syslog important "newTime = " + newTime~second
syslog "newTime = " + newTime ~ hour + " SkipComms = " + SkipComms~bool
syslog "Rudder limit = " + customUri "HorizontalControl.rudLimit" ~ degree

Syntax: syslog has the following form:

syslog ⟨severity⟩?   service = ⟨service-name⟩ ⟧?  ⟨contents⟩
  • ⟨severity⟩: One of: none, debug, info, error, important, fault, critical. By default, info.
  • ⟨service-name⟩: One of: direct, courier, express, priority, normal, bulk, count, multi. By default, the service is unspecified.
  • ⟨contents⟩ can be:
    • A literal string, e.g., "some value = ";
    • An identifier or customUri with desired reported units, e.g., newTime ~ second;
    • A concatenation of the above elements with the + operator.

test_code

Allows wrapping python code for mission testing purposes.

todo: expand/review

Section started with paraphrasing from the README under RegressionTests.

Regression test missions

Regression test missions are normal LRAUV missions, with the addition of python code wrapped in an test_code section. For example:

mission testFoo {
  test_code {{{
    # python code that sets value of "passed" variable, i.e.,
    passed = True
  }}}
  ...
}

One way to write a regression test is to just provide the above simple test script, and use when clauses in the mission with syslog critical elements that are activated when the mission goes awry. Any triggered syslog critical ... will cause the test mission to terminate, and fail the regression test.

Another way (which can be used in tandem with the above method) is to analyze the data from the simulation in the python procedure. Under the lrauv-application codebase, utility library classes are provided in Tools/regression, which do not need to be explicitly imported.

The most used library is Slate.py, which provides:

[array of data] = slate.read("var1", "var2", "var3")

Examples:

depth = slate.read("depth")[0]

(lats, lons) = slate.read("latitude", "longitude")

Missions run at faster-than-realtime speed during testing. However, if the tag valgrind is added after test_code and before the python code, then the mission is simulated with valgrind running in verbose mode, and will catch memory leaks and faults such as using uninitialized memory. Any fault or memory leak will cause the test to fail. Note that the simulation will run much more slowly, approaching real-time. So, test_code valgrind ... is recommended only for missions that will complete within a few minutes of real-time.

Running regression tests

Under the lrauv-application codebase, regression tests are run using Tools/regression/runTest.py. Without any arguments, all missions in the RegressionTests/ folder with filenames that start with the word "test". Optionally the path to a mission can be provided to run only that mission. If a 2nd argument is provided, the mission won't be run, but the python test code will be run using the logs from a previous run of the mission.

Syntax: test_code has the following form:

test_code  valgrind ⟧? {{{
   ⟨python-code⟩
}}}

timeout

todo: expand/review

mission timeout {
  arguments {
    timeout = 3.5 hour
  }

  timeout duration=timeout
}

touch

todo: expand/review

touch is similar to assign, except there is no right-hand-side expression for the identifier as only the time of last write is updated but the value is not changed (so, the effect is similar to a filesystem touch operation).

Example with Universal:platform_communications:

readDatum {
  timeout duration=P30M {
    touch in sequence Universal:platform_communications
  }
  Universal:platform_communications
}

valgrind

todo: expand/review

See test_code.


when

todo: expand/review

See run.


while

todo: expand/review

See run, readData.