Skip to content

Commit f22c28e

Browse files
authored
Add function vsm_settings, aero_geometry_settings and struc_geometry_settings (#99)
- [x] Add function vsm_settings_file - [x] Add docstrings - [x] Add example load_extra_settings.jl - [x] Add fpc_settings.yaml for the example above - [x] Add script reuse_lint - [x] Add aero_geometry_file and structure_geometry_file - [x] Fix JETLS warnings - [x] Update documentation
1 parent dab207c commit f22c28e

16 files changed

Lines changed: 206 additions & 21 deletions

REUSE.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ version = 1
44
path = ["data/settings.yaml", "data/settings_cabauw.yaml", "data/system.yaml", "data/system_cabauw.yaml",
55
"data/settings2.yaml", "data/system2.yaml", "data/Test_flight.arrow", "data/transition.arrow2",
66
"data/failure_low_right.csv", "data/transition.csv", "data/failure_low_right.arrow",
7-
"data/failure_low_right.arrow2", "data/sim_log.arrow", "data/transition.arrow"]
7+
"data/failure_low_right.arrow2", "data/sim_log.arrow", "data/transition.arrow", "data/fpc_settings.yaml"]
88
SPDX-FileCopyrightText = "2025 Uwe Fechner, Bart van de Lint"
99
SPDX-License-Identifier = "CC-BY-4.0"
1010

data/fpc_settings.yaml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# settings for the 20 qm kite (just as example for an extra settings file)
2+
fpc_settings:
3+
dt: 0.025 # time step of the flight path controller
4+
log_level: 2 # log level, 0=quiet
5+
prn: false
6+
prn_ndi_gain: false
7+
prn_est_psi_dot: false
8+
prn_va: false
9+
use_radius: true
10+
use_chi: true
11+
12+
reset_int1: true # reset the main integrator to the last estimated turn rate
13+
reset_int2: false # reset the integrator of the D part at the second time step
14+
reset_int1_to_zero: true
15+
init_opt_to_zero: false # if the root finder should start with zero
16+
17+
p: 20 # P gain of the PID controller
18+
i: 1.2 # I gain of the PID controller
19+
d: 10 # D gain of the PID controller
20+
gain: 0.04 # additional factor for P, I and D
21+
c1: 0.0612998898221 # was: 0.0786
22+
c2: 1.22597628388 # was: 2.508
23+
24+
k_c1: 1.6 # correction factor, used by the NDI block; increase k_c1, if the radius is too small;
25+
k_c2: 6.0 # C2 for the reelout phase was: 7.0
26+
k_c2_high: 12.0 # C2 for the reelout phase at high elevation angles was: 14.0
27+
k_c2_int: 0.6 # C2 for the intermediate phase LOW_RIGHT, LOW_TURN, LOW_LEFT
28+
k_ds: 2.0 # influence of the depower angle on the steering sensitivity

data/system.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,7 @@ system:
33
wc_settings: "wc_settings.yaml" # settings of the winch controller
44
fpc_settings: "fpc_settings.yaml" # flight path controller settings
55
fpp_settings: "fpp_settings.yaml" # flight path planner settings
6+
vsm_settings: "vsm_settings.yaml" # vortex step model settings
7+
aero_geometry: "aero_geometry.yaml" # aerodynamic geometry
8+
structural_geometry: "structural_geometry.yaml" # structural geometry
69

docs/src/developer_notes.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ They run `jetls check` for `src/` and `examples/` respectively.
7070

7171
## More effective development with AI tools using Kaimon
7272

73-
It is suggested to install Kaimon if you are using AI tools like Claude or Github Copilot. It allows faster
73+
It is suggested to install Kaimon if you are using AI tools like Claude or GitHub Copilot. It allows faster
7474
development and reduces the token usage (energy and costs).
7575

7676
See: https://github.com/kahliburke/Kaimon.jl
@@ -128,6 +128,6 @@ ollama pull qwen3-embedding:0.6b
128128

129129
The Search tab will show a health indicator for both services. If either is not running, the indicator turns red with an error message.
130130

131-
Before you can search, index the project. From the Search tab press m (manage), than a (add) and enter the path
131+
Before you can search, index the project. From the Search tab press m (manage), then a (add) and enter the path
132132
for each project you want to index. Then press i (index). To index one project might take 10 minutes, but you have
133133
to do that only once.

