Introduction

The SystemStructure provides a flexible framework for defining mechanical systems using discrete mass-spring-damper models. It serves as input to the SymbolicAWEModel, which automatically generates symbolic differential algebraic equations from the structural definition.

See Building a system using Julia and Building a system using YAML for tutorials on creating systems.

Public enumerations

SymbolicAWEModels.DynamicsType — Type
DynamicsType `DYNAMIC` `STATIC` `BODY_STATIC` `KINEMATIC`

Enumeration for the dynamic model governing a point's motion, a rigid body's motion, or a station's twist. DYNAMIC quantities carry differential state and are solved by the dynamics; the others are prescribed — no state, held constant within a step, but mutable between steps. A wing's aerodynamic-surface points are ordinary DYNAMIC (particle wing) or BODY_STATIC (rigid wing) points; their wing membership comes from station membership (point.is_wing_node).

Elements

  • DYNAMIC: Solved by the dynamics. A point moves by Newton's second law; a rigid body integrates its 6-DOF state; a station twist solves its equilibrium.
  • STATIC: Prescribed, no state. A point's position is welded in the world frame; a rigid body is clamped to the world; a station twist is a prescribed control input read live via the registered getter.
  • BODY_STATIC: A point rides a Body — static in the rigid body's body frame; it feeds its net force (and the moment about the body COM) into the body.
  • KINEMATIC: A twist source whose deflection is prescribed by geometry (e.g. a flap hinge between two bodies).
source
SymbolicAWEModels.WingType — Type
WingType `RIGID_DYNAMICS` `PARTICLE_DYNAMICS`

Enumeration for the structural representation of a wing.

Elements

  • RIGID_DYNAMICS: Wing uses quaternion-based rigid body dynamics, with the deformation confined to the twist degrees of freedom of its Stations. Aerodynamic forces/moments are applied to the wing center of mass; its structural points are BODY_STATIC and ride the body.
  • PARTICLE_DYNAMICS: Wing has no rigid body constraint. Its structural points are ordinary DYNAMIC particles and the aerodynamic loads are applied to them directly, so the wing deforms with the structure.
source
SymbolicAWEModels.SegmentType — Type
SegmentType `POWER_LINE` `STEERING_LINE` `BRIDLE`
Deprecated

SegmentType is no longer used as a Segment constructor parameter. It is kept only so that old code hits a deprecation error instead of UndefVarError.

source
SymbolicAWEModels.PrincipalFrameMethod — Type
PrincipalFrameMethod

Strategy for computing the principal frame from an inertia tensor.

  • EIGEN_DECOMP: full 3-axis eigendecomposition + permutation search (principal_frame). General-purpose; correct for any body.
  • Y_ROTATION: closed-form rotation about Y only (calc_inertia_y_rotation). Use for wings symmetric about the XZ-plane where the generic permutation search is ambiguous when two principal moments are close.
source

Aerodynamic models

SymbolicAWEModels.AeroNone — Type
AeroNone()

No aerodynamic forces (returns zeros). A body with aero = AeroNone() is a plain rigid/kinematic body. Needs no VSM geometry and carries no state.

source
SymbolicAWEModels.AeroDirect — Type
AeroDirect()

Stored forces from the nonlinear VSM solve, piecewise-constant between updates. Carries a VSMEngine; the no-arg form is the engine-less marker filled in during wing construction.

source
SymbolicAWEModels.AeroLinearized — Type
AeroLinearized()

First-order Taylor expansion using the Jacobian from VSM linearization (RIGID_DYNAMICS only). Carries a VSMEngine; the no-arg form is the engine-less marker filled in during wing construction.

source
SymbolicAWEModels.AeroPlate — Type
AeroPlate(calc_cl, calc_cd; drag_corr=1.0)

Flat-plate CL/CD lookup aerodynamics. Carries the shared polar lookups (calc_cl/calc_cd: α_deg → coefficient) and drag correction used by all of a wing's flat-plate (1-point STATIC) Stations. One polar set per wing.

source
SymbolicAWEModels.ContinuousAero — Type
ContinuousAero()

Frozen-circulation VSM aerodynamics with live symbolic force assembly (PARTICLE_DYNAMICS only). The VSM solver runs every vsm_interval steps and solves only the circulation distribution (VortexStepMethod.solve_base!); the resulting per-refined-panel induced velocity is frozen. Each RHS step then evaluates the calc_forces! chain symbolically per refined panel — geometry interpolated from the live strut points with the frozen mesh weights, effective angle of attack, polar lookups, and lift/drag directions all live — capturing aerodynamic damping between refreshes. Carries a VSMEngine; the no-arg form is the engine-less marker filled in during wing construction.

source
SymbolicAWEModels.AeroPressure — Type
AeroPressure(; frame_tol_frac=2.0, live_polars=false)

VSM aerodynamics whose per-section force is distributed onto arbitrary structural points (a chord-line skeleton, a strut, or a double-skin membrane of point masses) by the airfoil surface traction pattern (PARTICLE_DYNAMICS only). VSM owns the totals; the traction pattern owns only placement and direction.

Like ContinuousAero this is a continuous mode: the full VSM solve! runs every vsm_interval, freezing the circulation-derived induced velocity v_ind and the per-node surface traction pattern, while the per-panel total force is re-derived symbolically every RHS step from v_ind and the live apparent wind (shared build_panel_force_eqs). The frozen traction sets only the distribution shape: each wing node's force is its frozen traction plus an equal share of (live panel force − frozen pattern net), so per panel the point forces sum to the live total exactly.

Its mesh also deforms with the structure: the unrefined sections are rebuilt onto the structural LE/TE stations and refined (polars and Cp contours spanwise-interpolated onto the refined panels), each refined section's LE/TE a live function of the station points' pos_w. frame_tol_frac is the frame-alignment guard: construction errors if any surface node maps to a point farther than frame_tol_frac × the local chord. Carries a VSMEngine; the no-arg form is the engine-less marker filled in during wing construction.

live_polars replaces the tabulated (α, δ) polars with polars regenerated from the deformed shape every solve (see solve_with_live_polars!): each panel's chordwise deformation deforms its Kulfan fit, NeuralFoil is evaluated on a grid of angles about the panel's own angle of attack, and those values become its rewritten polar. The flap angle δ then carries no information and is dropped from the equations entirely, so the RHS has no live deflection left in it — only α stays live. Use it where the chord bends into a shape a single hinge angle cannot stand for.

A live polar spans only the angles it was sampled over and is held flat past them, so bring-up still wants damping enough to keep the solve inside that range — releasing the SK100 from its placed geometry at start_world_damping = 20 accelerates the wing to 20 m/s in 10 ms and slews α some 20° inside one 0.05 s step, where 300 settles. Past the range the answer is bounded rather than lost, which is the difference from a tabulated polar spanning the whole range: stale, not wrong-signed.

source
SymbolicAWEModels.UnsteadyAero — Type
UnsteadyAero(; apparent_mass=0.0, wagner=false, wagner_gains=(0.165, 0.335),
             wagner_rates=(0.0455, 0.3))

Unsteady corrections a wing adds on top of its frozen-circulation VSM forces, held by the wing's VSMEngine and off by default. apparent_mass scales the entrained-air inertia apply_apparent_mass! puts on the wing nodes, 1 being the thin-plate value and 0 disabling it. wagner enables the two-state Wagner lift lag, whose indicial response is 1 - A1·exp(-b1·s) - A2·exp(-b2·s) in semi-chords travelled, with gains (A1, A2) and rates (b1, b2); the defaults are R. T. Jones' fit to Wagner's function. The four lag constants are registered parameters, so retuning them is a sync and not a rebuild; only wagner itself is structural, because it is what adds or removes the two states.

  • apparent_mass::Float64: Scale on the thin-plate entrained-air mass; 0 leaves the nodes' inertia alone.

  • wagner::Bool: Whether the wing carries the two-state Wagner lift lag.

  • wagner_gains::StaticArraysCore.MVector{2, Float64}: Wagner indicial gains (A1, A2), the share of lift each lag state withholds.

  • wagner_rates::StaticArraysCore.MVector{2, Float64}: Wagner indicial rates (b1, b2), per semi-chord travelled.

source
SymbolicAWEModels.aero_component — Function
aero_component(mode::AbstractAeroModel, wing::AbstractWing, sys_struct; name, params) -> System

Build the aero subsystem for wing, selected by dispatch on both the wing's aero model and its dynamics type (RigidWing/ParticleWing). Returns a System exposing the connectors fixed by the dynamics type, all in the wing body frame (the wiring layer aero_eqs! drives inputs and reads outputs; connectors a mode ignores still exist for binding):

  • RIGID_DYNAMICS (num = length(wing.station_idxs)): in va[1:3], rho, R_b_w[1:3,1:3], omega[1:3], twist[1:num], twist_vel[1:num]; out force[1:3], moment[1:3], twist_moment[1:num].
  • PARTICLE_DYNAMICS (np = number of wing nodes): in point_pos[1:3,1:np], point_vel[1:3,1:np], va[1:3,1:np], rho[1:np]; out point_force[1:3,1:np].

