Example PRD

LPC20 stretch - a design that does not close

The starter with 2 h / 100 km: MADETOOL reports a diagnosed non-closure (BLOCKED).

Source (read-only): MADETOOL/tests/fixtures/PRD_LPC20_stretch.txt

# =============================================================================
#  MADETOOL - Product Requirements Document (PRD)                  format 1.7
# =============================================================================
#  INTEGRATION TEST FIXTURE: the starter PRD at revision G (2.0 h endurance,
#  100 km range), the set that does not close with the example data (R10-07).
#  Since release 1.0.0 the shipped starter (PRD.txt, revision H) asks 1.0 h and
#  50 km; this file keeps the stretch set as the non-closing test case of
#  test_long_diverged (expected: a diagnosed DIVERGED or BLOCKED, R9-18).
#  Data-file paths are relative to this fixtures folder.
#
#  Every value with  src = PLACEHOLDER  is an example, NOT customer data.
#  Values with src = "ALES-2 baseline (user)" come from an existing 20 kg
#  aircraft (3.5 m span, NACA 4412, V-tail, 12S pack) and must be confirmed.
#  The tool reports every placeholder in its validation summary.
#
#  HOW TO WRITE THIS FILE
#  ----------------------
#  [section]                                  groups keys
#  key  = value unit REF | attr = value ...   fixed value / target
#  key >= value unit REF | ...                requirement: must be AT LEAST
#  key <= value unit REF | ...                requirement: must NOT EXCEED
#  # ...                                      comment (to end of line)
#
#  value   : 12.5   3e-4   [300 200 150]   "quoted text"   WORD
#  unit    : case-sensitive, e.g. m km ft kg lb s min h m/s kt km/h W kW hp
#            Wh Wh/kg K degC deg % (full list: docs/02_PRD_SCHEMA.md)
#  REF     : airspeeds MUST state TAS | EAS | CAS | IAS
#            altitudes MUST state AGL | MSL (AGL is from site_elevation)
#  keyword : TBD  = not known yet (never treated as zero)
#            NONE = no limit / not applicable
#            AUTO = the tool sizes/estimates it
#            DEFAULT = use the model default (model options only)
#
#  Requirement attributes (after "|"):
#    type = HARD_LIMIT  must never be violated
#           MINIMUM     minimum acceptable capability; FAIL if not met
#           TARGET      desired value; deviation reported (tol = allowed deviation)
#           PREFERENCE  nice to have; ranks trade-study options
#    prio = 1 (highest) .. 5        src = where the number comes from
#    id   = "customer ID"           note = "free text"
#    Operating condition: alt = 1000 m MSL | CRUISE | SITE
#                         isa_dev = 15 K   or   oat = 35 degC
#                         config = CLEAN | TAKEOFF | LANDING
#    If no isa_dev/oat is given: alt = SITE uses site_isa_dev,
#    every other condition uses enroute_isa_dev.
#
#  Author: Syed Yasir Rehan Ali <yasir@alates.tr> | WhatsApp: +90-551-681-9256
# =============================================================================

[prd]
format_version = 1.7
revision       = "G"
date           = "2026-10-31"
author         = "Syed Yasir Rehan Ali <yasir@alates.tr>"
status         = DRAFT

[aircraft]
name             = "TEST-LPC20-STRETCH (starter PRD revision G: 2.0 h endurance, 100 km range)"
mission_role     = "ISR - EO/IR gimbal, day and night"
description      = "Integration test fixture: the starter's revision G set (2 h, 100 km), which does not close with the example data. Not a requirement set."
propulsion_code  = 1                     # 1..7  (docs/03_CODES.md)
propulsion_label = BATTERY_ELECTRIC      # optional cross-check of the code
vtol_code        = 1                     # 0..5
vtol_label       = LIFT_PLUS_CRUISE      # optional cross-check of the code

[configuration]
layout                    = CONVENTIONAL
tail                      = V_TAIL
wing_position             = HIGH
fuselage                  = POD_AND_BOOM
cruise_propulsor_position = PUSHER
n_cruise_propulsors       = 1
landing_gear              = SKIDS

[payload]
mass_max    >= 3.0 kg          | type = MINIMUM | prio = 1 | src = PLACEHOLDER
mass_normal =  2.0 kg          | src = PLACEHOLDER
volume      >= TBD             | type = MINIMUM | prio = 3 | src = PLACEHOLDER
dims        =  [250 180 160] mm  | src = PLACEHOLDER
power_avg   =  30 W            | src = PLACEHOLDER
power_peak  =  60 W            | src = PLACEHOLDER
cg_offset   =  TBD
mount       =  BELLY_GIMBAL
interface   =  "12 V power, Ethernet video, UART control (example)"
droppable   =  NO

