From 52e135f536f5a4d67a1f2ceeb599303e7f3766fe Mon Sep 17 00:00:00 2001 From: Uwe Fechner Date: Sun, 21 Jun 2026 14:10:52 +0200 Subject: [PATCH 1/5] Initial refactoring --- examples/batch_plot.jl | 160 +++------------------- examples/plot_functions.jl | 176 +++++++++++++++++++++++++ examples/plot_helpers.jl | 13 ++ examples/plots.jl | 262 +++++++++---------------------------- 4 files changed, 267 insertions(+), 344 deletions(-) create mode 100644 examples/plot_functions.jl create mode 100644 examples/plot_helpers.jl diff --git a/examples/batch_plot.jl b/examples/batch_plot.jl index 14ca4dd4..010803f9 100644 --- a/examples/batch_plot.jl +++ b/examples/batch_plot.jl @@ -79,24 +79,9 @@ const PLOT_FILE = Ref{String}( ) # --------------------------------------------------------------------------- -# Helper accessors (same as in plots.jl) +# Core plot logic (shared with plots.jl via plot_functions.jl) # --------------------------------------------------------------------------- -function l_tether(sl) - hcat(sl.l_tether...)[1,:] -end - -function force(sl) - hcat(sl.winch_force...)[1,:] -end - -function v_reelout(sl) - hcat(sl.v_reelout...)[1,:] -end - -# Derive dt from the log instead of from an app object -function log_dt(sl) - length(sl.time) > 1 ? sl.time[2] - sl.time[1] : 0.05 -end +include("plot_functions.jl") # --------------------------------------------------------------------------- # Load helper @@ -106,172 +91,59 @@ function load_plot_log() end # --------------------------------------------------------------------------- -# Plot functions (adapted from plots.jl — no KiteViewers references) +# Plot wrappers — load the log, then delegate to the shared implementation # --------------------------------------------------------------------------- function plot_main() - log = load_plot_log() - sl = log.syslog - display(plotx(sl.time, log.z, rad2deg.(sl.elevation), rad2deg.(sl.azimuth), - l_tether(sl), force(sl), v_reelout(sl), sl.cycle; - ylabels=["height [m]", "elevation [°]", "azimuth [°]", "length [m]", - "force [N]", "v_ro [m/s]", "cycle [-]"], - yzoom=0.9, fig="main")) - nothing + _plot_main(load_plot_log(); ysize=10) end function plot_power() log = load_plot_log() - sl = log.syslog - display(plotx(sl.time, force(sl), v_reelout(sl), force(sl) .* v_reelout(sl), sl.e_mech, sl.acc; - ylabels=["force [N]", L"v_\mathrm{ro}~[m/s]", L"P_\mathrm{m}~[W]", "Energy [Wh]", "acc [m/s^2]"], - fig="power")) - nothing + _plot_power(log; ysize=10, energy=log.syslog.e_mech, dt=0.0) end function plot_control() - log = load_plot_log() - sl = log.syslog - display(plotx(sl.time, rad2deg.(sl.elevation), rad2deg.(sl.azimuth), - rad2deg.(wrap2pi.(sl.heading)), force(sl), - 100*sl.depower, 100*sl.steering, sl.sys_state, sl.cycle, sl.fig_8; - ylabels=["elevation [°]", "azimuth [°]", "heading [°]", "force [N]", - "depower [%]", "steering [%]", "fpp_state", "cycle", "fig8"], - fig="control", ysize=10, yzoom=0.7)) - sleep(0.05) - display(plotx(sl.time, rad2deg.(sl.elevation), rad2deg.(sl.azimuth), - -rad2deg.(wrap2pi.(sl.heading)), 100*sl.depower, 100*sl.steering, - rad2deg.(sl.var_07), sl.var_06, sl.sys_state, sl.cycle; - ylabels=["elevation [°]", "azimuth [°]", "psi [°]", "depower [%]", - "steering [%]", "chi_set", "ndi_gain", "fpp_state", "cycle"], - fig="fpc", ysize=10, yzoom=0.7)) - nothing + _plot_control(load_plot_log(); ysize=10) end function plot_control_II() - log = load_plot_log() - sl = log.syslog - display(plotx(sl.time, rad2deg.(sl.azimuth), -rad2deg.(wrap2pi.(sl.heading)), - 100*sl.steering, sl.var_12, rad2deg.(sl.course .- pi), - rad2deg.(sl.var_09), rad2deg.(sl.var_10), sl.var_06, sl.sys_state; - ylabels=["azimuth [°]", "psi [°]", "steering [%]", "c2", "chi", - "psi_dot_set", "psi_dot", "ndi_gain", "fpp_state"], - fig="fpc", ysize=10, yzoom=0.7)) - nothing + _plot_control_II(load_plot_log(); ysize=10) end function plot_winch_control() - log = load_plot_log() - sl = log.syslog - display(plotx(sl.time, rad2deg.(sl.elevation), rad2deg.(sl.azimuth), - force(sl), sl.var_04, v_reelout(sl), - 100*sl.depower, 100*sl.steering, sl.var_03; - ylabels=["elevation [°]", "azimuth [°]", "force [N]", "set_force", - "v_reelout [m/s]", "depower [%]", "steering [%]", "wc_state"], - fig="winch_control", ysize=10)) - display(plot(sl.time, [v_reelout(sl), sl.var_05]; - labels=["v_reelout", "pid2_v_set_out"], - ylabel="v_reelout [m/s]", - xlabel="time [s]", - fig="winch", ysize=10)) - nothing + _plot_winch_control(load_plot_log(); ysize=10) end function plot_aerodynamics(plot_lift_drag=false) - log = load_plot_log() - sl = log.syslog - if plot_lift_drag - display(plotx(sl.time, sl.var_08, rad2deg.(sl.AoA), sl.CL2, sl.CD2; - ylabels=["LoD [-]", L"AoA~[°]", "CL [-]", "CD [-]"], - fig="aerodynamics")) - display(plotxy(rad2deg.(sl.AoA[2:end]), sl.CL2[2:end]; - xlabel="AoA [°]", ylabel="CL [-]", - fig="CL as function of AoA")) - display(plotxy(rad2deg.(sl.AoA[2:end]), sl.CD2[2:end]; - xlabel="AoA [°]", ylabel="CD [-]", - fig="CD_tot as function of AoA")) - else - display(plotx(sl.time, sl.var_08, rad2deg.(sl.AoA), 100*sl.steering, - sl.var_15, rad2deg.(sl.var_16); - ylabels=["LoD [-]", L"AoA~[°]", "steering [%]", - "yaw_rate [°/s]", L"side\_slip~[°]"], - fig="aerodynamics")) - end - nothing + _plot_aerodynamics(load_plot_log(); plot_lift_drag=plot_lift_drag) end function plot_elev_az() - log = load_plot_log() - sl = log.syslog - display(plotxy(rad2deg.(sl.azimuth), rad2deg.(sl.elevation); - ylabel="elevation [°]", xlabel="azimuth [°]", fig="elev_az")) - nothing + _plot_elev_az(load_plot_log()) end function plot_elev_az2() - log = load_plot_log() - sl = log.syslog - index = 1 - for i in 1:length(sl.cycle) - if sl.cycle[i] == 2; index = i; break; end - end - display(plotxy(rad2deg.(sl.azimuth)[index:end], rad2deg.(sl.elevation)[index:end]; - ylabel="elevation [°]", xlabel="azimuth [°]", fig="elev_az")) - nothing + _plot_elev_az_n(load_plot_log(), 2) end function plot_elev_az3() - log = load_plot_log() - sl = log.syslog - index = 1 - for i in 1:length(sl.cycle) - if sl.cycle[i] == 3; index = i; break; end - end - display(plotxy(rad2deg.(sl.azimuth)[index:end], rad2deg.(sl.elevation)[index:end]; - ylabel="elevation [°]", xlabel="azimuth [°]", fig="elev_az")) - nothing + _plot_elev_az_n(load_plot_log(), 3) end function plot_side_view() - log = load_plot_log() - display(plotxy(log.x, log.z; - ylabel="pos_x [m]", xlabel="height [m]", fig="side_view")) - nothing + _plot_side_view(load_plot_log()) end function plot_side_view2() - log = load_plot_log() - sl = log.syslog - index = 1 - for i in 1:length(sl.cycle) - if sl.cycle[i] == 2; index = i; break; end - end - display(plotxy(log.x[index:end], log.z[index:end]; - ylabel="pos_x [m]", xlabel="height [m]", fig="side_view")) - nothing + _plot_side_view_n(load_plot_log(), 2) end function plot_side_view3() - log = load_plot_log() - sl = log.syslog - index = 1 - for i in 1:length(sl.cycle) - if sl.cycle[i] == 3; index = i; break; end - end - display(plotxy(log.x[index:end], log.z[index:end]; - ylabel="pos_x [m]", xlabel="height [m]", fig="side_view")) - nothing + _plot_side_view_n(load_plot_log(), 3) end function plot_front_view3() - log = load_plot_log() - sl = log.syslog - index = 1 - for i in 1:length(sl.cycle) - if sl.cycle[i] == 3; index = i; break; end - end - display(plotxy(log.y[index:end], log.z[index:end]; - xlabel="pos_y [m]", ylabel="height [m]", fig="front_view")) - nothing + _plot_front_view_n(load_plot_log(), 3) end # --------------------------------------------------------------------------- diff --git a/examples/plot_functions.jl b/examples/plot_functions.jl new file mode 100644 index 00000000..97ff7c63 --- /dev/null +++ b/examples/plot_functions.jl @@ -0,0 +1,176 @@ +# Core plot functions shared by plots.jl (interactive GUI) and batch_plot.jl (CLI). +# Each function takes a log object and accepts keyword arguments for the few +# parameters that differ between the two UIs (ysize, energy source, dt). + +include("plot_helpers.jl") + +# --------------------------------------------------------------------------- +# Helper: find the first index where sl.cycle == n +# --------------------------------------------------------------------------- +function _cycle_index(sl, n) + for i in 1:length(sl.cycle) + if sl.cycle[i] == n; return i; end + end + return 1 +end + +# --------------------------------------------------------------------------- +# _plot_main +# --------------------------------------------------------------------------- +function _plot_main(log; ysize=10) + sl = log.syslog + display(plotx(sl.time, log.z, rad2deg.(sl.elevation), rad2deg.(sl.azimuth), + l_tether(sl), force(sl), v_reelout(sl), sl.cycle; + ylabels=["height [m]", "elevation [°]", "azimuth [°]", "length [m]", + "force [N]", "v_ro [m/s]", "cycle [-]"], + yzoom=0.9, fig="main", ysize=ysize)) + nothing +end + +# --------------------------------------------------------------------------- +# _plot_power +# --------------------------------------------------------------------------- +function _plot_power(log; ysize=10, energy=nothing, dt=0.0) + sl = log.syslog + if energy === nothing + v_ro = v_reelout(sl) + f_ = force(sl) + energy = similar(v_ro) + en = 0.0 + for i in eachindex(energy) + en += f_[i] * v_ro[i] * dt + energy[i] = en + end + end + display(plotx(sl.time, force(sl), v_reelout(sl), force(sl) .* v_reelout(sl), + energy ./ 3600, sl.acc; + ylabels=["force [N]", L"v_\mathrm{ro}~[m/s]", L"P_\mathrm{m}~[W]", + "Energy [Wh]", "acc [m/s^2]"], + fig="power", ysize=ysize)) + nothing +end + +# --------------------------------------------------------------------------- +# _plot_control (two sub-plots: control + fpc) +# --------------------------------------------------------------------------- +function _plot_control(log; ysize=10) + sl = log.syslog + display(plotx(sl.time, rad2deg.(sl.elevation), rad2deg.(sl.azimuth), + rad2deg.(wrap2pi.(sl.heading)), force(sl), + 100*sl.depower, 100*sl.steering, sl.sys_state, sl.cycle, sl.fig_8; + ylabels=["elevation [°]", "azimuth [°]", "heading [°]", "force [N]", + "depower [%]", "steering [%]", "fpp_state", "cycle", "fig8"], + fig="control", ysize=ysize, yzoom=0.7)) + sleep(0.05) + display(plotx(sl.time, rad2deg.(sl.elevation), rad2deg.(sl.azimuth), + -rad2deg.(wrap2pi.(sl.heading)), 100*sl.depower, 100*sl.steering, + rad2deg.(sl.var_07), sl.var_06, sl.sys_state, sl.cycle; + ylabels=["elevation [°]", "azimuth [°]", "psi [°]", "depower [%]", + "steering [%]", "chi_set", "ndi_gain", "fpp_state", "cycle"], + fig="fpc", ysize=ysize, yzoom=0.7)) + nothing +end + +# --------------------------------------------------------------------------- +# _plot_control_II +# --------------------------------------------------------------------------- +function _plot_control_II(log; ysize=10) + sl = log.syslog + display(plotx(sl.time, rad2deg.(sl.azimuth), -rad2deg.(wrap2pi.(sl.heading)), + 100*sl.steering, sl.var_12, rad2deg.(sl.course .- pi), + rad2deg.(sl.var_09), rad2deg.(sl.var_10), sl.var_06, sl.sys_state; + ylabels=["azimuth [°]", "psi [°]", "steering [%]", "c2", "chi", + "psi_dot_set", "psi_dot", "ndi_gain", "fpp_state"], + fig="fpc", ysize=ysize, yzoom=0.7)) + nothing +end + +# --------------------------------------------------------------------------- +# _plot_winch_control (two sub-plots) +# --------------------------------------------------------------------------- +function _plot_winch_control(log; ysize=10) + sl = log.syslog + display(plotx(sl.time, rad2deg.(sl.elevation), rad2deg.(sl.azimuth), + force(sl), sl.var_04, v_reelout(sl), + 100*sl.depower, 100*sl.steering, sl.var_03; + ylabels=["elevation [°]", "azimuth [°]", "force [N]", "set_force", + "v_reelout [m/s]", "depower [%]", "steering [%]", "wc_state"], + fig="winch_control", ysize=ysize)) + display(plot(sl.time, [v_reelout(sl), sl.var_05]; + labels=["v_reelout", "pid2_v_set_out"], + ylabel="v_reelout [m/s]", + xlabel="time [s]", + fig="winch", ysize=ysize)) + nothing +end + +# --------------------------------------------------------------------------- +# _plot_aerodynamics +# --------------------------------------------------------------------------- +function _plot_aerodynamics(log; plot_lift_drag=false) + sl = log.syslog + if plot_lift_drag + display(plotx(sl.time, sl.var_08, rad2deg.(sl.AoA), sl.CL2, sl.CD2; + ylabels=["LoD [-]", L"AoA~[°]", "CL [-]", "CD [-]"], + fig="aerodynamics")) + display(plotxy(rad2deg.(sl.AoA[2:end]), sl.CL2[2:end]; + xlabel="AoA [°]", ylabel="CL [-]", + fig="CL as function of AoA")) + display(plotxy(rad2deg.(sl.AoA[2:end]), sl.CD2[2:end]; + xlabel="AoA [°]", ylabel="CD [-]", + fig="CD_tot as function of AoA")) + else + display(plotx(sl.time, sl.var_08, rad2deg.(sl.AoA), 100*sl.steering, + sl.var_15, rad2deg.(sl.var_16); + ylabels=["LoD [-]", L"AoA~[°]", "steering [%]", + "yaw_rate [°/s]", L"side\_slip~[°]"], + fig="aerodynamics")) + end + nothing +end + +# --------------------------------------------------------------------------- +# _plot_elev_az variations +# --------------------------------------------------------------------------- +function _plot_elev_az(log) + sl = log.syslog + display(plotxy(rad2deg.(sl.azimuth), rad2deg.(sl.elevation); + ylabel="elevation [°]", xlabel="azimuth [°]", fig="elev_az")) + nothing +end + +function _plot_elev_az_n(log, cycle_number) + sl = log.syslog + idx = _cycle_index(sl, cycle_number) + display(plotxy(rad2deg.(sl.azimuth)[idx:end], rad2deg.(sl.elevation)[idx:end]; + ylabel="elevation [°]", xlabel="azimuth [°]", fig="elev_az")) + nothing +end + +# --------------------------------------------------------------------------- +# _plot_side_view variations +# --------------------------------------------------------------------------- +function _plot_side_view(log) + display(plotxy(log.x, log.z; + ylabel="pos_x [m]", xlabel="height [m]", fig="side_view")) + nothing +end + +function _plot_side_view_n(log, cycle_number) + sl = log.syslog + idx = _cycle_index(sl, cycle_number) + display(plotxy(log.x[idx:end], log.z[idx:end]; + ylabel="pos_x [m]", xlabel="height [m]", fig="side_view")) + nothing +end + +# --------------------------------------------------------------------------- +# _plot_front_view_n +# --------------------------------------------------------------------------- +function _plot_front_view_n(log, cycle_number) + sl = log.syslog + idx = _cycle_index(sl, cycle_number) + display(plotxy(log.y[idx:end], log.z[idx:end]; + xlabel="pos_y [m]", ylabel="height [m]", fig="front_view")) + nothing +end diff --git a/examples/plot_helpers.jl b/examples/plot_helpers.jl new file mode 100644 index 00000000..e0be5e64 --- /dev/null +++ b/examples/plot_helpers.jl @@ -0,0 +1,13 @@ +# Shared helper accessors used by both plots.jl and batch_plot.jl + +function l_tether(sl) + hcat(sl.l_tether...)[1,:] +end + +function force(sl) + hcat(sl.winch_force...)[1,:] +end + +function v_reelout(sl) + hcat(sl.v_reelout...)[1,:] +end \ No newline at end of file diff --git a/examples/plots.jl b/examples/plots.jl index 9157f61e..d5116aac 100644 --- a/examples/plots.jl +++ b/examples/plots.jl @@ -1,5 +1,15 @@ -function l_tether(sl) - hcat(sl.l_tether...)[1,:] +# Shared plot functions (core logic) live in plot_functions.jl +include("plot_functions.jl") + +# --------------------------------------------------------------------------- +# Helpers for log loading (specific to the interactive GUI) +# --------------------------------------------------------------------------- +function fulldir(name) + if occursin("~", name) + return replace(dirname(name), "~" => homedir()) + else + return joinpath(pwd(), dirname(name)) + end end function resolved_log_file(name) @@ -20,255 +30,107 @@ function log_file_exists() return false end -function force(sl) - hcat(sl.winch_force...)[1,:] -end - -function v_reelout(sl) - hcat(sl.v_reelout...)[1,:] -end - -function plot_timing() - log_file_exists() || return - log = load_log(basename(KiteViewers.plot_file[]); path=fulldir(KiteViewers.plot_file[])) - - sl = log.syslog - time_limit = app.dt/app.set.time_lapse - t_sim = collect(sl.t_sim) - tl = fill(time_limit * 1000, length(t_sim)) - display(MakieControlPlots.plotx(sl.time, [t_sim, tl], 100*sl.steering, 100*sl.depower; - ylabels=["t_sim [ms]", "steering [%]","depower [%]"], - labels=[["t_sim", "time_limit"], "", ""], - fig="timing")) - println("Time limit: $(time_limit*1000) ms") - println("Mean time per timestep: $(mean(sl.t_sim)) ms") - println("Maximum time per timestep: $(maximum(sl.t_sim[10:end])) ms") - index = Int64(round(12/app.dt)) - println("Maximum for t>12s : $(maximum(sl.t_sim[index:end])) ms") - nothing -end - -function plot_timing2() - log_file_exists() || return - log = load_log(basename(KiteViewers.plot_file[]); path=fulldir(KiteViewers.plot_file[])) - - sl = log.syslog - time_limit = app.dt/app.set.time_lapse - t_sim = collect(sl.t_sim) - tl = fill(time_limit * 1000, length(t_sim)) - display(MakieControlPlots.plot(sl.time, [t_sim, tl], ylabel="t_sim [ms]", labels=["t_sim","time_limit"], fig="timing2")) - nothing -end - -function fulldir(name) - if occursin("~", name) - return replace(dirname(name), "~" => homedir()) - else - return joinpath(pwd(), dirname(name)) - end +function _load_log() + load_log(basename(KiteViewers.plot_file[]); path=fulldir(KiteViewers.plot_file[])) end +# --------------------------------------------------------------------------- +# Wrappers — load the log from the interactive viewer then delegate +# --------------------------------------------------------------------------- function plot_main() log_file_exists() || return - log = load_log(basename(KiteViewers.plot_file[]); path=fulldir(KiteViewers.plot_file[])) - sl = log.syslog - display(plotx(log.syslog.time, log.z, rad2deg.(sl.elevation), rad2deg.(sl.azimuth), l_tether(sl), force(sl), - v_reelout(sl), sl.cycle; - ylabels=["height [m]", "elevation [°]", "azimuth [°]", "length [m]", "force [N]", "v_ro [m/s]", "cycle [-]"], - yzoom=0.9, fig="main")) - nothing + _plot_main(_load_log(); ysize=16) end function plot_power() log_file_exists() || return - log = load_log(basename(KiteViewers.plot_file[]); path=fulldir(KiteViewers.plot_file[])) - sl = log.syslog - energy = similar(v_reelout(sl)) - en = 0.0 - v_ro = v_reelout(sl) - f_ = force(sl) - for i in eachindex(energy) - en += f_[i] * v_ro[i] * app.dt - energy[i] = en - end - display(plotx(log.syslog.time, force(sl), v_reelout(sl), force(sl) .* v_reelout(sl), energy./3600, sl.acc; - ylabels=["force [N]", L"v_\mathrm{ro}~[m/s]", L"P_\mathrm{m}~[W]", "Energy [Wh]", "acc [m/s^2]"], - fig="power")) - nothing + _plot_power(_load_log(); ysize=16, dt=app.dt) end function plot_control() log_file_exists() || return - log = load_log(basename(KiteViewers.plot_file[]); path=fulldir(KiteViewers.plot_file[])) - sl = log.syslog - display(plotx(log.syslog.time, rad2deg.(sl.elevation), rad2deg.(sl.azimuth), rad2deg.(wrap2pi.(sl.heading)), force(sl), 100*sl.depower, 100*sl.steering, sl.sys_state, sl.cycle, sl.fig_8; - ylabels=["elevation [°]", "azimuth [°]", "heading [°]", "force [N]", "depower [%]", "steering [%]", "fpp_state", "cycle", "fig8"], - fig="control", ysize=16, yzoom=0.7)) - sleep(0.05) - display(plotx(log.syslog.time, rad2deg.(sl.elevation), rad2deg.(sl.azimuth), -rad2deg.(wrap2pi.(sl.heading)), 100*sl.depower, 100*sl.steering, rad2deg.(sl.var_07), sl.var_06, sl.sys_state, sl.cycle; - ylabels=["elevation [°]", "azimuth [°]", "psi [°]", "depower [%]", "steering [%]", "chi_set", "ndi_gain", "fpp_state", "cycle"], - fig="fpc", ysize=16, yzoom=0.7)) - nothing + _plot_control(_load_log(); ysize=16) end function plot_control_II() log_file_exists() || return - log = load_log(basename(KiteViewers.plot_file[]); path=fulldir(KiteViewers.plot_file[])) - sl = log.syslog - display(plotx(log.syslog.time, rad2deg.(sl.azimuth), -rad2deg.(wrap2pi.(sl.heading)), 100*sl.steering, sl.var_12, rad2deg.(sl.course.-pi), rad2deg.(sl.var_09), rad2deg.(sl.var_10), sl.var_06, sl.sys_state; - ylabels=["azimuth [°]", "psi [°]", "steering [%]", "c2", "chi", "psi_dot_set", "psi_dot", "ndi_gain", "fpp_state"], - fig="fpc", ysize=16, yzoom=0.7)) - nothing + _plot_control_II(_load_log(); ysize=16) end function plot_winch_control() log_file_exists() || return - log = load_log(basename(KiteViewers.plot_file[]); path=fulldir(KiteViewers.plot_file[])) - sl = log.syslog - display(plotx(log.syslog.time, rad2deg.(sl.elevation), rad2deg.(sl.azimuth), force(sl), sl.var_04, v_reelout(sl), 100*sl.depower, 100*sl.steering, sl.var_03; - ylabels=["elevation [°]", "azimuth [°]", "force [N]", "set_force", "v_reelout [m/s]", "depower [%]", "steering [%]", "wc_state"], - fig="winch_control", ysize=14)) - display(plot(log.syslog.time, [v_reelout(sl), sl.var_05]; - labels=["v_reelout", "pid2_v_set_out"], - ylabel="v_reelout [n/s]", - xlabel="time [s]", - fig="winch", ysize=14)) - nothing + _plot_winch_control(_load_log(); ysize=14) +end + +function plot_aerodynamics(plot_lift_drag=false) + log_file_exists() || return + _plot_aerodynamics(_load_log(); plot_lift_drag=plot_lift_drag) end function plot_elev_az() log_file_exists() || return - log = load_log(basename(KiteViewers.plot_file[]); path=fulldir(KiteViewers.plot_file[])) - sl = log.syslog - display(plotxy(rad2deg.(sl.azimuth), rad2deg.(sl.elevation); - ylabel="elevation [°]", - xlabel="azimuth [°]", - fig="elev_az")) - nothing + _plot_elev_az(_load_log()) end function plot_elev_az2() log_file_exists() || return - log = load_log(basename(KiteViewers.plot_file[]); path=fulldir(KiteViewers.plot_file[])) - sl = log.syslog - index=1 - for i in 1:length(sl.cycle) - if sl.cycle[i] == 2 - index=i - break - end - end - display(plotxy(rad2deg.(sl.azimuth)[index:end], rad2deg.(sl.elevation)[index:end]; - ylabel="elevation [°]", - xlabel="azimuth [°]", - fig="elev_az")) - nothing + _plot_elev_az_n(_load_log(), 2) end function plot_elev_az3() log_file_exists() || return - log = load_log(basename(KiteViewers.plot_file[]); path=fulldir(KiteViewers.plot_file[])) - sl = log.syslog - index=1 - for i in 1:length(sl.cycle) - if sl.cycle[i] == 3 - index=i - break - end - end - display(plotxy(rad2deg.(sl.azimuth)[index:end], rad2deg.(sl.elevation)[index:end]; - ylabel="elevation [°]", - xlabel="azimuth [°]", - fig="elev_az")) - nothing + _plot_elev_az_n(_load_log(), 3) end function plot_side_view() log_file_exists() || return - log = load_log(basename(KiteViewers.plot_file[]); path=fulldir(KiteViewers.plot_file[])) - display(plotxy(log.x, log.z; - ylabel="pos_x [m]", - xlabel="height [m]", - fig="side_view")) - nothing + _plot_side_view(_load_log()) end function plot_side_view2() log_file_exists() || return - log = load_log(basename(KiteViewers.plot_file[]); path=fulldir(KiteViewers.plot_file[])) - index = 1 - sl = log.syslog - for i in 1:length(sl.cycle) - if sl.cycle[i] == 2 - index=i - break - end - end - display(plotxy(log.x[index:end], log.z[index:end]; - ylabel="pos_x [m]", - xlabel="height [m]", - fig="side_view")) - nothing + _plot_side_view_n(_load_log(), 2) end function plot_side_view3() log_file_exists() || return - log = load_log(basename(KiteViewers.plot_file[]); path=fulldir(KiteViewers.plot_file[])) - index = 1 - sl = log.syslog - for i in 1:length(sl.cycle) - if sl.cycle[i] == 3 - index=i - break - end - end - display(plotxy(log.x[index:end], log.z[index:end]; - ylabel="pos_x [m]", - xlabel="height [m]", - fig="side_view")) - nothing + _plot_side_view_n(_load_log(), 3) end function plot_front_view3() log_file_exists() || return - log = load_log(basename(KiteViewers.plot_file[]); path=fulldir(KiteViewers.plot_file[])) - index = 1 - sl = log.syslog - for i in 1:length(sl.cycle) - if sl.cycle[i] == 3 - index=i - break - end - end - display(plotxy(log.y[index:end], log.z[index:end]; - xlabel="pos_y [m]", - ylabel="height [m]", - fig="front_view")) - nothing + _plot_front_view_n(_load_log(), 3) end -function plot_aerodynamics(plot_lift_drag = false) +# --------------------------------------------------------------------------- +# Timing plots (only in the interactive GUI) +# --------------------------------------------------------------------------- +function plot_timing() log_file_exists() || return - log = load_log(basename(KiteViewers.plot_file[]); path=fulldir(KiteViewers.plot_file[])) - sl = log.syslog - - if plot_lift_drag - display(plotx(sl.time, sl.var_08, rad2deg.(sl.AoA), sl.CL2, sl.CD2; - ylabels=["LoD [-]", L"AoA~[°]", "CL [-]", "CD [-]"], - fig="aerodynamics")) - display(plotxy(rad2deg.(sl.AoA[2:end]), sl.CL2[2:end]; - xlabel="AoA [°]", - ylabel="CL [-]", - fig="CL as function of AoA")) - display(plotxy(rad2deg.(sl.AoA[2:end]), sl.CD2[2:end]; - xlabel="AoA [°]", - ylabel="CD [-]", - fig="CD_tot as function of AoA")) + log = _load_log() + sl = log.syslog + time_limit = app.dt/app.set.time_lapse + t_sim = collect(sl.t_sim) + tl = fill(time_limit * 1000, length(t_sim)) + display(MakieControlPlots.plotx(sl.time, [t_sim, tl], 100*sl.steering, 100*sl.depower; + ylabels=["t_sim [ms]", "steering [%]","depower [%]"], + labels=[["t_sim", "time_limit"], "", ""], + fig="timing")) + println("Time limit: $(time_limit*1000) ms") + println("Mean time per timestep: $(mean(sl.t_sim)) ms") + println("Maximum time per timestep: $(maximum(sl.t_sim[10:end])) ms") + index = Int64(round(12/app.dt)) + println("Maximum for t>12s : $(maximum(sl.t_sim[index:end])) ms") + nothing +end - else - display(plotx(sl.time, sl.var_08, rad2deg.(sl.AoA), 100*sl.steering, sl.var_15, rad2deg.(sl.var_16); - ylabels=["LoD [-]", L"AoA~[°]", "steering [%]", "yaw_rate [°/s]", L"side\_slip~[°]"], - fig="aerodynamics")) - end +function plot_timing2() + log_file_exists() || return + log = _load_log() + sl = log.syslog + time_limit = app.dt/app.set.time_lapse + t_sim = collect(sl.t_sim) + tl = fill(time_limit * 1000, length(t_sim)) + display(MakieControlPlots.plot(sl.time, [t_sim, tl], ylabel="t_sim [ms]", labels=["t_sim","time_limit"], fig="timing2")) nothing end \ No newline at end of file From 5e2c84b91738f76cb7cf2f725a49a7fc269ab12e Mon Sep 17 00:00:00 2001 From: Uwe Fechner Date: Sun, 21 Jun 2026 17:08:06 +0200 Subject: [PATCH 2/5] Improve performance --- examples/plot_helpers.jl | 6 +++--- examples/plot_loading.jl | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/plot_helpers.jl b/examples/plot_helpers.jl index e0be5e64..f0ef3800 100644 --- a/examples/plot_helpers.jl +++ b/examples/plot_helpers.jl @@ -1,13 +1,13 @@ # Shared helper accessors used by both plots.jl and batch_plot.jl function l_tether(sl) - hcat(sl.l_tether...)[1,:] + getindex.(sl.l_tether, 1) end function force(sl) - hcat(sl.winch_force...)[1,:] + getindex.(sl.winch_force, 1) end function v_reelout(sl) - hcat(sl.v_reelout...)[1,:] + getindex.(sl.v_reelout, 1) end \ No newline at end of file diff --git a/examples/plot_loading.jl b/examples/plot_loading.jl index c9edcc29..01bc47b7 100644 --- a/examples/plot_loading.jl +++ b/examples/plot_loading.jl @@ -15,8 +15,8 @@ let if isfile(log_path * ".arrow") log = load_log(basename(log_path); path=dirname(log_path)) sl = log.syslog - force = hcat(sl.winch_force...)[1,:] - v_ro = hcat(sl.v_reelout...)[1,:] + force = getindex.(sl.winch_force, 1) + v_ro = getindex.(sl.v_reelout, 1) power = force .* v_ro p1 = MakieControlPlots.plot(sl.time, force; xlabel="time [s]", From 2ba3a4bdf7bd5b115251a1afda489686c161f5b4 Mon Sep 17 00:00:00 2001 From: Uwe Fechner Date: Sun, 21 Jun 2026 17:16:39 +0200 Subject: [PATCH 3/5] Fix warnings --- examples/plots.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/plots.jl b/examples/plots.jl index d5116aac..340f15e6 100644 --- a/examples/plots.jl +++ b/examples/plots.jl @@ -1,5 +1,6 @@ # Shared plot functions (core logic) live in plot_functions.jl include("plot_functions.jl") +using KiteViewers # --------------------------------------------------------------------------- # Helpers for log loading (specific to the interactive GUI) From 7803c3cb210102725651b9177355d6bcce1b8af4 Mon Sep 17 00:00:00 2001 From: Uwe Fechner Date: Sun, 21 Jun 2026 17:35:51 +0200 Subject: [PATCH 4/5] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- examples/plot_functions.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/plot_functions.jl b/examples/plot_functions.jl index 97ff7c63..e0f2bbee 100644 --- a/examples/plot_functions.jl +++ b/examples/plot_functions.jl @@ -38,12 +38,12 @@ function _plot_power(log; ysize=10, energy=nothing, dt=0.0) energy = similar(v_ro) en = 0.0 for i in eachindex(energy) - en += f_[i] * v_ro[i] * dt + en += f_[i] * v_ro[i] * dt / 3600 energy[i] = en end end display(plotx(sl.time, force(sl), v_reelout(sl), force(sl) .* v_reelout(sl), - energy ./ 3600, sl.acc; + energy, sl.acc; ylabels=["force [N]", L"v_\mathrm{ro}~[m/s]", L"P_\mathrm{m}~[W]", "Energy [Wh]", "acc [m/s^2]"], fig="power", ysize=ysize)) From e4519c509c054d1c96d1fae14b241cda6c6bc000 Mon Sep 17 00:00:00 2001 From: Uwe Fechner Date: Sun, 21 Jun 2026 18:08:57 +0200 Subject: [PATCH 5/5] Refactoring --- examples/batch_plot.jl | 10 +++++----- examples/plot_functions.jl | 30 +++++++++++++++--------------- examples/plots.jl | 10 +++++----- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/examples/batch_plot.jl b/examples/batch_plot.jl index 010803f9..b445ee07 100644 --- a/examples/batch_plot.jl +++ b/examples/batch_plot.jl @@ -94,24 +94,24 @@ end # Plot wrappers — load the log, then delegate to the shared implementation # --------------------------------------------------------------------------- function plot_main() - _plot_main(load_plot_log(); ysize=10) + _plot_main(load_plot_log()) end function plot_power() log = load_plot_log() - _plot_power(log; ysize=10, energy=log.syslog.e_mech, dt=0.0) + _plot_power(log; energy=log.syslog.e_mech, dt=0.0) end function plot_control() - _plot_control(load_plot_log(); ysize=10) + _plot_control(load_plot_log()) end function plot_control_II() - _plot_control_II(load_plot_log(); ysize=10) + _plot_control_II(load_plot_log()) end function plot_winch_control() - _plot_winch_control(load_plot_log(); ysize=10) + _plot_winch_control(load_plot_log()) end function plot_aerodynamics(plot_lift_drag=false) diff --git a/examples/plot_functions.jl b/examples/plot_functions.jl index e0f2bbee..506401c5 100644 --- a/examples/plot_functions.jl +++ b/examples/plot_functions.jl @@ -1,6 +1,6 @@ # Core plot functions shared by plots.jl (interactive GUI) and batch_plot.jl (CLI). # Each function takes a log object and accepts keyword arguments for the few -# parameters that differ between the two UIs (ysize, energy source, dt). +# parameters that differ between the two UIs (energy source, dt). include("plot_helpers.jl") @@ -17,20 +17,20 @@ end # --------------------------------------------------------------------------- # _plot_main # --------------------------------------------------------------------------- -function _plot_main(log; ysize=10) +function _plot_main(log) sl = log.syslog display(plotx(sl.time, log.z, rad2deg.(sl.elevation), rad2deg.(sl.azimuth), l_tether(sl), force(sl), v_reelout(sl), sl.cycle; ylabels=["height [m]", "elevation [°]", "azimuth [°]", "length [m]", "force [N]", "v_ro [m/s]", "cycle [-]"], - yzoom=0.9, fig="main", ysize=ysize)) + yzoom=0.9, fig="main", ysize=16)) nothing end # --------------------------------------------------------------------------- # _plot_power # --------------------------------------------------------------------------- -function _plot_power(log; ysize=10, energy=nothing, dt=0.0) +function _plot_power(log; energy=nothing, dt=0.0) sl = log.syslog if energy === nothing v_ro = v_reelout(sl) @@ -46,61 +46,61 @@ function _plot_power(log; ysize=10, energy=nothing, dt=0.0) energy, sl.acc; ylabels=["force [N]", L"v_\mathrm{ro}~[m/s]", L"P_\mathrm{m}~[W]", "Energy [Wh]", "acc [m/s^2]"], - fig="power", ysize=ysize)) + fig="power", ysize=16)) nothing end # --------------------------------------------------------------------------- # _plot_control (two sub-plots: control + fpc) # --------------------------------------------------------------------------- -function _plot_control(log; ysize=10) +function _plot_control(log) sl = log.syslog display(plotx(sl.time, rad2deg.(sl.elevation), rad2deg.(sl.azimuth), rad2deg.(wrap2pi.(sl.heading)), force(sl), 100*sl.depower, 100*sl.steering, sl.sys_state, sl.cycle, sl.fig_8; ylabels=["elevation [°]", "azimuth [°]", "heading [°]", "force [N]", "depower [%]", "steering [%]", "fpp_state", "cycle", "fig8"], - fig="control", ysize=ysize, yzoom=0.7)) + fig="control", ysize=16, yzoom=0.7)) sleep(0.05) display(plotx(sl.time, rad2deg.(sl.elevation), rad2deg.(sl.azimuth), -rad2deg.(wrap2pi.(sl.heading)), 100*sl.depower, 100*sl.steering, rad2deg.(sl.var_07), sl.var_06, sl.sys_state, sl.cycle; ylabels=["elevation [°]", "azimuth [°]", "psi [°]", "depower [%]", "steering [%]", "chi_set", "ndi_gain", "fpp_state", "cycle"], - fig="fpc", ysize=ysize, yzoom=0.7)) + fig="fpc", ysize=16, yzoom=0.7)) nothing end # --------------------------------------------------------------------------- # _plot_control_II # --------------------------------------------------------------------------- -function _plot_control_II(log; ysize=10) +function _plot_control_II(log) sl = log.syslog display(plotx(sl.time, rad2deg.(sl.azimuth), -rad2deg.(wrap2pi.(sl.heading)), 100*sl.steering, sl.var_12, rad2deg.(sl.course .- pi), rad2deg.(sl.var_09), rad2deg.(sl.var_10), sl.var_06, sl.sys_state; ylabels=["azimuth [°]", "psi [°]", "steering [%]", "c2", "chi", "psi_dot_set", "psi_dot", "ndi_gain", "fpp_state"], - fig="fpc", ysize=ysize, yzoom=0.7)) + fig="fpc", ysize=16, yzoom=0.7)) nothing end # --------------------------------------------------------------------------- # _plot_winch_control (two sub-plots) # --------------------------------------------------------------------------- -function _plot_winch_control(log; ysize=10) +function _plot_winch_control(log) sl = log.syslog display(plotx(sl.time, rad2deg.(sl.elevation), rad2deg.(sl.azimuth), force(sl), sl.var_04, v_reelout(sl), 100*sl.depower, 100*sl.steering, sl.var_03; ylabels=["elevation [°]", "azimuth [°]", "force [N]", "set_force", "v_reelout [m/s]", "depower [%]", "steering [%]", "wc_state"], - fig="winch_control", ysize=ysize)) + fig="winch_control", ysize=14)) display(plot(sl.time, [v_reelout(sl), sl.var_05]; labels=["v_reelout", "pid2_v_set_out"], ylabel="v_reelout [m/s]", xlabel="time [s]", - fig="winch", ysize=ysize)) + fig="winch", ysize=14)) nothing end @@ -122,8 +122,8 @@ function _plot_aerodynamics(log; plot_lift_drag=false) else display(plotx(sl.time, sl.var_08, rad2deg.(sl.AoA), 100*sl.steering, sl.var_15, rad2deg.(sl.var_16); - ylabels=["LoD [-]", L"AoA~[°]", "steering [%]", - "yaw_rate [°/s]", L"side\_slip~[°]"], + ylabels=["LoD [-]", "AoA [°]", "steering [%]", + "yaw_rate [°/s]", "side_slip [°]"], fig="aerodynamics")) end nothing diff --git a/examples/plots.jl b/examples/plots.jl index 340f15e6..db37be7e 100644 --- a/examples/plots.jl +++ b/examples/plots.jl @@ -40,27 +40,27 @@ end # --------------------------------------------------------------------------- function plot_main() log_file_exists() || return - _plot_main(_load_log(); ysize=16) + _plot_main(_load_log()) end function plot_power() log_file_exists() || return - _plot_power(_load_log(); ysize=16, dt=app.dt) + _plot_power(_load_log(); dt=app.dt) end function plot_control() log_file_exists() || return - _plot_control(_load_log(); ysize=16) + _plot_control(_load_log()) end function plot_control_II() log_file_exists() || return - _plot_control_II(_load_log(); ysize=16) + _plot_control_II(_load_log()) end function plot_winch_control() log_file_exists() || return - _plot_winch_control(_load_log(); ysize=14) + _plot_winch_control(_load_log()) end function plot_aerodynamics(plot_lift_drag=false)