A mode supports a dynamics type by defining the matching method (rigid, particle, or both). Add a method on a custom AbstractAeroModel subtype to plug in your own aerodynamics.

source
SymbolicAWEModels.is_builtin_aero — Function
is_builtin_aero(mode::AbstractAeroModel) -> Bool

true for the package's built-in aero models. Custom models return false, which forces a model rebuild (the compiled cache cannot be reused for user-supplied equations). Each built-in mode sets this in its aero_modes/ file.

source
SymbolicAWEModels.aero_hash_id — Function
aero_hash_id(mode::AbstractAeroModel) -> Tuple

Structural fields of mode that change the generated equations and therefore must enter the model-cache key. Return only fields that alter the equation structure, never runtime-mutable values (those are read live via registered getters). Defaults to an empty tuple.

source
aero_hash_id(mode::ContinuousAero)

The frozen mesh-interpolation weights and billow offsets are baked into the generated equations, so they are structural and enter the model-cache hash.

source
aero_hash_id(mode::AeroPressure)

The surface-node→point map is baked into the generated scatter equations, so it is structural and enters the model-cache hash (distinguishing it from any stale frozen-force build that used the default empty id). The panel→flap-station map is likewise baked into the δ wiring.

source

Winch models

SymbolicAWEModels.AbstractWinchModel — Type
abstract type AbstractWinchModel

Selects the winch motor dynamics. Each concrete model carries its own parameter fields and adds a winch_component(model, sys_struct, idx; name, params) method building the MTK subsystem (mirrors AbstractAeroModel). The model lives in Winch.model; common drum parameters (gear_ratio, drum_radius, coulomb_friction, viscous_coefficient, inertia_total) stay on the Winch struct. New models = new struct + a few methods; see TorqueWinch.

source
SymbolicAWEModels.TorqueWinch — Type
TorqueWinch(; friction_epsilon=6.0)

Torque-controlled winch motor (the default winch model). set_value is the motor torque [N·m]. Coulomb friction is smoothed by friction_epsilon (the smooth_sign transition width). The drum parameters (gear_ratio, drum_radius, coulomb_friction, viscous_coefficient, inertia_total) live on the Winch struct; friction_epsilon is a numerical property of this model and lives here (mutable, live-tunable).

Equations

ω_motor   = vel / ratio,   ratio = drum_radius / gear_ratio
friction  = smooth_sign(ω_motor, friction_epsilon) * coulomb_friction * ratio +
            viscous_coefficient * ω_motor * ratio^2
tau_total = set_value + ratio * force - friction
acc       = ifelse(brake > 0.5, 0, ratio * tau_total / inertia_total)
source
SymbolicAWEModels.CascadedLengthWinch — Type
CascadedLengthWinch(; v_max, position_gain, velocity_gain, friction_epsilon=6.0)

Length-controlled winch motor. set_value is the target tether length [m]. An outer proportional law turns the length error into a velocity reference, hard-clamped at ±v_max; an inner proportional law with load feedforward (+friction − ratio·force) tracks it. No integrator, so no windup at the clamp; the closed-loop speed response is first-order.

Drum parameters (gear_ratio, drum_radius, coulomb_friction, viscous_coefficient, inertia_total) live on the Winch; the gains and friction_epsilon are this model's own fields (mutable, live-tunable).

Equations

ω_motor       = vel / ratio,   ratio = drum_radius / gear_ratio
friction      = smooth_sign(ω_motor, friction_epsilon) * coulomb_friction * ratio +
                viscous_coefficient * ω_motor * ratio^2
vel_unclamped = position_gain * (set_value − len)
vel_ref       = clamp(vel_unclamped, −v_max, v_max)
tau_cmd       = velocity_gain * (vel_ref − vel) + friction − ratio * force
tau_net       = tau_cmd + ratio * force − friction
acc           = ifelse(brake > 0.5, 0, ratio * tau_net / inertia_total)
source

Core model type

SymbolicAWEModels.SymbolicAWEModel — Type
mutable struct SymbolicAWEModel <: AbstractKiteModel

The main state container for a kite power system model, built using ModelingToolkit.jl.

Holds the physical structure (SystemStructure), the compiled model (SerializedModel), the atmospheric model, and the ODE integrator. Interact with it through init! and next_step! rather than through its fields.

Type Parameters

  • S: Scalar type, typically SimFloat.
  • V: Vector type, typically KVec3.
  • P: Number of tether points in the system.
  • sys_struct::SystemStructure: Reference to the point mass system with points, segments, pulleys and tethers

  • serialized_model::SymbolicAWEModels.SerializedModel: Container for the compiled and serialized model components

  • integrator::Union{Nothing, OrdinaryDiffEqCore.ODEIntegrator}: The ODE integrator for the full nonlinear model Default: nothing

  • t_0::Float64: Relative start time of the current time interval Default: 0.0

  • iter::Int64: Number of next_step! calls Default: 0

  • t_vsm::Float64: Time spent in the VSM linearization step Default: zero(SimFloat)

  • t_step::Float64: Time spent in the ODE integration step Default: zero(SimFloat)

  • param_registry::Any: Build-time flattened-parameter registry (transient, never serialized). Default: nothing

  • initial_registry::Any: Build-time initial-condition registry (transient, never serialized). Default: nothing

  • backend::ModelBackend: Assembly/feature backend; defaults to MonolithBackend. Default: default_backend()

source
SymbolicAWEModels.SymbolicAWEModel — Method
SymbolicAWEModel(set::Settings, sys_struct::SystemStructure; kwargs...)

Constructs a SymbolicAWEModel from an existing SystemStructure.

This is the primary inner constructor. It takes a SystemStructure that defines the physical layout of the kite system and prepares it for symbolic model generation.

Arguments

  • set::Settings: Configuration parameters.
  • sys_struct::SystemStructure: The physical system definition.
  • kwargs...: Further keyword arguments passed to the SymbolicAWEModel constructor.

Returns

  • SymbolicAWEModel: A model ready for symbolic equation generation via init!.
source

Backends

SymbolicAWEModels.ModelBackend — Type
ModelBackend

Abstract supertype selecting how a SymbolicAWEModel is assembled and which features it supports. Concrete backends: MonolithBackend (the default) and KernelBackend. The backend is a field of the model and is the dispatch axis for all backend-varying behaviour (problem assembly, linearization, control-function generation).

Backends differ at assembly only. Every equation is written once, in components.jl, and both backends build from that one definition — the monolith through the generators in generate_system/, the kernel by wrapping it in a component. A quantity one backend reports and the other does not is a missing assembly or readout, never a licence to restate the math on the other side.

source
SymbolicAWEModels.MonolithBackend — Type
MonolithBackend()

Default backend. create_sys! builds one flattened ModelingToolkit System that mtkcompile turns into a single RHS. Supports every feature (linearization, control functions). Compile time grows with the total node count.

source
SymbolicAWEModels.KernelBackend — Type
KernelBackend()

Backend that compiles one kernel per component type and runs them from a build-time schedule over gather/scatter buffers. Compile time is flat in node count, because refining a model adds instances of kernels that already exist. Features without an implementation throw BackendUnsupportedError.

source

System structure and components

SymbolicAWEModels.SystemStructure — Type
struct SystemStructure

A discrete mass-spring-damper representation of a kite system: all components of the physical model, from points and segments to winches and wings.

Components

  • Point: Point masses.
  • Station: Collections of points for wing deformation.
  • Segment: Spring-damper elements.
  • Pulley: Elements that redistribute line lengths.
  • Tether: Collections of segments controlled by a winch.
  • Winch: Ground-based winches.
  • Body: Rigid bodies; a wing is a body that carries aero, so sys.wings holds the subset of sys.bodies that does.
  • Tube: Inflated tubes between two bodies; a chain of them forms a beam.
  • Transform: Spatial transformations for initial positioning.
source
SymbolicAWEModels.SystemStructure — Method
SystemStructure(name, set; points, stations, segments, pulleys, tethers,
                winches, wings, transforms, bodies, tubes)

Constructs a SystemStructure object representing a complete mechanical system. Resolves every symbolic reference to a numeric index, fills in derived properties and validates the result.

name is also the system_name that keys the compiled-model cache, so systems of the same structural shape should share one.

Arguments

  • name::String: Model identifier, free-form.
  • set::Settings: Configuration parameters from KiteUtils.jl.