[performance]
# Endurance / range: normal payload, take-off to landing, reserves EXCLUDED.
endurance       >= 2.0 h       | type = MINIMUM | prio = 1 | src = PLACEHOLDER
range           >= 100 km      | type = MINIMUM | prio = 2 | src = PLACEHOLDER
speed_max_level >= 30 m/s TAS  | alt = CRUISE | isa_dev = 0 K | type = MINIMUM | prio = 2 | src = PLACEHOLDER
speed_cruise    =  22 m/s TAS  | alt = CRUISE | isa_dev = 0 K | type = TARGET | tol = 5 % | prio = 2 | src = PLACEHOLDER
speed_stall     <= 15 m/s EAS  | config = CLEAN | type = TARGET | tol = 1 m/s | prio = 3 | src = PLACEHOLDER
altitude_max    >= 3000 m MSL  | isa_dev = 0 K | type = MINIMUM | prio = 2 | src = PLACEHOLDER
altitude_cruise =  800 m AGL   | isa_dev = 0 K | type = TARGET | tol = 100 m | prio = 2 | src = PLACEHOLDER
climb_rate      >= 2.5 m/s     | alt = SITE | type = MINIMUM | prio = 3 | src = PLACEHOLDER

[constraints]
mtow          <= 20 kg             | type = HARD_LIMIT | prio = 1 | src = "ALES-2 baseline (user) - confirm"
wingspan      <= 3.5 m             | type = HARD_LIMIT | prio = 1 | src = "ALES-2 baseline (user) - confirm"
length        <= 2.2 m             | type = PREFERENCE | prio = 4 | src = PLACEHOLDER
height        <= NONE              | type = PREFERENCE | prio = 5 | src = PLACEHOLDER
transport_box =  [1400 500 450] mm   | src = PLACEHOLDER
assembly_time <= 10 min            | type = PREFERENCE | prio = 4 | src = PLACEHOLDER

[launch_recovery]
takeoff_method  = VTOL               # VTOL RUNWAY HAND CATAPULT BUNGEE ROCKET_ASSIST VEHICLE_ROOF
recovery_method = VTOL               # VTOL RUNWAY BELLY PARACHUTE NET DEEP_STALL
# With recovery_method = RUNWAY (format 1.3) also give these three, with their source:
#   approach_angle   = <value> deg | src = <source>   approach (glide) angle from the obstacle height
#   braking_friction = <value>     | src = <source>   wheel-braking friction; NONE = no wheel brakes
#   free_roll_time   = <value> s   | src = <source>   touchdown to full braking
# and, for RUNWAY take-off or recovery, environment.runway_surface (PAVED GRASS GRAVEL DIRT)
# and environment.obstacle_height.
landing_speed_schedule = MILITARY    | src = "user decision 2026-10-28 (D-22)" | note = "approach 1.2, flare 1.15, touchdown 1.1 x V_stall (runway landing only)"

[environment]
site_elevation  = 100 m MSL     | src = PLACEHOLDER
site_isa_dev    = 20 K          | src = PLACEHOLDER | note = "hot day: ISA+20 K = 35 degC at sea level"
enroute_isa_dev = 0 K           | src = PLACEHOLDER
wind_mean       = 8 m/s         | src = PLACEHOLDER
wind_gust       = 12 m/s        | src = PLACEHOLDER
crosswind       = 6 m/s         | src = PLACEHOLDER | note = "if omitted, wind_mean is used as crosswind"
runway_length   = NONE
runway_surface  = NONE
isa_dev_cold    = -20 K         | src = PLACEHOLDER | note = "cold design day: structural lift-thrust case at sea level (PE)"

[vtol]
lift_energy         = SHARED_BATTERY  # SHARED_BATTERY DEDICATED_BATTERY GENERATOR
n_lift_rotors       = 4
lift_rotor_diameter = AUTO       | note = "largest rotor that fits with rotor_clearance (disk_loading_max is NONE); revision E and older: 0.56 m (22 in)"
rotor_clearance     = 0.05 m     | src = PLACEHOLDER | note = "plan-view clearance of the rotor disks (rotor-fit rule)"
hover_tw_min        >= 1.5      | type = HARD_LIMIT | prio = 1 | src = PLACEHOLDER | note = "max lift thrust / weight, site hot day"
disk_loading_max    <= NONE     | type = PREFERENCE | prio = 5 | src = PLACEHOLDER
hover_tw_oei_min    >= NONE     | type = PREFERENCE | prio = 5 | src = PLACEHOLDER | note = "rotor-out hover not required for this 4-rotor layout"

