aerosandbox.geometry#

Subpackages#

Submodules#

Package Contents#

Classes#

Airfoil

An airfoil. See constructor docstring for usage details.

KulfanAirfoil

An airfoil. See constructor docstring for usage details.

Wing

Definition for a Wing.

WingXSec

Definition for a wing cross-section ("X-section").

ControlSurface

Definition for a control surface, which is attached to a particular WingXSec via WingXSec's control_surfaces=[] parameter.

Fuselage

Definition for a Fuselage or other slender body (pod, fuel tank, etc.).

FuselageXSec

Definition for a fuselage cross-section ("X-section").

Airplane

Definition for an airplane.

Propulsor

Definition for a Propulsor, which could be a propeller, a rotor, or a jet engine.

Functions#

is_casadi_type(object[, recursive])

Returns a boolean of whether an object is a CasADi data type or not. If the recursive flag is True,

reflect_over_XZ_plane(input_vector)

Takes in a vector or an array and flips the y-coordinates.

aerosandbox.geometry.is_casadi_type(object, recursive=True)[source]#

Returns a boolean of whether an object is a CasADi data type or not. If the recursive flag is True, iterates recursively, returning True if any subelement (at any depth) is a CasADi type.

Parameters:
  • object (Any) – The object to evaluate.

  • recursive (bool) – If the object is a list or tuple, recursively iterate through every subelement. If any of the

  • subelements (at any depth) –

Return type:

bool

Returns: A boolean if the object is (or contains, if recursive=True) a CasADi data type.

aerosandbox.geometry.reflect_over_XZ_plane(input_vector)[source]#

Takes in a vector or an array and flips the y-coordinates. :param input_vector: A vector or list of vectors to flip. :return: Vector with flipped sign on y-coordinate.

class aerosandbox.geometry.Airfoil(name='Untitled', coordinates=None, **deprecated_keyword_arguments)[source]#

Bases: aerosandbox.geometry.polygon.Polygon

An airfoil. See constructor docstring for usage details.

Parameters:
  • name (str) –

  • coordinates (Union[None, str, pathlib.Path, aerosandbox.numpy.ndarray]) –

__repr__()[source]#

Return repr(self).

Return type:

str

to_kulfan_airfoil(n_weights_per_side=8, N1=0.5, N2=1.0, normalize_coordinates=True, use_leading_edge_modification=True)[source]#
Parameters:
  • n_weights_per_side (int) –

  • N1 (float) –

  • N2 (float) –

  • normalize_coordinates (bool) –

  • use_leading_edge_modification (bool) –

Return type:

aerosandbox.geometry.airfoil.kulfan_airfoil.KulfanAirfoil

generate_polars(alphas=np.linspace(-13, 13, 27), Res=np.geomspace(1000.0, 100000000.0, 12), cache_filename=None, xfoil_kwargs=None, unstructured_interpolated_model_kwargs=None, include_compressibility_effects=True, transonic_buffet_lift_knockdown=0.3, make_symmetric_polars=False)[source]#

Generates airfoil polar surrogate models (CL, CD, CM functions) from XFoil data and assigns them in-place to this Airfoil’s polar functions.

In other words, when this function is run, the following functions will be added (or overwritten) to the instance:
  • Airfoil.CL_function(alpha, Re, mach)

  • Airfoil.CD_function(alpha, Re, mach)

  • Airfoil.CM_function(alpha, Re, mach)

Where alpha is in degrees.

Warning: In-place operation! Modifies this Airfoil object by setting Airfoil.CL_function, etc. to the new polars.

Parameters:
  • alphas – The range of alphas to sample from XFoil at. Given in degrees.

  • Res – The range of Reynolds numbers to sample from XFoil at. Dimensionless.

  • cache_filename (str) –

    A path-like filename (ideally a “*.json” file) that can be used to cache the XFoil results, making it much faster to regenerate the results.

    • If the file does not exist, XFoil will be run, and a cache file will be created.

    • If the file does exist, XFoil will not be run, and the cache file will be read instead.

  • xfoil_kwargs (Dict[str, Any]) – Keyword arguments to pass into the AeroSandbox XFoil module. See the aerosandbox.XFoil constructor for options.

  • unstructured_interpolated_model_kwargs (Dict[str, Any]) – Keyword arguments to pass into the UnstructuredInterpolatedModels that contain the polars themselves. See the aerosandbox.UnstructuredInterpolatedModel constructor for options.

  • include_compressibility_effects (bool) – Includes compressibility effects in the polars, such as wave drag, mach tuck, CL effects across normal shocks. Note that accuracy here is dubious in the transonic regime and above - you should really specify your own CL/CD/CM models

  • transonic_buffet_lift_knockdown (float) –

  • make_symmetric_polars (bool) –

Return type:

None

Returns: None (in-place), adds the following functions to the instance:

  • Airfoil.CL_function(alpha, Re, mach)

  • Airfoil.CD_function(alpha, Re, mach)

  • Airfoil.CM_function(alpha, Re, mach)

get_aero_from_neuralfoil(alpha, Re, mach=0.0, n_crit=9.0, xtr_upper=1.0, xtr_lower=1.0, model_size='large', control_surfaces=None, include_360_deg_effects=True)[source]#
Parameters:
  • alpha (Union[float, aerosandbox.numpy.ndarray]) –

  • Re (Union[float, aerosandbox.numpy.ndarray]) –

  • mach (Union[float, aerosandbox.numpy.ndarray]) –

  • n_crit (Union[float, aerosandbox.numpy.ndarray]) –

  • xtr_upper (Union[float, aerosandbox.numpy.ndarray]) –

  • xtr_lower (Union[float, aerosandbox.numpy.ndarray]) –

  • model_size (str) –

  • control_surfaces (List[ControlSurface]) –

  • include_360_deg_effects (bool) –

Return type:

Dict[str, Union[float, aerosandbox.numpy.ndarray]]

plot_polars(alphas=np.linspace(-20, 20, 500), Res=10**np.arange(3, 9), mach=0.0, show=True, Re_colors=None)[source]#
Parameters:
  • alphas (Union[aerosandbox.numpy.ndarray, List[float]]) –

  • Res (Union[aerosandbox.numpy.ndarray, List[float]]) –

  • mach (float) –

  • show (bool) –

Return type:

None

local_camber(x_over_c=np.linspace(0, 1, 101))[source]#

Returns the local camber of the airfoil at a given point or points.

Parameters:

x_over_c (Union[float, aerosandbox.numpy.ndarray]) – The x/c locations to calculate the camber at [1D array, more generally, an iterable of floats]

Returns:

Local camber of the airfoil (y/c) [1D array].

Return type:

Union[float, aerosandbox.numpy.ndarray]

local_thickness(x_over_c=np.linspace(0, 1, 101))[source]#

Returns the local thickness of the airfoil at a given point or points.

Parameters:

x_over_c (Union[float, aerosandbox.numpy.ndarray]) – The x/c locations to calculate the thickness at [1D array, more generally, an iterable of floats]

Returns:

Local thickness of the airfoil (y/c) [1D array].

Return type:

Union[float, aerosandbox.numpy.ndarray]

max_camber(x_over_c_sample=np.linspace(0, 1, 101))[source]#

Returns the maximum camber of the airfoil.

Parameters:

x_over_c_sample (aerosandbox.numpy.ndarray) – Where should the airfoil be sampled to determine the max camber?

Return type:

float

Returns: The maximum thickness, as a fraction of chord.

max_thickness(x_over_c_sample=np.linspace(0, 1, 101))[source]#

Returns the maximum thickness of the airfoil.

Parameters:

x_over_c_sample (aerosandbox.numpy.ndarray) – Where should the airfoil be sampled to determine the max thickness?

Return type:

float

Returns: The maximum thickness, as a fraction of chord.

draw(draw_mcl=False, draw_markers=True, backend='matplotlib', show=True)[source]#

Draw the airfoil object.

Parameters:
  • draw_mcl – Should we draw the mean camber line (MCL)? [boolean]

  • backend – Which backend should we use? “plotly” or “matplotlib”

  • show – Should we show the plot? [boolean]

Return type:

None

Returns: None

LE_index()[source]#

Returns the index of the leading edge point in the airfoil coordinates.

Return type:

int

lower_coordinates()[source]#

Returns an Nx2 ndarray of [x, y] coordinates that describe the lower surface of the airfoil.

Order is from the leading edge to the trailing edge.

Includes the leading edge point; be careful about duplicates if using this method in conjunction with Airfoil.upper_coordinates().

Return type:

aerosandbox.numpy.ndarray

upper_coordinates()[source]#

Returns an Nx2 ndarray of [x, y] coordinates that describe the upper surface of the airfoil.

Order is from the trailing edge to the leading edge.

Includes the leading edge point; be careful about duplicates if using this method in conjunction with Airfoil.lower_coordinates().

Return type:

aerosandbox.numpy.ndarray

LE_radius(softness=1e-06)[source]#
Parameters:

softness (float) –

TE_thickness()[source]#

Returns the thickness of the trailing edge of the airfoil.

Return type:

float

TE_angle()[source]#

Returns the trailing edge angle of the airfoil, in degrees.

Return type:

float

repanel(n_points_per_side=100, spacing_function_per_side=np.cosspace)[source]#

