Private API
This page documents the internal functions and types of SymbolicAWEModels.jl
. These are not part of the public API and may change without notice. They are listed here for developers and for those interested in the model's internal workings.
Core Types and Constructors
SymbolicAWEModels.SerializedModel
— Type@with_kw mutable struct SerializedModel{...}
A type-stable container for the compiled and serialized components of a SymbolicAWEModel
.
This struct holds the products of the ModelingToolkit.jl
compilation process, such as the simplified system, the ODE problem, and various generated functions.
Storing these components allows for fast reloading of a pre-compiled model, avoiding the time-consuming symbolic processing step on subsequent runs with the same configuration.
set_hash::Vector{UInt8}
sys_struct_hash::Vector{UInt8}
sys::Union{Nothing, ModelingToolkit.System}
: Simplified system of the mtk model Default: nothingfull_sys::Union{Nothing, ModelingToolkit.System}
: Unsimplified system of the mtk model Default: nothinglin_prob::Union{Nothing, ModelingToolkit.LinearizationProblem}
: Linearization function of the mtk model Default: nothinglin_outputs::Union{Nothing, Vector{Union{Symbolics.Num, Symbolics.Arr}}}
: Default: nothingprob::Union{Nothing, SciMLBase.ODEProblem}
: ODE function of the mtk model Default: nothingdefaults::Vector{Pair}
: Default: Pair[]guesses::Vector{Pair}
: Default: Pair[]set_psys::Any
: Default: nothingset_set_values::Any
: Default: nothingset_set::Any
: Default: nothingset_lin_set_values::Any
: Default: nothingget_set_values::Any
: Default: nothingget_wing_state::Any
: Default: nothingget_vsm_y::Any
: Default: nothingget_segment_state::Any
: Default: nothingget_winch_state::Any
: Default: nothingget_tether_state::Any
: Default: nothingget_struct_state::Any
: Default: nothingget_point_state::Any
: Default: nothingget_pulley_state::Any
: Default: nothingget_group_state::Any
: Default: nothingget_lin_x::Any
: Default: nothingget_lin_dx::Any
: Default: nothingget_lin_y::Any
: Default: nothinglin_model::Union{Nothing, @NamedTuple{A::Matrix{Float64}, B::Matrix{Float64}, C::Matrix{Float64}, D::Matrix{Float64}}}
: Default: nothingsimple_lin_model::Union{Nothing, @NamedTuple{A::Matrix{Float64}, B::Matrix{Float64}, C::Matrix{Float64}, D::Matrix{Float64}}}
: Default: nothing
SymbolicAWEModels.SimFloat
— Typeconst SimFloat = Float64
This type is used for all real variables, used in the Simulation. Possible alternatives: Float32, Double64, Dual Other types than Float64 or Float32 do require support of Julia types by the solver.
SymbolicAWEModels.KVec3
— Typeconst KVec3 = MVector{3, SimFloat}
Basic 3-dimensional vector, stack allocated, mutable.
SymbolicAWEModels.SVec3
— Typeconst SVec3 = SVector{3, SimFloat}
Basic 3-dimensional vector, stack allocated, immutable.
VortexStepMethod.RamAirWing
— TypeVortexStepMethod.RamAirWing(set::Settings; prn=true, kwargs...)
Create a RamAirWing
geometry object from the settings provided.
This is a constructor helper that reads the model and foil file paths from the Settings
object and initializes the RamAirWing
object from VortexStepMethod.jl
.
SymbolicAWEModels.create_4_attach_ram_sys_struct
— Functioncreate_4_attach_ram_sys_struct(set::Settings)
Create a detailed SystemStructure
for a ram-air kite with a 4-point attachment bridle.
This function procedurally builds a complex kite model. Its key feature is that all four bridle attachment points on each of the four wing Group
sections are modeled as deforming with the group's twist dynamics.
This model includes:
- A flexible wing simulated with 4 deformable
Group
sections. - A detailed bridle system with multiple segments and
Pulley
s to distribute forces. - Four main tethers (left/right power, left/right steering) connecting the bridle to the ground winches.
- A 3-winch system controlling the tethers.
Arguments
set::Settings
: Configuration parameters defining the kite's geometry and properties.
Returns
SystemStructure
: A newSystemStructure
object representing the detailed model.
SymbolicAWEModels.create_tether
— Functioncreate_tether(tether_idx, set, points, segments, tethers, attach_point, type, dynamics_type; z, axial_stiffness, axial_damping)
Procedurally create a multi-segment tether.
This function builds a tether from a specified number of segments, connecting a given attach_point
on the kite to a new anchor point on the ground.
State Management and Model Simplification
SymbolicAWEModels.getstate
— Functiongetstate(sys_struct::SystemStructure) -> Tuple
Capture and return a snapshot of the key dynamic states of the system.
SymbolicAWEModels.setstate!
— Functionsetstate!(sys_struct::SystemStructure, state)
Set the key dynamic states of the system from a snapshot tuple.
SymbolicAWEModels.set_measured!
— Functionset_measured!(sys_struct, heading, turn_rate, tether_len, tether_vel)
Adjust the model's state to match a set of "measured" or target values.
This function is typically used in state estimation or stabilization loops. It takes a set of target values (e.g., from a sensor or a reference trajectory) and forces the corresponding states in the SystemStructure
to match, calculating kinematically consistent values for other related states.
SymbolicAWEModels.copy!
— Functioncopy!(sys1::SystemStructure, sys2::SystemStructure)
Copy the dynamic state from one SystemStructure
(sys1
) to another (sys2
).
This function is designed to transfer the state (positions, velocities, etc.) between two system models, which can have different levels of fidelity. For example, it can copy the state from a detailed multi-segment tether model (sys1
) to a simplified single-segment model (sys2
).
The function handles several cases:
- If
sys1
andsys2
have the same structure, it performs a direct copy of all point states. - If
sys2
is a simplified (1-segment per tether) version ofsys1
, it copies the positions and velocities of the tether endpoints. - It also copies the state of wings, groups, winches, and pulleys where applicable.
SymbolicAWEModels.reinit!
— Functionreinit!(transforms::Vector{Transform}, sys_struct::SystemStructure)
Apply the initial spatial transformations to all components in a SystemStructure
.
This function iterates through all transforms and applies the specified translation and rotation to position and orient the kite system components correctly in the world frame at the beginning of a simulation.
reinit!(sys_struct::SystemStructure, set::Settings)
Re-initialize a SystemStructure
from a Settings
object.
This function resets various component states (e.g., winch lengths, group twists, pulley positions) to their initial values as defined in the Settings
object. It is typically called before starting a new simulation run.
reinit!(s::SymbolicAWEModel, solver; prn, precompile, reload, lin_outputs) -> (ODEIntegrator, Bool)
Reinitialize an existing kite power system model with new state values from s.set
.
Arguments
s::SymbolicAWEModel
: The kite power system state object.solver
: The solver to be used.prn::Bool=false
: Whether to print progress information.precompile::Bool=false
: Load the precompiled version of the model.reload::Bool=true
: Force reloading the model from disk.lin_outputs::Vector{Num}=Num[]
: Outputs for the linearized model.
Returns
(ODEIntegrator, Bool)
: A tuple containing the reinitialized integrator and a success flag.
SymbolicAWEModels.update_sys_struct!
— Functionupdate_sys_struct!(s::SymbolicAWEModel, sys_struct::SystemStructure, integ=s.integrator)
Update the high-level SystemStructure
from the low-level integrator state vector.
This function reads the raw state vector from the ODE integrator and uses the generated getter functions to populate the human-readable fields in the SystemStructure
.
SymbolicAWEModels.get_set_hash
— Functionget_set_hash(set::Settings; fields)
Calculate a SHA1 hash for a subset of fields in the Settings
object.
SymbolicAWEModels.get_sys_struct_hash
— Functionget_sys_struct_hash(sys_struct::SystemStructure)
Calculate a SHA1 hash for the topology of a SystemStructure
.
Physics and Geometry Helpers
SymbolicAWEModels.calc_speed_acc
— Functioncalc_speed_acc(winch::AsyncMachine, tether_vel, norm_, set_speed)
Calculate winch acceleration for a speed-controlled asynchronous machine model.
SymbolicAWEModels.calc_moment_acc
— Functioncalc_moment_acc(winch::TorqueControlledMachine, tether_vel, norm_, set_torque)
Calculate winch acceleration for a torque-controlled machine model.
SymbolicAWEModels.calc_angle_of_attack
— Functioncalc_angle_of_attack(va_wing_b)
Calculate the angle of attack [rad] from the apparent wind vector in the body frame.
SymbolicAWEModels.calc_heading
— Functioncalc_heading(R_t_w, R_v_w)
Calculate the heading angle [rad] of the wing.
Heading is defined as the rotation angle between the tether frame and the view frame.
SymbolicAWEModels.calc_R_t_w
— Functioncalc_R_t_w(elevation, azimuth)
Calculate the rotation matrix from the tether frame (_t
) to the world frame (_w
).
The tether frame is a spherical coordinate system defined by elevation and azimuth angles.
SymbolicAWEModels.calc_R_v_w
— Functioncalc_R_v_w(wing_pos, e_x)
Calculate the rotation matrix from the view frame (_v
) to the world frame (_w
).
The view frame is defined with its z-axis pointing from the origin to the wing, and its x-axis aligned with the wing's x-axis projected onto the view plane.
SymbolicAWEModels.cad_to_body_frame
— Functioncad_to_body_frame(wing::RamAirWing, pos)
Transform a position from the CAD frame to the wing's body frame.
SymbolicAWEModels.calc_pos
— Functioncalc_pos(wing::RamAirWing, gamma, frac)
Calculate a position on the kite based on spanwise (gamma
) and chordwise (frac
) parameters.
SymbolicAWEModels.find_axis_point
— Functionfind_axis_point(P, l, v=[0,0,1])
Calculate the coordinates of a point Q
that lies on a line defined by vector v
and is at a distance l
from a given point P
.
SymbolicAWEModels.quaternion_to_rotation_matrix
— Functionquaternion_to_rotation_matrix(q)
Convert a quaternion q
(scalar-first format [w, x, y, z]) to a 3x3 rotation matrix.
SymbolicAWEModels.rotation_matrix_to_quaternion
— Functionrotation_matrix_to_quaternion(R)
Convert a 3x3 rotation matrix R
to a quaternion (scalar-first format [w, x, y, z]).
SymbolicAWEModels.rotate_v_around_k
— Functionrotate_v_around_k(v, k, θ)
Rotate vector v
around axis k
by angle θ
using Rodrigues' rotation formula.
SymbolicAWEModels.sym_normalize
— Functionsym_normalize(vec)
Symbolic-safe normalization of a vector.
SymbolicAWEModels.apply_heading
— Functionapply_heading(vec, R_t_w, curr_R_t_w, heading)
Apply a heading rotation to a vector.
SymbolicAWEModels.get_rot_pos
— Functionget_rot_pos(transform::Transform, wings, points)
Get the position of the rotating object (wing or point) for a given transform.
SymbolicAWEModels.get_base_pos
— Functionget_base_pos(transform::Transform, wings, points)
Get the base position for a given transform, resolving chained transforms if necessary.
SymbolicAWEModels.calc_aoa
— Functioncalc_aoa(s::SymbolicAWEModel)
Calculate the mean angle of attack [rad] over the wingspan from the VSM solver.
Equations and System Management
SymbolicAWEModels.create_sys!
— Functioncreate_sys!(s::SymbolicAWEModel, system::SystemStructure; prn=true)
Create the full ModelingToolkit.System
for the AWE model.
This is the main top-level function that orchestrates the generation of the entire set of differential-algebraic equations (DAEs). It calls specialized sub-functions to build the equations for each part of the system (forces, wing dynamics, scalar kinematics, linearized aerodynamics) and assembles them into a single System
object.
Arguments
s::SymbolicAWEModel
: The main model object to be populated.system::SystemStructure
: The physical structure definition.prn::Bool=true
: If true, print progress information.
Returns
set_values
: The symbolic variable representing the control inputs.
SymbolicAWEModels.scalar_eqs!
— Functionscalar_eqs!(s, eqs, psys, pset; R_b_w, wind_vec_gnd, ...)
Generate equations for derived scalar kinematic quantities.
This function calculates variables that are useful for control and analysis but are not fundamental states of the system, such as elevation, azimuth, heading, and course angles, along with their time derivatives.
Arguments
s::SymbolicAWEModel
: The main model object.eqs
,psys
,pset
: Accumulating vectors and symbolic parameters.R_b_w
,wind_vec_gnd
, etc.: Symbolic variables for the system's state.
Returns
eqs
: The updated list of system equations.
SymbolicAWEModels.wing_eqs!
— Functionwing_eqs!(s, eqs, psys, pset, defaults; tether_wing_force, ...)
Generate the differential equations for the wing's rigid body dynamics.
This function builds the equations for:
- Quaternion kinematics for the wing's orientation.
- Euler's rotation equations for the angular acceleration, including gyroscopic effects.
- Newton's second law for the translational motion of the wing's center of mass.
Arguments
s::SymbolicAWEModel
: The main model object.eqs
,psys
,pset
,defaults
: Accumulating vectors and symbolic parameters.tether_wing_force
,tether_wing_moment
: Aggregate forces/moments from tethers.aero_force_b
,aero_moment_b
: Aerodynamic forces/moments.ω_b
,α_b
,R_b_w
,wing_pos
,wing_vel
,wing_acc
: Symbolic state variables.
Returns
(eqs, defaults)
: A tuple containing the updated equation and default value lists.
SymbolicAWEModels.linear_vsm_eqs!
— Functionlinear_vsm_eqs!(s, eqs, guesses, psys; aero_force_b, ...)
Generate linearized aerodynamic equations using the Vortex Step Method (VSM).
This function approximates the complex, nonlinear aerodynamic forces and moments by using a first-order Taylor expansion around the current operating point. The Jacobian of the aerodynamic forces with respect to the state variables (va_wing_b
, ω_b
, twist_angle
) is pre-calculated and provided as a parameter (vsm_jac
).
Arguments
s::SymbolicAWEModel
: The main model object.eqs
,guesses
,psys
: Accumulating vectors and symbolic parameters.aero_force_b
,aero_moment_b
, etc.: Symbolic variables for aerodynamic and state quantities.
Returns
(eqs, guesses)
: A tuple containing the updated equation and guess lists.
SymbolicAWEModels.force_eqs!
— Functionforce_eqs!(s, system, psys, pset, eqs, defaults, guesses; R_b_w, wing_pos, ...)
Generate the force and constraint equations for the mass-spring-damper components.
This function builds the core equations for:
- Points: Newton's second law for dynamic points, force balance for quasi-static points, and kinematic constraints for points attached to the wing.
- Segments: Spring-damper forces (Hooke's law) and aerodynamic drag forces.
- Pulleys: Length redistribution dynamics or constraints.
- Winches: Tether length and velocity dynamics based on the winch model.
- Groups: Rotational dynamics for wing twist deformation.
Arguments
s::SymbolicAWEModel
: The main model object.system::SystemStructure
: The physical structure definition.psys
,pset
: Symbolic parameters representingsystem
ands.set
.eqs
,defaults
,guesses
: The accumulating vectors for the MTK system.R_b_w
,wing_pos
, etc.: Symbolic variables for the wing's state.
Returns
(eqs, defaults, guesses, tether_wing_force, tether_wing_moment)
: A tuple containing the updated equation lists and the calculated aggregate forces and moments exerted by the tethers on the wing.
SymbolicAWEModels.linearize_vsm!
— Functionlinearize_vsm!(s::SymbolicAWEModel, integ=s.integrator)
Update the linearized aerodynamic model from the Vortex Step Method (VSM).
This function takes the current kinematic state of the wing (apparent wind, angular velocity, twist angles), linearizes the VSM aerodynamics around this operating point, and updates the Jacobian (vsm_jac
) and the steady-state forces (vsm_x
) in the SystemStructure
. This is typically called periodically during a simulation.
SymbolicAWEModels.jacobian
— Functionjacobian(f::Function, x::AbstractVector, ϵ::AbstractVector) -> Matrix
Numerically compute the Jacobian of a vector-valued function f
at point x
.
This function uses a simple forward finite difference method to approximate the partial derivatives of f
with respect to each component of x
.
Arguments
f::Function
: The function to differentiate (y = f(x)
).x::AbstractVector
: The point at which to evaluate the Jacobian.ϵ::AbstractVector
: A vector of perturbation sizes for each component ofx
.
Returns
Matrix
: The Jacobian matrixJ
, whereJ[i, j] = ∂f[i] / ∂x[j]
.
SymbolicAWEModels.generate_getters
— Functiongenerate_getters(sys, sys_struct, lin_prob, lin_y_vec) -> NamedTuple
Generate and compile optimized getter and setter functions for the model.
This internal function uses the symbolic system definition from ModelingToolkit.jl
to create fast, non-allocating functions for accessing and modifying the system's state and parameters directly within the ODE integrator's data structures. This is a key optimization that avoids symbolic lookups during the simulation loop.
Returns
NamedTuple
: A named tuple containing all the generated functions.
Utility and Internal Functions
SymbolicAWEModels.get_model_name
— Functionget_model_name(set::Settings; precompile=false)
Construct a unique filename for the serialized model based on its configuration.
SymbolicAWEModels.calc_height
— FunctionReturns the height (z-position) [m] of the wing.
SymbolicAWEModels.set_depower_steering!
— Functionset_depower_steering!(s::SymbolicAWEModel, depower, steering)
Set the kite's depower and steering by adjusting the tether length set-points.
SymbolicAWEModels.min_chord_len
— Functionmin_chord_len(s::SymbolicAWEModel)
Calculate the minimum chord length of the wing at the tip.
SymbolicAWEModels.pos
— FunctionReturns the position vector [m] for each point.
SymbolicAWEModels.spring_forces
— FunctionReturns the spring force [N] for each segment.
SymbolicAWEModels.calc_spring_props
— Functioncalc_spring_props(sam, tether_sam; prn=false) -> (Vector, Vector, Matrix, Float64)
Calculate the equivalent axial stiffness and damping, and return the step response data.
This function orchestrates the process by performing a step response test on the tether_sam
model and then analyzing the resulting tether length data.
Arguments
sam::SymbolicAWEModel
: The reference model, used for its physical properties.tether_sam::SymbolicAWEModel
: A copy of the model to perform the step test on.
Keywords
prn::Bool=false
: If true, enables printing of intermediate results.
Returns
Tuple{Vector{Float64}, Vector{Float64}, Matrix{Float64}, Float64}
: A tuple containing:axial_stiffness
[N]axial_damping
[Ns]tether_lens
(the step response data)dt
(the simulation time step)
calc_spring_props(sam, tether_lens, F_step; p=5, prn=false) -> (Vector, Vector)
Calculate spring constant k
and damping coefficient c
from a step response.
This function analyzes the time series of tether lengths (tether_lens
) resulting from a step force (F_step
) to estimate the parameters of an equivalent second-order mass-spring-damper system.
Arguments
sam::SymbolicAWEModel
: The model from which to take physical parameters (mass).tether_lens::Matrix{Float64}
: A matrix of tether length time series data.F_step::Float64
: The magnitude of the applied step force.
Keywords
p::Int=5
: The percentage band used to determine the settling time.prn::Bool=false
: If true, enables printing of detailed calculations.
Returns
Tuple{Vector{Float64}, Vector{Float64}}
: A tuple containing two vectors:k_values
(spring constants [N/m])c_values
(damping coefficients [Ns/m])
SymbolicAWEModels.set_v_wind_ground!
— Functionset_v_wind_ground!(s::SymbolicAWEModel, v_wind_gnd=s.set.v_wind, upwind_dir=-π/2)
Set the ground wind speed [m/s] and upwind direction [rad].
SymbolicAWEModels.in_percent_band
— Functionin_percent_band(x, steady, delta_x, i, p) -> Bool
Helper function to check if a time series has settled within a percentage band.
It checks if all values of the time series x
from index i
to the end are within a tolerance band defined by p
percent of the total change delta_x
.
SymbolicAWEModels.step
— Functionstep(sam, steps, F_step, F_0; abs_tol, consecutive_steps_needed, prn) -> Matrix
Apply a step force to a model and simulate its dynamic response.
This function records the length of each tether over a specified number of simulation steps. It includes an early exit condition if the system's state settles.
Arguments
sam::SymbolicAWEModel
: The model to be simulated.steps::Int
: The total number of simulation steps.F_step::Float64
: The magnitude of the step force to apply.F_0::Vector{KVec3}
: The initial force vector for each tether attachment point.
Keywords
abs_tol::Float64=1e-6
: Absolute tolerance for the settling check.consecutive_steps_needed::Int=10
: Number of consecutive steps required to be within tolerance to be considered settled.prn::Bool=false
: If true, enables printing of status messages.
Returns
Matrix{Float64}
: A matrix where each row corresponds to a tether and each column to a time step, containing the tether lengths.
SymbolicAWEModels.create_model_archive
— Functioncreate_model_archive(source_dir, archive_path)
Finds all model*.bin
files in the source_dir
, copies them to a temporary directory, and compresses that directory into a .tar.gz
archive at the specified archive_path
.
SymbolicAWEModels.filecmp
— Functionfilecmp(path1::AbstractString, path2::AbstractString) -> Bool
Compare two files byte-by-byte to check if they are identical.
SymbolicAWEModels.extract_model_archive
— Functionextract_model_archive(archive_path, dest_dir)
Safely decompress a .tar.gz
file by first extracting to a temporary directory and then copying the contents to the final destination.
Arguments
archive_path::String
: The path to the.tar.gz
file to be extracted.dest_dir::String
: The path to the target directory.
SymbolicAWEModels.create_default_models
— Functioncreate_default_models(; prn=true)
Create and initialize a set of default SymbolicAWEModel
instances for precompilation.
Base Overloads (Internal Use)
Base.getindex
— FunctionBase.getindex(x::ModelingToolkit.Symbolics.SymArray, idxs::Vector{Int16})
Extend getindex
to allow indexing a symbolic array with a vector of indices.
Base.getproperty
— FunctionBase.getproperty(sam::SymbolicAWEModel, sym::Symbol)
Overload getproperty
to allow direct access to fields within the nested serialized_model
.
Base.setproperty!
— FunctionBase.setproperty!(sam::SymbolicAWEModel, sym::Symbol, val)
Overload setproperty!
to allow direct setting of fields within the nested serialized_model
.
Plotting Recipes (Internal Use)
RecipesBase.apply_recipe
— Function@recipe function f(sys::SystemStructure; zoom=false, front=false, kite_pos=nothing, reltime=nothing)
A plot recipe for a SystemStructure
type (assumed to be defined, e.g., in SymbolicAWEModels.jl
) using RecipesBase.jl
.
This recipe allows plotting a SystemStructure
in 2D, showing either a side view (X-Z plane) or a front view (Y-Z plane). It supports zooming in on the last point of the system (assumed to be the kite or primary object of interest).
Type Assumptions for SystemStructure
This recipe assumes SystemStructure
has fields:
points::Vector{Point}
: Where eachPoint
object has apos_w
field (e.g.,p.pos_w
) that yields a 3D position vector (likeSVector{3, Float64}
).segments::Vector{Segment}
: Where eachSegment
object has apoints
field (e.g.,seg.points
) that yields a tuple of two integers, representing 1-based indices into thesys.points
vector.
Adjust field access within the recipe if your struct definitions differ.
Attributes
These can be passed as keyword arguments to the plot
call:
zoom::Bool
(default:get(plotattributes, :zoom, false)
): Iftrue
, the plot view zooms in on the last point insys.points
.front::Bool
(default:get(plotattributes, :front, false)
): Iftrue
, shows the front view (Y-Z). Otherwise, shows the side view (X-Z).kite_pos::Union{AbstractVector{<:Real}, Nothing}
(default:get(plotattributes, :kite_pos, nothing)
): Optionally, an additional 3D position vector (e.g.,SVector{3, Float64}(x,y,z)
or[x,y,z]
) to be plotted as a distinct point. This point is included in zoom calculations ifzoom
is true andkite_pos
is the last effective point.reltime::Union{Real, Nothing}
(default:get(plotattributes, :reltime, nothing)
): If provided, sets the plot title to "Time: [reltime] s".
Example
# Make sure SystemStructure, Point, Segment are defined and you have an instance `my_system`.
# using Plots # Or any other RecipesBase-compatible plotting backend
# Basic side view
# plot(my_system)
# Zoomed side view
# plot(my_system, zoom=true)
# Front view
# plot(my_system, front=true)
# Zoomed front view with a specific kite position and time display
# extra_kite_marker = SVector(10.0, 2.0, 30.0) # Or KVec3(10.0, 2.0, 30.0)
# current_time = 1.23
# plot(my_system, zoom=true, front=true, kite_pos=extra_kite_marker, reltime=current_time)