Skip to content

Commit c7b4142

Browse files
committed
Improve bins and update docs
1 parent 77ee2f9 commit c7b4142

File tree

2 files changed

+80
-58
lines changed

2 files changed

+80
-58
lines changed

src/VortexStepMethod.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ function plot_polar_data end
5454
Basic 3-dimensional vector, stack allocated, mutable.
5555
"""
5656
const MVec3 = MVector{3, Float64}
57+
const MMat3 = MMatrix{3, 3, Float64}
5758

5859
"""
5960
const PosVector=Union{MVec3, Vector}

src/kite_geometry.jl

Lines changed: 79 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ Create interpolation functions for leading/trailing edges and area.
111111
- Tuple of (le_interp, te_interp, area_interp) interpolation functions
112112
- Where le_interp and te_interp are tuples themselves, containing the x, y and z interpolations
113113
"""
114-
function create_interpolations(vertices, circle_center_z, radius, gamma_tip, R; interp_steps=40)
114+
function create_interpolations(vertices, circle_center_z, radius, gamma_tip, R=I(3); interp_steps=40)
115115
gamma_range = range(-gamma_tip+1e-6, gamma_tip-1e-6, interp_steps)
116116
stepsize = gamma_range.step.hi
117117
vz_centered = [v[3] - circle_center_z for v in vertices]
@@ -201,7 +201,7 @@ function center_to_com!(vertices, faces)
201201
centroid = (v1 + v2 + v3) / 3
202202

203203
area_total += area
204-
com += area * centroid
204+
com -= area * centroid
205205
else
206206
throw(ArgumentError("Triangulate faces in a CAD program first"))
207207
end
@@ -212,7 +212,7 @@ function center_to_com!(vertices, faces)
212212
@info "Centering vertices of .obj file to the center of mass: $com"
213213
com[2] = 0.0
214214
for v in vertices
215-
v .-= com
215+
v .+= com
216216
end
217217
return com
218218
end
@@ -362,30 +362,29 @@ end
362362

363363

364364
"""
365-
RamAirWing
366-
367-
Represents a curved wing that inherits from Wing with additional geometric properties.
368-
369-
# Fields
370-
- All fields from Wing:
371-
- `n_panels::Int16`: Number of panels in aerodynamic mesh
372-
- `n_groups::Int16`: Number of panel groups, each panel group has it's own twisting moment
373-
- `spanwise_distribution`::PanelDistribution: see: [PanelDistribution](@ref)
374-
- `spanwise_direction::MVec3`: Wing span direction vector
375-
- `sections::Vector{Section}`: List of wing sections, see: [Section](@ref)
376-
- `refined_sections::Vector{Section}`
377-
- `remove_nan::Bool`: Wether to remove the NaNs from interpolations or not
378-
- Additional fields:
379-
- `circle_center_z::MVec3`: Center of circle coordinates
380-
- `gamma_tip::Float64`: Angle between the body frame z axis and the vector going from the kite circular shape center to the wing tip.
381-
- `inertia_tensor::Matrix{Float64}`: see: [`calculate_inertia_tensor`](@ref)
382-
- `radius::Float64`: Radius of curvature
383-
- `le_interp::NTuple{3, Extrapolation}`: see: [Extrapolation](https://juliamath.github.io/Interpolations.jl/stable/extrapolation/)
384-
- `te_interp::NTuple{3, Extrapolation}`
385-
- `area_interp::Extrapolation`
386-
- `theta_dist::Vector{Float64}`
387-
- `delta_dist::Vector{Float64}`
388-
365+
RamAirWing <: AbstractWing
366+
367+
A ram-air wing model that represents a curved parafoil with deformable aerodynamic surfaces.
368+
369+
## Core Features
370+
- Curved wing geometry derived from 3D mesh (.obj file)
371+
- Aerodynamic properties based on 2D airfoil data (.dat file)
372+
- Support for control inputs (twist angles and trailing edge deflections)
373+
- Inertial and geometric properties calculation
374+
375+
## Notable Fields
376+
- `n_panels::Int16`: Number of panels in aerodynamic mesh
377+
- `n_groups::Int16`: Number of control groups for distributed deformation
378+
- `mass::Float64`: Total wing mass in kg
379+
- `gamma_tip::Float64`: Angular extent from center to wing tip
380+
- `inertia_tensor::Matrix{Float64}`: Full 3x3 inertia tensor in the kite body frame
381+
- `T_cad_body::MVec3`: Translation vector from CAD frame to body frame
382+
- `R_cad_body::MMat3`: Rotation matrix from CAD frame to body frame
383+
- `radius::Float64`: Wing curvature radius
384+
- `theta_dist::Vector{Float64}`: Panel twist angle distribution
385+
- `delta_dist::Vector{Float64}`: Trailing edge deflection distribution
386+
387+
See constructor `RamAirWing(obj_path, dat_path; kwargs...)` for usage details.
389388
"""
390389
mutable struct RamAirWing <: AbstractWing
391390
n_panels::Int16
@@ -402,7 +401,8 @@ mutable struct RamAirWing <: AbstractWing
402401
mass::Float64
403402
gamma_tip::Float64
404403
inertia_tensor::Matrix{Float64}
405-
center_of_mass::MVec3
404+
T_cad_body::MVec3
405+
R_cad_body::MMat3
406406
radius::Float64
407407
le_interp::NTuple{3, Extrapolation}
408408
te_interp::NTuple{3, Extrapolation}
@@ -413,27 +413,47 @@ mutable struct RamAirWing <: AbstractWing
413413
end
414414

415415
"""
416-
RamAirWing(obj_path, dat_path; alpha=0.0, crease_frac=0.75, wind_vel=10., mass=1.0,
417-
n_panels=54, n_sections=n_panels+1, spanwise_distribution=UNCHANGED,
418-
spanwise_direction=[0.0, 1.0, 0.0], remove_nan::Bool=true)
419-
420-
Constructor for a [RamAirWing](@ref) that allows to use an `.obj` and a `.dat` file as input.
421-
422-
# Parameters
423-
- obj_path: Path to the `.obj` file used for creating the geometry
424-
- dat_path: Path to the `.dat` file, a standard format for 2d foil geometry
425-
426-
# Keyword Parameters
427-
- crease_frac=0.9: The x coordinate around which the trailing edge rotates on a normalized 2d foil,
428-
used in the xfoil polar generation
429-
- wind_vel=10.0: Apparent wind speed in m/s, used in the xfoil polar generation
430-
- mass=1.0: Mass of the wing in kg, used for the inertia calculations
431-
- `n_panels`=56: Number of panels.
432-
- `n_sections=n_panels+1`: Number of sections (there is a section on each side of each panel.)
433-
- `n_groups=n_panels ÷ 4`: Number of panel groups
434-
- `spanwise_distribution`=UNCHANGED: see: [PanelDistribution](@ref)
435-
- `spanwise_direction`=[0.0, 1.0, 0.0]
436-
- `remove_nan::Bool`: Wether to remove the NaNs from interpolations or not
416+
RamAirWing(obj_path, dat_path; kwargs...)
417+
418+
Create a ram-air wing model from 3D geometry and airfoil data files.
419+
420+
This constructor builds a complete aerodynamic model by:
421+
1. Loading or generating wing geometry from the .obj file
422+
2. Creating aerodynamic polars from the airfoil .dat file
423+
3. Computing inertial properties and coordinate transformations
424+
4. Setting up control surfaces and panel distribution
425+
426+
# Arguments
427+
- `obj_path`: Path to .obj file containing 3D wing geometry
428+
- `dat_path`: Path to .dat file containing 2D airfoil profile
429+
430+
# Keyword Arguments
431+
- `crease_frac=0.9`: Normalized trailing edge hinge location (0-1)
432+
- `wind_vel=10.0`: Reference wind velocity for XFoil analysis (m/s)
433+
- `mass=1.0`: Wing mass (kg)
434+
- `n_panels=56`: Number of aerodynamic panels across wingspan
435+
- `n_groups=4`: Number of control groups for deformation
436+
- `n_sections=n_panels+1`: Number of spanwise cross-sections
437+
- `align_to_principal=false`: Align body frame to principal axes of inertia
438+
- `spanwise_distribution=UNCHANGED`: Panel distribution type
439+
- `remove_nan=true`: Interpolate NaN values in aerodynamic data
440+
- `alpha_range=deg2rad.(-5:1:20)`: Angle of attack range for polars (rad)
441+
- `delta_range=deg2rad.(-5:1:20)`: Trailing edge deflection range for polars (rad)
442+
443+
# Returns
444+
A fully initialized `RamAirWing` instance ready for aerodynamic simulation.
445+
446+
# Example
447+
```julia
448+
# Create a ram-air wing from geometry files
449+
wing = RamAirWing(
450+
"path/to/wing.obj",
451+
"path/to/airfoil.dat";
452+
mass=1.5,
453+
n_panels=40,
454+
n_groups=4
455+
)
456+
```
437457
"""
438458
function RamAirWing(
439459
obj_path, dat_path;
@@ -458,28 +478,29 @@ function RamAirWing(
458478
if !ispath(info_path)
459479
@info "Reading $obj_path"
460480
vertices, faces = read_faces(obj_path)
461-
center_of_mass = center_to_com!(vertices, faces)
481+
T_cad_body = center_to_com!(vertices, faces)
462482
inertia_tensor = calculate_inertia_tensor(vertices, faces, mass, zeros(3))
463483

464484
if align_to_principal
465-
inertia_tensor, R_b_p = calc_inertia_y_rotation(inertia_tensor)
466-
circle_center_z, radius, gamma_tip = find_circle_center_and_radius(vertices)
467-
le_interp, te_interp, area_interp = create_interpolations(vertices, circle_center_z, radius, gamma_tip, R_b_p; interp_steps)
485+
inertia_tensor, R_cad_body = calc_inertia_y_rotation(inertia_tensor)
468486
else
469-
circle_center_z, radius, gamma_tip = find_circle_center_and_radius(vertices)
470-
le_interp, te_interp, area_interp = create_interpolations(vertices, circle_center_z, radius, gamma_tip, I(3); interp_steps)
487+
R_cad_body = I(3)
471488
end
489+
circle_center_z, radius, gamma_tip = find_circle_center_and_radius(vertices)
490+
le_interp, te_interp, area_interp = create_interpolations(vertices, circle_center_z, radius, gamma_tip, R_cad_body; interp_steps)
472491

473492
@info "Writing $info_path"
474-
serialize(info_path, (inertia_tensor, center_of_mass, radius, gamma_tip,
493+
serialize(info_path, (inertia_tensor, T_cad_body, R_cad_body, radius, gamma_tip,
475494
le_interp, te_interp, area_interp))
476495
end
477496

478497
@info "Loading kite info from $info_path and polars from $polar_path"
479498
try
480-
(inertia_tensor::Matrix, center_of_mass::Vector,
499+
(inertia_tensor::Matrix, T_cad_body::Vector, R_cad_body::Matrix,
481500
radius::Real, gamma_tip::Real, le_interp, te_interp, area_interp) = deserialize(info_path)
482501

502+
((R_cad_body == I(3)) == align_to_principal) && throw(ArgumentError("Delete $info_path and try again."))
503+
483504
if !ispath(polar_path)
484505
width = 2gamma_tip * radius
485506
area = area_interp(gamma_tip)
@@ -515,7 +536,7 @@ function RamAirWing(
515536

516537
RamAirWing(n_panels, n_groups, spanwise_distribution, panel_props, spanwise_direction, sections,
517538
refined_sections, remove_nan, non_deformed_sections,
518-
mass, gamma_tip, inertia_tensor, center_of_mass, radius,
539+
mass, gamma_tip, inertia_tensor, T_cad_body, R_cad_body, radius,
519540
le_interp, te_interp, area_interp, zeros(n_panels), zeros(n_panels), cache)
520541

521542
catch e

0 commit comments

Comments
 (0)