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_
...
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
- Can refer to a TethysL or XML script, that is, with
-
⟨body⟩
- One or more of:
redefineArg ⟨identifier⟩ = ⟨expression⟩
where:⟨identifier⟩
is an argument in the inserted file⟨expression⟩
is valid and with compatible units
- One or more of:
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.
- A literal string, e.g.,
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