Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
5336847
Lift/drag validation of V3Kite against the AWETrim ROM
ufechner7 Oct 27, 2026
50f051d
validate_lift_drag: request_timeout, name the AWETrim branch in the e…
ufechner7 Oct 27, 2026
2ed1530
install_awetrim: install the feat/server-aero-forces branch
ufechner7 Oct 27, 2026
cbca9ca
validate_lift_drag: info message at the start
ufechner7 Oct 27, 2026
0022e7d
JETLS: no type inlay hints, from .JETLSConfig.toml.default
ufechner7 Oct 27, 2026
8e7418c
validate_lift_drag: compare drag on AWETrim's basis, VSM wing + all b…
ufechner7 Oct 27, 2026
8fabed5
Fly every AWETrim request against rom_config_aerostructural2.yaml
ufechner7 Oct 28, 2026
a992f61
validate_lift_drag: only the ROM trim, no query at V3Kite's angle of …
ufechner7 Oct 28, 2026
b0c6b4c
validate_lift_drag: 1.60 m instead of 1.58 m, inside the ROM's validi…
ufechner7 Oct 28, 2026
6ffbd43
Note: the lift/drag validation compares two different trim conditions
ufechner7 Oct 28, 2026
5bdb1e5
Depower seed 1.6 -> 1.5 m: the startup solve converges on rom_config_…
ufechner7 Oct 28, 2026
240de86
Startup on rom_config_aerostructural2: box 36x15, guess 32x14, guess-…
ufechner7 Oct 28, 2026
b946d3e
Add SKIP_WINDS
ufechner7 Oct 30, 2026
6dbe2f0
Update overview
ufechner7 Oct 30, 2026
6a99b69
validate_masses.jl: masses of V3Kite vs. AWETrim's model
ufechner7 Oct 30, 2026
edc039a
AWETrim flies V3Kite's bridle mass, 1.62 kg; 26x11 startup retry
ufechner7 Oct 30, 2026
035908e
Update Maasvlakte overview: 5 m/s with the 1.62 kg bridle
ufechner7 Oct 30, 2026
ddeeca4
kv 0.030 at 3-4 m/s: Maasvlakte 4 m/s flies with the 12.62 kg wing
ufechner7 Oct 30, 2026
b148356
Update Maasvlakte overview: 4 m/s with kv 0.030
ufechner7 Oct 30, 2026
0c20bba
kv 0.020 at 3-3.5 m/s: Maasvlakte 3.5 m/s flies with the 12.62 kg wing
ufechner7 Oct 30, 2026
790da1d
Update Maasvlakte overview: 3.5 m/s with kv 0.020
ufechner7 Oct 30, 2026
1198de9
Update Maasvlakte overview: 8.5 m/s with the 1.62 kg bridle
ufechner7 Oct 30, 2026
02bc86a
first_lap_force_frac 0.93 -> 0.96: Maasvlakte 9 m/s flies with the 12…
ufechner7 Oct 30, 2026
83d3718
Update Maasvlakte overview: 9 m/s with first_lap_force_frac 0.96
ufechner7 Oct 30, 2026
4254fc8
High-wind shape: no symmetry, no climb limit from 12.5 m/s aloft
ufechner7 Oct 31, 2026
da5eff1
Update Maasvlakte overview: 10 m/s with the high-wind shape
ufechner7 Oct 31, 2026
01f736e
High-wind start length: Maasvlakte 11 m/s starts at 180 m
ufechner7 Oct 31, 2026
2f5af60
Update Maasvlakte overview: 11 m/s starting at 180 m
ufechner7 Oct 31, 2026
4400e19
Update overviews: Maasvlakte 6-8.25 m/s and Cabauw 5-7 m/s reflown
ufechner7 Oct 31, 2026
2a4a407
reel_in_beta 20 -> 22: Cabauw 3 m/s flies with kv 0.020
ufechner7 Oct 31, 2026
296b570
Update Cabauw overview: 3 m/s with reel_in_beta 22
ufechner7 Oct 31, 2026
124312b
Startup length retry; high-wind start at 170 m
ufechner7 Oct 31, 2026
8e9863a
Update overviews: Cabauw 4 m/s and Maasvlakte 11 m/s at 170 m
ufechner7 Oct 31, 2026
2fcd0c8
Angle-of-attack floor -7°, the ROM's validity
ufechner7 Oct 31, 2026
94b4fcb
Update Cabauw overview: 8 m/s with the angle-of-attack floor
ufechner7 Oct 31, 2026
68a5306
Cabauw 9 and 10 m/s: high-wind box 45° x 20°, 2.0 laps from 16.5 m/s …
ufechner7 Nov 1, 2026
22e0919
Update Cabauw overview: 9 and 10 m/s with the high-wind box
ufechner7 Nov 1, 2026
67536a2
Dpn't skip
ufechner7 Nov 1, 2026
2b5f1b1
A cached startup seed uses up its retry
ufechner7 Nov 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .JETLSConfig.toml.default
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@ match_by = "code"
match_type = "literal"
severity = "off"
path = "examples/**/*.jl"

