1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306 | # Copyright (c) 2026 MBARI
# MBARI Proprietary Information. Confidential. All Rights Reserved
# Unauthorized copying or distribution of this file via any medium is strictly
# prohibited.
#
# WARNING - This file contains information whose export is restricted by the
# Export Administration Act of 1979 (Title 50, U.S.C., App. 2401 et seq.), as
# amended. Violations of these export laws are subject to severe civil and/or
# criminal penalties.
aggregate TerrainAvoidance {
"""
Terrain avoidance: runs the vertical overrides that the backseat TA module commands.
Use with Insert/StandardEnvelopes.tl. Insert it below StandardEnvelopes and BackseatDriver.
TA commands only with Shadow = false here and shadow: false in the backseat config.
Backseat sends _.verticalCmdMode (-1 none, 1 stop, 2 depth, 5 pitch, 100 back off),
_.depthCmd (meter) and _.pitchCmd (radian, positive = nose up).
"""
arguments {
VerticalCmdTimeout = 15 second
"""Max time without a backseat command before the override is cancelled."""
ReverseSpeed = -1 meter_per_second
"""Astern speed during a back-off."""
PublishPeriod = 2 second
"""How often the TA params below are re-published to the backseat."""
# Backseat module params, published as _.ta*. The backseat rejects all four
# altitudes unless abort <= min <= caution and min <= target.
TargetAltitude = 35 meter
"""Fly height above the seafloor (module h_target). Keep above MinAltitude."""
CautionAltitude = 25 meter
"""Arms a blind climb below this when both sensors drop out (module h_caution). Keep above MinAltitude."""
AvoidMinAltitude = 15 meter
"""Module escalates below this (module h_min). Keep above MinAltitude."""
AbortAltitude = 12 meter
"""Below this, the backseat backs off, then the insert stops the mission (only with AllowAbort; module h_abort). Keep above MinAltitude."""
MaxClimbAngle = 20 degree
"""Max climb angle (module gamma_max_deg)."""
LookAheadRange = 100 meter
"""Terrain look-ahead range (module profile_range_m)."""
NominalSpeed = 1 meter_per_second
"""Cruise speed the module assumes (module nominal_speed_mps)."""
MinActiveDepth = 5 meter
"""Shallower than this, the backseat starts no override and releases one in progress (a started back-off completes). A pitch override also stops here (module min_active_depth_m)."""
Shadow = true
"""true = backseat only decides and logs. false = allow TA commands (backseat config must allow them too)."""
AllowAbort = false
"""false = TA starts no back-off or stop; it climbs instead. A back-off already started still ends in a stop."""
}
output {
VerticalOverrideMode = -1 count
DepthSetpoint = NaN meter
PitchAngle = NaN radian
ParamsLogged = false
Armed = false
# Last backseat mode logged as ignored, so that each one is logged once.
IgnoredMode = -1 count
# Same codes as _.verticalCmdMode.
NormalMode = -1 count
StopMode = 1 count
DepthMode = 2 count
PitchMode = 5 count
BackoffMode = 100 count
}
run in parallel
# The slate var age is reset by every message, also one with an unchanged mode.
aggregate VerticalCmdTimeout {
run when (
elapsed ( customUri "_.verticalCmdMode" ) >= VerticalCmdTimeout
and VerticalOverrideMode != NormalMode
)
assign in sequence VerticalOverrideMode = NormalMode
syslog fault "TerrainAvoidance: backseat went silent during an override, returning control to the mission."
}
# Only commands received after arming count, so a stale command from an
# earlier mission or from shadow is never used.
aggregate Arm {
run when ( not Shadow and not Armed )
assign in sequence DepthSetpoint = NaN meter
assign in sequence PitchAngle = NaN radian
assign in sequence IgnoredMode = NormalMode
assign in sequence Armed = true
}
aggregate Disarm {
run when ( Shadow and Armed )
assign in sequence Armed = false
assign in sequence IgnoredMode = NormalMode
}
aggregate ModeCmd {
run while (
Armed
and not Shadow
and elapsed ( customUri "_.verticalCmdMode" ) < elapsed ( Armed )
and elapsed ( customUri "_.verticalCmdMode" ) < VerticalCmdTimeout
)
aggregate UpdateVerticalMode {
run when (
customUri "_.verticalCmdMode" != VerticalOverrideMode
and ( customUri "_.verticalCmdMode" == NormalMode
or ( ( AllowAbort or VerticalOverrideMode == BackoffMode )
and customUri "_.verticalCmdMode" == StopMode )
or customUri "_.verticalCmdMode" == DepthMode
or customUri "_.verticalCmdMode" == PitchMode
or ( AllowAbort and customUri "_.verticalCmdMode" == BackoffMode ) )
)
assign in sequence VerticalOverrideMode = customUri "_.verticalCmdMode"
assign in sequence IgnoredMode = NormalMode
syslog important "TerrainAvoidance: mode updated to " + VerticalOverrideMode~count
}
# The latched mode sent again ends a run of ignored modes, so the next one is logged.
aggregate ClearIgnored {
run when (
customUri "_.verticalCmdMode" == VerticalOverrideMode
and IgnoredMode != NormalMode
)
assign in sequence IgnoredMode = NormalMode
}
# For example from an older backseat.
aggregate UnknownCmd {
run when (
customUri "_.verticalCmdMode" != IgnoredMode
and customUri "_.verticalCmdMode" != NormalMode
and customUri "_.verticalCmdMode" != StopMode
and customUri "_.verticalCmdMode" != DepthMode
and customUri "_.verticalCmdMode" != PitchMode
and customUri "_.verticalCmdMode" != BackoffMode
)
assign in sequence VerticalOverrideMode = NormalMode
assign in sequence IgnoredMode = customUri "_.verticalCmdMode"
syslog fault "TerrainAvoidance: unknown backseat mode " + IgnoredMode~count + ", override released."
}
# A back-off already latched still ends in a stop.
aggregate AbortDisabledCmd {
run when (
not AllowAbort
and VerticalOverrideMode != BackoffMode
and VerticalOverrideMode != StopMode
and customUri "_.verticalCmdMode" != IgnoredMode
and ( customUri "_.verticalCmdMode" == StopMode
or customUri "_.verticalCmdMode" == BackoffMode )
)
assign in sequence IgnoredMode = customUri "_.verticalCmdMode"
syslog important "TerrainAvoidance: AllowAbort = false, ignoring backseat mode " + IgnoredMode~count
}
}
aggregate UpdateDepth {
run when (
Armed
and elapsed ( customUri "_.depthCmd" ) < elapsed ( Armed )
and elapsed ( customUri "_.depthCmd" ) < elapsed ( DepthSetpoint )
)
assign in sequence DepthSetpoint = customUri "_.depthCmd"
}
aggregate UpdatePitch {
run when (
Armed
and elapsed ( customUri "_.pitchCmd" ) < elapsed ( Armed )
and elapsed ( customUri "_.pitchCmd" ) < elapsed ( PitchAngle )
)
assign in sequence PitchAngle = customUri "_.pitchCmd"
}
aggregate ShadowIgnoreCmd {
run when (
Shadow
and elapsed ( customUri "_.verticalCmdMode" ) < VerticalCmdTimeout
and customUri "_.verticalCmdMode" != IgnoredMode
)
assign in sequence IgnoredMode = customUri "_.verticalCmdMode"
syslog important "TerrainAvoidance: Shadow = true, ignoring backseat mode " + IgnoredMode~count
}
aggregate ShadowRelease {
run when (
Shadow
and VerticalOverrideMode != NormalMode
)
assign in sequence VerticalOverrideMode = NormalMode
syslog important "TerrainAvoidance: Shadow = true, override released."
}
# Re-publish so a backseat that starts late still gets the params.
aggregate PublishTAParams {
run when (
elapsed ( customUri "_.taTargetAltitude" ) > PublishPeriod )
assign in sequence customUri "_.taTargetAltitude" = TargetAltitude
assign in sequence customUri "_.taCautionAltitude" = CautionAltitude
assign in sequence customUri "_.taMinAltitude" = AvoidMinAltitude
assign in sequence customUri "_.taAbortAltitude" = AbortAltitude
assign in sequence customUri "_.taMaxClimbAngle" = MaxClimbAngle
assign in sequence customUri "_.taLookAheadRange" = LookAheadRange
assign in sequence customUri "_.taNominalSpeed" = NominalSpeed
assign in sequence customUri "_.taMinActiveDepth" = MinActiveDepth
assign in sequence customUri "_.taShadow" = Shadow
assign in sequence customUri "_.taAllowAbort" = AllowAbort
}
aggregate LogTAParams {
run when ( not ParamsLogged )
syslog info "TerrainAvoidance params: target " + TargetAltitude~meter
+ ", caution " + CautionAltitude~meter
+ ", min " + AvoidMinAltitude~meter
+ ", abort " + AbortAltitude~meter
+ ", climb " + MaxClimbAngle~degree
+ ", range " + LookAheadRange~meter
+ ", speed " + NominalSpeed~meter_per_second
+ ", min active depth " + MinActiveDepth~meter
+ ", shadow " + Shadow~bool
+ ", allow abort " + AllowAbort~bool
assign in sequence ParamsLogged = true
}
aggregate StopMission {
run when ( VerticalOverrideMode == StopMode )
syslog critical "TerrainAvoidance: backseat abort, stopping mission."
}
# Hockey stop. No pitch angle: astern with the nose up moves the vehicle down.
aggregate BackoffOverride {
run while ( VerticalOverrideMode == BackoffMode and not isNaN ( DepthSetpoint ) )
behavior Guidance:SetSpeed {
run in parallel
set speed = ReverseSpeed
}
behavior Guidance:Pitch {
run in parallel
set depth = DepthSetpoint
}
}
aggregate DepthOverride {
run while ( VerticalOverrideMode == DepthMode and not isNaN ( DepthSetpoint ) )
behavior Guidance:Pitch {
run in parallel
set depth = DepthSetpoint
}
}
# Backstop: the backseat itself releases shallower than MinActiveDepth.
aggregate PitchOverride {
run while (
VerticalOverrideMode == PitchMode
and not isNaN ( PitchAngle )
and Universal:depth > MinActiveDepth
)
behavior Guidance:Pitch {
run in parallel
set pitch = PitchAngle
}
}
}
|