# `Monty.Frameworks.Models.MotorSystem.SurfacePolicyActionDetailsTelemetry`
[🔗](https://github.com/d-led/ex.tbp.monty/blob/v0.1.0/packages/ex_tbp_monty_core/lib/monty/frameworks/models/motor_system/surface_policy_action_details_telemetry.ex#L1)

What a surface policy wants remembered about the actions it just chose.

Mirrors `tbp/monty/frameworks/models/motor_system.py::SurfacePolicyActionDetailsTelemetry`.
One entry per step, in the order the steps happened:

  * `pc_heading` — which principal curvature the policy headed for, `"min"`,
    `"max"`, `"no"` or `"jump"`, or `nil` when it is not a surface move;
  * `avoidance_heading` — whether the step was one of the policy's moves to
    get out of a tight spot;
  * `z_defined_pc` — the principal curvature vectors the policy used.

Monty keeps this on the motor system because there is nowhere else for it to
go yet ("TODO: Get rid of this once we have another path for telemetry"), and
the same is true here.

# `pc_heading`

```elixir
@type pc_heading() :: :min | :max | :no | :jump | nil
```

# `t`

```elixir
@type t() :: %Monty.Frameworks.Models.MotorSystem.SurfacePolicyActionDetailsTelemetry{
  avoidance_heading: [boolean() | nil],
  pc_heading: [pc_heading()],
  z_defined_pc: [term()]
}
```

# `append`

```elixir
@spec append(t(), term()) :: t()
```

Adds one step's worth of telemetry, at the end.

A step with no telemetry adds nothing, which is what keeps the three lists the
same length as the list of steps that had a surface policy.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