Returns a repaneled copy of the airfoil with cosine-spaced coordinates on the upper and lower surfaces.

Parameters:
  • n_points_per_side (int) –

    Number of points per side (upper and lower) of the airfoil [int]

    Notes: The number of points defining the final airfoil will be n_points_per_side * 2 - 1, since one point (the leading edge point) is shared by both the upper and lower surfaces.

  • spacing_function_per_side – Determines how to space the points on each side of the airfoil. Can be np.linspace or np.cosspace, or any other function of the call signature f(a, b, n) that returns a spaced array of n points between a and b. [function]

Return type:

Airfoil

Returns: A copy of the airfoil with the new coordinates.

normalize(return_dict=False)[source]#
Returns a copy of the Airfoil with a new set of coordinates, such that:
  • The leading edge (LE) is at (0, 0)

  • The trailing edge (TE) is at (1, 0)

  • The chord length is equal to 1

The trailing-edge (TE) point is defined as the midpoint of the line segment connecting the first and last coordinate points (upper and lower surface TE points, respectively). The TE point is not necessarily one of the original points in the airfoil coordinates (Airfoil.coordinates); in general, it will not be one of the points if the TE thickness is nonzero.

The leading-edge (LE) point is defined as the coordinate point with the largest Euclidian distance from the trailing edge. (In other words, if you were to center a circle on the trailing edge and progressively grow it, what’s the last coordinate point that it would intersect?) The LE point is always one of the original points in the airfoil coordinates.

The chord is defined as the Euclidian distance between the LE and TE points.

Coordinate modifications to achieve the constraints described above (LE @ origin, TE at (1, 0), and chord of 1) are done by means of a translation and rotation.

Parameters:

return_dict (bool) –

Determines the output type of the function. - If False (default), returns a copy of the Airfoil with the new coordinates. - If True, returns a dictionary with keys:

  • ”airfoil”: a copy of the Airfoil with the new coordinates

  • ”x_translation”: the amount by which the airfoil’s LE was translated in the x-direction

  • ”y_translation”: the amount by which the airfoil’s LE was translated in the y-direction

  • ”scale_factor”: the amount by which the airfoil was scaled (if >1, the airfoil had to get

    bigger)

  • ”rotation_angle”: the angle (in degrees) by which the airfoil was rotated about the LE.

    Sign convention is that positive angles rotate the airfoil counter-clockwise.

All of thes values represent the “required change”, e.g.:

  • ”x_translation” is the amount by which the airfoil’s LE had to be translated in the

    x-direction to get it to the origin.

  • ”rotation_angle” is the angle (in degrees) by which the airfoil had to be rotated (CCW).

Return type:

Union[Airfoil, Dict[str, Union[Airfoil, float]]]

Returns: Depending on the value of return_dict, either:

  • A copy of the airfoil with the new coordinates (default), or

  • A dictionary with keys “airfoil”, “x_translation”, “y_translation”, “scale_factor”, and “rotation_angle”.

    documentation for return_tuple for more information.

add_control_surface(deflection=0.0, hinge_point_x=0.75, modify_coordinates=True, modify_polars=True)[source]#

Returns a version of the airfoil with a trailing-edge control surface added at a given point. Implicitly repanels the airfoil as part of this operation.

Parameters:
  • deflection (float) – Deflection angle [degrees]. Downwards-positive.

  • hinge_point_x (float) – Chordwise location of the hinge, as a fraction of chord (x/c) [float]

  • modify_coordinates (bool) –

  • modify_polars (bool) –

Return type:

Airfoil

Returns: an Airfoil object with the new control deflection.

set_TE_thickness(thickness=0.0)[source]#

Creates a modified copy of the Airfoil that has a specified trailing-edge thickness.

Note that the trailing-edge thickness is given nondimensionally (e.g., as a fraction of chord).

Parameters:

thickness (float) – The target trailing-edge thickness, given nondimensionally (e.g., as a fraction of chord).

Return type:

Airfoil

Returns: The modified airfoil.

scale(scale_x=1.0, scale_y=1.0)[source]#

Scales an Airfoil about the origin.

Parameters:
  • scale_x (float) – Amount to scale in the x-direction.

  • scale_y (float) – Amount to scale in the y-direction. Scaling by a negative y-value will result in coordinates being re-ordered such that the order of the coordinates is still correct (i.e., starts from the upper-surface trailing edge, continues along the upper surface to the nose, then continues along the lower surface to the trailing edge).

Return type:

Airfoil

Returns: A copy of the Airfoil with appropriate scaling applied.

translate(translate_x=0.0, translate_y=0.0)[source]#

Translates an Airfoil by a given amount. :param translate_x: Amount to translate in the x-direction :param translate_y: Amount to translate in the y-direction

Returns: The translated Airfoil.

Parameters:
  • translate_x (float) –

  • translate_y (float) –

Return type:

Airfoil

rotate(angle, x_center=0.0, y_center=0.0)[source]#

Rotates the airfoil clockwise by the specified amount, in radians.

Rotates about the point (x_center, y_center), which is (0, 0) by default.

Parameters:
  • angle (float) – Angle to rotate, counterclockwise, in radians.

  • x_center (float) – The x-coordinate of the center of rotation.

  • y_center (float) – The y-coordinate of the center of rotation.

Return type:

Airfoil

Returns: The rotated Airfoil.

blend_with_another_airfoil(airfoil, blend_fraction=0.5, n_points_per_side=100)[source]#

Blends this airfoil with another airfoil. Merges both the coordinates and the aerodynamic functions.

Parameters:
  • airfoil (Airfoil) – The other airfoil to blend with.

  • blend_fraction (float) –

    The fraction of the other airfoil to use when blending. Defaults to 0.5 (50%).

    • A blend fraction of 0 will return an identical airfoil to this one (self).

    • A blend fraction of 1 will return an identical airfoil to the other one (airfoil parameter).

  • n_points_per_side (int) – The number of points per side to use when blending the coordinates of the two airfoils.

Return type:

Airfoil

Returns: A new airfoil that is a blend of this airfoil and another one.

write_dat(filepath=None, include_name=True)[source]#

Writes a .dat file corresponding to this airfoil to a filepath.

Parameters:
  • filepath (Union[str, pathlib.Path]) – filepath (including the filename and .dat extension) [string] If None, this function returns the .dat file as a string.

  • include_name (bool) – Should the name be included in the .dat file? (In a standard *.dat file, it usually is.)

Return type:

str

Returns: None

class aerosandbox.geometry.KulfanAirfoil(name='Untitled', lower_weights=None, upper_weights=None, leading_edge_weight=0.0, TE_thickness=0.0, N1=0.5, N2=1.0)[source]#

Bases: aerosandbox.geometry.airfoil.airfoil.Airfoil

An airfoil. See constructor docstring for usage details.

Parameters:
  • name (str) –

  • lower_weights (aerosandbox.numpy.ndarray) –

  • upper_weights (aerosandbox.numpy.ndarray) –

  • leading_edge_weight (float) –

  • TE_thickness (float) –

  • N1 (float) –

  • N2 (float) –

property kulfan_parameters#
property coordinates: aerosandbox.numpy.ndarray#
Return type:

aerosandbox.numpy.ndarray

__repr__()[source]#

Return repr(self).

Return type:

str

to_airfoil(n_coordinates_per_side=200, spacing_function_per_side=np.cosspace)[source]#
Return type:

aerosandbox.geometry.airfoil.airfoil.Airfoil

repanel(n_points_per_side=100, spacing_function_per_side=np.cosspace)[source]#

Returns a repaneled copy of the airfoil with cosine-spaced coordinates on the upper and lower surfaces.

Parameters:
  • n_points_per_side (int) –

    Number of points per side (upper and lower) of the airfoil [int]

    Notes: The number of points defining the final airfoil will be n_points_per_side * 2 - 1, since one point (the leading edge point) is shared by both the upper and lower surfaces.

  • spacing_function_per_side – Determines how to space the points on each side of the airfoil. Can be np.linspace or np.cosspace, or any other function of the call signature f(a, b, n) that returns a spaced array of n points between a and b. [function]

Return type:

aerosandbox.geometry.airfoil.airfoil.Airfoil

Returns: A copy of the airfoil with the new coordinates.

normalize(return_dict=False)[source]#
Returns a copy of the Airfoil with a new set of coordinates, such that:
  • The leading edge (LE) is at (0, 0)

  • The trailing edge (TE) is at (1, 0)

  • The chord length is equal to 1

The trailing-edge (TE) point is defined as the midpoint of the line segment connecting the first and last coordinate points (upper and lower surface TE points, respectively). The TE point is not necessarily one of the original points in the airfoil coordinates (Airfoil.coordinates); in general, it will not be one of the points if the TE thickness is nonzero.

The leading-edge (LE) point is defined as the coordinate point with the largest Euclidian distance from the trailing edge. (In other words, if you were to center a circle on the trailing edge and progressively grow it, what’s the last coordinate point that it would intersect?) The LE point is always one of the original points in the airfoil coordinates.

The chord is defined as the Euclidian distance between the LE and TE points.

Coordinate modifications to achieve the constraints described above (LE @ origin, TE at (1, 0), and chord of 1) are done by means of a translation and rotation.

Parameters:

return_dict (bool) –

Determines the output type of the function. - If False (default), returns a copy of the Airfoil with the new coordinates. - If True, returns a dictionary with keys:

  • ”airfoil”: a copy of the Airfoil with the new coordinates

  • ”x_translation”: the amount by which the airfoil’s LE was translated in the x-direction

  • ”y_translation”: the amount by which the airfoil’s LE was translated in the y-direction

  • ”scale_factor”: the amount by which the airfoil was scaled (if >1, the airfoil had to get

    bigger)

  • ”rotation_angle”: the angle (in degrees) by which the airfoil was rotated about the LE.

    Sign convention is that positive angles rotate the airfoil counter-clockwise.

All of thes values represent the “required change”, e.g.:

  • ”x_translation” is the amount by which the airfoil’s LE had to be translated in the

    x-direction to get it to the origin.

  • ”rotation_angle” is the angle (in degrees) by which the airfoil had to be rotated (CCW).

Return type:

Union[KulfanAirfoil, Dict[str, Union[KulfanAirfoil, float]]]

Returns: Depending on the value of return_dict, either:

  • A copy of the airfoil with the new coordinates (default), or

  • A dictionary with keys “airfoil”, “x_translation”, “y_translation”, “scale_factor”, and “rotation_angle”.

    documentation for return_tuple for more information.

draw(*args, draw_markers=False, **kwargs)[source]#

Draw the airfoil object.

Parameters:
  • draw_mcl – Should we draw the mean camber line (MCL)? [boolean]

  • backend – Which backend should we use? “plotly” or “matplotlib”

  • show – Should we show the plot? [boolean]

Returns: None

get_aero_from_neuralfoil(alpha, Re, mach=0.0, n_crit=9.0, xtr_upper=1.0, xtr_lower=1.0, model_size='large', control_surfaces=None, include_360_deg_effects=True)[source]#
Parameters:
  • alpha (Union[float, aerosandbox.numpy.ndarray]) –

  • Re (Union[float, aerosandbox.numpy.ndarray]) –

  • mach (Union[float, aerosandbox.numpy.ndarray]) –

  • n_crit (Union[float, aerosandbox.numpy.ndarray]) –

  • xtr_upper (Union[float, aerosandbox.numpy.ndarray]) –

  • xtr_lower (Union[float, aerosandbox.numpy.ndarray]) –

  • model_size (str) –

  • control_surfaces (List[ControlSurface]) –

  • include_360_deg_effects (bool) –

Return type:

Dict[str, Union[float, aerosandbox.numpy.ndarray]]

upper_coordinates(x_over_c=np.linspace(1, 0, 101))[source]#

Returns an Nx2 ndarray of [x, y] coordinates that describe the upper surface of the airfoil.

Order is from the trailing edge to the leading edge.

Includes the leading edge point; be careful about duplicates if using this method in conjunction with Airfoil.lower_coordinates().

Parameters:

x_over_c (Union[float, aerosandbox.numpy.ndarray]) –

Return type:

aerosandbox.numpy.ndarray

lower_coordinates(x_over_c=np.linspace(0, 1, 101))[source]#

Returns an Nx2 ndarray of [x, y] coordinates that describe the lower surface of the airfoil.

Order is from the leading edge to the trailing edge.

Includes the leading edge point; be careful about duplicates if using this method in conjunction with Airfoil.upper_coordinates().

Parameters:

x_over_c (Union[float, aerosandbox.numpy.ndarray]) –

Return type:

aerosandbox.numpy.ndarray

local_camber(x_over_c=np.linspace(0, 1, 101))[source]#

Returns the local camber of the airfoil at a given point or points.

Parameters:

x_over_c (Union[float, aerosandbox.numpy.ndarray]) – The x/c locations to calculate the camber at [1D array, more generally, an iterable of floats]

Returns:

Local camber of the airfoil (y/c) [1D array].

Return type:

Union[float, aerosandbox.numpy.ndarray]

local_thickness(x_over_c=np.linspace(0, 1, 101))[source]#

Returns the local thickness of the airfoil at a given point or points.

Parameters:

x_over_c (Union[float, aerosandbox.numpy.ndarray]) – The x/c locations to calculate the thickness at [1D array, more generally, an iterable of floats]

Returns:

Local thickness of the airfoil (y/c) [1D array].

Return type:

Union[float, aerosandbox.numpy.ndarray]

LE_radius(relative_softness=0.03)[source]#
Parameters:

relative_softness (float) –

TE_angle()[source]#

Returns the trailing edge angle of the airfoil, in degrees.

area()[source]#

Returns the area of the polygon.

set_TE_thickness(thickness=0.0)[source]#

Creates a modified copy of the KulfanAirfoil that has a specified trailing-edge thickness.

Note that the trailing-edge thickness is given nondimensionally (e.g., as a fraction of chord).

Parameters:

thickness (float) – The target trailing-edge thickness, given nondimensionally (e.g., as a fraction of chord).

Return type:

KulfanAirfoil

Returns: The modified KulfanAirfoil.

scale(scale_x=1.0, scale_y=1.0)[source]#

Scales a KulfanAirfoil about the origin.

Parameters:
  • scale_x (float) – Amount to scale in the x-direction. Note: not supported by KulfanAirfoil due to inherent limitations of parameterization; only given here so that argument symmetry to Airfoil.scale() is retained. Raises a ValueError if modified, along with instructions to use Airfoil if needed.

  • scale_y (float) – Amount to scale in the y-direction. Scaling by a negative y-value will result in lower_weights and upper_weights being flipped as appropriate.

Return type:

KulfanAirfoil

Returns: A copy of the KulfanAirfoil with appropriate scaling applied.

blend_with_another_airfoil(airfoil, blend_fraction=0.5)[source]#

Blends this airfoil with another airfoil. Merges both the coordinates and the aerodynamic functions.

Parameters:
  • airfoil (Union[KulfanAirfoil, aerosandbox.geometry.airfoil.airfoil.Airfoil]) – The other airfoil to blend with.

  • blend_fraction (float) –

    The fraction of the other airfoil to use when blending. Defaults to 0.5 (50%).

    • A blend fraction of 0 will return an identical airfoil to this one (self).

    • A blend fraction of 1 will return an identical airfoil to the other one (airfoil parameter).

  • n_points_per_side – The number of points per side to use when blending the coordinates of the two airfoils.

Return type:

KulfanAirfoil

Returns: A new airfoil that is a blend of this airfoil and another one.

class aerosandbox.geometry.Wing(name=None, xsecs=None, symmetric=False, color=None, analysis_specific_options=None, **kwargs)[source]#

Bases: aerosandbox.common.AeroSandboxObject

Definition for a Wing.

Anatomy of a Wing:

A wing consists chiefly of a collection of cross-sections, or “xsecs”. A cross-section is a 2D “slice” of a wing. These can be accessed with Wing.xsecs, which gives a list of xsecs in the Wing. Each xsec is a WingXSec object, a class that is defined separately.

You may also see references to wing “sections”, which are different than cross-sections (xsecs)! Sections are the portions of the wing that are in between xsecs. In other words, a wing with N cross-sections (xsecs, WingXSec objects) will always have N-1 sections. Sections are never explicitly defined, since you can get all needed information by lofting from the adjacent cross-sections. For example, section 0 (the first one) is a loft between cross-sections 0 and 1.

Wings are lofted linearly between cross-sections.

If the wing is symmetric across the XZ plane, just define the right half and supply symmetric=True in the constructor.

If the wing is not symmetric across the XZ plane (e.g., a single vertical stabilizer), just define the wing.

Parameters:
  • name (Optional[str]) –

  • xsecs (List[WingXSec]) –

  • symmetric (bool) –

  • color (Optional[Union[str, Tuple[float]]]) –

  • analysis_specific_options (Optional[Dict[type, Dict[str, Any]]]) –

__repr__()[source]#

Return repr(self).

Return type:

str

translate(xyz)[source]#

Translates the entire Wing by a certain amount.

Parameters:

xyz (Union[aerosandbox.numpy.ndarray, List[float]]) –

Return type:

Wing

Returns: The new wing object.

span(type='yz', include_centerline_distance=False, _sectional=False)[source]#

Computes the span, with options for various ways of measuring this (see type argument).

If the wing is symmetric, both left/right sides are included in order to obtain the full span. In the case where the root cross-section is not coincident with the center plane (e.g., XZ plane), this function’s behavior depends on the include_centerline_distance argument.