Keyword Arguments

  • points, stations, segments, etc.: Vectors of the system components.
  • vsm_set: VSMSettings for VSM wings; read from the project file's vsm_settings: when omitted.
  • wind_mode::WindMode=ProfileWind(): PerPointWind makes every point's wind_vec a settable parameter instead of a height-profile output.
  • ignore_l0::Bool=false: Set every segment l0 to its placed length (relax_segments!).
  • placed::Bool=false: The positions given are the initial pose already: start there (start_placed!) instead of running place!, keeping every l0.
  • prn::Bool=true: If true, print info messages about auto-generated components.

Returns

  • SystemStructure: A complete system ready for building a SymbolicAWEModel.
source
SymbolicAWEModels.Point — Type
mutable struct Point

A point mass, representing a node in the mass-spring system.

  • idx::Int64: Index in the points vector (assigned by SystemStructure).

  • name::Union{Nothing, Int64, Symbol}

  • transform_idx::Int64: Resolved transform index (filled by SystemStructure).

  • wing_idx::Int64: Resolved wing index (filled by SystemStructure). 0 = no wing.

  • body_idx::Int64: Resolved rigid-body index for a body-anchored point (filled by SystemStructure). 0 = not anchored.

  • transform_ref::Union{Int64, Symbol}

  • wing_ref::Union{Int64, Symbol}

  • body_ref::Union{Int64, Symbol}

  • pos_ENU::StaticArraysCore.MVector{3, Float64}

  • pos_undeformed_b::StaticArraysCore.MVector{3, Float64}

  • pos_b::StaticArraysCore.MVector{3, Float64}

  • anchor_b::StaticArraysCore.MVector{3, Float64}: Anchor offset in the rigid body's body frame [m] (body-anchored points), derived from pos_ENU by SystemStructure when left at zero.

  • pos_w::StaticArraysCore.MVector{3, Float64}

  • vel_w::StaticArraysCore.MVector{3, Float64}

  • ext_force_w::StaticArraysCore.MVector{3, Float64}

  • force::StaticArraysCore.MVector{3, Float64}

  • aero_force_b::StaticArraysCore.MVector{3, Float64}

  • drag_force::StaticArraysCore.MVector{3, Float64}

  • va_b::StaticArraysCore.MVector{3, Float64}

  • wind_vec::StaticArraysCore.MVector{3, Float64}

  • type::DynamicsType

  • extra_mass::Float64: User-provided mass [kg].

  • total_mass::Float64: Total mass [kg]: extra_mass + segment contributions (computed during simulation).

  • apparent_mass::Float64: Entrained-air mass [kg] resisting acceleration without adding weight.

  • body_frame_damping::StaticArraysCore.MVector{3, Float64}: Per-axis damping in body frame [N·s/m].

  • world_frame_damping::StaticArraysCore.MVector{3, Float64}: Per-axis damping in world frame [N·s/m].

  • area::Float64: Cross-sectional area for drag [m²].

  • drag_coeff::Float64: Drag coefficient [-].

  • fix_sphere::Bool: If true, constrain point to a sphere.

  • fix_static::Bool: If true, dynamically freeze point position.

  • is_wing_node::Bool: Derived: true when the point is an aerodynamic-surface structural node of a wing (a member of one of the wing's stations). Set by SystemStructure from station membership; drives the wing-node equations.

  • tube_idx::Int64: Resolved anchoring tube index (filled by SystemStructure). 0 = not beam-anchored.

  • tube_ref::Union{Int64, Symbol}

  • beam_frac::Float64: Parameter s ∈ [0,1] along the beam element (auto-derived from pos_ENU).

  • beam_offset_b::StaticArraysCore.MVector{3, Float64}: Perpendicular offset off the centerline in the rest element frame [m] (auto-derived).

source
SymbolicAWEModels.Point — Method
Point(name, pos_ENU, type; wing=nothing, transform=nothing, ...)

Constructs a Point object, which can be of three different DynamicsTypes:

  • STATIC: The point does not move. $\ddot{\mathbf{r}} = \mathbf{0}$
  • DYNAMIC: The point moves according to Newton's second law. $\ddot{\mathbf{r}} = \mathbf{F}/m$
  • BODY_STATIC: The point is static in a Body's body frame; it rides the body and feeds its net force and moment into it. Anchor it with body, tube, or wing (a wing is a body, so wing rides that wing's own body). body and wing may both be set only when body is a non-wing body; a body naming a different wing errors during resolution.

A wing's aerodynamic-surface structural points are ordinary DYNAMIC (particle wing) or BODY_STATIC (rigid wing) points that are members of one of the wing's stations; their is_wing_node flag is then set from that membership and drives the per-point aero and wing-frame fitting.

Arguments

  • name::Union{Int, Symbol}: Name/identifier for the point (e.g., :kcu, :le_1, or 1 for legacy).
  • pos_ENU::KVec3: Position of the point before place! moves it [m].
  • type::DynamicsType: Dynamics type of the point (STATIC, DYNAMIC, etc.). Pass BODY_STATIC together with body to anchor the point to a rigid body.

Keyword Arguments

  • wing::Union{Int, Symbol}: The wing the point belongs to (name or index). Without it the point belongs to none: no body-frame damping, and no body frame to express its apparent wind in.
  • transform::Union{Int, Symbol}: Reference to the transform (name or index), defaulting to none.
  • body::Union{Int, Symbol}: Reference to a Body to anchor the point to (requires type = BODY_STATIC). The point then rides the body kinematically and feeds its net force (and the moment about the body COM) into the body. Defaults to no anchor.
  • anchor_b::KVec3: Anchor offset in the body frame [m] (used with body).
  • vel_w::KVec3=zeros(KVec3): Initial velocity of the point in world frame.
  • extra_mass::Float64=0.0: User-provided mass of the point [kg].
  • apparent_mass::Float64=0.0: Entrained-air mass of the point [kg], which resists acceleration but carries no weight.
  • body_frame_damping::Union{Float64,KVec3}=zeros(KVec3): Per-axis damping for body frame.
  • world_frame_damping::Union{Float64,KVec3}=zeros(KVec3): Per-axis damping for world frame.
  • fix_sphere::Bool=false: If true, constrains the point to a sphere.
  • fix_static::Bool=false: If true, dynamically freezes the point.

Returns

  • Point: A new Point object. The idx field is assigned later by SystemStructure.
source
SymbolicAWEModels.Station — Type
mutable struct Station