# No inferred-type inlay hints in the editor; the `end`-tag hints stay.
[inlay_hint.types]
enabled = false
30 changes: 23 additions & 7 deletions bin/install_awetrim
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
# Copyright (c) 2026 Uwe Fechner
# SPDX-License-Identifier: MIT
#
# bash script to install the develop branch of https://github.com/awegroup/AWETrim
# in the folder ../AWETrim
# bash script to install the feat/server-aero-forces branch of
# https://github.com/awegroup/AWETrim in the folder ../AWETrim. That branch is
# develop plus the POST /aero_forces endpoint examples/validate_lift_drag.jl
# needs; switch BRANCH back to develop once it is merged.
#
# AWETrim is a Python project, so it gets its own venv with the dev and server
# extras installed in editable mode; bin/run_server (here and in AWETrim) expects
Expand All @@ -14,7 +16,9 @@
#
# Re-running the script is safe: an existing checkout is fetched and fast-forwarded
# rather than re-cloned, and the venv is only created if it is missing. A checkout
# with local modifications is left alone apart from the dependency install.
# with local modifications is left alone apart from the dependency install. A
# branch that exists only in the local checkout (not pushed yet) is checked out
# as it is.
#
# At the end the optimizer's two caches in output/ are cleared (the failed-request
# cache opt_failure_cache.yaml and the solution cache opt_chain_cache/): their keys
Expand All @@ -24,7 +28,7 @@
set -euo pipefail

REPO_URL="https://github.com/awegroup/AWETrim"
BRANCH="develop"
BRANCH="feat/server-aero-forces"
TARGET="../AWETrim"

if [[ $(basename "$(pwd)") == "bin" ]]; then
Expand All @@ -49,12 +53,23 @@ fi
# --- clone or update ----------------------------------------------------------
if [[ -d $TARGET/.git ]]; then
echo "Found an existing checkout in $(cd "$TARGET" && pwd), updating it ..."
git -C "$TARGET" fetch origin "$BRANCH"
on_origin=false
if git -C "$TARGET" ls-remote --exit-code --heads origin "$BRANCH" >/dev/null 2>&1; then
on_origin=true
git -C "$TARGET" fetch origin "$BRANCH"
elif ! git -C "$TARGET" rev-parse --verify --quiet "refs/heads/$BRANCH" >/dev/null; then
echo "ERROR: branch $BRANCH is neither on origin nor in the local checkout." >&2
exit 1
fi
if [[ -n $(git -C "$TARGET" status --porcelain) ]]; then
echo "WARNING: the checkout has local modifications, skipping the branch update." >&2
else
git -C "$TARGET" checkout "$BRANCH"
git -C "$TARGET" merge --ff-only "origin/$BRANCH"
if $on_origin; then
git -C "$TARGET" merge --ff-only "origin/$BRANCH"
else
echo "Branch $BRANCH is not on origin; using the local branch as it is."
fi
fi
elif [[ -e $TARGET ]]; then
echo "ERROR: $TARGET exists but is not a git repository." >&2
Expand Down Expand Up @@ -89,4 +104,5 @@ echo "Clearing the optimizer caches in $RKC_ROOT/output ..."
rm -f "$RKC_ROOT/output/opt_failure_cache.yaml"
rm -rf "$RKC_ROOT/output/opt_chain_cache"