Parameters:
  • type (str) –

    One of the following options, as a string:

    • ”xyz”: First, computes the quarter-chord point of each WingXSec. Then, connects these with

    straight lines. Then, adds up the lengths of these lines.

    • ”xy” or “top”: Same as “xyz”, except it projects each line segment onto the XY plane before adding up the

    lengths.

    • ”yz” (default) or “front”: Same as “xyz”, except it projects each line segment onto the YZ plane (i.e., front view)

    before adding up the lengths.

    • ”xz” or “side”: Same as “xyz”, except it projects each line segment onto the XZ plane before adding up the

    lengths. Rarely needed.

    • ”x”: Same as “xyz”, except it only counts the x-components of each line segment when adding up the

    lengths.

    • ”y”: Same as “xyz”, except it only counts the y-components of each line segment when adding up the

    lengths.

    • ”z”: Same as “xyz”, except it only counts the z-components of each line segment when adding up the

    lengths.

  • include_centerline_distance – A boolean flag that tells the function what to do if a wing’s root is not

  • plane (coincident with the centerline) –

    • If True, we first figure out which WingXSec has its quarter-chord point closest to the centerline

    plane (i.e., XZ plane). Then, we compute the distance from that quarter-chord point directly to the centerline plane (along Y). We then add that distance to the span calculation. In other words, the fictitious span connecting the left and right root cross-sections is included.

    • If False, this distance is ignored. In other words, the fictitious span connecting the left and

    right root cross-sections is not included. This is the default behavior.

    Note: For computation, either the root WingXSec (i.e., index=0) or the tip WingXSec (i.e., index=-1) is used, whichever is closer to the centerline plane. This will almost-always be the root WingXSec, but some weird edge cases (e.g., a half-wing defined on the left-hand-side of the airplane, rather than the conventional right-hand side) will result in the tip WingXSec being used.

  • _sectional (bool) – A boolean. If False, returns the total span. If True, returns a list of spans for each of the n-1 lofted sections (between the n wing cross-sections in wing.xsec).

Return type:

Union[float, List[float]]

area(type='planform', include_centerline_distance=False, _sectional=False)[source]#

Computes the wing area, with options for various ways of measuring this (see type argument):

If the wing is symmetric, both left/right sides are included in order to obtain the full area. In the case where the root cross-section is not coincident with the center plane (e.g., XZ plane), this function’s behavior depends on the include_centerline_distance argument.

Parameters:
  • type (str) –

    One of the following options, as a string:

    • ”planform” (default): First, lofts a quadrilateral mean camber surface between each WingXSec. Then,

    computes the area of each of these sectional surfaces. Then, sums up all the areas and returns it. When airplane designers refer to “wing area” (in the absence of any other qualifiers), this is typically what they mean.

    • ”wetted”: Computes the actual surface area of the wing that is in contact with the air. Will

    typically be a little more than double the “planform” area above; intuitively, this is because it adds both the “top” and “bottom” surface areas. Accounts for airfoil thickness/shape effects.

    • ”xy” or “projected” or “top”: Same as “planform”, but each sectional surface is projected onto the XY plane

    (i.e., top-down view) before computing the areas. Note that if you try to use this method with a vertically-oriented wing, like most vertical stabilizers, you will get an area near zero.

    • ”xz” or “side”: Same as “planform”, but each sectional surface is projected onto the XZ plane before

    computing the areas.

  • include_centerline_distance – A boolean flag that tells the function what to do if a wing’s root chord is

  • plane (not coincident with the centerline) –

    • If True, we first figure out which WingXSec is closest to the centerline plane (i.e., XZ plane).

    Then, we imagine that this WingXSec is extruded along the Y axis to the centerline plane (assuming a straight extrusion to produce a rectangular mid-camber surface). In doing so, we use the wing geometric chord as the extrusion width. We then add the area of this fictitious surface to the area calculation.

    • If False, this function will simply ignore this fictitious wing area. This is the default behavior.

  • _sectional (bool) – A boolean. If False, returns the total area. If True, returns a list of areas for each of the n-1 lofted sections (between the n wing cross-sections in wing.xsec).

Return type:

Union[float, List[float]]

aspect_ratio(type='geometric')[source]#

Computes the aspect ratio of the wing, with options for various ways of measuring this.

  • geometric: geometric aspect ratio, computed in the typical fashion (b^2 / S).

  • effective: Differs from the geometric aspect ratio only in the case of symmetric wings whose root

cross-section is not on the centerline. In these cases, it includes the span and area of the fictitious wing center when computing aspect ratio.

Parameters:

type (str) – One of the above options, as a string.

Return type:

float

is_entirely_symmetric()[source]#
Return type:

bool

mean_geometric_chord()[source]#

Returns the mean geometric chord of the wing (S/b). :return:

Return type:

float

mean_aerodynamic_chord()[source]#

Computes the length of the mean aerodynamic chord of the wing. Uses the generalized methodology described here:

Returns: The length of the mean aerodynamic chord.

Return type:

float

mean_twist_angle()[source]#

Returns the mean twist angle (in degrees) of the wing, weighted by area. :return: mean twist angle (in degrees)

Return type:

float

mean_sweep_angle(x_nondim=0.25)[source]#

Returns the mean sweep angle (in degrees) of the wing, relative to the x-axis. Positive sweep is backwards, negative sweep is forward.

This is purely measured from root to tip, with no consideration for the sweep of the individual cross-sections in between.

Parameters:

x_nondim

The nondimensional x-coordinate of the cross-section to use for sweep angle computation.

  • If you provide 0, it will use the leading edge of the cross-section.

  • If you provide 0.25, it will use the quarter-chord point of the cross-section.

  • If you provide 1, it will use the trailing edge of the cross-section.

Returns:

The mean sweep angle, in degrees.

Return type:

float

mean_dihedral_angle(x_nondim=0.25)[source]#

Returns the mean dihedral angle (in degrees) of the wing, relative to the XY plane. Positive dihedral is bending up, negative dihedral is bending down.

This is purely measured from root to tip, with no consideration for the dihedral of the individual cross-sections in between.

Parameters:

x_nondim

The nondimensional x-coordinate of the cross-section to use for sweep angle computation.

  • If you provide 0, it will use the leading edge of the cross-section.

  • If you provide 0.25, it will use the quarter-chord point of the cross-section.

  • If you provide 1, it will use the trailing edge of the cross-section.

Returns:

The mean dihedral angle, in degrees

Return type:

float

aerodynamic_center(chord_fraction=0.25, _sectional=False)[source]#

Computes the location of the aerodynamic center of the wing. Uses the generalized methodology described here:

Args: chord_fraction: The position of the aerodynamic center along the MAC, as a fraction of MAC length.

Typically, this value (denoted h_0 in the literature) is 0.25 for a subsonic wing. However, wing-fuselage interactions can cause a forward shift to a value more like 0.1 or less. Citing Cook, Michael V., “Flight Dynamics Principles”, 3rd Ed., Sect. 3.5.3 “Controls-fixed static stability”. PDF: https://www.sciencedirect.com/science/article/pii/B9780080982427000031

Returns: The (x, y, z) coordinates of the aerodynamic center of the wing.

Parameters:

chord_fraction (float) –

Return type:

aerosandbox.numpy.ndarray

taper_ratio()[source]#

Gives the taper ratio of the Wing. Strictly speaking, only valid for trapezoidal wings.

Returns:

Taper ratio of the Wing.

Return type:

float

volume(_sectional=False)[source]#

Computes the volume of the Wing.

Parameters:
  • _sectional (bool) – A boolean. If False, returns the total volume. If True, returns a list of volumes for each of

  • sections (the n-1 lofted) –

Returns:

The computed volume.

Return type:

Union[float, List[float]]

get_control_surface_names()[source]#

Gets the names of all control surfaces on this wing.

Returns:

A list of control surface names.

Return type:

List[str]

set_control_surface_deflections(control_surface_mappings)[source]#

Sets the deflection of all control surfaces on this wing, based on the provided mapping.

Parameters:

control_surface_mappings (Dict[str, float]) –

A dictionary mapping control surface names to their deflection angles, in degrees.

Note: control surface names are set in the asb.ControlSurface constructor.

Returns:

None. (in-place)

Return type:

None

control_surface_area(by_name=None, type='planform')[source]#

Computes the total area of all control surfaces on this wing, optionally filtered by their name.

Control surfaces are defined on a section-by-section basis, and are defined in the WingXSec constructor using its control_surfaces argument.

Note: If redundant control surfaces are defined (e.g., elevons, as defined by separate ailerons + elevator), the area will be duplicated.

If the wing is symmetric, control surfaces on both left/right sides are included in order to obtain the full area.

Parameters:
  • by_name (Optional[str]) –

    If not None, only control surfaces with this name will be included in the area calculation.

    Note: control surface names are set in the asb.ControlSurface constructor.

  • type (Optional[str]) –

    One of the following options, as a string:

    • ”planform” (default): First, lofts a quadrilateral mean camber surface between each WingXSec. Then,

    computes the area of each of these sectional surfaces. Then, computes what fraction of this area is control surface. Then, sums up all the areas and returns it. When airplane designers refer to “control surface area” (in the absence of any other qualifiers), this is typically what they mean.

    • ”wetted”: Computes the actual surface area of the control surface that is in contact with the air.

    Will typically be a little more than double the “planform” area above; intuitively, this is because it adds both the “top” and “bottom” surface areas. Accounts for airfoil thickness/shape effects.

    • ”xy” or “projected” or “top”: Same as “planform”, but each sectional surface is projected onto the XY plane

    (i.e., top-down view) before computing the areas. Note that if you try to use this method with a vertically-oriented wing, like most vertical stabilizers, you will get an area near zero.

    • ”xz” or “side”: Same as “planform”, but each sectional surface is projected onto the XZ plane before

    computing the areas.

Return type:

float

mesh_body(method='quad', chordwise_resolution=36, chordwise_spacing_function_per_side=np.cosspace, mesh_surface=True, mesh_tips=True, mesh_trailing_edge=True, mesh_symmetric=True)[source]#