A set of bridle lines that share the same twist angle and trailing edge angle.

  • idx::Int64: Index in the stations vector (assigned by SystemStructure).

  • name::Union{Nothing, Int64, Symbol}

  • point_idxs::Vector{Int64}: Resolved point indices (filled by SystemStructure).

  • point_refs::Vector{Union{Int64, Symbol}}

  • le_pos::StaticArraysCore.MVector{3, Float64}: Leading edge position in body frame [m] (from closest VSM panel).

  • chord::StaticArraysCore.MVector{3, Float64}: Chord vector in body frame [m] (from closest VSM panel).

  • y_airf::StaticArraysCore.MVector{3, Float64}: Spanwise vector in local panel frame (from closest VSM panel).

  • type::DynamicsType

  • moment_frac::Float64: Chordwise rotation point fraction (0=LE, 1=TE).

  • damping::Float64: Damping coefficient for twist dynamics [N·m·s/rad].

  • stiffness::Float64: Torsional restoring stiffness for twist dynamics [N·m/rad]. The resulting moment (stiffness * twist_angle) is divided by the station's inertia, same as the aero/tether moments, before being applied to the twist angular acceleration. Models the panel's own structural resistance to twisting, independent of any restoring moment from bridle tension geometry. Defaults to 0.0 (no effect, matching prior behaviour) when not set.

  • twist::Float64: Current twist angle [rad].

  • twist_ω::Float64: Current twist angular velocity [rad/s].

  • tether_force::Float64: Tether force contribution [N].

  • tether_moment::Float64: Tether moment contribution [N·m].

  • aero_moment::Float64: Aerodynamic moment [N·m].

  • unrefined_section_idxs::Vector{Int64}: Indices of VSM unrefined sections in this station.

  • panel_idxs::Vector{Int64}: Indices of the VSM panels whose twist moment this station takes.

  • body_mass::Float64: Share [kg] of its wing's mass that sits on no point, by the area of its panels; its twist inertia counts it with the mass of its points.

  • area::Float64: Surface area [m²] (flat-plate sections; NaN when unused).

  • wing_idx::Int64: Resolved owning-wing index (filled by SystemStructure). 0 = inferred from body membership.

  • wing_ref::Union{Int64, Symbol}

  • body_idxs::Vector{Int64}: Resolved member-body indices — all bodies in this chordwise piece (filled by SystemStructure).

  • body_refs::Vector{Union{Int64, Symbol}}

  • flap_body_idxs::Vector{Int64}: Resolved flap-hinge body indices, ordered [main, flap] (filled by SystemStructure). Empty = no flap.

  • flap_body_refs::Vector{Union{Int64, Symbol}}

  • flap_point_idxs::Vector{Int64}: Resolved flap-hinge point indices [fore, hinge, aft] (filled by SystemStructure). Empty = none.

  • flap_point_refs::Vector{Union{Int64, Symbol}}

  • flap_axis::StaticArraysCore.MVector{3, Float64}: Flap-hinge axis (unit); a body flap's main body frame, a point flap's wing frame.

  • flap_chord_refs::Vector{StaticArraysCore.MVector{3, Float64}}: Reference chord directions [main, flap] for δ (each body's frame; auto-derived at build).

  • flap_rest_delta::Float64: Deflection δ of the undeformed (as-placed) configuration [rad] (captured at build).

source
SymbolicAWEModels.Station — Method
Station(name, points, type, moment_frac; damping=50.0)

Constructs a Station object representing a collection of points on a kite body that share a common twist deformation.

Station geometry (lepos, chord, yairf) is computed later by SystemStructure using the closest VSM panel to the station's mean point position.

Arguments

  • name::Union{Int, Symbol}: Name/identifier for the station.
  • points::Vector: References to points (names or indices).
  • type::DynamicsType: DYNAMIC or STATIC.
  • moment_frac::SimFloat: Chordwise rotation point (0=LE, 1=TE).

Keyword Arguments

  • damping::SimFloat=50.0: Damping coefficient for twist dynamics.
  • stiffness::SimFloat=0.0: Torsional restoring stiffness [N·m/rad]. Adds a -stiffness * twist_angle / inertia term to the twist angular acceleration, independent of the bridle-tension restoring moment.
  • x_airf=nothing: Chord-direction reference (body frame). When given, stored as the chord field — twist is measured relative to it. Defaults to auto-derived from the closest VSM panel during SystemStructure construction.
  • y_airf=nothing: Spanwise reference (body frame). Auto-derived when omitted.
  • area=NaN: Surface area [m²] for flat-plate (AeroPlate) sections.
  • twist=0.0: Initial twist angle [rad] (prescribed input for STATIC sections).
  • wing=0: Owning-wing reference (name or idx). Needed for the KINEMATIC flap variant; other surfaces infer their wing from body membership.
  • bodies=[]: Member-body references — all bodies in this chordwise piece (retained for future use, e.g. deriving twist or multi-element chords).
  • flap_bodies=[]: Ordered [main, flap] body references of the flap hinge. When given (with type=KINEMATIC) the surface carries a live deflection δ, the signed angle between the two bodies about flap_axis; empty = no flap.
  • flap_points=[]: Ordered [fore, hinge, aft] point references of a point flap — the alternative to flap_bodies. δ is the signed angle the aft segment (hinge→aft) makes with the fore segment (fore→hinge) about flap_axis, referenced to the initial pose. A chord that bends rather than hinges needs no bodies to read a deflection off, and the two segments are read from the structure the polars are indexed on. Give both flap_bodies and flap_points and the points win.
  • flap_axis=[0,1,0]: Flap-hinge axis (unit), in the main flap body's frame, or the owning wing's for a point flap.
  • flap_chord_refs=[]: Reference chord directions [main, flap]; auto-derived (each body's x-axis) at build when omitted.
  • flap_rest_delta=0.0: Rest deflection [rad]; auto-captured at build so the as-placed pose is δ=0. Internal — not a YAML field (YAML angles are degrees).

Returns

  • Station: A new Station object. The idx and point_idxs are resolved by SystemStructure. When x_airf/y_airf are omitted the geometry fields (lepos, chord, yairf) are computed during SystemStructure construction from the closest VSM panel.
source
SymbolicAWEModels.Segment — Type
mutable struct Segment

A segment representing a spring-damper connection from one point to another.

The spring-damper model uses per-unit-length stiffness and damping:

  • Effective stiffness: k = unit_stiffness / length [N/m]
  • Effective damping: c = unit_damping / length [N·s/m]

unit_stiffness is either a Real (linear) or a callable F(ε) of the axial strain ε = (len − l0)/l0 returning the spring force [N] (nonlinear); the callable owns the full law, including any slack/compression behaviour, so compression_frac is ignored for it.

unit_stiffness is typed Any (not a type parameter) so the segment stays a concrete type — SystemStructure.segments is written every step, and a parametric element type would make that collection abstract and allocate.

  • idx::Int64: Index in the segments vector (assigned by SystemStructure).

  • name::Union{Nothing, Int64, Symbol}

  • point_idxs::Tuple{Int64, Int64}: Resolved endpoint indices (filled by SystemStructure).

  • point_refs::Tuple{Union{Int64, Symbol}, Union{Int64, Symbol}}

  • unit_stiffness::Any: Stiffness per unit length: Real [N] (k = unit_stiffness/length), or callable F(ε) → force [N].

  • unit_damping::Float64: Damping per unit length [N·s]. Effective c = unit_damping/length [N·s/m].

  • l0::Float64: Rest (unstretched) length [m].

  • compression_frac::Float64: Compressive/tensile stiffness ratio (0-1) under compression. 0 = a slack segment carries no spring force.

  • compression_damping_frac::Float64: Fraction of unit_damping that still acts under compression (0-1). 1 = damping is unaffected by compression; 0 = a slack segment is undamped.

  • diameter::Float64: Segment diameter [m].

  • density::Float64: Material density [kg/m³].

  • len::Float64: Current length [m] (updated during simulation).

  • force::Float64: Current force [N] (updated during simulation).

source
SymbolicAWEModels.Segment — Method
Segment(name, set, point_i, point_j; l0, compression_frac,
        compression_damping_frac, diameter_mm, unit_stiffness, unit_damping,
        density, youngs_modulus, damping_per_stiffness)

Constructs a Segment using settings for material properties.

Arguments

  • name::Union{Int, Symbol}: Name/identifier for the segment.
  • set::Settings: The settings object containing material properties.
  • point_i, point_j: References to the two endpoint points (names or indices).

Keyword Arguments

  • l0::SimFloat=zero(SimFloat): Unstretched length [m]. Calculated from point positions if zero.
  • compression_frac::SimFloat=0.1: Compressive/tensile stiffness ratio (0-1). 0 = a slack segment carries no spring force.
  • compression_damping_frac::SimFloat=1.0: Fraction of unit_damping still acting under compression (0-1). See segment_spring_force.
  • diameter_mm::Float64=NaN: Tether diameter [mm]. If NaN, uses set.d_tether.
  • unit_stiffness::Float64=NaN: Stiffness per unit length [N]. Effective k = unit_stiffness/length.
  • unit_damping::Float64=NaN: Damping per unit length [N·s]. Effective c = unit_damping/length.
  • density::Float64=NaN: Material density [kg/m³]. If NaN, uses set.rho_tether.
  • youngs_modulus::Float64=NaN: Diameter-independent alternative to unit_stiffness [Pa]. See resolve_material.
  • damping_per_stiffness::Float64=NaN: Diameter-independent alternative to unit_damping [s].
source
SymbolicAWEModels.Segment — Method
Segment(name, point_i, point_j, unit_stiffness, unit_damping, diameter; l0, compression_frac, compression_damping_frac)

Basic constructor for a Segment object.

Arguments

  • name::Union{Int, Symbol}: Name/identifier for the segment.
  • point_i, point_j: References to the two endpoint points (names or indices).
  • unit_stiffness: Stiffness per unit length [N]. Effective k = unit_stiffness/length [N/m].
  • unit_damping: Damping per unit length [N·s]. Effective c = unit_damping/length [N·s/m].
  • diameter: Segment diameter [m].

Keyword Arguments

  • compression_frac::SimFloat=0.1: Compressive/tensile stiffness ratio (0-1). 0 = a slack segment carries no spring force.
  • compression_damping_frac::SimFloat=1.0: Fraction of unit_damping still acting under compression (0-1). See segment_spring_force.
  • density::SimFloat=NaN: Material density [kg/m³] used for mass.
source
SymbolicAWEModels.Pulley — Type
mutable struct Pulley

A pulley described by two segments with the common point of the segments being the pulley.

  • idx::Int64: Index in the pulleys vector (assigned by SystemStructure).

  • name::Union{Nothing, Int64, Symbol}

  • segment_idxs::Tuple{Int64, Int64}: Resolved segment indices (filled by SystemStructure).

  • segment_refs::Tuple{Union{Int64, Symbol}, Union{Int64, Symbol}}

  • type::DynamicsType

  • efficiency::Float64: Fraction of line tension the sheave passes on (0-1); the rest opposes travel.

  • damping::Float64: Artificial damping on rope travel [N·s/m], for debugging. Not a sheave property.

  • brake::Bool: Freeze the rope split where it is, for debugging. Not a sheave property.

  • friction_epsilon::Float64: Friction smoothing width [m/s]: the rope speed below which the sign ramps in.

  • sum_len::Float64: Sum of connected segment lengths [m].

  • len::Float64: Current pulley length [m] (updated during simulation).

  • vel::Float64: Current pulley velocity [m/s] (updated during simulation).

source
SymbolicAWEModels.Pulley — Method
Pulley(name, segment_i, segment_j, type; efficiency, damping, brake, friction_epsilon)

Constructs a Pulley object that enforces length redistribution between two segments.

Arguments

  • name::Union{Int, Symbol}: Name/identifier for the pulley.
  • segment_i, segment_j: References to the two segments (names or indices).
  • type::DynamicsType: Dynamics type (DYNAMIC).
  • efficiency: Fraction of line tension the sheave passes on (0-1).
  • damping: Artificial damping on rope travel [N·s/m], for debugging.
  • brake: Freeze the rope split where it is, for debugging.
  • friction_epsilon: Friction smoothing width [m/s].

efficiency is the whole friction model: the friction is (1 − efficiency) · line_tension (the mean of the two leg tensions), so it scales with load, not rope speed. Defaults to 0.95 (sealed ball-bearing sheave; 0.88–0.92 for a bronze bushing); 1.0 is an ideal pulley.

damping (default 0) and brake (default false) are debugging aids, not sheave properties: they settle or freeze a ringing rope split. friction_epsilon is the rope speed below which the friction's sign is ramped in (smooth_sign); the friction linearises to (1 − efficiency) · line_tension / friction_epsilon around zero, so a narrow width makes a stiff system out of a small force and wants raising rather than lowering.

source
SymbolicAWEModels.Tether — Type
mutable struct Tether

A collection of segments forming a flexible line.

Can be constructed two ways:

  • Route 1 (explicit segments): Provide segment references directly.
  • Route 2 (auto-generation): Provide start/end points and n_segments; intermediate points and segments are created by expand_auto_tethers!.

unit_stiffness is either a Real (linear) or a callable F(ε) of the axial strain returning force [N]; a callable propagates to every auto-generated segment (Route 2), making the whole line nonlinear.

unit_stiffness is typed Any (not a type parameter) to keep Tether concrete, since SystemStructure.tethers is read every step. The material fields (unit_stiffness through compression_damping_frac) describe the segments Route 2 generates; a Route 1 tether reads them off its own segments.

Initial length

Two distinct lengths, set independently at place!:

  • init_stretched_len — the placed (stretched) standoff; place! scales the free end's world position so the geometry spans this length.
  • len — the unstretched rest length and the reeled ODE state. place! derives it from the placed length via either init_stretch_frac (len = frac · stretched) or init_tether_force (len = stretched · (1 − force/stiffness), default 0 → len = stretched).

For a specific initial unstretched length L through place!, place at a known init_stretched_len = S and set init_stretch_frac = L / S. On a structure that is already placed, set_unstretched_length! writes len and the segments' l0 without moving anything; the next place! derives len from the geometry again and overwrites it.

  • idx::Int64: Index in the tethers vector (assigned by SystemStructure).

  • name::Union{Nothing, Int64, Symbol}

  • segment_idxs::Vector{Int64}: Resolved segment indices (filled by SystemStructure).

  • segment_refs::Vector{Union{Int64, Symbol}}

  • start_point_idx::Int64: Resolved start point index (filled by SystemStructure).

  • start_point_ref::Union{Nothing, Int64, Symbol}

  • end_point_idx::Int64: Resolved end point index (filled by SystemStructure).

  • end_point_ref::Union{Nothing, Int64, Symbol}

  • n_segments::Int64

  • unit_stiffness::Any

  • unit_damping::Float64

  • diameter::Float64

  • density::Float64

  • youngs_modulus::Float64

  • damping_per_stiffness::Float64

  • compression_frac::Float64

  • compression_damping_frac::Float64

  • stretched_len::Float64: Current stretched length [m] (updated during simulation).

  • len::Float64: Unstretched tether length [m] (sum of segment l0). ODE state variable. Segment l0 = len / n_segments.

  • init_stretched_len::Union{Nothing, Float64}: Initial stretched standoff [m] — the placed point geometry (Σ segment norms). Drives placement of root tethers. nothing = use the authored length, i.e. no scaling.

  • init_tether_force::Union{Nothing, Float64}: Target initial spring force [N], default 0. place! solves the unstretched len from the placed stretched length: len = stretched · (1 − force/unit_stiffness). Mutually exclusive with init_stretch_frac.

  • init_stretch_frac::Union{Nothing, Float64}: Initial unstretched/stretched length fraction. place! sets len = init_stretch_frac · stretched; 0.9 gives 10% pre-stretch, 1.0 no tension, >1.0 slack. Must be positive. Mutually exclusive with init_tether_force.

source
SymbolicAWEModels.Tether — Method
Tether(name, segments, stretched_length=nothing;
       start_point=nothing, end_point=nothing,
       tether_force=nothing, stretch_frac=nothing)

Route 1: Construct a Tether from explicit segment references.

Arguments

  • name::Union{Int, Symbol}: Name/identifier for the tether.
  • segments::Vector: References to segments (names or indices).
  • stretched_length=nothing: Stretched standoff [m] (placed point geometry). Drives placement of root tethers. nothing = use the geometric length.

Keyword Arguments

  • start_point=nothing: Optional start point ref.
  • end_point=nothing: Optional end point ref.
  • tether_force=nothing: Target initial spring force [N], default 0.
  • stretch_frac=nothing: Initial len/stretched fraction. Mutually exclusive with tether_force.
source
SymbolicAWEModels.Tether — Method
Tether(name, stretched_length=nothing;
       start_point, end_point, n_segments,
       unit_stiffness=NaN, unit_damping=NaN, diameter=NaN,
       compression_frac=0.1, compression_damping_frac=1.0,
       tether_force=nothing, stretch_frac=nothing)

Route 2: Construct a Tether for auto-generation of intermediate points and segments by expand_auto_tethers!.

Arguments

  • name::Union{Int, Symbol}: Name/identifier for the tether.
  • stretched_length=nothing: Stretched standoff [m] (placed point geometry). Drives placement of root tethers. nothing = use the geometric length.

Keyword Arguments

  • start_point: Reference to the start point (required).
  • end_point: Reference to the end point (required).
  • n_segments::Int: Number of segments to generate (required).
  • unit_stiffness::Float64=NaN: Per-unit-length stiffness [N]. NaN = derive from Settings during auto-expansion.
  • unit_damping::Float64=NaN: Per-unit-length damping [N·s]. NaN = derive from Settings during auto-expansion.
  • diameter::Float64=NaN: Tether diameter [m]. NaN = derive from Settings during auto-expansion.
  • density::Float64=NaN: Material density [kg/m³]. NaN = derive from Settings during auto-expansion.
  • youngs_modulus::Float64=NaN: Diameter-independent alternative to unit_stiffness [Pa]. See resolve_material.
  • damping_per_stiffness::Float64=NaN: Diameter-independent alternative to unit_damping [s].
  • compression_frac::Float64=0.1: Compressive/tensile stiffness ratio (0-1) of every generated segment. See Segment.
  • compression_damping_frac::Float64=1.0: Fraction of unit_damping still acting under compression (0-1). See Segment.
  • tether_force=nothing: Target initial spring force [N], default 0.
  • stretch_frac=nothing: Initial len/stretched fraction. Mutually exclusive with tether_force.
source
SymbolicAWEModels.Winch — Type
mutable struct Winch

A set of tethers (or a single tether) connected to a winch mechanism.

The winch has no length field of its own: its length is the mean of its tethers' unstretched lengths (winch.len ~ mean(tether.len for tether in tethers)) and D(tether.len) ~ winch_vel. To set the initial reeled length, set the initial unstretched len of each connected tether (see Tether "Initial length"); brake > 0.5 then freezes it.

  • idx::Int64: Index in the winches vector (assigned by SystemStructure).

  • name::Union{Nothing, Int64, Symbol}

  • tether_idxs::Vector{Int64}: Resolved tether indices (filled by SystemStructure).

  • tether_refs::Vector{Union{Int64, Symbol}}

  • winch_point_idx::Int64: Resolved winch point index (filled by SystemStructure).

  • winch_point_ref::Union{Int64, Symbol}

  • init_vel::Float64: Initial reel-out velocity [m/s]. Applied on reinit!.

  • vel::Float64: Current reel-out velocity [m/s]. ODE state variable.

  • acc::Float64: Current winch acceleration [m/s²] from motor dynamics.

  • set_value::Float64: Abstract setpoint passed to the winch component as the set_value connector. Interpretation is the component's choice (e.g. motor torque, current, set velocity, set length). The default component treats it as motor torque [N·m].

  • brake::Float64: Brake input in [0, 1]. The outer integrator freezes winch_vel and tether_len when > 0.5; custom components may interpret intermediate values as a continuous brake.

  • speed_controlled::Bool: If true, reel-out velocity is prescribed externally rather than integrated from motor dynamics: winch acceleration is forced to 0 (ignoring model). Set the velocity via winch.vel.

  • force::StaticArraysCore.MVector{3, Float64}

  • gear_ratio::Float64: Gear ratio [-].

  • drum_radius::Float64: Drum radius [m].

  • coulomb_friction::Float64: Coulomb friction force [N].

  • viscous_coefficient::Float64: Viscous friction coefficient [N·s/m].

  • inertia_total::Float64: Total rotational inertia [kg·m²].

  • friction::Float64: Current friction force [N] (updated during simulation).

  • model::AbstractWinchModel: Winch motor dynamics model carrying its own parameters. Defaults to TorqueWinch. See AbstractWinchModel.

source
SymbolicAWEModels.Winch — Method
Winch(name, set, tethers; winch_point, ...)

Constructs a Winch object that controls tether length through torque or speed regulation.

Arguments

  • name::Union{Int, Symbol}: Name/identifier for the winch.
  • set::Settings: Settings object for winch parameters.
  • tethers::Vector: References to tethers connected to this winch (names or indices).

Keyword Arguments

  • winch_point: Reference to the ground attachment point (name or index). Required.
  • init_vel::SimFloat=0.0: Initial reel-out rate [m/s].
  • brake=0.0: Brake input in [0, 1]. > 0.5 engages a hard freeze on winch_vel and tether_len at the outer integrator.
  • speed_controlled::Bool=false: If true, prescribe reel-out velocity via winch.vel instead of integrating motor dynamics; winch acceleration is forced to 0, ignoring model.
  • friction_epsilon::SimFloat=6.0: Coulomb-friction smoothing width; forwarded into the default TorqueWinch (ignored when an explicit non-default model is passed).
  • model::AbstractWinchModel=TorqueWinch(): Winch motor dynamics model. See AbstractWinchModel for plugging in your own.
source
SymbolicAWEModels.Winch — Method
Winch(name, tethers, gear_ratio, drum_radius, coulomb_friction,
      viscous_coefficient, inertia_total; winch_point, ...)

Constructs a Winch by directly providing physical parameters.

Arguments

  • name::Union{Int, Symbol}: Name/identifier for the winch.
  • tethers::Vector: References to tethers (names or indices).
  • gear_ratio, drum_radius, coulomb_friction, viscous_coefficient, inertia_total: Physical parameters.

Keyword Arguments

  • winch_point: Reference to ground attachment point. Required.
  • init_vel::SimFloat=0.0: Initial reel-out rate [m/s].
source
SymbolicAWEModels.AbstractWing — Type
abstract type AbstractWing

Abstract base type for all wing implementations.

Concrete subtypes must implement rigid body dynamics and provide a reference frame for attached points and stations.

source
SymbolicAWEModels.VSMEngine — Type
mutable struct VSMEngine{BA, W, SL}

Vortex Step Method aerodynamic engine carried by a VSM aero mode (AbstractVSMAero engine field). Holds the VortexStepMethod objects, the linearization state, and the structural↔panel mapping.

Fields

  • vsm_aero, vsm_wing, vsm_solver: VortexStepMethod objects.
  • aero_y: operating-point inputs [alpha, beta, ω1, ω2, ω3, twist...].
  • aero_x: baseline wind-axis coefficients [CL, CD, CS, CM1, CM2, CM3, cm...].
  • aero_jac: dense Jacobian d(aero_x)/d(aero_y).
  • point_to_vsm_point, wing_segments: PARTICLE_DYNAMICS structural↔panel maps.
  • aero_scale_chord: force scale compensating chord-length error (PARTICLE).
  • aero_z_offset: body-frame z-shift of VSM panels (RIGID).
  • unsteady: the wing's UnsteadyAero corrections.
source
SymbolicAWEModels.VSMWing — Function
VSMWing(name, set, stations, vsm_set; transform=nothing,
        angular_damping=[0.0, 150.0, 0.0], ...)

Construct a Wing with Vortex Step Method aerodynamics. Builds the VSMEngine (vsm_wing/vsm_aero/vsm_solver) internally and attaches it to the wing.

Arguments

  • name::Union{Int, Symbol}: Name/identifier for the wing.
  • set::Settings: Settings object for VSM configuration.
  • stations::Vector: References to stations (names or indices).
  • vsm_set: VSM settings for engine creation. Required for VSM-backed aero modes (AbstractVSMAero); may be nothing for engine-less modes like AeroNone.

Keyword Arguments

  • transform=nothing: Reference to the transform. Defaults to 1.
  • Q_KA_to_ENU, pos_ENU, inertia_diag: Placeholders that SystemStructure overwrites from the wing's points and mesh.
  • extra_mass, com, unit_inertia: the wing body's own mass [kg], COM and per-unit-mass inertia, without its points (see Body); com and unit_inertia default to the .obj mesh's.
  • angular_damping: Per-axis spin damping [1/s]; a scalar is broadcast.
  • dynamics_type::WingType=RIGID_DYNAMICS: Aerodynamic model type.
  • aero::AbstractAeroModel: Aerodynamic model (defaults by dynamics_type).
  • group_points_moment::Bool=true: When false, in-group (station) points add no moment to the wing body; their force still contributes. Runtime-switchable.
  • point_to_vsm_point, wing_segments: VSM structural↔panel maps.
  • z_ref_points, y_ref_points, origin: Body-frame references.
  • aero_scale_chord, aero_z_offset: VSM force/panel adjustments.
source
SymbolicAWEModels.PlateWing — Function
PlateWing(name, stations, calc_cl, calc_cd;
          dynamics_type=PARTICLE_DYNAMICS, transform=nothing,
          angular_damping=[0.0, 150.0, 0.0], drag_corr=0.93,
          z_ref_points=nothing, y_ref_points=nothing, origin=nothing)

Construct a flat-plate Wing (no VSM engine; vsm === nothing). Each flat-plate section is a 1-point STATIC Station carrying the section's body-frame reference frame, area, and prescribed twist; the shared polar lookups live on the wing's AeroPlate aero model. Supports both RIGID_DYNAMICS and PARTICLE_DYNAMICS.

Arguments

  • name: Wing name/identifier.
  • stations: References (names or indices) to the wing's flat-plate sections — each a 1-point STATIC Station.
  • calc_cl: CL lookup callable(alpha_deg) → CL.
  • calc_cd: CD lookup callable(alpha_deg) → CD.

Keyword Arguments

  • dynamics_type: RIGID_DYNAMICS or PARTICLE_DYNAMICS (default).
  • transform: Reference to transform (name or index).
  • angular_damping: Per-axis spin damping [1/s]; a scalar is broadcast.
  • drag_corr: Drag correction factor (stored on the AeroPlate model).
  • z_ref_points, y_ref_points, origin: Body-frame references.
source
SymbolicAWEModels.create_plate_interpolations — Function
create_plate_interpolations(alpha_deg, cl_data, cd_data;
    alpha_cd=nothing, spline=:cubic)

Create CL and CD interpolation objects from polar data vectors.

Arguments

  • alpha_deg: angle of attack values [deg]
  • cl_data: lift coefficient values
  • cd_data: drag coefficient values
  • alpha_cd: separate alpha values for CD (default: same as CL)
  • spline: :cubic for cubic spline, :linear for piecewise linear

Returns

  • (cl_interp, cd_interp) tuple of interpolation objects
source
SymbolicAWEModels.Body — Type
Body{A<:AbstractAeroModel, D<:WingDynamics}

A 6-DOF body integrated (or fitted) in the principal frame, optionally carrying aerodynamics. A plain body has aero = AeroNone(); a "wing" carries a real aero mode (see [sys_struct.wings]). type is DYNAMIC (free 6-DOF), KINEMATIC (pose fitted from structural points — particle wings) or STATIC (clamped). D mirrors the rigid/particle distinction into the type domain for aero dispatch. All bodies share the 6-DOF generator rigid_body_eqs!.

The body's own mass properties (extra_mass, extra_inertia_b, extra_com_offset_b) are set directly or derived from its mesh or points. A DYNAMIC or STATIC body adds the points it carries — its BODY_STATIC riders, and a RIGID_DYNAMICS wing's nodes — as point masses of their total_mass at their anchors: total_mass, com_offset_b and the principal inertia describe the body with them (update_mass_properties!). Aero/wing fields are inert when aero is AeroNone. Loads are gravity (-g·total_mass at the COM), the settable external wrench, tube wrenches, and aerodynamics.

  • idx::Int64: Index in the bodies vector (assigned by SystemStructure).

  • name::Union{Nothing, Int64, Symbol}

  • transform_idx::Int64: Resolved transform index (filled by SystemStructure). 0 = no transform.

  • transform_ref::Union{Int64, Symbol}

  • wing_idx::Int64: Resolved parent wing index (filled by SystemStructure). 0 = no parent wing.

  • wing_ref::Union{Int64, Symbol}

  • extra_mass::Float64: Own mass [kg], without the points the body carries.

  • total_mass::Float64: extra_mass plus the total_mass of the points the body carries [kg].

  • apparent_mass::Float64: Entrained-air mass [kg] resisting acceleration without adding weight.

  • inertia_principal::StaticArraysCore.MVector{3, Float64}

  • R_b_to_p::Matrix{Float64}

  • com_offset_b::StaticArraysCore.MVector{3, Float64}

  • extra_inertia_b::Matrix{Float64}

  • extra_com_offset_b::StaticArraysCore.MVector{3, Float64}

  • principal_frame_method::PrincipalFrameMethod: Method used to compute the principal frame (see PrincipalFrameMethod).

  • ext_force_w::StaticArraysCore.MVector{3, Float64}

  • ext_force_b::StaticArraysCore.MVector{3, Float64}

  • ext_moment_b::StaticArraysCore.MVector{3, Float64}

  • angular_damping::StaticArraysCore.MVector{3, Float64}: Angular damping [d_x, d_y, d_z] [1/s] about the body-frame axes.

  • world_frame_damping::StaticArraysCore.MVector{3, Float64}: Per-mass translational damping [d_x, d_y, d_z] [1/s] on the world axes.

  • body_frame_damping::StaticArraysCore.MVector{3, Float64}: Per-mass translational damping [d_x, d_y, d_z] [1/s] on the body axes.

  • fix_sphere::Bool: If true, COM motion is confined to a sphere about the world origin.

  • fix_static::Bool: If true, dynamically freezes the body where it is, without rebuilding.

  • type::DynamicsType: Dynamics type: DYNAMIC (free 6-DOF), KINEMATIC (fitted) or STATIC (frozen).

  • pos_ENU::StaticArraysCore.MVector{3, Float64}

  • Q_KA_to_ENU::Vector{Float64}

  • Q_b_to_w::Vector{Float64}

  • ω_b::StaticArraysCore.MVector{3, Float64}

  • pos_w::StaticArraysCore.MVector{3, Float64}

  • vel_w::StaticArraysCore.MVector{3, Float64}

  • acc_w::StaticArraysCore.MVector{3, Float64}

  • com_w::StaticArraysCore.MVector{3, Float64}

  • com_vel::StaticArraysCore.MVector{3, Float64}

  • Q_p_to_w::Vector{Float64}

  • ω_p::StaticArraysCore.MVector{3, Float64}

  • aero::AbstractAeroModel: Initial body→world orientation quaternion: how place! turns the body.

  • station_idxs::Vector{Int64}: Resolved station indices (filled by SystemStructure).

  • station_refs::Vector{Union{Int64, Symbol}}

  • wind_disturb::StaticArraysCore.MVector{3, Float64}

  • drag_frac::Float64: Raw station references.

  • va_b::StaticArraysCore.MVector{3, Float64}

  • wind_vec::StaticArraysCore.MVector{3, Float64}

  • aero_force_b::StaticArraysCore.MVector{3, Float64}

  • aero_moment_b::StaticArraysCore.MVector{3, Float64}

  • elevation::Float64: Wind velocity at the wing, world frame [m/s]: a height-profile output, or the settable input under PerPointWind.

  • elevation_vel::Float64

  • elevation_acc::Float64

  • azimuth::Float64

  • azimuth_vel::Float64

  • azimuth_acc::Float64

  • heading::Float64

  • turn_rate::StaticArraysCore.MVector{3, Float64}

  • turn_acc::StaticArraysCore.MVector{3, Float64}

  • course::Float64

  • aoa::Float64

  • group_points_moment::Bool: Whether in-group (station) points contribute their moment to the body.

  • z_ref_points::Union{Nothing, Tuple{WeightedRefPoints, WeightedRefPoints}}

  • y_ref_points::Union{Nothing, Tuple{WeightedRefPoints, WeightedRefPoints}}

  • origin::Union{Nothing, WeightedRefPoints}

source
SymbolicAWEModels.Body — Method
Body(name; extra_mass, inertia_principal | inertia, pos, vel=zeros,
          Q_b_to_w=[1,0,0,0], ω_b=zeros, com_offset_b=zeros, R_b_to_p=I,
          angular_damping=0, world_frame_damping=0, body_frame_damping=0,
          fix_sphere=false, fix_static=false, type=DYNAMIC,
          transform=nothing, wing=nothing,
          ext_force_w=zeros, ext_moment_b=zeros)

Construct a standalone rigid body. pos/vel are the body origin's initial world-frame position/velocity; Q_b_to_w/ω_b its initial orientation/spin. The principal-frame ODE state is derived from these by init_rigid_body!.

type is DYNAMIC (free 6-DOF, default) or STATIC (clamped to its initial pose — e.g. a cantilever root). transform optionally references a Transform that repositions/rotates the body's initial pose (azimuth, elevation, heading), like a wing. wing names the parent wing whose frame and motion the body-frame damping resolves against, as a Point's wing does.

angular_damping is a scalar (isotropic) or length-3 per-axis spin damping [1/s]. world_frame_damping and body_frame_damping damp the COM velocity resolved on the world and body axes respectively; both are per-mass [1/s], like a Point's. fix_sphere=true confines COM motion to a sphere about the world origin (radial DOF frozen), like a RIGID_DYNAMICS wing's fix_sphere. fix_static=true holds the body where it is; unlike type=STATIC it is a parameter, so it can be toggled on a built model.

extra_mass, com_offset_b and the inertia are the body's own, without the BODY_STATIC points riding it: SystemStructure adds those. Supply the inertia about the body's own COM in one of two ways: inertia_principal (a length-3 diagonal principal inertia, with R_b_to_p giving the body→principal rotation), or inertia (a full 3×3 body-frame tensor). Give one, not both. Either is stored as a tensor; the stored inertia_principal and R_b_to_p diagonalise the total with the riders, so R_b_to_p can differ from the one passed.

source
SymbolicAWEModels.Tube — Type
Tube{M<:AbstractTubeModel}

An inflated tube between two Bodys, simulated as model: a TimoshenkoTube beam element or a lumped ElasticTube. Its ends sit at an anchor on each body, and the placed bodies fix its rest length.

  • idx::Int64: Index in SystemStructure.tubes (assigned by SystemStructure).

  • name::Union{Nothing, Int64, Symbol}

  • body_a_idx::Int64: Resolved index of body A (filled by SystemStructure).

  • body_b_idx::Int64: Resolved index of body B (filled by SystemStructure).

  • body_a_ref::Union{Int64, Symbol}

  • body_b_ref::Union{Int64, Symbol}

  • anchor_a_b::StaticArraysCore.MVector{3, Float64}

  • anchor_b_b::StaticArraysCore.MVector{3, Float64}

  • diameter::Float64: Outer diameter [m], one for the whole element.

  • pressure::Float64: Inflation pressure [Pa].

  • law::Symbol: Name of the stiffness law the rigidities are derived from, e.g. :breukels2011.

  • model::AbstractTubeModel: The structural element the tube is simulated as.

source
SymbolicAWEModels.Tube — Method
Tube(name, body_a, body_b; diameter, pressure, law=:breukels2011,
     model=TimoshenkoTube(), anchor_a=zeros, anchor_b=zeros)

A tube from body_a to body_b (names or indices), its ends at anchor_a and anchor_b in each body's frame. Rigidities model leaves nothing are derived from law at diameter [m] and pressure [Pa].

source
SymbolicAWEModels.TimoshenkoTube — Type
TimoshenkoTube

A 2-node corotational Timoshenko beam element; a chain of tubes forms a beam. The stiffness couples each node's transverse displacement to its rotation, so transverse shear is represented.

Each rigidity (EA axial, GA shear with correction factor shear_coeff, Φ = 12·EI/(k·GA·L²), GJ torsion, EIy/EIz bending about the two transverse axes) is either a Real (linear) or a callable of that mode's strain/curvature returning the effective rigidity there. All callables must share one type.

  • EA::Any: Axial rigidity: Real EA [N], or callable EA(ε) of axial strain ε=δ/L₀.

  • GA::Any: Shear rigidity (before shear_coeff): Real GA [N], or callable GA(γ) of shear angle.

  • GJ::Any: Torsional rigidity: Real GJ [N·m²], or callable GJ(κ) of twist rate κ=Δθ/L₀.

  • EIy::Any: Bending rigidity about y: Real EIy [N·m²], or callable EIy(κ) of curvature κ=Δθ/L₀.

  • EIz::Any: Bending rigidity about z: Real EIz [N·m²], or callable EIz(κ) of curvature κ=Δθ/L₀.

  • shear_coeff::Float64: Shear correction factor k (e.g. 5/6 solid, 8/9 inflated tube).

  • damping::Float64: Rayleigh damping β [s]: the element wrench is also evaluated at β times the deformation rate (C = βK), so every mode is damped in proportion to its rigidity and rigid motion stays undamped by construction.

  • rest_length::Float64: Rest chord length [m], taken from the placed geometry at the first place!.

  • R_a_rel0::Matrix{Float64}

  • R_b_rel0::Matrix{Float64}

source
SymbolicAWEModels.TimoshenkoTube — Method
TimoshenkoTube(; EA=nothing, GA=nothing, GJ=nothing, EIy=nothing, EIz=nothing,
               shear_coeff=5/6, damping=0)

A TimoshenkoTube. Each rigidity is a Real or a callable of its strain/curvature; the ones left nothing are derived from the tube's law when the Tube is built.

source
SymbolicAWEModels.ElasticTube — Type
ElasticTube

Lumped 6-DOF spring between a tube's two anchors: the relative pose of the anchors, decomposed in body A's frame into axial, shear (both transverse axes), torsion and bending (both transverse axes) springs, with Rayleigh damping.

Each stiffness is either a Real (linear law, force = k·Δ) or a callable interpolation f (nonlinear law, force = f(Δ)), mixable per DOF; callables must share one type, which keeps the fields concrete.

  • stiffness_axial::Any: Axial stiffness: Real [N/m], or interpolation force(Δx) (body A x-axis).

  • stiffness_shear::Any: Shear stiffness: Real [N/m], or interpolation force(Δ) (both transverse).

  • stiffness_torsion::Any: Torsional stiffness: Real [N·m/rad], or interpolation moment(Δθ) (x-axis).

  • stiffness_bending::Any: Bending stiffness: Real [N·m/rad], or interpolation moment(Δθ) (transverse).

  • damping::Float64: Rayleigh damping β [s]: each DOF is damped in proportion to its own stiffness (C = βK), so rigid motion stays undamped by construction.

  • rest_offset_a::StaticArraysCore.MVector{3, Float64}

  • R_rel0::Matrix{Float64}

source
SymbolicAWEModels.ElasticTube — Method
ElasticTube(; stiffness_axial, stiffness_shear, stiffness_torsion,
            stiffness_bending, damping=0)

A lumped ElasticTube with the four given stiffnesses, each a Real or a callable of its relative DOF.

source
SymbolicAWEModels.Transform — Type
mutable struct Transform

Describes the spatial transformation (position and orientation) of system components relative to a base reference point.

  • idx::Int64: Index in the transforms vector (assigned by SystemStructure).

  • name::Union{Nothing, Int64, Symbol}

  • wing_idx::Union{Nothing, Int64}: Resolved wing index (filled by SystemStructure).

  • wing_ref::Union{Nothing, Int64, Symbol}

  • rot_point_idx::Union{Nothing, Int64}: Resolved rotation point index (filled by SystemStructure).

  • rot_point_ref::Union{Nothing, Int64, Symbol}

  • base_point_idx::Union{Nothing, Int64}: Resolved base point index (filled by SystemStructure).

  • base_point_ref::Union{Nothing, Int64, Symbol}

  • base_transform_idx::Union{Nothing, Int64}: Resolved base transform index (filled by SystemStructure).

  • base_transform_ref::Union{Nothing, Int64, Symbol}

  • elevation::Float64: Elevation angle [rad].

  • azimuth::Float64: Azimuth angle [rad].

  • heading::Float64: Heading angle [rad].

  • elevation_vel::Float64: Angular velocity in elevation direction [rad/s].

  • azimuth_vel::Float64: Angular velocity in azimuth direction [rad/s].

  • turn_rate::Float64: Angular velocity around radial axis [rad/s].

  • base_pos::Union{Nothing, StaticArraysCore.MVector{3, Float64}}: Base position [m]. Nothing = derived from base_transform.

source
SymbolicAWEModels.Transform — Method
Transform(name, elevation, azimuth, heading; base_point, base_pos, base_transform, wing, rot_point)

Constructs a Transform object that orients system components using spherical coordinates.

Arguments

  • name::Union{Int, Symbol}: Name/identifier for the transform.
  • elevation, azimuth, heading: Spherical coordinates [rad].

Keyword Arguments

Base Reference (choose one method):

  • base_pos & base_point: Use a fixed position and a reference point.
  • base_transform: Chain to another transform's position.

Target Object (choose one):

  • wing: Reference to the wing to position at (elevation, azimuth).
  • rot_point: Reference to the point to position at (elevation, azimuth).
source

Indexing

SymbolicAWEModels.NamedCollection — Type
NamedCollection{T} <: AbstractVector{T}

A wrapper around a vector that enables both numeric and symbolic indexing.

By subtyping AbstractVector, this type works transparently with all existing code that expects vectors, including @unpack macros and iteration.

Names are extracted from items that have a name field. Items without names (or with name=nothing) are only accessible by numeric index.

  • items::Vector: The underlying vector of items

  • name_to_idx::Dict{Symbol, Int64}: Mapping from symbolic names to indices

source
SymbolicAWEModels.NameRef — Type
NameRef = Union{Int, Symbol}

A reference to another component, either by symbolic name (:ground) or integer index (1).

Name resolution

Components reference each other by name or index at construction time. These are stored in _ref fields (e.g. point_refs, wing_ref). During SystemStructure construction, assign_indices_and_resolve! maps every ref to a numeric index via build_name_dict (name → vector position) and stores the result in the corresponding _idx fields (e.g. point_idxs, wing_idx).

Each component has a name field (const, set once at construction) that identifies it for lookup.

source
SymbolicAWEModels.WeightedRefPoints — Type
WeightedRefPoints

Weighted combination of reference points for body-frame definition. Supports single points, equal-weight averaging, and arbitrary weight combinations.

Fields

  • refs: Unresolved names/indices (filled at construction)
  • ids: Resolved point indices (filled by resolve!)
  • weights: Normalized weights (sum to 1.0)
source

Inflated-tube rigidity

SymbolicAWEModels.TubeRigidityLaw — Type
TubeRigidityLaw

Callable effective rigidity of an inflated tube for one TimoshenkoTube mode, evaluated at that mode's curvature [1/m]. mode == :torsion returns GJ(κ) = c1·atan(c2·κ)/κ (Breukels). mode == :bending returns EI(κ): the linear rigidity below the knee curvature and the smooth power-law approach to the collapse moment above it. One struct covers both modes because all callable rigidities of a tube must share a type.

  • mode::Symbol: Which rigidity this law returns: :bending or :torsion.

  • EI0::Float64: Linear bending rigidity below the knee [N·m²].

  • moment_knee::Float64: Moment at the knee, where softening starts [N·m].

  • moment_collapse::Float64: Asymptotic collapse moment [N·m].

  • curvature_knee::Float64: Curvature at the knee [1/m].

  • exponent::Float64: Exponent of the post-knee power-law approach to moment_collapse.

  • knee_slope::Float64: Slope the moment deficit leaves the knee at. M_w/(M_c − M_w) is C1 there, exponent is the plain power law.

  • c1::Float64: Torsion coefficient c1 [N·m].

  • c2::Float64: Torsion coefficient c2 [m].

source

System state

KiteUtils.SysState — Type
SysState(s::SymbolicAWEModel, zoom=1.0)

Construct a SysState holding the current state of the model.

Arguments

  • s::SymbolicAWEModel: The source model.
  • zoom::SimFloat=1.0: A scaling factor for the position coordinates.

Returns

  • SysState: A new state struct representing the current model state.
source
KiteUtils.update_sys_state! — Function
update_sys_state!(ss::SysState, s::SymbolicAWEModel, zoom=1.0)

Update a SysState from the model's integrator: converts units (e.g. radians to degrees) and computes derived values like AoA. Roll, pitch and yaw are KiteUtils.euler_KS(ss.orient).

Arguments

  • ss::SysState: The state struct to be updated.
  • s::SymbolicAWEModel: The source model.
  • zoom::SimFloat=1.0: A scaling factor for the position coordinates.
source
update_sys_state!(sys_state, y::AbstractVector, sam::SymbolicAWEModel, t::Real)

Update a SysState for a linear state-space simulation, using output y and model sam.

source
SymbolicAWEModels.update_from_sysstate! — Function
update_from_sysstate!(sys::SystemStructure, sys_state::SysState)

Copy the state a SysState carries (point positions, wing orientations, winch lengths, twist angles, segment spring forces) into an existing SystemStructure, e.g. to plot one snapshot of a SysLog with the Makie extension. Fields SysState cannot supply (net point forces, winch forces, station moments) are set to NaN so they are not plotted.

sys must have been created with the same model configuration as the simulation that produced the log; its point count must match the parametric type P of SysState{P}.

Every field the log can reach is written, whether or not the compiler integrates it, because a derived field can still seed u0 as a torn variable.

source