Vehicle Definition
In this example we simulate the eVTOL transition maneuver of a tandem tilt-wing multirotor aircraft. The aircraft configuration resembles the Vahana eVTOL aircraft but with tilt and stacked rotors:
|
|
Due to the complexity of this simulation, each step of the simulation setup is quite involved. Hence, we have broken down each step into a function that can be call when we setup the simulation.
Below is the function that defines the vehicle for the simulation (uns.UVLMVehicle
). Along with defining the vehicle geometry, it also defines two tilting systems (a tilting system is a set of components that tilt together) and three rotor systems (a rotor system is a set of rotors with a common RPM). Later in the next section we will define the control inputs for these tilting and rotor systems.
|
|
"""
Generates the geometry of Vahana aircraft
"""
function generate_vahana_vehicle(;
# VEHICLE OPTIONS
xfoil = true, # Whether to run XFOIL
n_factor::Int = 1, # Discretization factor
add_wings = true, # Whether to add the wings
add_rotors = true, # Whether to add the rotors
VehicleType = uns.VLMVehicle, # Type of vehicle to generate (uns.QVLMVehicle for quasi-steady solver)
data_path = uns.def_data_path,# Database path
# OUTPUT OPTIONS
run_name = "vahana",
verbose = true,
v_lvl = 0
)
############################################################################
# PARAMETERS
############################################################################
if verbose; println("\t"^(v_lvl)*"Defining parameters..."); end;
# ------------ GEOMETRIC PARAMETERS ------------------------------------
# Tilt and fixed rotors
tiltrotor_file = "VahanaTilt.csv" # Tilt-rotor file
R_w = 0.75 # (m) main-wing rotor radius (reference)
R_tw = R_w # (m) tandem-wing rotor radius (reference)
CW_w = true # Clockwise rotation of main-wing rotor
CW_tw = false # Clockwise rotation of tandem-wing rotor
nr_w = 2 # Number of rotors per side of main wing
nr_tw = 2 # Number of rotors per side of tandem wing
pitch = 0.0 # (deg) collective pitch for tiltrotors rotors on main and tandem wings
main_outtilt = 10 # (deg) Mount main-wing rotors with this out-tilt angle
tandem_pitchtilt= 10 # (deg) Mount tandem-wing rotors with this alternating pitch-tilt angle
xoc_offset_main = 0.175 # Axial distance of main-wing rotors from LE, divided by chord
xoc_offset_tandem = 0.10 # Axial distance of tandem-wing rotors from LE, divided by chord
soD = 0.1 # Tip-to-tip distance of rotors, divided by diameter
ReD07 = 1.5e6 # Assumed diameter-based Reynolds number for all rotors at r/R=0.7
ReD = ReD07/0.7 # Reynolds number at blade tip (for XFOIL)
n_rotor = 7*n_factor # Number of blade elements per blade
r_rotor = 1/20 # Geometric expansion between blade elements
tilt_read_polar = vlm.ap.read_polar # What polar reader to use
# Stacked rotors
stackedrotor_file = "VahanaStacked.csv" # Stacked-rotor file
stacked = [nr_w, nr_w+1] # Index of main-wing rotors that will be stacked rotors
stckd_xoc_offset= -1.40 # Axial distance of stacked rotors from LE, divided by chord
stckd_zoc_offset= 0.10 # Height of stacked rotors above wing, divided by chord
stckd_zoR_offset= -0.05 # Stacking distance between stacked rotors, divided by R
stckd_corotating= true # Co-rotating stacked rotors if true, counter-rotating otherwise
stckd_phase = -10 # (deg) initial phase difference of stacked rotors (index angle)
stckd_pitch_up = 5.0 # (deg) collective pitch of upper rotor in stack
stckd_pitch_low = stckd_pitch_up + 7.5 # (deg) collective pitch of lower rotor in stack
stacked_read_polar = vlm.ap.read_polar2 # What polar reader to use
# Main wing
b_w = 5.86 # (m) span
AR_w = 7.4 # Aspect ratio (b/c_tip)
tr_w = 1.0 # Taper ratio (c_tip/c_root)
twist_r_w = 14.0 # (deg) twist at root
twist_t_w = twist_r_w # (deg) twist at tip
lambda_w = main_outtilt # (deg) sweep
gamma_w = 5.0 # (deg) dihedral
md_w = 0.9 # Length of middle section, divided by span
pivot_w = 1/4 # Pivot point along chord of tilt-wing
n_w = 24*n_factor # Number of wing elements per side
r_w = 2.0 # Geometric expansion of wing elements
# Main-wing winglets
b_wl = b_w/4 # (m) span of winglet from top to bottom
AR_wl = 3.0 # Aspect ratio (b/c_tip)
tr_wl = (b_wl/AR_wl)/(b_w/AR_w/tr_w) # Taper ratio (c_tip/c_root)
twist_r_wl = 2.5 # (deg) twist at root
twist_t_wl = 0.0 # (deg) twist at tip
lambda_wl = 40.0 # (deg) sweep
gamma_wl = 15.0 # (deg) dihedral
n_wl = 8*n_factor # Number of wing elements per side
r_wl = 2.0 # Geometric expansion of wing elements
# Tandem wing
b_tw = b_w*1.0 # (m) span
AR_tw = 9.5 # Aspect ratio (b/c_tip)
tr_tw = 1.0 # Taper ratio (c_tip/c_root)
twist_r_tw = 14.0 # (deg) twist at root
twist_t_tw = twist_r_tw # (deg) twist at tip
lambda_tw = 0.0 # (deg) sweep
gamma_tw = 0.0 # (deg) dihedral
md_tw = 0.2 # Length of middle section, divided by span
pivot_tw = pivot_w # Pivot point along chord of tilt-wing
n_tw = 2*n_w # Number of wing elements per side
r_tw = r_w # Geometric expansion of wing elements
# Fuselage
l_f = 5.86 # (m) length
h_f = 2.81*2/3 # (m) height
# ------------ ASSEMBLY PARAMETERS ------------------------------------
# Position of wings on fuselage
h_pos_w = 0.90*h_f # (m) height position of wing
h_pos_tw = 0.15*h_f # (m) height position of tandem wing
l_pos_w = 0.95*l_f-b_w/AR_w/tr_w# (m) length position of wing
l_pos_tw = 0.05*l_f # (m) length position of tandem wing
# Position of rotors along main wing
d_rotor_w = (1+soD)*(2*R_w) # Distance between rotors
y_pos_rotor_w = Float64[b_w/2 - i*d_rotor_w for i in 0:nr_w-1] # y-positions
# Position of rotors along tandem wing
d_rotor_tw = (1+soD)*(2*R_tw) # Distance between rotors on wing
y_pos_rotor_tw = Float64[b_tw/2 - i*d_rotor_tw for i in 0:nr_tw-1] # y-positions
init_ori = 90.0 # (deg) initial orientation of wings
init_ori_rotor = 0.0 # (deg) initial orientation of rotors
init_ori_stackedrotor = 30.0 # (deg) initial orientation of stacked rotors
############################################################################
# GENERATE COMPONENTS
############################################################################
if verbose; println("\t"^(v_lvl)*"Generating components..."); end;
# ------------ ROTORS ------------------------------------------------
# Generate base rotors (one for each rotation orientation)
if add_rotors
tiltrotors = vlm.Rotor[] # Tilt rotors
if verbose; println("\t"^(v_lvl+1)*"Generating first tilt-rotor..."); end;
push!(tiltrotors, uns.generate_rotor(tiltrotor_file; pitch=pitch,
n=n_rotor, blade_r=r_rotor, CW=!CW_w, ReD=ReD,
verbose=verbose, v_lvl=v_lvl+2, xfoil=xfoil,
read_polar=tilt_read_polar,
data_path=data_path, plot_disc=false))
if verbose; println("\t"^(v_lvl+1)*"Generating second tilt-rotor..."); end;
push!(tiltrotors, uns.generate_rotor(tiltrotor_file; pitch=pitch,
n=n_rotor, blade_r=r_rotor, CW=CW_w, ReD=ReD,
verbose=verbose, v_lvl=v_lvl+2, xfoil=xfoil,
read_polar=tilt_read_polar,
data_path=data_path, plot_disc=false))
stackedrotors = vlm.Rotor[] # Upper rotor in stacked rotors
if verbose; println("\t"^(v_lvl+1)*"Generating first stacked-rotor..."); end;
push!(stackedrotors, uns.generate_rotor(stackedrotor_file; pitch=stckd_pitch_up,
n=n_rotor, blade_r=r_rotor, CW=!CW_w, ReD=ReD,
verbose=verbose, v_lvl=v_lvl+2, xfoil=xfoil,
read_polar=stacked_read_polar,
data_path=data_path, plot_disc=false))
if verbose; println("\t"^(v_lvl+1)*"Generating second stacked-rotor..."); end;
push!(stackedrotors, uns.generate_rotor(stackedrotor_file; pitch=stckd_pitch_up,
n=n_rotor, blade_r=r_rotor, CW=CW_w, ReD=ReD,
verbose=verbose, v_lvl=v_lvl+2, xfoil=xfoil,
read_polar=stacked_read_polar,
data_path=data_path, plot_disc=false))
stackedrotors_low = vlm.Rotor[] # Lower rotor in stacked rotors
if stckd_pitch_up != stckd_pitch_low
if verbose; println("\t"^(v_lvl+1)*"Generating first lower-stacked-rotor..."); end;
push!(stackedrotors_low, uns.generate_rotor(stackedrotor_file; pitch=stckd_pitch_low,
n=n_rotor, blade_r=r_rotor, CW=!CW_w, ReD=ReD,
verbose=verbose, v_lvl=v_lvl+2, xfoil=xfoil,
read_polar=stacked_read_polar,
data_path=data_path, plot_disc=false))
if verbose; println("\t"^(v_lvl+1)*"Generating second lower-stacked-rotor..."); end;
push!(stackedrotors_low, uns.generate_rotor(stackedrotor_file; pitch=stckd_pitch_low,
n=n_rotor, blade_r=r_rotor, CW=CW_w, ReD=ReD,
verbose=verbose, v_lvl=v_lvl+2, xfoil=xfoil,
read_polar=stacked_read_polar,
data_path=data_path, plot_disc=false))
else
for rotor in stackedrotors
push!(stackedrotors_low, rotor)
end
end
end
# ------------ MAIN WING ---------------------------------------------
# Generate wing
if verbose; println("\t"^(v_lvl+1)*"Generating main wing assembly..."); end;
# Middle section
pos_md_w = [0.0, md_w]
clen_md_w = [1/tr_w, md_w + (1/tr_w)*(1-md_w)]
twist_md_w = [twist_r_w, twist_r_w + md_w*(twist_t_w-twist_r_w)]
wing_md = vlm.complexWing(b_w, AR_w, ceil(Int, md_w*n_w), pos_md_w, clen_md_w, twist_md_w,
lambda_w*ones(1), gamma_w*ones(1);
symmetric=true, chordalign=0.0,
_ign1=true)
# Left section
pos_l_w = [0, -(1-md_w)] # NOTE: Here we define this wing section from right to left
clen_l_w = [1, clen_md_w[end]]
twist_l_w = [twist_t_w, twist_md_w[end]]
wing_L = vlm.complexWing(b_w, AR_w, ceil(Int, (1-md_w)*n_w/2), pos_l_w, clen_l_w,
twist_l_w, -lambda_w*ones(1), -gamma_w*ones(1);
symmetric=false, chordalign=0.0,
_ign1=true)
# Right section
pos_r_w = [0, (1-md_w)]
clen_r_w = [clen_md_w[end], 1]
twist_r_w = [twist_md_w[end], twist_t_w]
wing_R = vlm.complexWing(b_w, AR_w, ceil(Int, (1-md_w)*n_w/2), pos_r_w, clen_r_w,
twist_r_w, lambda_w*ones(1), gamma_w*ones(1);
symmetric=false, chordalign=0.0,
_ign1=true)
# Translate right and left sections to position
O_w_R = (md_w*b_w/2)*[0, 1, 0]
O_w_L = [1 0 0; 0 -1 0; 0 0 1]*O_w_R
vlm.setcoordsystem(wing_R, O_w_R, Im)
vlm.setcoordsystem(wing_L, O_w_L, Im)
# Winglets
winglet_R = vlm.simpleWing(b_wl, AR_wl, tr_wl, twist_r_wl, lambda_wl, gamma_wl;
twist_tip=twist_t_wl, n=n_wl, r=r_wl)
winglet_L = vlm.simpleWing(b_wl, AR_wl, tr_wl, twist_r_wl, lambda_wl, gamma_wl;
twist_tip=twist_t_wl, n=n_wl, r=r_wl)
# Translate winglets to position
O_wl_R = (b_w/2)*[0, 1, 0]
O_wl_R += ((1-md_w)*b_w/2)*[tan(lambda_w*pi/180), 0, tan(gamma_w*pi/180)]
O_wl_L = [1 0 0; 0 -1 0; 0 0 1]*O_wl_R
Oaxis_wl_R = gt.rotation_matrix(0.0, 0.0, 90.0)
Oaxis_wl_L = gt.rotation_matrix(0.0, 0.0, -90.0)
vlm.setcoordsystem(winglet_R, O_wl_R, Oaxis_wl_R)
vlm.setcoordsystem(winglet_L, O_wl_L, Oaxis_wl_L)
# Generate main-wing rotors (from right to left)
if add_rotors
if verbose; println("\t"^(v_lvl+2)*"Generating main-wing rotors..."); end;
O_rotor_w = [ # Position of each rotor
(ypos - md_w*b_w/2)*[tan(lambda_w*pi/180), 0, -tan(gamma_w*pi/180)] +
ypos*[0, 1, 0] +
[-(i in stacked ? stckd_xoc_offset : xoc_offset_main)*AR_w/b_w, 0, 0] +
[0, 0, (i in stacked ? stckd_zoc_offset*tan(gamma_w*pi/180) : 0)*AR_w/b_w]
for (i, ypos) in enumerate(y_pos_rotor_w)]
rotors_w = vlm.Rotor[] # Rotors get stored in these arrays
rotors_w_stacked_up = vlm.Rotor[]
rotors_w_stacked_low = vlm.Rotor[]
for i in 1:2*nr_w
right = i<=nr_w # Indicates which side of the wing
copy_rotor = i in stacked ? stackedrotors[1+i%2] : tiltrotors[1+i%2]
this_rotor = deepcopy(copy_rotor) # Alternates rotation orientation
this_O = O_rotor_w[ right ? i : nr_w-(i-nr_w-1)] # Chooses position
this_O = [1 0 0; 0 (-1)^!right 0; 0 0 1]*this_O # Places it in correct side
this_Oaxis = i in stacked ? gt.rotation_matrix(0.0, 90, 0.0) :
gt.rotation_matrix((-1)^(i%2==0)*main_outtilt, 0.0, 0.0)
# Place rotor in position
vlm.setcoordsystem(this_rotor, this_O, this_Oaxis; user=true)
# Rotate rotor to be tip-to-tip with others
vlm.rotate(this_rotor, (-1)^(!CW_w) * (i in stacked ? init_ori_stackedrotor : init_ori_rotor))
# Add the original polars that are not copied with deepcopy
this_rotor.airfoils = copy_rotor.airfoils
this_rotor._polars = copy_rotor._polars
this_rotor._polarroot = copy_rotor._polarroot
this_rotor._polartip = copy_rotor._polartip
if !(i in stacked)
push!(rotors_w, this_rotor)
else
push!(rotors_w_stacked_up, this_rotor)
# Generate lower rotor if this is a stacked rotor
copy_rotor = stackedrotors_low[ 1+(i+1*!stckd_corotating)%2 ]
this_rotor = deepcopy(copy_rotor)
# Place rotor in position
this_O += R_w*[0, 0, stckd_zoR_offset]
vlm.setcoordsystem(this_rotor, this_O, this_Oaxis; user=true)
# Rotate rotor to be tip-to-tip with others
vlm.rotate(this_rotor, (-1)^(!CW_w) * (init_ori_stackedrotor+stckd_phase))
# Add the original polars that are not copied with deepcopy
this_rotor.airfoils = copy_rotor.airfoils
this_rotor._polars = copy_rotor._polars
this_rotor._polarroot = copy_rotor._polarroot
this_rotor._polartip = copy_rotor._polartip
push!(rotors_w_stacked_low, this_rotor)
end
end
end
# Assemble fixed section of the wing (middle section + stacked rotors)
main_wing_fixed = vlm.WingSystem()
vlm.addwing(main_wing_fixed, "WingM", wing_md)
if add_rotors
for (i, rotor) in enumerate(rotors_w_stacked_up)
vlm.addwing(main_wing_fixed, "StackedRotorUp$i", rotor)
end
for (i, rotor) in enumerate(rotors_w_stacked_low)
vlm.addwing(main_wing_fixed, "StackedRotorLow$i", rotor)
end
end
# Assemble wing tip sections
main_wing_R = vlm.WingSystem()
vlm.addwing(main_wing_R, "Tip", wing_R)
vlm.addwing(main_wing_R, "Winglet", winglet_R)
main_wing_L = vlm.WingSystem()
vlm.addwing(main_wing_L, "Tip", wing_L)
vlm.addwing(main_wing_L, "Winglet", winglet_L)
# Assemble moving sections of the wing
main_wing_moving = vlm.WingSystem()
vlm.addwing(main_wing_moving, "WingR", main_wing_R)
vlm.addwing(main_wing_moving, "WingL", main_wing_L)
if add_rotors
for (i, rotor) in enumerate(rotors_w)
vlm.addwing(main_wing_moving, "Rotor$i", rotor)
end
end
# Align moving and fixed section with their pivot line
x_off_w = pivot_w*b_w/AR_w # offset to align with pivot line
O_off_w = [-x_off_w, 0.0, 0.0]
vlm.setcoordsystem(wing_md, O_off_w, Im)
for vlmwing in main_wing_moving.wings
if typeof(vlmwing)==vlm.Rotor
vlm.setcoordsystem(vlmwing, vlmwing._wingsystem.O + O_off_w,
vlmwing._wingsystem.Oaxis; user=false)
else
vlm.setcoordsystem(vlmwing, vlmwing.O + O_off_w, vlmwing.Oaxis)
end
end
# Place tilting sections at main-wing tip
O_mv = (md_w*b_w/2)*[tand(lambda_w), 0, tand(gamma_w)]
# Initial rotation of moving sections
Oaxis_wmv = gt.rotation_matrix(0.0, -init_ori, 0.0)
vlm.setcoordsystem(main_wing_moving, O_mv, Oaxis_wmv)
# Assemble main wing
main_wing = vlm.WingSystem()
vlm.addwing(main_wing, "Fixed", main_wing_fixed)
vlm.addwing(main_wing, "Moving", main_wing_moving)
# Position of main wing
O_w = [l_pos_w + x_off_w, 0, h_pos_w]
Oaxis_w = gt.rotation_matrix(0.0, 0.0, 0.0)
vlm.setcoordsystem(main_wing, O_w, Oaxis_w)
# ------------ TANDEM WING -------------------------------------------
if verbose; println("\t"^(v_lvl+1)*"Generating tandem wing assembly..."); end;
# Generate tandem wing
twing = vlm.simpleWing(b_tw, AR_tw, tr_tw, twist_r_tw, lambda_tw,
gamma_tw; twist_tip=twist_t_tw, n=n_tw, r=r_tw)
# Middle section
pos_md_tw = [-md_tw, 0.0, md_tw]
clen_md_tw = [md_tw + (1/tr_tw)*(1-md_tw), 1/tr_tw, md_tw + (1/tr_tw)*(1-md_tw)]
twist_md_tw = [twist_r_tw + md_tw*(twist_t_tw-twist_r_tw),
twist_r_tw, twist_r_tw + md_tw*(twist_t_tw-twist_r_tw)]
twing_md = vlm.complexWing(b_tw, AR_tw, ceil(Int, md_tw*n_tw), pos_md_tw,
clen_md_tw, twist_md_tw,
lambda_tw*ones(2), gamma_tw*ones(2);
symmetric=false, chordalign=0.0,
_ign1=true)
# Left section
pos_l_tw = [-1, pos_md_tw[1]]
clen_l_tw = [1, clen_md_tw[1]]
twist_l_tw = [twist_t_tw, twist_md_tw[1]]
twing_L = vlm.complexWing(b_tw, AR_tw, ceil(Int, (1-md_tw)*n_tw/2), pos_l_tw,
clen_l_tw, twist_l_tw,
lambda_tw*ones(1), gamma_tw*ones(1);
symmetric=false, chordalign=0.0,
_ign1=true)
# Right section
pos_r_tw = [pos_md_tw[end], 1]
clen_r_tw = [clen_md_tw[end], 1]
twist_r_tw = [twist_md_tw[end], twist_t_tw]
twing_R = vlm.complexWing(b_tw, AR_tw, ceil(Int, (1-md_tw)*n_tw/2), pos_r_tw,
clen_r_tw, twist_r_tw,
lambda_tw*ones(1), gamma_tw*ones(1);
symmetric=false, chordalign=0.0,
_ign1=true)
## Generate tandem-wing rotors (from right to left)
if add_rotors
if verbose; println("\t"^(v_lvl+2)*"Generating tandem-wing rotors..."); end;
O_rotor_tw = [ ypos*[tan(lambda_tw*pi/180), 1, tan(gamma_tw*pi/180)] +
[-xoc_offset_tandem*AR_tw/b_tw, 0, 0]
for ypos in y_pos_rotor_tw]
rotors_tw = vlm.Rotor[]
for i in 1:2*nr_tw
right = i<=nr_tw # Indicates which side of the wing
copy_rotor = tiltrotors[1+(i+(CW_tw!=CW_w))%2]
this_rotor = deepcopy(copy_rotor) # Alternates rotation orientation
this_O = O_rotor_tw[ right ? i : nr_tw-(i-nr_tw-1)] # Chooses position
this_O = [1 0 0; 0 (-1)^!right 0; 0 0 1]*this_O # Places it in correct side
this_Oaxis = gt.rotation_matrix(0, (-1)^(i%2==0)*(-1)^right*tandem_pitchtilt, 0)
# Place rotor in position
vlm.setcoordsystem(this_rotor, this_O, this_Oaxis; user=true)
# Rotates rotor to be tip-to-tip with others
vlm.rotate(this_rotor, (-1)^(!CW_tw) * init_ori_rotor)
# Add the original polars that are not copied with deepcopy
this_rotor.airfoils = copy_rotor.airfoils
this_rotor._polars = copy_rotor._polars
this_rotor._polarroot = copy_rotor._polarroot
this_rotor._polartip = copy_rotor._polartip
push!(rotors_tw, this_rotor)
end
end
# Assemble moving sections of the wing
tandem_wing_moving = vlm.WingSystem()
vlm.addwing(tandem_wing_moving, "WingR", twing_R)
vlm.addwing(tandem_wing_moving, "WingL", twing_L)
if add_rotors
for (i, rotor) in enumerate(rotors_tw)
vlm.addwing(tandem_wing_moving, "Rotor$i", rotor)
end
end
# Align moving and fixed section with their pivot line
x_off_tw = pivot_tw*b_tw/AR_tw # offset to align with pivot line
O_off_tw = [-x_off_tw, 0.0, 0.0]
vlm.setcoordsystem(twing_md, O_off_tw, Im)
for vlmwing in tandem_wing_moving.wings
if typeof(vlmwing)==vlm.Rotor
vlm.setcoordsystem(vlmwing, vlmwing._wingsystem.O + O_off_tw,
vlmwing._wingsystem.Oaxis; user=false)
else
vlm.setcoordsystem(vlmwing, vlmwing.O + O_off_tw, vlmwing.Oaxis)
end
end
# Initial rotation of moving sections
Oaxis_twmv = gt.rotation_matrix(0.0, -init_ori, 0.0)
vlm.setcoordsystem(tandem_wing_moving, zeros(3), Oaxis_twmv)
# Assemble tandem wing
tandem_wing = vlm.WingSystem()
vlm.addwing(tandem_wing, "FixedWing", twing_md)
vlm.addwing(tandem_wing, "Moving", tandem_wing_moving)
# Position of tandem wing
O_tw = [l_pos_tw + x_off_tw, 0, h_pos_tw]
Oaxis_tw = gt.rotation_matrix(0.0, 0.0, 0.0)
vlm.setcoordsystem(tandem_wing, O_tw, Oaxis_tw)
# ------------ FUSELAGE ----------------------------------------------
if verbose; println("\t"^(v_lvl+1)*"Generating fuselage..."); end;
# Generate fuselage
fuselage = generatefuselage_vahana(l_f; ncells=20)
# All grids get stored here
body = gt.MultiGrid(3)
gt.addgrid(body, "Fuselage", fuselage)
# Generate pylons of stacked rotors
if add_rotors
if verbose; println("\t"^(v_lvl+1)*"Generating pylons..."); end;
pylon_pos = 0.70
pylon_length = stckd_xoc_offset*AR_w/b_w * pylon_pos
for i in stacked
pylon = generatepylon(pylon_length; ncells=5)
right = i<=nr_w
this_O = O_rotor_w[ right ? i : nr_w-(i-nr_w-1)] # Chooses position
this_O = [1 0 0; 0 (-1)^!right 0; 0 0 1]*this_O # Places it in correct side
this_O += main_wing.O # Translates it with the wing
# Offsets it according to length
this_O += [1/3*0.5*pylon_pos, 0, 3*R_w*stckd_zoR_offset]
rotation = gt.rotation_matrix2(0, 0, 0)
gt.lintransform!(pylon, rotation, this_O)
gt.addgrid(body, "Pylon$i", pylon)
end
end
############################################################################
# DEFINE VEHICLE
############################################################################
# System of all FLOWVLM objects
system = vlm.WingSystem()
vlm.addwing(system, "MainWing", main_wing)
vlm.addwing(system, "TandemWing", tandem_wing)
# Tilting systems
tilting_systems = (main_wing_moving, tandem_wing_moving)
# Rotors grouped by systems with shared RPM control
if add_rotors
rotor_systems = (rotors_w, rotors_w_stacked_up, rotors_w_stacked_low, rotors_tw)
else
rotor_systems = ()
end
# System solved through VLM solver
vlm_system_m = vlm.WingSystem()
vlm.addwing(vlm_system_m, "letL", winglet_L)
vlm.addwing(vlm_system_m, "L", wing_L)
vlm.addwing(vlm_system_m, "middle", wing_md)
vlm.addwing(vlm_system_m, "R", wing_R)
vlm.addwing(vlm_system_m, "letR", winglet_R)
vlm_system_t = vlm.WingSystem()
vlm.addwing(vlm_system_t, "L", twing_L)
vlm.addwing(vlm_system_t, "R", twing_R)
vlm_system = vlm.WingSystem()
if add_wings
vlm.addwing(vlm_system, "MWing", vlm_system_m)
vlm.addwing(vlm_system, "TWing", vlm_system_t)
end
# All rotors
if add_rotors
rotors = vcat(rotors_w, rotors_w_stacked_up, rotors_w_stacked_low, rotors_tw)
end
# System that will shed a VPM wake
wake_system = vlm.WingSystem()
if add_wings
vlm.addwing(wake_system, "SolveVLM", vlm_system)
end
if add_rotors
if VehicleType==uns.VLMVehicle
for (i, rotor) in enumerate(rotors)
vlm.addwing(wake_system, "Rotor$i", rotor)
end
else
# Mute warnings regarding potential colinear vortex filaments. This is
# needed since the quasi-steady solver will probe induced velocities at the
# lifting line of the blade
uns.vlm.VLMSolver._mute_warning(true)
end
end
# Visualization grids that are rotated and translated along with the vehicle
grids = [body]
# Define vehicle
vehicle = VehicleType( system;
tilting_systems=tilting_systems,
rotor_systems=rotor_systems,
vlm_system=vlm_system,
wake_system=wake_system,
grids=grids
)
return vehicle
end
The function that defines the fuselage is given in the full example under examples/vahana/vahana_vehicle.jl