echo "Done. Start the AWETrim server with bin/run_server"
echo "Done. Start the AWETrim server with bin/run_server start;"
echo "a server that is already running keeps the old code until bin/run_server restart."
12 changes: 11 additions & 1 deletion data/fc_settings_reelout.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ fc_settings:
winch: # compliance of the force-mode winch (its gains are in wc_settings.yaml) and force guards
compliance: 0.0 # Fixed at POSITION mode; REEL_OUT needs the drum free [-]
entry_f_min: 350.0 # Entry-guard (guard_lfc) force floor, phases 0-2; not wc's f_low [N]
first_lap_force_frac: 0.93 # f_high x this in lap 1 AND for the startup solve; 1.0 = no lap-1 de-rating [-]
first_lap_force_frac: 0.96 # f_high x this in lap 1 AND for the startup solve; 1.0 = no lap-1 de-rating;
# 0.93 until 2026-10-31, see docs/fig8_tuning_log.md [-]

reelout: # REEL_OUT winch and phase 5; kv/f_low/f_high/v_sat are in wc_settings.yaml
reelout_l_max: 380.0 # Length at which reel-out stops; AWETrim's reopt ceiling is ~325 m [m]
Expand Down Expand Up @@ -123,6 +124,11 @@ fc_settings:
low_wind_speeds: [4.51, 5.15, 5.80, 6.40] # Wind speed at low_wind_height, ascending [m/s]
low_wind_l_tether: [195.0, 195.0, 195.0, 150.0] # Tether length reel-out starts at; less guidance phase lag [m]
low_wind_guess_el_center: [25.0, 27.0, 27.0, 29.0] # Startup guess; 29° at 195 m lands in a 470 W optimum [deg]
# With the 12.62 kg wing the Maasvlakte 11 m/s (14.2 at 100 m) startup has no solution at 150 m
# and converges from 160 m up (2026-10-31); 10 m/s (12.9) flies at 150 m.
high_wind_speed: 14.0 # Wind speed at low_wind_height from which reel-out starts at the length below; 0 = off [m/s]
high_wind_l_tether: 170.0 # Tether length reel-out starts at from high_wind_speed on; 160 failed the curvature
# gate at Maasvlakte 11 m/s, 180 laps >= 2.5 at Cabauw 8 m/s (2026-10-31) [m]

run: # simulation conditions and pass criteria
vsm_interval: 5 # Steps between VSM aero updates, 1 = tightest; at 10 the identification flights sink at depower 0.375 (2026-10-02) [-]
Expand All @@ -133,3 +139,7 @@ fc_settings:
entry_time: 62.0 # Settle time after park_time before the metrics [s]
min_elevation: 6.5 # Floor criterion over the WHOLE run; also the reopt install gate [deg]
min_span_frac: 0.7 # Pattern-SIZE criterion, fraction of f8_a / f8_b [-]
min_laps: 2.5 # Laps criterion: figure-eight laps in the scored window [-]
min_laps_high: 2.0 # The same from min_laps_high_wind on: Cabauw 9 and 10 m/s fly 30-32 s laps from
# their shortest feasible starts, 170 and 180 m, i.e. 2.0 laps (2026-11-01) [-]
min_laps_high_wind: 16.5 # Wind speed at low_wind_height from which min_laps_high applies; 0 = off [m/s]
39 changes: 30 additions & 9 deletions data/traj_opt.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,27 @@ traj_opt:
free_speed_reference_points: 6 # free_speed solves for the reference power AFTER the run; 0 = off [-]