docs/src/functions.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ copy_examples
1515
se
1616
se_dict
1717
sync_wind!
18+
wc_settings
19+
fpc_settings
20+
fpp_settings
21+
vsm_settings_file
22+
aero_geometry_file
23+
structural_geometry_file
1824
```
1925
Also look at the default example: [settings.yaml](https://github.com/ufechner7/KiteUtils.jl/blob/main/data/settings.yaml) .
2026

examples/Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ ControlPlots = "23c2ee80-7a9e-4350-b264-8e670f12517c"
33
KiteUtils = "90980105-b163-44e5-ba9f-8b1c83bb0533"
44
KiteViewers = "2e593061-95e7-45e4-95f4-df0491f2e601"
55
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
6+
Parameters = "d96e819e-fc66-5662-9728-84c9c7592b0a"
67
REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
78
Rotations = "6038ab10-8711-5258-84ad-4b1120ba62dc"
89
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
10+
StructTypes = "856f2bd8-1eba-4b0a-8007-ebc267875bd4"
911

1012
[sources]
1113
KiteUtils = {path = ".."}

examples/load_extra_settings.jl

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# SPDX-FileCopyrightText: 2022 Uwe Fechner
2+
# SPDX-License-Identifier: MIT
3+
4+
# example of loading extra settings
5+
using KiteUtils, Parameters, StructTypes
6+
using KiteUtils.YAML
7+
8+
@with_kw mutable struct FPCSettings @deftype Float64
9+
dt::Float64 = 0.02
10+
log_level::Int64 = 2
11+
prn::Bool = false
12+
prn_ndi_gain::Bool = false
13+
prn_est_psi_dot::Bool = false
14+
prn_va::Bool = false
15+
use_radius::Bool = true
16+
use_chi::Bool = true
17+
reset_int1::Bool = true
18+
reset_int2::Bool = false
19+
reset_int1_to_zero::Bool = true
20+
init_opt_to_zero::Bool = false
21+
p = 20.0
22+
i = 1.2
23+
d = 10.0
24+
gain = 0.04
25+
c1 = 0.0612998898221 # was: 0.0786
26+
c2 = 1.22597628388 # was: 2.508
27+
k_c1 = 1.6
28+
k_c2 = 6.0
29+
k_c2_high = 12.0
30+
k_c2_int = 0.6
31+
k_ds = 2.0
32+
end
33+
34+
StructTypes.StructType(::Type{FPCSettings}) = StructTypes.Mutable()
35+
36+
if basename(pwd()) == "examples"
37+
set_data_path("../data")
38+
else
39+
set_data_path("data")
40+
end
41+
42+
# update the fields of fcs from a config file with the same field names
43+
# the config file is expected to be in YAML format
44+
function update(fcs::FPCSettings)
45+
config_file = joinpath(get_data_path(), fpc_settings())
46+
if Sys.iswindows()
47+
config_file = replace(config_file, "/" => "\\")
48+
end
49+
if ! isfile(config_file)
50+
println("Warning: $config_file not found, using default settings.")
51+
return
52+
end
53+
dict = YAML.load_file(config_file)
54+
sec_dict = Dict(Symbol(k) => v for (k, v) in dict["fpc_settings"])
55+
StructTypes.constructfrom!(fcs, sec_dict)
56+
end
57+
58+
fcs = FPCSettings()
59+
update(fcs)

src/KiteUtils.jl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export Logger, MyFloat, Settings, SysLog, SysState
5050

5151
import Base.length
5252
import ReferenceFrameRotations as RFR
53+
5354
export demo_log, demo_state, demo_syslog, export_log, import_log, load_log, save_log # functions for logging
5455
export euler2rot, length, log!, menu, syslog
5556
export demo_state_4p, initial_kite_ref_frame # functions for four point kite model
@@ -58,9 +59,11 @@ export acos2, quat2euler, quat2viewer, wrap2pi # geome
5859
export fromEG2W, fromENU2EG, fromEX2EG, fromKS2EX, fromW2SE # reference frame transformations
5960
export azn2azw, calc_clock_angle, calc_course , calc_heading, calc_heading_w # geometric functions
6061
export calc_orient_rot, enu2ned, is_right_handed_orthonormal, ned2enu
61-
export wind_vec_from_angles, angles_from_wind_vec
62+
export angles_from_wind_vec, wind_vec_from_angles
6263
export copy_settings, get_data_path, load_settings, set_data_path # functions for reading and copying parameters
63-
export fpc_settings, fpp_settings, se, se_dict, update_settings, wc_settings
64+
export aero_geometry_file, fpc_settings, fpp_settings, se, se_dict,
65+
structural_geometry_file, update_settings,
66+
vsm_settings_file, wc_settings
6467
export calculate_rotational_inertia
6568
export AbstractKiteModel
6669
export init!, next_step!, update_sys_state!

src/settings.jl

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,9 @@ function Base.setproperty!(set::Settings, sym::Symbol, val)
358358
setfield!(set, sym, Float64(val))
359359
elseif sym == :wind_vec && !(val isa SVec3) &&
360360
val isa AbstractVector
361+
if length(val) != 3
362+
throw(ArgumentError("wind_vec must be an AbstractVector of length 3"))
363+
end
361364
setfield!(set, sym,
362365
SVec3(val[1], val[2], val[3]))
363366
else
@@ -530,24 +533,96 @@ function update_settings(dict, sections, settings=SETTINGS)
530533
StructTypes.constructfrom!(settings, result)
531534
end
532535

536+
"""
537+
wc_settings(project=PROJECT)
538+
539+
Get the winch controller (WC) settings filename from the project file.
540+
541+
Returns the filename specified in the `wc_settings` field of the system section.
542+
The project file defaults to the currently active PROJECT.
543+
"""
533544
function wc_settings(project=PROJECT)
534545
# determine which wc_settings to load
535546
dict = YAML.load_file(joinpath(DATA_PATH[1], project))
536547
dict["system"]["wc_settings"]
537548
end
538549

550+
"""
551+
fpc_settings(project=PROJECT)
552+
553+
Get the flight path controller (FPC) settings filename from the project file.
554+
555+
Returns the filename specified in the `fpc_settings` field of the system section.
556+
The project file defaults to the currently active PROJECT.
557+
"""
539558
function fpc_settings(project=PROJECT)
540559
# determine which fpc_settings to load
541560
dict = YAML.load_file(joinpath(DATA_PATH[1], project))
542561
dict["system"]["fpc_settings"]
543562
end
544563

564+
"""
565+
fpp_settings(project=PROJECT)
566+
567+
Get the flight path planner (FPP) settings filename from the project file.
568+
569+
Returns the filename specified in the `fpp_settings` field of the system section.
570+
The project file defaults to the currently active PROJECT.
571+
"""
545572
function fpp_settings(project=PROJECT)
546-
# determine which fpc_settings to load
573+
# determine which fpp_settings to load
547574
dict = YAML.load_file(joinpath(DATA_PATH[1], project))
548575
dict["system"]["fpp_settings"]
549576
end
550577

578+
"""
579+
vsm_settings_file(project=PROJECT)
580+
581+
Get the vortex step model (VSM) settings filename from the project file.
582+
583+
Returns the filename specified in the `vsm_settings` field of the system section.
584+
The project file defaults to the currently active PROJECT.
585+
"""
586+
function vsm_settings_file(project=PROJECT)
587+
# determine which vsm_settings to load
588+
dict = YAML.load_file(joinpath(DATA_PATH[1], project))
589+
dict["system"]["vsm_settings"]
590+
end
591+
592+
"""
593+
aero_geometry_file(project=PROJECT)
594+
595+
Get the aerodynamic geometry filename from the project file.
596+
597+
Returns the filename specified in the `aero_geometry` field of the system section.
598+
The project file defaults to the currently active PROJECT.
599+
"""
600+
function aero_geometry_file(project=PROJECT)
601+
# determine which aero_geometry to load
602+
dict = YAML.load_file(joinpath(DATA_PATH[1], project))
603+
dict["system"]["aero_geometry"]
604+
end
605+
606+
"""
607+
structural_geometry_file(project=PROJECT)
608+
609+
Get the structural geometry filename from the project file.
610+
611+
Returns the filename specified in the `structural_geometry` field of the system section.
612+
Falls back to `struc_geometry` for compatibility.
613+
The project file defaults to the currently active PROJECT.
614+
"""
615+
function structural_geometry_file(project=PROJECT)
616+
# determine which structural_geometry to load (or legacy struc_geometry)
617+
dict = YAML.load_file(joinpath(DATA_PATH[1], project))
618+
sys = dict["system"]
619+
if haskey(sys, "structural_geometry")
620+
sys["structural_geometry"]
621+
else
622+
sys["struc_geometry"]
623+
end
624+
end
625+
551626
"""
552627
se(project=PROJECT; relax=false)
553628

src/transformations.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ function quat2viewer(q::QuatRotation)
155155
ay = @SVector [1, 0, 0] # in ENU reference frame this is pointing to the west
156156
az = @SVector [0, 0, -1] # in ENU reference frame this is pointing down
157157
rot = rot3d(ax, ay, az, x, y, z)
158-
x, y, z = rot*ax, rot*ay, rot*az # obtain x, y, z in inertial reference frame
158+
x, z = rot*ax, rot*az # obtain x, z in inertial reference frame
159159
pos_kite_ = @SVector ones(3)
160160
pos_before = pos_kite_ .+ z
161161
rotation = KiteUtils.rot(pos_kite_, pos_before, -x)
@@ -269,7 +269,7 @@ upwind direction and upwind elevation. All angles in radians.
269269
- `upwind_elevation`: angle of the upwind direction above the
270270
east-north plane [rad]
271271
272-
Returns an `MVector{3, Float64}` (east, north, up).
272+
Returns an `SVec3` (east, north, up).
273273
"""
274274
function wind_vec_from_angles(v_wind, upwind_dir, upwind_elevation)
275275
downwind_azimuth = upwind_dir + π

0 commit comments

Comments
 (0)