Meshes the outer mold line surface of the wing.

Uses the (points, faces) standard mesh format. For reference on this format, see the documentation in aerosandbox.geometry.mesh_utilities.

Order of faces:

  • On the right wing (or, if Wing.symmetric is False, just the wing itself):

    • If mesh_surface is True:

      • First face is nearest the top-side trailing edge of the wing root.

      • Proceeds chordwise, along the upper surface of the wing from back to front. Upon reaching the

      leading edge, continues along the lower surface of the wing from front to back.

      • Then, repeats this process for the next spanwise slice of the wing, and so on.

    • If mesh_trailing_edge is True:

      • Continues by meshing the trailing edge of the wing. Meshes the inboard trailing edge first, then

      proceeds spanwise to the outboard trailing edge.

    • If mesh_tips is True:

      • Continues by meshing the wing tips. Meshes the inboard tip first, then meshes the outboard tip.

      • Within each tip, meshes from the

Parameters:
  • method

    One of the following options, as a string:

    • ”tri”: Triangular mesh.

    • ”quad”: Quadrilateral mesh.

  • chordwise_resolution (int) – Number of points to use per wing chord, per wing section.

  • chordwise_spacing_function_per_side (Callable[[float, float, float], aerosandbox.numpy.ndarray]) – A function that determines how to space points in the chordwise

  • np.cosspace (direction along the top and bottom surfaces. Common values would be np.linspace or) –

  • mesh_surface (bool) –

  • mesh_tips (bool) –

  • mesh_trailing_edge (bool) –

  • mesh_symmetric (bool) –

Return type:

Tuple[aerosandbox.numpy.ndarray, aerosandbox.numpy.ndarray]

:param : :param but it can be any function with the call signature f: :type but it can be any function with the call signature `f: a, b, n :param between `a and b. [function]: :param mesh_surface: If True, includes the actual wing surface in the mesh. :param mesh_tips: If True, includes the wing tips (both on the inboard-most section and on the outboard-most :param section) in the mesh.: :param mesh_trailing_edge: If True, includes the wing trailing edge in the mesh, if the trailing-edge thickness :param is nonzero.: :param mesh_symmetric: Has no effect if the wing is not symmetric. If the wing is symmetric this determines whether :param the generated mesh is also symmetric: :type the generated mesh is also symmetric: right side :param or if if only one side of the wing: :type or if if only one side of the wing: right side

Returns: Standard unstructured mesh format: A tuple of points and faces, where:

  • points is a n x 3 array of points, where n is the number of points in the mesh.

  • faces is a m x 3 array of faces if method is “tri”, or a m x 4 array of faces if method is “quad”.

    • Each row of faces is a list of indices into points, which specifies a face.

mesh_thin_surface(method='tri', chordwise_resolution=36, chordwise_spacing_function=np.cosspace, add_camber=True)[source]#

Meshes the mean camber line of the wing as a thin-sheet body.

Uses the (points, faces) standard mesh format. For reference on this format, see the documentation in aerosandbox.geometry.mesh_utilities.

Order of faces:
  • On the right wing (or, if Wing.symmetric is False, just the wing itself):
    • First face is the face nearest the leading edge of the wing root.

    • Proceeds along a chordwise strip to the trailing edge.

    • Then, goes to the subsequent spanwise location and does another chordwise strip, et cetera until we get to the wing tip.

  • On the left wing (applicable only if Wing.symmetric is True):
    • Same order: Starts at the root leading edge, goes in chordwise strips.

Order of vertices within each face:
  • On the right wing (or, if Wing.symmetric is False, just the wing itself):
    • Front-left

    • Back-left

    • Back-right

    • Front-right

  • On the left wing (applicable only if Wing.symmetric is True):
    • Front-left

    • Back-left

    • Back-right

    • Front-right