guess: # initial guess; seeds a multi-modal solve: changes the answer, not the run time
guess_a: 30.0 # width of the guess; azimuth spans ±guess_a [deg]
guess_b: 12.0 # height of the guess, peak to peak [deg]
guess_a: 32.0 # width of the guess; azimuth spans ±guess_a [deg]
guess_b: 14.0 # height of the guess, peak to peak [deg]
guess_el_center: 29.0 # centre elevation of the guess; first knob to move on a 422 [deg]
guess_el_center_high: 30.0 # centre elevation at/above the ref wind (a step, not a ramp) [deg]
guess_el_center_wind_ref: 8.0 # wind at/above which guess_el_center_high applies [m/s]
startup_retry_el_offsets: [-1.0, 2.0, -2.0] # seeds tried in order on a startup 422; [] never retries [deg]
# Guess sizes [guess_a, guess_b] tried at the base centre on a startup 422, before the offsets.
# rom_config_aerostructural2 (2026-10-28): 32x14 converges at 5, 6, 8, 8.25 m/s, 30x13 at 7, 8,
# 8.25 and 34x15 at 5, 6, 7, 8.25 m/s; no single size covers all; 26x11 at 5 m/s with the
# 12.62 kg wing (bridle 1.62 kg, 2026-10-30) where all the others fail [deg]
startup_retry_guess_sizes: [[30.0, 13.0], [34.0, 15.0], [26.0, 11.0]]
# Added to the starting tether when every seed above fails, and the model set up again there.
# Cabauw 4 m/s (2026-10-31) has no startup solution at 150, 155 or 160 m and converges at 165-175 m;
# Cabauw 10 m/s none at 160, 170 or 175 m and one at 180 m [m]
startup_retry_length_steps: [10.0, 20.0]

seed: # depower seed of the solve, ramped with the wind
input_depower: 1.6 # depower SEED in metres of tape (server bounds 1.1-2.3), not depower_setpoint [m]
input_depower: 1.5 # depower SEED in metres of tape (server bounds 1.1-2.3), not depower_setpoint [m]
input_depower_wind_ref: 7.0 # wind at which input_depower IS the seed [m/s]
input_depower_per_wind: 0.25 # tape added per m/s above that; one-sided [m/(m/s)]
input_depower_per_wind: 0.0 # tape added per m/s above that; one-sided; 0.25 seeded 8 m/s at 1.75 m, which
# fails on rom_config_aerostructural2 where 1.5 m converges [m/(m/s)]
input_depower_seed_max: 1.85 # ramp ceiling, below the server's 2.3 m [m]
# Estimate of the tape length the startup reply is FLOWN at, which sizes the turn-radius
# request; 0 takes the seed above. Fitted 2026-10-05 to the startup replies of the base
Expand All @@ -39,17 +49,21 @@ traj_opt:
depower_offset: 0.0 # [-]

