Skip to content

Insert/TerrainAvoidance.tl

  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
    }
  }
}