Parameters:
  • method

    A string, which determines whether to mesh the fuselage as a series of quadrilaterals or triangles.

    • ”quad” meshes the fuselage as a series of quadrilaterals.

    • ”tri” meshes the fuselage as a series of triangles.

  • chordwise_resolution (int) – Determines the number of chordwise panels to use in the meshing. [int]

  • chordwise_spacing_function (Callable[[float, float, float], aerosandbox.numpy.ndarray]) – Determines how to space the chordwise panels. Can be np.linspace or

  • np.cosspace (a, b, n) –

  • `f (or any other function of the call signature) –

  • [function] (n points between a and b.) –

  • add_camber (bool) – Controls whether to mesh the thin surface with camber (i.e., mean camber line), or to just

  • [bool] (mesh the flat planform.) –

Return type:

Tuple[aerosandbox.numpy.ndarray, aerosandbox.numpy.ndarray]

Returns: Standard unstructured mesh format: A tuple of points and faces, where:

  • points is a n x 3 array of points, where n is the number of points in the mesh.

  • faces is a m x 3 array of faces if method is “tri”, or a m x 4 array of faces if method is “quad”.

    • Each row of faces is a list of indices into points, which specifies a face.

mesh_line(x_nondim=0.25, z_nondim=0, add_camber=True)[source]#

Meshes a line that goes through each of the WingXSec objects in this wing.

Parameters:
  • x_nondim (Union[float, List[float]]) – The nondimensional (chord-normalized) x-coordinate that the line should go through. Can either

  • cross-sections (value used at all) –

  • the (or can be an iterable of values to be used at) –

  • cross-sections. (respective) –

  • z_nondim (Union[float, List[float]]) – The nondimensional (chord-normalized) y-coordinate that the line should go through. Here,

  • component (y-coordinate means the "vertical") –

  • cross-sections

  • cross (or can be an iterable of values to be used at the respective) –

  • sections.

  • add_camber (bool) – Controls whether the camber of each cross-section’s airfoil should be added to the line or

  • camber. (not. Essentially modifies z_nondim to be z_nondim +) –

Return type:

List[aerosandbox.numpy.ndarray]

Returns: A list of points, where each point is a 3-element array of the form [x, y, z]. Goes from the root to the tip. Ignores any wing symmetry (e.g., only gives one side).

draw(*args, **kwargs)[source]#

An alias to the more general Airplane.draw() method. See there for documentation.

Parameters:
  • *args – Arguments to pass through to Airplane.draw()

  • **kwargs – Keyword arguments to pass through to Airplane.draw()

Returns: Same return as Airplane.draw()

draw_wireframe(*args, **kwargs)[source]#

An alias to the more general Airplane.draw_wireframe() method. See there for documentation.

Parameters:
  • *args – Arguments to pass through to Airplane.draw_wireframe()

  • **kwargs – Keyword arguments to pass through to Airplane.draw_wireframe()

Returns: Same return as Airplane.draw_wireframe()

draw_three_view(*args, **kwargs)[source]#

An alias to the more general Airplane.draw_three_view() method. See there for documentation.

Parameters:
  • *args – Arguments to pass through to Airplane.draw_three_view()

  • **kwargs – Keyword arguments to pass through to Airplane.draw_three_view()

Returns: Same return as Airplane.draw_three_view()

subdivide_sections(ratio, spacing_function=np.linspace)[source]#

Generates a new Wing that subdivides the existing sections of this Wing into several smaller ones. Splits each section into N=`ratio` smaller sub-sections by inserting new cross-sections (xsecs) as needed.

This can allow for finer aerodynamic resolution of sectional properties in certain analyses.

Parameters:
  • ratio (int) – The number of new sections to split each old section into.

  • spacing_function (Callable[[float, float, float], aerosandbox.numpy.ndarray]) –

    A function that takes in three arguments: the start, end, and number of points to generate.

    The default is np.linspace, which generates a linearly-spaced array of points.

    Other options include np.cosspace, which generates a cosine-spaced array of points.

Return type:

Wing

Returns: A new Wing object with subdivided sections.

_compute_xyz_le_of_WingXSec(index)[source]#
Parameters:

index (int) –

_compute_xyz_te_of_WingXSec(index)[source]#
Parameters:

index (int) –

_compute_xyz_of_WingXSec(index, x_nondim, z_nondim)[source]#
_compute_frame_of_WingXSec(index)[source]#

Computes the local reference frame associated with a particular cross-section (XSec) of this wing.

Parameters:

index (int) – Which cross-section (as indexed in Wing.xsecs) should we get the frame of?

Returns:

A tuple of (xg_local, yg_local, zg_local), where each entry refers to the respective (normalized) axis of the local reference frame of the WingXSec. Given in geometry axes.

Return type:

Tuple[aerosandbox.numpy.ndarray, aerosandbox.numpy.ndarray, aerosandbox.numpy.ndarray]

_compute_frame_of_section(index)[source]#

Computes the local reference frame associated with a particular section. (Note that sections and cross sections are different! cross-sections, or xsecs, are the vertices, and sections are the parts in between. In other words, a wing with N cross-sections (xsecs) will always have N-1 sections.

Parameters:
  • index (int) – Which section should we get the frame of? If given i, this retrieves the frame of the section

  • i+1. (between xsecs i and) –

Returns:

A tuple of (xg_local, yg_local, zg_local), where each entry refers to the respective (normalized) axis of the local reference frame of the section. Given in geometry axes.

Return type:

Tuple[aerosandbox.numpy.ndarray, aerosandbox.numpy.ndarray, aerosandbox.numpy.ndarray]

class aerosandbox.geometry.WingXSec(xyz_le=None, chord=1.0, twist=0.0, airfoil=None, control_surfaces=None, analysis_specific_options=None, **deprecated_kwargs)[source]#

Bases: aerosandbox.common.AeroSandboxObject

Definition for a wing cross-section (“X-section”).

Parameters:
  • xyz_le (Union[aerosandbox.numpy.ndarray, List]) –

  • chord (float) –

  • twist (float) –

  • airfoil (aerosandbox.geometry.airfoil.Airfoil) –

  • control_surfaces (Optional[List[ControlSurface]]) –

  • analysis_specific_options (Optional[Dict[type, Dict[str, Any]]]) –

__repr__()[source]#

Return repr(self).

Return type:

str

translate(xyz)[source]#

Returns a copy of this WingXSec that has been translated by xyz.

Parameters:

xyz (Union[aerosandbox.numpy.ndarray, List]) – The amount to translate the WingXSec. Given as a 3-element NumPy vector.

Return type:

WingXSec

Returns: A new WingXSec object.

xsec_area()[source]#

Computes the WingXSec’s cross-sectional (xsec) area.

Returns: The (dimensional) cross-sectional area of the WingXSec.

class aerosandbox.geometry.ControlSurface(name='Untitled', symmetric=True, deflection=0.0, hinge_point=0.75, trailing_edge=True, analysis_specific_options=None)[source]#

Bases: aerosandbox.common.AeroSandboxObject

Definition for a control surface, which is attached to a particular WingXSec via WingXSec’s control_surfaces=[] parameter.

Parameters:
  • name (str) –

  • symmetric (bool) –

  • deflection (float) –

  • hinge_point (float) –

  • trailing_edge (bool) –

  • analysis_specific_options (Optional[Dict[type, Dict[str, Any]]]) –

__repr__()[source]#

Return repr(self).

Return type:

str

class aerosandbox.geometry.Fuselage(name='Untitled', xsecs=None, color=None, analysis_specific_options=None, **kwargs)[source]#

Bases: aerosandbox.AeroSandboxObject

Definition for a Fuselage or other slender body (pod, fuel tank, etc.).

Anatomy of a Fuselage:

A fuselage consists chiefly of a collection of cross-sections, or “xsecs”. A cross-section is a 2D “slice” of a fuselage. These can be accessed with Fuselage.xsecs, which gives a list of xsecs in the Fuselage. Each xsec is a FuselageXSec object, a class that is defined separately.

You may also see references to fuselage “sections”, which are different from cross-sections (xsecs)! Sections are the portions of the fuselage that are in between xsecs. In other words, a fuselage with N cross-sections (xsecs, FuselageXSec objects) will always have N-1 sections. Sections are never explicitly defined, since you can get all needed information by lofting from the adjacent cross-sections. For example, section 0 (the first one) is a loft between cross-sections 0 and 1.

Fuselages are lofted linearly between cross-sections.

Parameters:
  • name (Optional[str]) –

  • xsecs (List[FuselageXSec]) –

  • color (Optional[Union[str, Tuple[float]]]) –

  • analysis_specific_options (Optional[Dict[type, Dict[str, Any]]]) –

__repr__()[source]#

Return repr(self).

Return type:

str

abstract add_loft(kind, to_xsec, from_xsec=None, n_points=5, spacing=np.cosspace)[source]#
Parameters:
  • kind (str) –

  • to_xsec (FuselageXSec) –

  • from_xsec (FuselageXSec) –

  • n_points (int) –

  • spacing (Callable[[float, float, int], aerosandbox.geometry.common.np.ndarray]) –

Return type:

Fuselage

translate(xyz)[source]#

Translates the entire Fuselage by a certain amount.

Parameters:

xyz (Union[aerosandbox.geometry.common.np.ndarray, List[float]]) –

Return type:

Fuselage

Returns: self

area_wetted()[source]#

Returns the wetted area of the fuselage.

Returns:

Return type:

float

area_projected(type='XY')[source]#

Returns the area of the fuselage as projected onto one of the principal planes.

Parameters:

type (str) –

A string, which determines which principal plane to use for projection. One of:

  • ”XY”, in which case the projected area is onto the XY plane (i.e., top-down)

  • ”XZ”, in which case the projected area is onto the XZ plane (i.e., side-view)

Return type:

float

Returns: The projected area.

area_base()[source]#

Returns the area of the base (i.e. “trailing edge”) of the fuselage. Useful for certain types of drag calculation.

Returns:

Return type:

float

fineness_ratio(assumed_shape='cylinder')[source]#

Approximates the fineness ratio using the volume and length. The fineness ratio of a fuselage is defined as:

FR = length / max_diameter

Parameters:

assumed_shape

A string, which determines the assumed shape of the fuselage for the approximation. One of:

  • ”cylinder”, in which case the fuselage is assumed to have a cylindrical shape.

  • ”sears-haack”, in which case the fuselage is assumed to have Sears-Haack fuselage shape.

Return type:

float

Returns: An approximate value of the fuselage’s fineness ratio.

length()[source]#

Returns the total front-to-back length of the fuselage. Measured as the difference between the x-coordinates of the leading and trailing cross-sections. :return:

Return type:

float

volume(_sectional=False)[source]#

Computes the volume of the Fuselage.

Parameters:
  • _sectional (bool) – A boolean. If False, returns the total volume. If True, returns a list of volumes for each of

  • sections (the n-1 lofted) –

Returns:

The computed volume.

Return type:

Union[float, List[float]]

x_centroid_projected(type='XY')[source]#

Returns the x_g coordinate of the centroid of the planform area.

Parameters:

type (str) –

A string, which determines which principal plane to use for projection. One of:

  • ”XY”, in which case the projected area is onto the XY plane (i.e., top-down)

  • ”XZ”, in which case the projected area is onto the XZ plane (i.e., side-view)

Return type:

float

Returns: The x_g coordinate of the centroid.

mesh_body(method='quad', tangential_resolution=36)[source]#

Meshes the fuselage as a solid (thickened) body.

Uses the (points, faces) standard mesh format. For reference on this format, see the documentation in aerosandbox.geometry.mesh_utilities.

Parameters:
  • method

    A string, which determines whether to mesh the fuselage as a series of quadrilaterals or triangles.

    • ”quad” meshes the fuselage as a series of quadrilaterals.

    • ”tri” meshes the fuselage as a series of triangles.

  • tangential_resolution (int) – An integer, which determines the number of points to use to mesh each cross-section.

Return type:

Tuple[aerosandbox.geometry.common.np.ndarray, aerosandbox.geometry.common.np.ndarray]

Returns: Standard unstructured mesh format: A tuple of`points` and faces, where:

  • points is a n x 3 array of points, where n is the number of points in the mesh.

  • faces is a m x 3 array of faces if method is “tri”, or a m x 4 array of faces if method is “quad”.

    • Each row of faces is a list of indices into points, which specifies a face.

mesh_line(y_nondim=0.0, z_nondim=0.0)[source]#

Returns points along a line that goes through each of the FuselageXSec objects in this Fuselage.

Parameters:
  • y_nondim (Union[float, List[float]]) – The nondimensional (width-normalized) y-coordinate that the line should go through. Can either

  • cross-sections (be a single value used at all) –

  • the (or can be an iterable of values to be used at) –

  • cross-sections. (respective) –

  • z_nondim (Union[float, List[float]]) – The nondimensional (height-normalized) z-coordinate that the line should go through. Can either

  • cross-sections

  • the

  • cross-sections.

Return type:

List[aerosandbox.geometry.common.np.ndarray]

Returns: A list of points, where each point is a 3-element array of the form [x, y, z]. Goes from the nose to the tail.

draw(*args, **kwargs)[source]#

An alias to the more general Airplane.draw() method. See there for documentation.

Parameters:
  • *args – Arguments to pass through to Airplane.draw()

  • **kwargs – Keyword arguments to pass through to Airplane.draw()

Returns: Same return as Airplane.draw()

draw_wireframe(*args, **kwargs)[source]#

An alias to the more general Airplane.draw_wireframe() method. See there for documentation.

Parameters:
  • *args – Arguments to pass through to Airplane.draw_wireframe()

  • **kwargs – Keyword arguments to pass through to Airplane.draw_wireframe()

Returns: Same return as Airplane.draw_wireframe()

draw_three_view(*args, **kwargs)[source]#

An alias to the more general Airplane.draw_three_view() method. See there for documentation.

Parameters:
  • *args – Arguments to pass through to Airplane.draw_three_view()

  • **kwargs – Keyword arguments to pass through to Airplane.draw_three_view()

Returns: Same return as Airplane.draw_three_view()

subdivide_sections(ratio, spacing_function=np.linspace)[source]#

Generates a new Fuselage that subdivides the existing sections of this Fuselage into several smaller ones. Splits each section into N=`ratio` smaller subsections by inserting new cross-sections (xsecs) as needed.

This can allow for finer aerodynamic resolution of sectional properties in certain analyses.

Parameters:
  • ratio (int) – The number of new sections to split each old section into.

  • spacing_function (Callable[[float, float, float], aerosandbox.geometry.common.np.ndarray]) –

    A function that takes in three arguments: the start, end, and number of points to generate.

    The default is np.linspace, which generates a linearly-spaced array of points.

    Other options include np.cosspace, which generates a cosine-spaced array of points.

Return type:

Fuselage

Returns: A new Fuselage object with subdivided sections.

_compute_frame_of_FuselageXSec(index)[source]#

Computes the local frame of a FuselageXSec, given the index of the FuselageXSec in the Fuselage.xsecs list.

Parameters:

index (int) – The index of the FuselageXSec in the Fuselage.xsecs list.

Return type:

Tuple[aerosandbox.geometry.common.np.ndarray, aerosandbox.geometry.common.np.ndarray, aerosandbox.geometry.common.np.ndarray]

Returns: A tuple:

xg_local: The x-axis of the local coordinate frame, in aircraft geometry axes. yg_local: The y-axis of the local coordinate frame, in aircraft geometry axes. zg_local: The z-axis of the local coordinate frame, in aircraft geometry axes.

class aerosandbox.geometry.FuselageXSec(xyz_c=None, xyz_normal=None, radius=None, width=None, height=None, shape=2.0, analysis_specific_options=None)[source]#

Bases: aerosandbox.AeroSandboxObject

Definition for a fuselage cross-section (“X-section”).

Parameters:
  • xyz_c (Union[aerosandbox.geometry.common.np.ndarray, List[float]]) –

  • xyz_normal (Union[aerosandbox.geometry.common.np.ndarray, List[float]]) –

  • radius (float) –

  • width (float) –

  • height (float) –

  • shape (float) –

  • analysis_specific_options (Optional[Dict[type, Dict[str, Any]]]) –

__repr__()[source]#

Return repr(self).

Return type:

str

xsec_area()[source]#

Computes the FuselageXSec’s cross-sectional (xsec) area.

The computation method is a closed-form approximation for the area of a superellipse. The exact equation for the area of a superellipse with shape parameter s is:

area = width * height * (gamma(1 + 1/n))^2 / gamma(1 + 2/n)

where gamma() is the gamma function. The gamma function is (relatively) computationally expensive to evaluate and differentiate, so we replace this area calculation with a closed-form approximation (with essentially no loss in accuracy):

area = width * height / (s^-1.8717618013591173 + 1)

This approximation has the following properties:

  • It is numerically exact for the case of s = 1 (a diamond)

  • It is numerically exact for the case of s = 2 (a circle)

  • It is correct in the asymptotic limit where s -> infinity (a square)

  • In the range of sensible s values (1 < s < infinity), its error is less than 0.6%.

  • It always produces a positive area for any physically-meaningful value of s (s > 0). In the range of s

values where s is physically-meaningful but not in a sensible range (0 < s < 1), this equation will over-predict area.

The value of the constant seen in this expression (1.872…) is given by log(4/pi - 1) / log(2), and it is chosen as such so that the expression is exactly correct in the s=2 (circle) case.

Returns:

xsec_perimeter()[source]#

Computes the FuselageXSec’s perimeter. (“Circumference” in the case of a circular cross-section.)

The computation method is a closed-form approximation for the perimeter of a superellipse. The exact equation for the perimeter of a superellipse is quite long and is not repeated here for brevity; a Google search will bring it up. More importantly, this exact equation can only be represented as an infinite sum - not particularly useful for fast computation.

We replace this exact equation with the following closed-form approximation obtained from symbolic regression:

Imagine a superellipse centered on the origin of a 2D plane. Now, imagine that the superellipse is stretched such that the first quadrant (e.g., x>0, y>0) goes from (1, 0) to (0, h). Assume it has shape parameter s (where, as a reminder, s=1 is a diamond, s=2 is a circle, s=Inf is a square).

Then, the perimeter of that single quadrant is:

h + (((((s-0.88487077) * h + 0.2588574 / h) ^ exp(s / -0.90069205)) + h) + 0.09919785) ^ (-1.4812293 / s)

See AeroSandbox/studies/SuperellipseProperties for details about how this was obtained.

We can extrapolate from here to the general case of a superellipse, as shown in the code below.

This approximation has the following properties:

  • For the s=1 case (diamond), the error is +0.2%.

  • For the s=2 case (circle), the error is -0.1%.

  • In the s -> infinity limit (square), the error is +0.1%.

Returns:

compute_frame()[source]#

Computes the local coordinate frame of the FuselageXSec, in aircraft geometry axes.

xg_local is aligned with the FuselageXSec’s normal vector.

zg_local is roughly aligned with the z-axis of the aircraft geometry axes, but projected onto the FuselageXSec’s plane.

yg_local is the cross product of zg_local and xg_local.

Returns: A tuple:

xg_local: The x-axis of the local coordinate frame, in aircraft geometry axes. yg_local: The y-axis of the local coordinate frame, in aircraft geometry axes. zg_local: The z-axis of the local coordinate frame, in aircraft geometry axes.

Return type:

Tuple[aerosandbox.geometry.common.np.ndarray, aerosandbox.geometry.common.np.ndarray, aerosandbox.geometry.common.np.ndarray]

get_3D_coordinates(theta=None)[source]#

Samples points from the perimeter of this FuselageXSec.

Parameters:
  • theta (Union[float, aerosandbox.geometry.common.np.ndarray]) – Coordinate in the tangential-ish direction to sample points at. Given in the 2D FuselageXSec

  • system (coordinate) –

    • y_2D points along the (global) y_g

    • z_2D points along the (global) z_g

    In other words, a value of:

    • theta=0 -> samples points from the right side of the FuselageXSec

    • theta=pi/2 -> samples points from the top of the FuselageXSec

    • theta=pi -> samples points from the left side of the FuselageXSec

    • theta=3pi/2 -> samples points from the bottom of the FuselageXSec

  • where

    • y_2D points along the (global) y_g

    • z_2D points along the (global) z_g

    In other words, a value of:

    • theta=0 -> samples points from the right side of the FuselageXSec

    • theta=pi/2 -> samples points from the top of the FuselageXSec

    • theta=pi -> samples points from the left side of the FuselageXSec

    • theta=3pi/2 -> samples points from the bottom of the FuselageXSec

Return type:

Tuple[Union[float, aerosandbox.geometry.common.np.ndarray]]

Returns: Points sampled from the perimeter of the FuselageXSec, as a [x, y, z] tuple.

If theta is a float, then each of x, y, and z will be floats.

If theta is an array, then x, y, and z will also be arrays of the same size.

equivalent_radius(preserve='area')[source]#

Computes an equivalent radius for non-circular cross-sections. This may be necessary when doing analysis that uses axisymmetric assumptions.

Can either hold area or perimeter fixed, depending on whether cross-sectional area or wetted area is more important.

Parameters:

preserve

One of:

  • ”area”: holds the cross-sectional area constant

  • ”perimeter”: holds the cross-sectional perimeter (i.e., the wetted area of the Fuselage) constant

Return type:

float

Returns: An equivalent radius value.

translate(xyz)[source]#

Returns a copy of this FuselageXSec that has been translated by xyz.

Parameters:

xyz (Union[aerosandbox.geometry.common.np.ndarray, List[float]]) – The amount to translate the FuselageXSec. Given as a 3-element NumPy vector.

Return type:

FuselageXSec

Returns: A copy of this FuselageXSec, translated by xyz.

class aerosandbox.geometry.Airplane(name=None, xyz_ref=None, wings=None, fuselages=None, propulsors=None, s_ref=None, c_ref=None, b_ref=None, analysis_specific_options=None)[source]#

Bases: aerosandbox.AeroSandboxObject

Definition for an airplane.

Anatomy of an Airplane:

An Airplane consists chiefly of a collection of wings and fuselages. These can be accessed with Airplane.wings and Airplane.fuselages, which gives a list of those respective components. Each wing is a Wing object, and each fuselage is a Fuselage object.

Parameters:
__repr__()[source]#

Return repr(self).

mesh_body(method='quad', thin_wings=False, stack_meshes=True)[source]#

Returns a surface mesh of the Airplane, in (points, faces) format. For reference on this format, see the documentation in aerosandbox.geometry.mesh_utilities.

Parameters:
  • method

  • thin_wings – Controls whether wings should be meshed as thin surfaces, rather than full 3D bodies.

  • stack_meshes

    Controls whether the meshes should be merged into a single mesh or not.

    • If True, returns a (points, faces) tuple in standard mesh format.

    • If False, returns a list of (points, faces) tuples in standard mesh format.

Returns:

draw(backend='pyvista', thin_wings=False, ax=None, use_preset_view_angle=None, set_background_pane_color=None, set_background_pane_alpha=None, set_lims=True, set_equal=True, set_axis_visibility=None, show=True, show_kwargs=None)[source]#

Produces an interactive 3D visualization of the airplane.

Parameters:
  • backend (str) –

    The visualization backend to use. Options are:

    • ”matplotlib” for a Matplotlib backend

    • ”pyvista” for a PyVista backend

    • ”plotly” for a Plot.ly backend

    • ”trimesh” for a trimesh backend

  • thin_wings (bool) – A boolean that determines whether to draw the full airplane (i.e. thickened, 3D bodies), or to use a

  • objects. (thin-surface representation for any Wing) –

  • show (bool) – A boolean that determines whether to display the object after plotting it. If False, the object is

  • True (returned but not displayed. If) –

  • returned. (the object is displayed and) –

  • use_preset_view_angle (str) –

  • set_background_pane_color (Union[str, Tuple[float, float, float]]) –

  • set_background_pane_alpha (float) –

  • set_lims (bool) –

  • set_equal (bool) –

  • set_axis_visibility (bool) –

  • show_kwargs (Dict) –

Returns: The plotted object, in its associated backend format. Also displays the object if show is True.

draw_wireframe(ax=None, color='k', thin_linewidth=0.2, thick_linewidth=0.5, fuselage_longeron_theta=None, use_preset_view_angle=None, set_background_pane_color=None, set_background_pane_alpha=None, set_lims=True, set_equal=True, set_axis_visibility=None, show=True)[source]#

Draws a wireframe of the airplane on a Matplotlib 3D axis.

Parameters:
  • ax – The axis to draw on. Must be a 3D axis. If None, creates a new axis.

  • color – The color of the wireframe.

  • thin_linewidth – The linewidth of the thin lines.

  • use_preset_view_angle (str) –

  • set_background_pane_color (Union[str, Tuple[float, float, float]]) –

  • set_background_pane_alpha (float) –

  • set_lims (bool) –

  • set_equal (bool) –

  • set_axis_visibility (bool) –

  • show (bool) –

draw_three_view(style='shaded', show=True)[source]#

Draws a standard 4-panel three-view diagram of the airplane using Matplotlib backend. Creates a new figure.

Parameters:
  • style (str) –

    Determines what drawing style to use for the three-view. A string, one of:

    • ”shaded”

    • ”wireframe”

  • show (bool) – A boolean of whether to show the figure after creating it, or to hold it so that the user can modify the figure further before showing.

Returns:

is_entirely_symmetric()[source]#

Returns a boolean describing whether the airplane is geometrically entirely symmetric across the XZ-plane. :return: [boolean]

aerodynamic_center(chord_fraction=0.25)[source]#

Computes the approximate location of the aerodynamic center of the wing. Uses the generalized methodology described here:

Parameters:
  • chord_fraction (float) – The position of the aerodynamic center along the MAC, as a fraction of MAC length.

  • Typically (denoted h_0 in the literature) –

  • value (this) –

  • Cook (wing-fuselage interactions can cause a forward shift to a value more like 0.1 or less. Citing) –

:param : :param Michael V.: :param “Flight Dynamics Principles”: :param 3rd Ed.: :param Sect. 3.5.3 “Controls-fixed static stability”. PDF: :param https: //www.sciencedirect.com/science/article/pii/B9780080982427000031

Returns: The (x, y, z) coordinates of the aerodynamic center of the airplane.

with_control_deflections(control_surface_deflection_mappings)[source]#

Returns a copy of the airplane with the specified control surface deflections applied.

Parameters:

control_surface_deflection_mappings (Dict[str, float]) –

A dictionary mapping control surface names to deflections.

  • Keys: Control surface names.

  • Values: Deflections, in degrees. Downwards-positive, following typical convention.

Return type:

Airplane

Returns: A copy of the airplane with the specified control surface deflections applied.

generate_cadquery_geometry(minimum_airfoil_TE_thickness=0.001, fuselage_tol=0.0001)[source]#

Uses the CADQuery library (OpenCASCADE backend) to generate a 3D CAD model of the airplane.

Parameters:
  • minimum_airfoil_TE_thickness (float) – The minimum thickness of the trailing edge of the airfoils, as a fraction

  • if (of each airfoil's chord. This will be enforced by thickening the trailing edge of the airfoils) –

  • extremely (necessary. This is useful for avoiding numerical issues in CAD software that can arise from) –

  • thin (i.e., <1e-6 meters) –

  • tol – The geometric tolerance (meters) to use when generating the CAD geometry. This is passed directly to the CADQuery

  • fuselage_tol (float) –

Return type:

Workplane

Returns: A CADQuery Workplane object containing the CAD geometry of the airplane.

export_cadquery_geometry(filename, minimum_airfoil_TE_thickness=0.001)[source]#

Exports the airplane geometry to a STEP file.

Parameters:
  • filename (Union[pathlib.Path, str]) – The filename to export to. Should include the “.step” extension.

  • minimum_airfoil_TE_thickness (float) – The minimum thickness of the trailing edge of the airfoils, as a fraction

  • if (of each airfoil's chord. This will be enforced by thickening the trailing edge of the airfoils) –

  • extremely (necessary. This is useful for avoiding numerical issues in CAD software that can arise from) –

  • thin (i.e., <1e-6 meters) –

Return type:

None

Returns: None, but exports the airplane geometry to a STEP file.

export_AVL(filename, include_fuselages=True)[source]#
Parameters:

include_fuselages (bool) –

export_XFLR(*args, **kwargs)[source]#
Return type:

str

export_XFLR5_xml(filename, mass_props=None, include_fuselages=False, mainwing=None, elevator=None, fin=None)[source]#

Exports the airplane geometry to an XFLR5 .xml file. To import the .xml file into XFLR5, go to File -> Import -> Import from XML.

Parameters:
  • filename (Union[pathlib.Path, str]) – The filename to export to. Should include the “.xml” extension.

  • mass_props (aerosandbox.weights.mass_properties.MassProperties) –

    The MassProperties object to use when exporting the airplane. If not specified, will default to a 1 kg point mass at the origin.

    • Note: XFLR5 does not natively support user-defined inertia tensors, so we have to synthesize an equivalent

    set of point masses to represent the inertia tensor.

  • include_fuselages (bool) – Whether to include fuselages in the export.

  • mainwing (aerosandbox.geometry.wing.Wing) – The main wing of the airplane. If not specified, will default to the first wing in the airplane.

  • elevator (aerosandbox.geometry.wing.Wing) – The elevator of the airplane. If not specified, will default to the second wing in the airplane.

  • fin (aerosandbox.geometry.wing.Wing) – The fin of the airplane. If not specified, will default to the third wing in the airplane.

Return type:

str

Returns: None, but exports the airplane geometry to an XFLR5 .xml file.

To import the .xml file into XFLR5, go to File -> Import -> Import from XML.

export_OpenVSP_vspscript(filename)[source]#

Exports the airplane geometry to a *.vspscript file compatible with OpenVSP. To import the .vspscript file into OpenVSP:

Open OpenVSP, then File -> Run Script -> Select the .vspscript file.

Parameters:

filename (Union[pathlib.Path, str]) – The filename to export to, given as a string or Path. Should include the “.vspscript” extension.

Return type:

str

Returns: A string of the file contents, and also saves the file to the specified filename

class aerosandbox.geometry.Propulsor(name='Untitled', xyz_c=None, xyz_normal=None, radius=1.0, length=0.0, color=None, analysis_specific_options=None)[source]#

Bases: aerosandbox.AeroSandboxObject

Definition for a Propulsor, which could be a propeller, a rotor, or a jet engine.

Assumes a disk- or cylinder-shaped propulsor.

Parameters:
  • name (Optional[str]) –

  • xyz_c (Union[aerosandbox.geometry.common.np.ndarray, List[float]]) –

  • xyz_normal (Union[aerosandbox.geometry.common.np.ndarray, List[float]]) –

  • radius (float) –

  • length (float) –

  • color (Optional[Union[str, Tuple[float]]]) –

  • analysis_specific_options (Optional[Dict[type, Dict[str, Any]]]) –

__repr__()[source]#

Return repr(self).

Return type:

str

xsec_area()[source]#

Returns the cross-sectional area of the propulsor, in m^2.

Return type:

float

xsec_perimeter()[source]#

Returns the cross-sectional perimeter of the propulsor, in m.

Return type:

float

volume()[source]#

Returns the volume of the propulsor, in m^3.

Return type:

float

compute_frame()[source]#

Computes the local coordinate frame of the propulsor, in aircraft geometry axes.

xg_local is aligned with the propulsor’s normal vector.

zg_local is roughly aligned with the z-axis of the aircraft geometry axes, but projected onto the propulsor’s plane.

yg_local is the cross product of zg_local and xg_local.

Returns: A tuple:

xg_local: The x-axis of the local coordinate frame, in aircraft geometry axes. yg_local: The y-axis of the local coordinate frame, in aircraft geometry axes. zg_local: The z-axis of the local coordinate frame, in aircraft geometry axes.

Return type:

Tuple[aerosandbox.geometry.common.np.ndarray, aerosandbox.geometry.common.np.ndarray, aerosandbox.geometry.common.np.ndarray]

get_disk_3D_coordinates(theta=None, l_over_length=None)[source]#
Parameters:
  • theta (Union[float, aerosandbox.geometry.common.np.ndarray]) –

  • l_over_length (Union[float, aerosandbox.geometry.common.np.ndarray]) –

Return type:

Tuple[Union[float, aerosandbox.geometry.common.np.ndarray]]

translate(xyz)[source]#

Returns a copy of this propulsor that has been translated by xyz.

Parameters:

xyz (Union[aerosandbox.geometry.common.np.ndarray, List[float]]) – The amount to translate the propulsor, in meters. Given in aircraft geometry axes, as with everything else.

Return type:

Propulsor

Returns: A copy of this propulsor, translated by xyz.