box: # pattern box the optimizer solves UNDER; 0.0 keeps the server default (|az| <= 45.8, 0.6 <= el <= 51.6)
pattern_azimuth_max: 28.0 # closes the wide basin seen at 5.5 m/s; good runs fly ±18-25 [deg]
pattern_azimuth_max_high: 34.0 # cap at/above pattern_elevation_amplitude_max_wind_ref: under the 45° climb
pattern_azimuth_max: 36.0 # 28 until 2026-10-28; rom_config_aerostructural2 turns ~43 % less and needs a
# wider and taller box: no startup solve at 5-8.25 m/s under 28 x 8.5 [deg]
pattern_azimuth_max_high: 45.0 # cap at/above pattern_elevation_amplitude_max_wind_ref; 36 until 2026-10-31:
# Cabauw 9 m/s (17.4 there) converges at 170 m and 10 m/s (19.3) at 180 m only
# with 45 and a 20° half-span cap. Older: under the 45° climb
# limit Cabauw 10 needs ±28.4-28.8° at 150 m and IPOPT 2-3° of room: 422 under
# 28 and 29 at r_min 22.8 m, under 30 at 23.5 m (quadratic depower
# conversion); converges under 31 and 32 (2026-10-03). 36 -> 34 (2026-10-05):
# at 36 the re-optimizations at Cabauw 10 grew to ±32° x 21°, RMS d 1.61°;
# at 34 ±22° x 16°, RMS d 1.44°, 22.7 instead of 20.4 kW [deg]
pattern_elevation_amplitude_max: 8.5 # largest elevation HALF-SPAN of the figure; 0.0 = off [deg];
pattern_elevation_amplitude_max: 15.0 # largest elevation HALF-SPAN of the figure; 0.0 = off; 8.5 until 2026-10-28 [deg];
# 8.0 left Maasvlakte 3.5 m/s infeasible at 8.12° (2026-09-24)
pattern_elevation_amplitude_max_high: 13.0 # cap at/above the ref wind (a step, not a ramp) [deg]
pattern_elevation_amplitude_max_wind_ref: 13.2 # wind AT the height below at/above which the high cap
pattern_elevation_amplitude_max_high: 20.0 # cap at/above the ref wind (a step, not a ramp); 15 until 2026-10-31 [deg]
pattern_elevation_amplitude_max_wind_ref: 16.5 # 13.2 until 2026-10-31, when the high caps equalled the base ones.
# Older: wind AT the height below at/above which the high cap
# applies: Maasvlakte 10 m/s is 12.9 there and flies under
# 8°, Maasvlakte 11 (14.2) and Cabauw 7-10 (13.5-19.3) need
# 10° or the startup solve loses its basin (2026-09-21);
Expand All @@ -59,6 +73,13 @@ traj_opt:
pattern_symmetric: true # mirror-symmetric figure about azimuth 0; the solve is multi-modal and
# otherwise lands lopsided (Cabauw 2026-09-25: centre -2.3°, lobes 214/147 points)
pattern_climb_angle_max: 45.0 # steepest climb of the path in the az/el plane; descending is free; 0 is off [°]
pattern_shape_wind_ref: 12.5 # wind at pattern_elevation_amplitude_max_wind_height at/above which the two
# _shape_high values below apply; 0 = off. With the 12.62 kg wing Maasvlakte
# 10 m/s (12.9 there) converges only without both (2026-10-31); 9 m/s is 11.6 [m/s]
pattern_symmetric_shape_high: false # pattern_symmetric at/above pattern_shape_wind_ref
pattern_climb_angle_max_shape_high: 0.0 # pattern_climb_angle_max at/above pattern_shape_wind_ref; 0 is off [°]
angle_of_attack_min: -7.0 # lowest trim angle of attack, the ROM's validity; .nan = the server's 0°, under which
# Cabauw 9 m/s (trims at -0.5 to +0.4°) has no solution (2026-10-31) [°]

gates: # every returned path, at startup and after a re-optimization
min_feasibility_margin: 0.82 # curvature gate AND request (as min_turn_radius); 0.0 = off; an 8 m/s number [-]
Expand Down
10 changes: 5 additions & 5 deletions data/wc_settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ wc_settings:
max_acc: 8.0 # rate limit of v_set; the reel-out's acceleration_limit [m/s^2]
damage_factor: 0.2 # winch damage weighting (unused here) [-]
jerk_factor: 0.9 # jerk weighting in the damage calculation (unused here) [-]
# kv: `v_set = kv * sqrt(force)`, one value at every wind speed. It used to be
# a column of winch_kv_table.yaml (now winch_table.yaml), flat at 0.0408 from 3 to 12 m/s, and was
# removed from there 2026-10-02. The 10 m/s row was 0.039, identified
# kv: `v_set = kv * sqrt(force)`. Since 2026-10-30 the kv column of winch_table.yaml
# overrides this value (0.030 at 3-4 m/s, see there); before, it was flat at 0.0408 from
# 3 to 12 m/s and was no column from 2026-10-02. The 10 m/s row was 0.039, identified
# 2026-08-27 (sweep below), and went back to the sweep's other passing value
# 2026-09-22 — see the note under the sweep. 11 and 12 m/s fly 0.0408
# UNTESTED at the current tether and winch controller: the 2026-08-26 notes
Expand Down Expand Up @@ -122,7 +122,7 @@ wc_settings:
# 3.42 m/s mean, on the limit, so kv cannot lower its force: 0.043 made the
# startup solve infeasible (2026-09-23). There the lever is f_high, see
# docs/fig8_tuning_log.md.
kv: 0.0408 # v_set = kv * sqrt(force); same at every wind speed, see above [-]
kv: 0.0408 # v_set = kv * sqrt(force); the kv column of winch_table.yaml overrides it [-]