[mission]
name                 = "ISR endurance / range"
cruise_speed_policy  = FIXED            # FIXED uses performance.speed_cruise
loiter_speed_policy  = BEST_ENDURANCE
climb_rate           = 2.5 m/s          | src = PLACEHOLDER
descent_rate         = 2.0 m/s          | src = PLACEHOLDER
vertical_climb_rate   = 2.0 m/s         | src = PLACEHOLDER
vertical_descent_rate = 1.0 m/s         | src = PLACEHOLDER
headwind             = 0 m/s            # 0 = still-air range
hover_time_takeoff   = 30 s             | src = PLACEHOLDER
hover_time_landing   = 45 s             | src = PLACEHOLDER
hover_height         = 20 m AGL         | src = PLACEHOLDER
transition_time_fwd  = 15 s             | src = PLACEHOLDER
transition_time_back = 20 s             | src = PLACEHOLDER
custom_profile       = NO
# custom_payload     = NORMAL           # NORMAL | MAX - required when custom_profile = YES

[mission.custom]
# Read only when mission.custom_profile = YES. Example profile:
# seg01 = VTOL_TAKEOFF    | time = 30 s | height = 20 m AGL   (climb at vertical_climb_rate, then hover)
# seg02 = TRANSITION_FWD  | time = 15 s
# seg03 = CLIMB           | to = CRUISE | rate = 2.5 m/s
# seg04 = CRUISE          | distance = 30 km | speed = CRUISE
# seg05 = LOITER          | time = 90 min | speed = BEST_ENDURANCE
# seg06 = CRUISE          | distance = 30 km | speed = BEST_RANGE
# seg07 = DESCENT         | to = 20 m AGL | rate = 2 m/s
# seg08 = TRANSITION_BACK | time = 20 s
# seg09 = VTOL_LANDING    | time = 45 s | height = 20 m AGL   (hover, then vertical descent)

[reserves]
# All components are added: loiter time + divert distance + extra hover
# (flown level at the reserve altitude / hover height)
# + contingency_fraction of the trip energy/fuel; then energy_fraction of the
# usable energy/fuel must still remain at landing.
# placement: HOLD_BEFORE_LANDING = hold at the destination before the final descent
# (physically consistent; the default of format 1.5 when the key is absent, decisions
# R2-07, R3-09, R5-04) | APPENDED = after landing (legacy; the climb to the reserve
# altitude is not flown).
time            = 10 min        | src = PLACEHOLDER
altitude        = 100 m AGL     | src = PLACEHOLDER
distance        = 0 km          | src = PLACEHOLDER
hover_time      = 30 s          | src = PLACEHOLDER
energy_fraction      = 10 %     | src = PLACEHOLDER
contingency_fraction = 5 %      | src = PLACEHOLDER
placement            = HOLD_BEFORE_LANDING

[component.battery]
chemistry            = LI_ION
pack_specific_energy = 200 Wh/kg  | src = PLACEHOLDER
usable_fraction      = 90 %       | src = PLACEHOLDER
eol_factor           = 90 %       | src = PLACEHOLDER
cell_voltage_nominal = 3.6 V      | src = PLACEHOLDER
series_cells         = 12         | src = "ALES-2 baseline (user): 12S"
capacity             = AUTO       # ALES-2 baseline uses 32 Ah; set it for FIXED_MTOW runs
max_c_rate_cont      = AUTO
max_c_rate_peak      = AUTO

[component.cruise_motor]
mass           = AUTO
power_max_cont = AUTO
kv             = AUTO
efficiency_max = AUTO

[component.cruise_prop]
diameter          = AUTO
pitch             = AUTO
blades            = 2
efficiency_cruise = AUTO

[component.lift_motor]
mass           = AUTO
power_max_cont = AUTO
kv             = AUTO
efficiency_max = AUTO

[component.lift_rotor]
blades          = 2
figure_of_merit = 0.60          | src = PLACEHOLDER
mass            = AUTO

[component.esc]
efficiency = AUTO

[component.avionics]
mass  = 0.8 kg                  | src = PLACEHOLDER
power = 25 W                    | src = PLACEHOLDER

[component.airfoil_wing]
name            = "NACA 4412"   | src = "ALES-2 baseline (user)"
data_file       = ""
cl_max_2d       = AUTO
cd_min_2d       = AUTO
cm_ac           = AUTO
alpha_zero_lift = AUTO

[data_files]
# External data files owned by the specialist modules; paths are relative to
# this PRD's folder. "" = not used. A value may be given in a data file OR in
# [component.*], not both.
propulsion_components = "../../data/propulsion/example_components_LPC20.txt"  # PE format; ILLUSTRATIVE placeholders
aero_data             = "../../data/aero/example_aero_data_LPC20.txt"         # AERO format; SYNTHETIC example
layout                = "../../data/layout/example_layout_LPC20.txt"          # MSC format; placeholders

