Reel-out runs

The building blocks of examples/simple_opt_reelout.jl, in the order a run uses them.

Running an example script

SimpleKiteControllers.run_example — Function
run_example(file; inputs...)

include the example script file (relative to the package's examples/, or absolute) into Main with the keyword inputs, which the script reads with script_inputs; a plain include of the same script runs with its defaults. Returns what the include returns. A script started this way may itself run_example another one before it reads its own inputs: they are restored afterwards.

run_example("simple_opt_reelout.jl"; show_plots = false,
            tos_overrides = Dict{Symbol, Any}(:max_reopt => 0))
source
SimpleKiteControllers.script_inputs — Function
script_inputs(file, defaults::NamedTuple) -> NamedTuple

The inputs run_example passed to the script file (call it with @__FILE__), merged over defaults, which name every input the script takes. Only the script run_example was called on gets them, once: another script it includes gets its own defaults. A keyword the script does not take is an error.

source
SimpleKiteControllers.run_input_defaults — Function
run_input_defaults() -> NamedTuple

Every input a caller of simple_opt_reelout.jl may pass with run_example("simple_opt_reelout.jl"; ...) (see src/script_inputs.jl), at its default:

  • show_plots: draw the figures.
  • run_archive: copy the log and its inputs to output/archives/<stamp>/.
  • path_tr_project: a system project whose turn-rate table sizes the path, nothing for the run's own.
  • fcs_overrides, tos_overrides, wc_overrides, set_overrides: sweep and test overrides of the controller, optimizer, winch and plant settings.
  • steer_disturbance, xtrack_offset, xtrack_phase, hold_compliance: test inputs of the stability and cross-track analyses.
  • steer_gain_factor, steer_gain_feedback_only, extra_steer_delay, hook_settle: the V1 stability hook.
  • replay_paths: a scenario folder whose optimizer results are replayed.
  • output_path: where the log goes instead of output/, nothing for output/.
source
SimpleKiteControllers.muted — Function
muted(f)

Call f() with stdout and logging silenced, e.g. a run_example inside a sweep. Rebinds Base.stdout instead of redirect_stdout, which can only restore a file-backed stream and so fails, with stdout left on devnull, in a REPL whose stdout is a custom IO (e.g. Kaimon's).

source

Simulated-time budget

SimpleKiteControllers.reelout_budget — Function
reelout_budget(wind_speed, default_v_wind, sim_time; l_reel, kv, v_cap, wind_factor)
    -> (; time, below_knot, v_nominal)

Simulated time [s] to fly at the overriding wind_speed [m/s] (ground wind at h_ref).

At and above BUDGET_KNOT (the wind at BUDGET_HEIGHT, i.e. wind_speed * wind_factor) it is the reel-out budget: BUDGET_ENTRY, plus l_reel [m] of tether reeled out at BUDGET_REEL_MARGIN of the nominal speed v_nominal, plus BUDGET_TAIL. v_nominal is the winch's own law kv * sqrt(force) at the conservative force estimate BUDGET_F_COEF * (wind_speed * wind_factor)², capped by the drum's speed limit v_cap [m/s].

Below the knot, which the sqrt-law does not cover, it is sim_time [s] (the project's) scaled by the ratio of the project's default_v_wind to wind_speed, raised to BUDGET_BELOW_KNOT_EXPONENT when that ratio exceeds 1.

kv is the winch's kv and wind_factor the ratio of the wind at BUDGET_HEIGHT to the one at h_ref, from the project's profile law.

source
SimpleKiteControllers.sim_budget — Function
sim_budget(project, project_set, fcs, sim_time, wind_speed, default_v_wind) -> Union{Float64, Nothing}

Simulated time [s] to ask init for, and the message that says how it was chosen.

With no wind-speed override (wind_speed nothing) it is sim_time (nothing: the project's own). With one, it is reelout_budget, fed with the drum's v_sat from the project's winch file, the winch's kv from the same file and the wind factor at BUDGET_HEIGHT of the project's own profile law. project_set is the project's Settings, fcs its FC_Settings (for reelout_l_max) and default_v_wind the project's wind before the override.

source

Feasibility gates

SimpleKiteControllers.ReeloutFeasibility — Type
ReeloutFeasibility

The turn-rate coefficients and curvature margins a reel-out run's reference path is gated against, as returned by check_reelout_feasibility. c1, c2 and delay are NaN when the table could not serve the (body_damping, depower_setpoint) cell.

check_startup_path applies the abort policy on top of these verdicts: which check refuses the run and which only warns.

Fields

  • c1::Float64: Turn-rate gain of the pattern depower [1/m]

  • c2::Float64: Turn-rate coefficient c2 of the pattern depower [-]

  • delay::Float64: Steering delay of the pattern depower's turn-rate law [s]

  • feas_start::Union{Nothing, NamedTuple}: check_pattern_feasible at the starting tether length, nothing when c1 is NaN

  • feas_end::Union{Nothing, NamedTuple}: check_pattern_feasible at the maximum tether length, nothing when c1 is NaN

  • c1_final::Float64: Turn-rate gain at depower_final [1/m], NaN when unavailable or equal to the pattern's

  • feas_final::Union{Nothing, NamedTuple}: What phase 5 flies: the starting path lifted by el_offset_final, scored at reelout_l_max with c1_final; nothing when unavailable

source
SimpleKiteControllers.Phase5MarginState — Type
Phase5MarginState

Mutable state for the in-air phase-5 margin tracking during a run.

Fields

  • margin::Float64: Phase-5 margin of the installed path; NaN if not in the table

  • warned::Bool: Whether the one warning per run has been spent

source
SimpleKiteControllers.c1_at — Function
c1_at(f, phase) -> Float64

The turn-rate gain to score a path against at flight phase phase: from phase 5 that is f.c1_final (the depower flown then, ~22 % less authority than the pattern's), before that f.c1. Falls back to the pattern's c1 whenever the table could not serve depower_final.

source
c1_at(f, phase, c1) -> Float64

The turn-rate gain to check a path against at flight phase phase, given c1, the table's gain at the depower asked about: the depower a reply carries (a candidate's own, when scoring it) or the one currently flown (when sizing a request). From phase 5 that is depower_final's, c1_at(f, phase); before that c1, falling back to the startup law f.c1 when c1 is NaN, a depower the table cannot serve.

source
SimpleKiteControllers.phase5_margin — Function
phase5_margin(f, az, el) -> Float64

What phase 5 will fly a candidate path (az, el) with: its curvature margin at depower_final's c1 and at reelout_l_max, the length the final laps happen at. Evaluated at install time, because the path installed during the LAST reel-out lap is the one phase 5 inherits. NaN when the table could not serve depower_final.

NOT comparable to an install's own margin, which is read at the current length: early in the reel-out the two differ by length more than by depower, converging as the length approaches reelout_l_max. The number worth watching is the last one, where only the depower is left.

source
SimpleKiteControllers.check_reelout_feasibility — Function
check_reelout_feasibility(fec, fcs, tos; l_tether) -> ReeloutFeasibility

Score an optimized reference path against the three static gates a reel-out run needs, WITHOUT applying any policy: no error, no abort decision. Returns the verdicts; the caller decides what refuses the run and what only warns.

Checks performed (all reported via @info/@warn here):

  • elevation floor — the path's lowest elevation against fcs.run.min_elevation + tos.gates.candidate_elevation_margin;
  • ground clearance — check_pattern_height at l_tether, when tos.gates.min_height > 0;
  • turn-rate coefficients for (fcs.run.body_damping, depower) — depower is the one the pattern is FLOWN at, fcs.course.depower_setpoint unless the caller flies the optimizer's own, where a reply judged at the setpoint's c1 is off by c1(flown)/c1(setpoint), ~22 % at 0.33 against 0.274 (Cabauw 8 m/s, 2026-09-18); a cell the table cannot serve costs the diagnosis, not the run (warned, coefficients become NaN);
  • curvature at the STARTING length (the worst case for one fixed path) and at fcs.reelout.reelout_l_max, plus the dead-time context for fcs.pattern.attractor_dist;
  • phase 5 — the same path lifted by fcs.reelout.el_offset_final, scored at depower_final's own c1 (looked up separately; warned, not refused).
source
SimpleKiteControllers.check_startup_path — Function
check_startup_path(fec, fcs, tos; l_tether, depower = fcs.course.depower_setpoint)
    -> ReeloutFeasibility

The abort policy on the startup path installed in fec: the gates of check_reelout_feasibility that REFUSE a reel-out run rather than only warn, each an error that says why. Returns the verdicts when the path passes.

  • The ELEVATION floor, fcs.run.min_elevation + tos.gates.candidate_elevation_margin: this repo's own criterion is an angle and fig8_metrics fails a run that breaks it. AWETrim constrains height and not elevation, so this is not something the solve avoids on its own.
  • The clearance floor tos.gates.min_height at l_tether, when set: the optimizer earns part of its min_height by reeling out within the lap, which an installed (azimuth, elevation) curve does not, so it must be told here rather than flown past.
  • The curvature margin at the STARTING length against tos.gates.min_feasibility_margin, at the depower the pattern is FLOWN at (depower): the optimizer knows nothing of the V3's turn-rate law, so a path the kite cannot turn along is a plausible thing for it to return, and flying it measures the steering clamp instead of the path. Skipped when the table cannot serve depower (feas_start is nothing).
source

Run state and loop

SimpleKiteControllers.RunSetup — Type
RunSetup

Everything one reel-out run of examples/simple_opt_reelout.jl READS, built once by setup_run: the settings, the plant s, the winch and its controllers, the optimizer's conditions and session, and the laws the gates and the loop read. Every function of the run takes it as setup and reads setup.<field> or destructures it. The script never rebinds it; mutable members (fcs, wc, s, fec, the opt_*_log vectors, ...) are changed in place.

The last block of fields is filled later, by the startup solve (solve_startup_path!) and the startup gates (startup_feasibility), through merge_into!; until then they hold their defaults. The type parameters are the plant's type S, which the package does not know, and the two turn-rate laws, read every step, so that the loop compiles against their concrete types.

The block functions of the run read their fields by name only, so a NamedTuple with the fields a function reads serves as well (the unit tests build them that way).

Fields

  • inputs::NamedTuple: The caller's inputs, merged over the defaults

  • show_plots::Bool: Whether the run shows its plots at the end

  • steer_disturbance::Union{Nothing, Function}: Test input: t -> Δu added to the steering

  • xtrack_offset::Union{Nothing, Function}: Test input: τ -> δ [deg], the attractor moved along the path normal

  • xtrack_phase::Int64: The phase xtrack_offset starts in

  • hold_compliance::Union{Nothing, NamedTuple}: Test input: (; gain, τF, τpos) of a compliant hold in phase 5

  • steer_gain_factor::Float64: V1 hook: factor on the steering

  • steer_gain_feedback_only::Bool: The factor on the feedback part only

  • extra_steer_delay::Int64: V1 hook: extra steering delay [samples]

  • hook_settle::Float64: [s] after phase 4 began, when the V1 hooks start

  • replay_paths::Union{Nothing, String}: Scenario folder whose optimizer answers are replayed

  • project_name::String: Systemreelout*.yaml

  • turbulence::Union{Float64, String}: Level in [0, 1], or "default"

  • project::String: Its file

  • fcs::FC_Settings: The controller's settings, overrides applied

  • tos::TrajOptSettings: The optimizer's settings, overrides applied

  • project_set::KiteUtils.Settings: The kite's settings, the wind override applied

  • l_tether::Float64: [m] the starting tether length of the settings

  • effective_sim_time::Float64: [s] asked of init, see sim_budget

  • output_path::String: Where the log, the summary and the marker go

  • run_done_file::String: The finished-run marker, see write_run_done

  • log_name::String: The log's name, <log_file>_opt

  • wc::WinchControllers.WCSettings: The ONE winch settings of both winch loops

  • wpc::WinchControllers.WinchPosController: The length loop of the plant's winch

  • dt0::Float64: [s] 1 / sample_freq

  • rcs::WinchControllers.WCSettings: The same object as wc, as the reel-out controller reads it

  • s::Any: The plant, built by the caller's init_model

  • rc::WinchControllers.WinchController: The reel-out winch controller

  • f_high_nominal::Float64: [N] the force ceiling before the first-lap reduction

  • guard_lfc::WinchControllers.LowerForceController: The force floor before the reel-out

  • l_set::Real: [m] the settled length, as the plant reports it (Float32 for V3Kite); the startup request sends it unconverted

  • fec::FigureEightController: The path in the air and the guidance on it

  • inflow::SimpleKiteControllers.InflowConditions: The wind sent with every request

  • cap_wind::Float64: [m/s] the wind the pattern box is sized at

  • winch::SimpleKiteControllers.WinchParams: The winch sent with the startup solve

  • winch_first_lap::SimpleKiteControllers.WinchParams: The same under the first-lap force limit

  • winch_reopt::SimpleKiteControllers.WinchParams: The winch sent with the re-optimizations

  • el_center_seed_base::Float64: [deg] centre elevation of the shipped guess

  • el_center_seed::Float64: [deg] the seed's centre, after solve_startup_path! the one it converged from

  • opt_chain::SimpleKiteControllers.OptChain: The session with the optimizer, and its caches

  • opt_r_scale::Float64: [-] anchor ratio and headroom of the turn-radius request

  • opt_r_min::Union{Nothing, Float64}: [m] the startup turn-radius request; nothing when off

  • opt_r_on::Bool: Whether a turn radius is requested

  • opt_r_sent::Union{Nothing, Float64}: [m] the radius the startup solve was sent

  • opt_box::Union{Nothing, SimpleKiteControllers.PatternLimits}: The pattern box sent; nothing when off

  • opt_depower_log::Vector{NamedTuple}: Every reply's depower

  • power_gate_off::Function: Pred -> whether the power gates are bypassed for a prediction [W]

  • wing_lift::Function: (az, el) -> the lobe lift [deg] of an installed path

  • c1_at_depower::Any: Depower -> turn-rate gain c1 [1/m] of the path side; NaN off the table

  • c1_ctrl_at::Any: Depower -> c1 [1/m] of the controller's table; NaN off it

  • c1_setpoint::Float64: [1/m] c1 at the depower setpoint, the loop's tuning point

  • c1_depower_max::Float64: [-] the highest depower of the controller's table

  • pattern_depower::Function: Reply -> the depower its path is flown at

  • el_floor::Float64: [deg] the elevation floor of every candidate path

  • startup_seed_offset::Float64: [deg] offset of the seed the startup solve converged from

  • guess_az::Vector{Float64}: That seed's guess, azimuth [deg]

  • guess_el::Vector{Float64}: That seed's guess, elevation [deg]

  • opt_startup_solve_s::Float64: [s] wall time of the startup solve

  • feas::Union{Nothing, ReeloutFeasibility}: The startup gates' verdict

  • margin5::Union{Nothing, Phase5MarginState}: The in-air phase-5 check

  • c1_at_phase::Union{Nothing, Function}: (phase, depower | st) -> c1 [1/m] to check a path against

  • phase5_margin_at::Union{Nothing, Function}: (az, el) -> the margin phase 5 flies a path with

source
SimpleKiteControllers.RunState — Type
RunState

Everything the startup functions and the simulation loop of examples/simple_opt_reelout.jl WRITE, in one place, so they take it as an argument (st) instead of rebinding script globals. The loop-only bookkeeping is grouped as in the loop. startup_feasibility and reelout_results.jl read the fields as st.<field>, and so does DelayedInjection in validate_margins.jl, during the loop: st is the one global of the run's state. Plain data: no model type, so the package can define it without depending on the model.

Fields

  • opt_result::Union{Nothing, SimpleKiteControllers.StepReply}: The reply the run flies (startup, or the retry that took over)

  • opt_table::Union{Nothing, Dict{String, Any}}: Its /trajectory table

  • opt_downloops::Union{Nothing, Bool}: Whether the flown path turns downwards in the loops, from its /trajectory table

  • opt_power_pred::Float64: [W] predicted mean reel-out power of the installed path

  • opt_paths_raw::Vector{Tuple{Vector{Float64}, Vector{Float64}}}: Every optimizer answer as it arrived, before any lift

  • opt_paths_at::Vector{Tuple{Float64, Int64}}: (sim time [s], phase) each of those was installed at

  • opt_r_scale::Union{Nothing, Float64}: Anchor ratio x headroom of the turn-radius request

  • opt_r_min::Union{Nothing, Float64}: [m] turn-radius request, or nothing

  • opt_box_now::Union{Nothing, SimpleKiteControllers.PatternLimits}: Pattern limits sent with the last re-optimization request

  • incumbent_score::Union{Nothing, @NamedTuple{margin::Float64, el_ok::Bool, clr_ok::Bool, height::Float64, ok::Bool}}: Score of the best startup path so far

  • inc_result::Union{Nothing, SimpleKiteControllers.StepReply}: The reply of the best startup path so far (the incumbent)

  • inc_table::Union{Nothing, Dict{String, Any}}: The incumbent's /trajectory table

  • inc_raw::Union{Nothing, Tuple{Vector{Float64}, Vector{Float64}}}: The incumbent's path as the optimizer sent it

  • startup_wing_frac::Float64: Share of the lobe lift the startup path could carry

  • c1_startup::Float64: [-] turn-rate gain the startup path is checked against

  • depower_flown_opt::Float64: [-] rel_depower the optimizer asked for

  • n_path_initial::Int64: Number of points of the path installed before the run

  • path_min_h_start::Float64: Lowest height of the startup path at the starting tether length [m]

  • az_c_path::Float64: Azimuth centre of the startup path [deg]

  • el_c_path::Float64: Elevation centre of the startup path [deg]

  • az_amp_path::Float64: Azimuth half-width of the startup path [deg]

  • el_height_path::Float64: Elevation span (peak to peak) of the startup path [deg]

  • pred_timeline::Vector{@NamedTuple{t::Float64, power::Float64}}: (; t, power): which path was flown when

  • p5_history::Vector{@NamedTuple{t::Float64, az::Vector{Float64}, el::Vector{Float64}, raw::Tuple{Vector{Float64}, Vector{Float64}}, margin::Float64, el_applied::Float64}}: Every path flown, for the phase-5 fallback

  • p5_fallback_done::Bool: Checked once, from the stop latch on, at the next crossing

  • p5_q_az_prev::Float64: [deg] Q's azimuth from the path centre, last step

  • p5_fallback::Union{Nothing, @NamedTuple{t::Float64, from_margin::Float64, to_margin::Float64, to_t::Float64}}: (; t, frommargin, tomargin, to_t) when a fallback was blended in

  • ccs::Union{Nothing, CourseControllerSettings}: Course controller settings

  • cc::Union{Nothing, CourseController}: Course controller

  • l_set::Float64: [m] tether length setpoint

  • transition_start::Float64: [s] time phase 3 began; reelout_delay counts from it

  • stop_start::Float64: [s] time the soft-stop deceleration latched; NaN = not yet

  • stop_v_entry::Float64: [m/s] v_set at the moment it latched

  • stop_dp_entry::Float64: [-] rel_depower at the moment it latched

  • stop_T::Float64: [s] duration of the linear decel to reach 0 at reeloutlmax

  • reelout_started::Bool: True once the gate has opened; LATCHED, never re-closes

  • reelout_start_t::Float64: [s] time it opened; the soft-start ramp counts from here

  • reelout_trigger_fired::Bool: True if the FORCE trigger opened it, not the timer

  • reelout_done::Bool: True once either stop criterion has ended reel-out

  • stop_reason::String: "length", "laps", or "" if reel-out never stopped

  • final_start::Float64: [s] time phase 5 began; the run ends fcs.reelout.final_time after it

  • e_mech::Float64: [Wh] running mechanical energy, logged for the viewer

  • first_lap_f_high_applied::Bool: Whether the first-lap reduction of the upper force limit is in force

  • ff_log::Vector{Float64}: [-] feed-forward steering per step

  • ff_chi_log::Vector{Float64}: [rad] chord correction per step

  • ff_u_filt::Float64: [-] low-passed feed-forward steering

  • ff_chi_filt::Float64: [rad] low-passed chord correction

  • dp_final_extra::Float64: [-] phase-5 force limiter's depower above depower_final

  • dp_final_extra_peak::Float64: [-] the most it asked for, for the summary

  • rel_depower_prev::Float64: [-] depower commanded last step; the gain reads c1 there

  • depower_flown::Float64: [-] current blended output

  • depower_blend_from::Float64: Depower the current blend started from [-]

  • depower_blend_to::Union{Nothing, Float64}: Depower the current blend goes to [-]; nothing when none is in progress

  • depower_blend_t0::Float64: Time the current depower blend started [s]

  • fig8_n::Int64: Live lap count: 0 before phase 4, 1 at first entry, +1 per traversal

  • fig8_idx_prev::Int64: Index of Q on the path at the previous step

  • fig8_idx_progress::Float64: Path points Q has advanced since phase 4 began, for the lap count

  • n_path::Int64: Number of points of the installed path

  • raw_az::Union{Nothing, Vector{Float64}}: Azimuth of the reference TRACKING is scored against [deg]

  • raw_el::Union{Nothing, Vector{Float64}}: Elevation of the reference TRACKING is scored against [deg]

  • chk_points::Int64: Resolution the path in the air is checked at

  • el_applied::Float64: [deg] lift the path in the air actually carries

  • lift_on::Bool: el_offset_final latched in; never cleared once set

  • el_shift_events::Vector{NamedTuple}: In-air shift attempts, one per outcome CHANGE

  • lift_t::Float64: [s] when it latched; NaN = never

  • lift_remaining::Float64: [m] of reel-out left at that moment

  • el_shift_warned::Bool: A held-back shift warns once

  • el_shift_lap::Int64: Lap of the last in-air shift attempt

  • el_shift_target::Float64: Elevation target of the last in-air shift attempt [deg]

  • geom_t::Vector{Float64}: Time of each logged step [s]

  • geom_az_c::Vector{Float64}: Azimuth centre of the pattern asked for at each step [deg]

  • geom_az_amp::Vector{Float64}: Azimuth half-width of the pattern asked for at each step [deg]

  • geom_el_h::Vector{Float64}: Elevation span of the pattern asked for at each step [deg]

  • geom_d_raw::Vector{Float64}: Cross-track error to the scored reference

  • n_droop_bins::Int64: Number of |azimuth| bins of the droop statistics: where in the pattern the kite ends up low

  • droop_n::Vector{Int64}: Number of samples in each |azimuth| bin

  • droop_flown::Vector{Float64}: [deg] kite below the path's elevation centre

  • droop_ref::Vector{Float64}: [-] depth of the path at Q, in half-spans

  • droop_sag::Vector{Float64}: [deg] kite below the path at Q

  • reopt_pending::Bool: A solve is queued on the server

  • reopt_n::Int64: Solves completed, accepted or rejected

  • reopt_lap::Float64: Lap count at which the last request went out

  • reopt_next_poll::Float64: [s] next /status poll

  • reopt_t_request::Float64: [s] when the pending request went out

  • reopt_blocked_s::Float64: [s] wall time spent frozen waiting for a reply

  • reopt_last_solve_s::Float64: [s] wall time the last blocking wait took

  • reopt_events::Vector{NamedTuple}: One row per solve, for the run summary

  • reopt_t_wall_request::Float64: [s] time() when the cycle's first request went out

  • reopt_cycles::Vector{NamedTuple}: (; t, l, status, wall_s) per completed cycle

  • blend_retries_total::Int64: Cold-restart attempts spent on a rejected reply

  • challenges_total::Int64: Cold challenger solves run against an accepted reply (challenge_growth)

  • challenges_won::Int64: Challenger solves that were installed instead of the reply they challenged

  • el_min_extra::Float64: [deg] shortfall of the last reply gated out; carried across cycles

  • blend_from::Union{Nothing, Tuple{Vector{Float64}, Vector{Float64}}}: The path the blend in progress starts from; fold-free across w in [0, 1]

  • blend_to::Union{Nothing, Tuple{Vector{Float64}, Vector{Float64}}}: The path the blend in progress goes to

  • blend_t0::Float64: Time the blend in progress started [s]

  • raw_from::Union{Nothing, Tuple{Vector{Float64}, Vector{Float64}}}: The scored reference's endpoint the SAME blend starts from

  • raw_to::Union{Nothing, Tuple{Vector{Float64}, Vector{Float64}}}: The scored reference's endpoint the blend goes to

  • t_phase4::Float64: [s] time phase 4 was first reached this run; NaN before that

  • xt_start::Float64: [s] first step of phase xtrack_phase; τ counts from here

  • hold_f_lp::Float64: [N] low-passed force of the compliant hold

  • hold_l0::Float64: [m] length the compliant hold began at

  • dist_t::Vector{Float64}: [s] time of each disturbed step

  • dist_d::Vector{Float64}: [-] disturbance added

  • dist_u::Vector{Float64}: [-] steering sent to the model, controller plus disturbance

  • steer_delay_buf::Vector{Float64}: FIFO of the raw steering commands, kept full of the last extra_steer_delay of them from the start of the run, so it is already primed with real history by the time the hook switches on. The feed-forward goes through a FIFO of its own, so the two stay aligned.

  • ff_delay_buf::Vector{Float64}: FIFO of the feed-forward steering, delayed like steer_delay_buf

  • xt_t::Vector{Float64}: [s] time of each phase-5 step

  • xt_delta::Vector{Float64}: [deg] offset commanded

  • xt_d::Vector{Float64}: [deg] signed cross-track error to the unshifted path, right of travel > 0

  • xt_q::Vector{Int64}: [-] index of the closest path point Q

  • xt_phase::Vector{Int64}: [-] flight phase, and the operating point for the model:

  • xt_L::Vector{Float64}: [m] tether length

  • xt_va::Vector{Float64}: [m/s] apparent wind speed

  • xt_vk::Vector{Float64}: [m/s] kite speed normal to the tether

  • xt_dp::Vector{Float64}: [-] depower

  • fig8m::Union{Nothing, NamedTuple}: The scored verdict, once reelout_results has it

  • opt_power_meas::Union{Nothing, Float64}: [W] measured mean reel-out power, or nothing

  • archive_dir::String: The run's archive folder, "none" until (or unless) it exists

source
SimpleKiteControllers.step_commands! — Function
step_commands!(st, setup, plant, t) -> (; rel_depower, rel_steering, v_set, phase, guide, cmd)

Everything of one step of the reel-out loop before the model is stepped: the attractor guidance (guide, from navigate_fig8, with the cross-track test input), the steering and depower (cmd, see steering_command!), the lift target, the lap count, the re-optimization, the path blends, the phase-5 fallback, the winch setpoint v_set and the steering hooks. plant is the model as read at the start of the step, see the top of this file.

source
SimpleKiteControllers.record_step! — Function
record_step!(st, setup, plant, t, commands)

After step!, which overwrites parts of sys_state: the controller's view of the step in the log's slots (commands from step_commands!), the path geometry logs and the running e_mech.

source

Run log and startup retries

SimpleKiteControllers.with_run_log — Function
with_run_log(f, path; min_level = Info)

Run f() with its log messages shown as usual and also written to path, message by message, so the file is complete up to a crash. A throw is written as a last [ Error: the run threw: … line and rethrown. The parent folder is created. Returns what f returns.

source
SimpleKiteControllers.startup_ladder_report — Function
startup_ladder_report(log) -> NamedTuple

What a run log of simple_opt_reelout.jl (log is the file written by with_run_log, or its text) says about the two retry paths of the startup:

  • seed_retries: startup solves sent again from another seed after a 422 (startup_retry_el_offsets), and seed_offset, the offset the solve converged from (nothing for the shipped guess);
  • ladder: whether retry_startup! ran, at margin_in against the gate gate, and per attempt attempts, lever => outcome with the outcome "422", "took over", "took over, cleared", "no better" or "below a floor" (each with its margin), and stopped when the levers ran out;
  • margin_start: the startup margin the run went on with, and threw, the first line of the error a run that stopped there threw (nothing otherwise).

ladder_line(report) is the one-line form.

source
SimpleKiteControllers.ladder_line — Function
ladder_line(report) -> String

startup_ladder_report in one line, e.g. startup: ladder at margin 0.979 < 1.30, 4 retries [radius correction: 422, ceiling step: 422, …], levers spent; flew margin 1.04; threw ….

source
SimpleKiteControllers.startup_log_lines — Function
startup_log_lines(log) -> Vector{String}

The startup section of a run log (see with_run_log), as two runs of the same code with the same optimizer answers write it: the messages up to the first progress line of the loop (step …), without their continuation lines, without the optimizer client's transport messages (RE_TRANSPORT, which differ between a server run and a cached one), and with wall times (… s), file time stamps, the folder of saved trajectories (…/trajectories/, which differs between checkouts) and the SimpleKiteControllers. prefix of printed types (shown only when Main does not import the type) masked.

source