# --- SPEED: how the force limits are enforced (PlanWinchSpeed.md, stage 4) --
force_limit: "soft" # "soft" (optimizer's tension curve) | "hard" (two limiters); winch_table.yaml overrides
Expand All @@ -131,6 +131,6 @@ wc_settings:
v_sat_beta: 10.0 # corner sharpness of the v_sat clamp; .inf = hard clamp [s/m]
soft_lfc: true # also replace the LowerForceController with a reel-in line
v_reel_in: -2.0 # reel-in speed at zero force [m/s]
reel_in_beta: 20.0 # sharpness of the line/curve handover; needs * kv * sqrt(f_low) >= 8 everywhere [s/m]
reel_in_beta: 22.0 # sharpness of the line/curve handover; needs * kv * sqrt(f_low) >= 8 everywhere [s/m]
use_awe_trim: 0.0 # blend of the LOCAL law towards AWETrim's curve, in [0, 1]; the server gets opt_awe_trim [-]
force_limit_tau: 1.0 # low-pass on the force before inverting; 0 = off [s]
29 changes: 26 additions & 3 deletions data/winch_table.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
# Wind-dependent winch-law parameters, interpolated linearly between rows and
# CLAMPED outside the identified range rather than extrapolated. Read by
# `winch_f_low(v_wind)` and `winch_force_limit(v_wind)`; each overrides the flat
# value of the same name in data/wc_settings.yaml. `kv` is no longer a column:
# it was 0.0408 at every wind speed, so the flat `kv` of data/wc_settings.yaml
# is used as is (its tuning notes moved there). Add a row and re-identify the curve
# value of the same name in data/wc_settings.yaml. Add a row and re-identify the curve
# here, not a new key elsewhere, when another wind speed is tuned.
#
# kv — gain of the reel-out law v_set = kv*sqrt(force), read by `winch_kv(v_wind)`
# (its tuning notes are at `kv` in data/wc_settings.yaml). It was flat at
# 0.0408 and no column from 2026-10-02 until 2026-10-30, when the kite got
# its 1.62 kg bridle (12.62 kg wing): the 4 m/s startup request then has no
# solution under the pattern box at 0.0408 or 0.050, and converges at 0.030
# (2967 W) and 0.025 (3074 W), so 0.030 at 4 m/s, the measured value closest
# to the old one. 3.5 m/s fails at 0.030, 0.025, 0.018 and 0.023 and converges
# from 0.019 to 0.022 (1.73-1.67 kW), so 0.020 at 3.5 and, untested, at 3 m/s.
# The 5 m/s row holds 0.0408 so that 5 m/s and up fly as before.
#
# f_low — force floor [N] below which the LowerForceController reels in. It has
# to move with the wind because the winch's rating does not and the
# kite's force does (with the square of the wind speed), so one value
Expand Down Expand Up @@ -51,23 +59,38 @@ entries:
- v_wind: 3.0
f_low: 350.0
force_limit: "soft"
kv: 0.020
- v_wind: 3.5
f_low: 525.0
force_limit: "soft"
kv: 0.020
- v_wind: 4.0
f_low: 700.0
force_limit: "soft"
kv: 0.030
- v_wind: 5.0
f_low: 700.0
force_limit: "soft"
kv: 0.0408
# Neutral for f_low (already flat from 4 to 9); force_limit is
# "soft" throughout the table now, so this row no longer marks a step.
- v_wind: 6.0
f_low: 700.0
force_limit: "soft"
kv: 0.0408
- v_wind: 9.0
f_low: 700.0
force_limit: "soft"
kv: 0.0408
- v_wind: 10.0
f_low: 700.0
force_limit: "soft"
kv: 0.0408
- v_wind: 11.0
f_low: 700.0
force_limit: "soft"
kv: 0.0408
- v_wind: 12.0
f_low: 700.0
force_limit: "soft"
kv: 0.0408
Loading
Loading