[design_choices]
mtow_guess      = 18 kg         | note = "iteration start value only"
wing_loading    = AUTO
aspect_ratio    = AUTO
taper_ratio     = 0.6           | src = PLACEHOLDER
sweep_c4        = 0 deg
dihedral        = 2 deg         | src = PLACEHOLDER
thickness_ratio = 12 %          | note = "consistent with NACA 4412"
tail_volume_h   = AUTO
tail_volume_v   = AUTO
power_loading   = AUTO
# Design-point rule D-07 (applied to the AUTO values above; user decision 2026-10-28):
wing_loading_margin  = 2 %      | src = "user decision 2026-10-28 (D-07)" | note = "W/S 2 % below the highest feasible W/S"
power_loading_margin = 5 %      | src = "user decision 2026-10-28 (D-07)" | note = "P/W 5 % above the envelope"
aspect_ratio_max     = 15       | src = "user decision 2026-10-28 (D-07)" | note = "AR = min(b_max^2/S, 15)"
wing_tip_deflection_max  = 15 %   | src = "user decision 2026-10-28 (D-23)" | note = "of the semispan at limit load; beyond it a stiffness analysis is needed"
hover_oei_control_margin = 5 %    | src = "user decision 2026-10-28 (D-24)" | note = "rotor-out hover, 6 or more lift rotors"
oei_bank_max             = 5 deg  | src = "user decision 2026-10-28 (D-25)" | note = "engine-out trim, laterally offset cruise propulsors (14 CFR 23.149(a) value)"
# prop_ground_clearance  = 0.10 m   # format 1.6: aircraft on wheels only (propeller disc to ground); not used by this VTOL
# wing_stiffness_sizing  = CHECK    # format 1.7: CHECK (default) only checks the tip deflection; SIZE grows the spar caps to meet it (open user decision U-12)

[stability]
static_margin_min >= 5 %        | type = HARD_LIMIT | prio = 1 | src = PLACEHOLDER
static_margin_max <= 20 %       | type = PREFERENCE | prio = 4 | src = PLACEHOLDER

[loads]
# PART23_PRE_A64 = 14 CFR Part 23 normal category before Amendment 23-64: public
# reference values only, NOT a UAS airworthiness requirement. For STANAG 4671 /
# STANAG 4703 / USER, enter every value (AUTO is not allowed).
basis            = PART23_PRE_A64
n_limit_pos      = AUTO
n_limit_neg      = AUTO
factor_of_safety = 1.5          | src = PLACEHOLDER | note = "14 CFR 23.303 (pre-Amdt 23-64) uses 1.5 for manned aircraft; confirm for this UAS"
gust_ude_vc      = AUTO
gust_ude_vd      = AUTO

[manufacturing]
structure_material = CFRP_GFRP
process            = VACUUM_INFUSION
max_part_length    <= 1.8 m     | type = HARD_LIMIT | prio = 2 | src = PLACEHOLDER | note = "mould / oven size"

[classification]
dod_group          <= 2         | type = HARD_LIMIT | prio = 1 | src = PLACEHOLDER
dod_table          = DOD_UAS_GROUPS
civil_jurisdiction = "Turkey (SHGM) - informational only; civil rules are separate inputs"

[model]
sizing_mode             = SIZE_TO_MISSION   # or FIXED_MTOW (uses constraints.mtow)
fidelity_default        = 2                 # 1 statistical, 2 semi-empirical, 3 user/external data
fidelity_sizing         = DEFAULT
fidelity_aero           = DEFAULT
fidelity_drag           = DEFAULT
fidelity_propulsion     = DEFAULT
fidelity_mass           = DEFAULT
fidelity_stability      = DEFAULT
fidelity_performance    = DEFAULT
allow_fidelity_fallback = NO
allow_generic_estimates = NO           # YES = labelled generic estimates when component data are missing
iter_max                = 50
iter_tol                = 1e-4
iter_relax              = 0.5
mass_margin             = 10 %         | src = PLACEHOLDER | note = "empty-mass growth margin"
ceiling_roc_min         = 100 ft/min   | note = "service-ceiling definition; confirm convention"
report_units            = SI_PLUS_US
output_dir              = "out"
make_plots              = NO
timestamp_outputs       = YES
debug                   = NO

[trade]
enable    = NO
parameter = "design_choices.aspect_ratio"
values    = [10 12 14 16]
metric    = MTOW
LPC20 stretch - a design that does not close | MADETOOL by ALATES