THE UNIVERSITY OF QUEENSLAND

Bachelor of Engineering Thesis

Fixed-Wing UAV Airframe Design and Validation

Student Name: Timothy Brown Course Code: MECH4500 Supervisor: Dr Ingo Jahn Submission Date: 25 October 2018

A thesis submitted in partial fulfilment of the requirements of the Bachelor of Engineering Degree in Mechanical and Aerospace Engineering

UQ Engineering

Faculty of Engineering, Architecture and Information Technology Acknowledgements

Firstly, I would like to express my gratitude to my supervisor, Dr. Ingo Jahn for allowing me to undertake this thesis. I am also grateful for the consistent help and guidance he has provided over the course of the project, as both his knowledge and wisdom know no insurmountable obstacle

I would like to thank my parents for their constant support during over the course of the project, with many long days and sleepless nights supported by their continual efforts.

I would also like to extend my thanks to Matthew Miotto and Christopher Voller. Their continual willingness to listen to and help solve problems over the long time I have known them cannot be understated, with much beneficial knowledge often gained as a result of their insights.

I would also like to thank the lecturers and tutors who have helped me over the course of my time at the university, whose continual efforts to further the knowledge of others has allowed me to grow my skillset and hone my skills.

Finally, I would like to acknowledge the friends that I have known for years, and those I have made during my time at university. These last four years have certainly been made much more interesting with everyone around, and their continual support often provides strength in times of hardship.

ii Abstract

In recent years, UAVs have become widely adopted in numerous fields. However, the costs associated with designing and building UAVs, even for hobbyists, are prohibitively expensive. A free tool that could enable the rapid preliminary design, optimisation and feasibility estimation of a vehicle would prove to be very useful for reducing the cost of entry of UAVs.

Simulation software was created based upon research conducted into the performance of UAVs in the areas of aerodynamics, engine and propeller performance. This software has the ability to simulate a large number of designs quickly, as well as conducting automatic sensitivity analyses and optimisation processes for a range of designs and missions (see Appendix U for a link to the software).

Validation of the simulation software was conducted in three main steps. Firstly, real UAVs were imported into the software and tested. Secondly, an optimisation process was conducted to analyse the results provided. Finally, off-design analyses were conducted for the optimised design and mission to investigate the variations in performance.

The real UAVs were found to be in good agreement with their simulated counterparts, especially given the assumptions made. The results obtained from the optimisation and off-design analyses were also in-line with the results predicted by literature, validating the correct functionality and accuracy of the simulation software. Additional complex combi- nations of effects were also found to arise during operation, providing further validation for the simulation software.

Overall, the simulation software created has large potential for future improvements while showing good validity and accuracy at its current iteration. It is able to provide insight into both simple and complex effects associated with the aerodynamics and engine/pro- peller performance of a UAV, and will serve as a useful platform to build upon in the future. Therefore, through the development of the capability to automatically simulate and optimise UAV designs and insight into the performance of fixed-wing UAVs, the accessibility of UAV design has been expanded.

iii Table of Contents

Acknowledgements ii

Abstract iii

Table of Contents iii

List of Tables vii

List of Figures viii

Nomenclature 1

1 Introduction 2 1.1 Project Outline ...... 3 1.2 Scope ...... 4 1.3 Objectives ...... 5

2 Literature Review 6 2.1 Past UAVs ...... 6 2.2 Alternate Design and Simulation Options ...... 7 2.3 Wing Parameters ...... 9 2.4 Propulsion ...... 15 2.5 Fuselage Data Source ...... 17 2.6 Mass Data Sources ...... 18

3 Methodology 19 3.1 Simulation Scope ...... 19 3.2 Equations of Flight ...... 20 3.3 Simulation Creation ...... 22 3.4 Simulation Data Flow ...... 23 3.5 Choices Made ...... 26

4 Validation 29 4.1 Performance of Real UAVs ...... 29 4.1.1 Limitations of Validation ...... 29 4.1.2 MQ-1B Predator ...... 30 4.1.3 Aerosonde ...... 37 4.1.4 ScanEagle ...... 43 4.1.5 Overall Real UAV Performance Analysis ...... 47 4.2 Example Design Process ...... 48 4.2.1 Pre-Simulation ...... 48 4.2.2 Optimisation Process ...... 50

iv 4.2.3 Final Results ...... 56 4.3 Off-Design Performance ...... 58 4.3.1 Design Variations ...... 58 4.3.2 Mission Variation ...... 67

5 Discussions and Recommendations 71 5.1 Trends Observed ...... 71 5.2 Problems Encountered ...... 74 5.3 Validity ...... 76 5.3.1 Performance of Real UAVs ...... 76 5.3.2 Example Design Process ...... 77 5.3.3 Off-Design Performance ...... 77 5.3.4 Overall Validity ...... 78 5.4 Future Potential ...... 79 5.5 Recommendations ...... 80

6 Conclusions 82 6.1 Contributions ...... 82

Appendices 88

A Example of the Effect of Wing Position 88

B Effective Flow Velocity Over a Swept Wing 88

C Supersonic Flow Over a Wing 89

D Example of the Effect of Wing Sweep 89

E Dutch Roll 90

F Effect of Wing Dihedral on Lateral Stability 91

G Wing Twisting 91

H Effects of Leading and Trailing Edge Flaps and Slots 92

I Effect of Wing Taper on Lift Distribution and Local Coefficient of Lift 93

J Variable-Pitch Propeller Performance Curves 94

K Code Description 95

L Forces on an Airbourne Fixed-Wing UAV 96

M Spherically Blunt Tangent-Ogive Nose Projectile 96

v N MQ-1B Dimensions 97

O MQ-1B Discretization 97

P Aerosonde Discretization 98

Q ScanEagle Discretization 98

R Example Design Process Mission 99

S Example Design Process Baseline Design 99

T Off-Design Mission Variation Mission File 100

U Simulation Code 101 U.1 Angsolver ...... 101 U.2 Batch ...... 101 U.3 Cogen ...... 103 U.4 Compiler ...... 105 U.5 Controlgen ...... 105 U.6 Controller ...... 106 U.7 Code: Convert ...... 110 U.8 Csolver ...... 111 U.9 Designparam ...... 111 U.10 Efficientflight ...... 113 U.11 Enviro ...... 115 U.12 Interpos ...... 116 U.13 Ldgen ...... 120 U.14 Massfinder ...... 121 U.15 Missionpath ...... 123 U.16 Resultsprocessing ...... 124 U.17 Sensitivity ...... 129 U.18 Side ...... 134 U.19 Tables ...... 135

vi List of Tables

4.1.1 MQ-1B physical and performance characteristics...... 30 4.1.2 Performance characteristics of the real and simulated MQ-1B...... 31 4.1.3 Aerosonde physical and performance characteristics...... 37 4.1.4 Performance characteristics of the real and simulated Aerosonde...... 37 4.1.5 ScanEagle physical and performance characteristics...... 43 4.1.6 Performance characteristics of the real and simulated ScanEagle...... 44 4.2.1 Optimised design parameters...... 56 4.3.1 Results from the off-design design variation analysis...... 58 K.1 Description of modules used within the simulation...... 95

List of Figures

3.4.1 Flowchart for data within the simulation...... 23 4.1.1 MQ-1B combined efficiency performance map...... 32 4.1.2 MQ-1B propeller efficiency map...... 32 4.1.3 MQ-1B lift/drag ratio performance map...... 33 4.1.4 MQ-1B engine power performance map based on craft mass and angle of attack...... 35 4.1.5 MQ-1B engine power performance map based on craft mass and velocity. . 35 4.1.6 Aerosonde performance map based on craft angle of attack and mass. . . 40 4.1.7 Aerosonde performance map based on craft velocity and mass...... 40 4.1.8 Aerosonde performance map based on craft velocity and angle of attack. . 41 4.1.9 ScanEagle performance map based on craft angle of attack and mass. . . . 45 4.1.10 ScanEagle performance map based on craft velocity and mass...... 45 4.1.11 ScanEagle performance map based on craft angle of attack and velocity. . 46 4.2.1 Results of the first simulation (fuselage only)...... 51 4.2.2 Results of the second simulation (fuselage only)...... 52 4.2.3 Results of the third optimisation (wings only)...... 53 4.2.4 Results of the fourth optimisation (wings only)...... 54 4.2.5 Results of the fifth optimisation (wings and fuselage)...... 55 4.3.1 Performance map of the ”big fuselage” design...... 59 4.3.2 Performance map of the ”small fuselage” design...... 60 4.3.3 Performance map of the ”big wing” design...... 61 4.3.4 Performance map of the ”small wing” design...... 62 4.3.5 Lift-to-drag ratio of the NACA 4510 airfoil...... 63 4.3.6 Performance map for the ”heavy” design...... 64 4.3.7 Performance map of the ”light” design...... 65 4.3.8 Flight parameters over the course of a mission...... 67 4.3.9 Lift-to-drag ratio of the vehicle at various angles of attack...... 68

vii A.1 Effects of wing position on side-slip stability...... 88 B.1 Effective flow over the chord of a swept wing...... 88 C.1 Critical flow over an airfoil...... 89 D.1 Effect of wing sweep on yawed flight...... 89 E.1 Diagram of a Dutch roll...... 90 F.1 Effect of wing dihedral on rolling and sideslip stability...... 91 G.1 Geometric and aerodynamic twisting...... 91 H.1 Effects of leading and trailing edge flaps and slots...... 92 I.1 Total lift generated along a wing for various tapers...... 93 I.2 Local lift coefficient along a wing for various tapers...... 93 J.1 Propeller efficiency at varying advance ratios and blade angles...... 94 L.1 Forces on a fixed-wing UAV in flight...... 96 M.1 Spherically blunt tangent-ogive nose projectile...... 96 N.1 Dimensions of the MQ-1B Predator...... 97

viii Nomenclature

α Angle of attack (deg) β Inclination of craft (deg) (θ + α) λ Taper ratio ρ Density (kg/m3) θ Flight climb angle (deg) ϕ Sweep of the 25% chord line (deg) A Reference area (m2)

AR Aspect ratio

CD Coefficient of drag

CL Coefficient of lift

CQ Coefficient of torque

CT Coefficient of thrust d Distance (m) D Propeller diameter (m) e Wing efficiency factor

FL Lift force (N)

FD Drag force (N)

FT Thrust force (N) g Acceleration due to gravity (≈ 9.8m/s) V J Advance ratio ( ) nD m Mass (kg) m˙ Fuel mass flow rate (kg/sec) M Mach number n Shaft rotation speed (Hz) P Power (W) q Dynamic pressure (Pa) Q Torque (Nm)

Rex Positional Reynolds number t Time (s) V Flight velocity (m/s)

1 1 Introduction

In recent decades, unmanned aerial vehicles (UAVs) have emerged and rapidly become a cornerstone in a large number of applications, ranging from military applications (such as the MQ- family of drones, including the infamous MQ-1 Predator drone [74]), to search and rescue [2] and goods delivery [3]. Given the lack of human passengers, UAVs are able to be smaller and lighter than an equivalent manned aircraft, with the added benefit of complete safety for the remote pilot. In addition, one remote pilot can control potentially hundreds of UAVs at a time, given their ability to operate near- or completely- autonomously. However, given the wide range of current applications, as well as the large number of potential applications for UAVs, designs are mostly imitations of other previously-established designs in order to reduce development costs, such as the modern quadcopter drone.

Any design that isn’t simply an imitation of a predecessor requires a full design from the ground up, complete with personalized simulation and testing. As a result, the costs associated with designing and building new UAVs are still exorbitantly high, such as the US$10 billion program cost and US$131 million unit cost for the RQ-4 Global Hawk [72], a successor to the MQ-1 Predator. In addition, commonly-used and highly-recommended design and simulation software is often lacking in features, prohibitively expensive or targeted specifically for professional use only (see Section 2.2).

A system that can accept a wide range of designs and determine their feasibility for a given mission would be highly valuable, as it would reduce the complexity of testing, and reduce the cost to design a UAV, allowing them to become cheaper and more common- place. Despite the more controversial uses of UAVs, such as military attacks, the positive applications of drones greatly outweigh their negatives, especially in life-saving fields such as search and rescue. Reducing the cost of entry and enabling one pilot to control a large number of drones for the cost of one aircraft would allow search and rescue teams to scour much larger areas in much less time, greatly improving the odds of finding their target (be it a person or a vehicle). As an example, Malaysian Airlines flight MH-370 has still yet to be found after disappearing on March 8, 2014. If swarms of long-range autonomous drones were able to be deployed immediately following its disappearance, as opposed to the manned aircraft and ships that were sent to the search area, the odds of finding the plane and its passengers would have been significantly greater, potentially saving the lives of the 239 passengers and crew.

2 1.1 Project Outline

The work of this thesis consists of a number of steps that were taken in order to facilitate the completion of the thesis. These steps are organised in the order that they were undertaken over the course of the project, and are outlined below:

Section 1 is the introduction to the thesis, firstly outlining the background and motivation for the thesis. The project outline is presented, followed by the thesis scope and objectives.

Section 2 is the literature review. Three particular past and present UAVs are presented that are elaborated on during validation. Alternate aircraft design and simulation tools are also examined. Next, wing parameters are analysed in order to determine their ef- fects on the performance of a UAV, alongside the performance of engines and propellers. Where relevant, the sources of the information used within the simulation are outlined (specifically the wing and fuselage aerodynamics, engine and propeller performance and mass data). It is worth noting that the data used for the simulation is far from exhaustive, but was used predominantly to provide representative values and validate the operation of the simulation. Since the simulation is designed to easily accept user-provided data, it was not deemed necessary to initially model a large range of geometries.

Section 3 is the methodology for the simulation creation. First, the scope of the simulation is defined. Next, the underlying equations for equilibrium flight are presented. The simulation creation process is then briefly outlined, followed by an outline of the full simulation code structure and a brief description of the data flow. This section is then concluded by an overview of important choices made during the creation of the simulation and their justifications.

Section 4 is the validation of the simulation. Firstly, the three UAVs presented in the literature review were simulated in order to determine if their performance matched their real-life counterparts. Next, an example design cycle was conducted, in order to validate the capability of the simulation to optimise a design and provide a reasonable solution. The validation is concluded with an off-design performance analysis, consisting of a design variation analysis, where the effects of fixed variations on an optimised design are exam- ined, followed by a mission variation analysis, where the performance of an optimised design is examined for a mission other than the one it was optimised for.

Section 5 is the discussion and recommendations section. The trends observed over the course of the project are outlined, followed by the problems encountered. Next, the overall validity of the simulation is discussed. The future potential of the simulation is then outlined, ending with recommendations for any future work.

Section 6 outlines the conclusions of the project and comments on whether the project met its assigned goals, and also provides an outline of the contributions made.

3 1.2 Scope

This thesis focuses on determining whether the performance of a UAV (in terms of aero- dynamic, engine and propeller performance) is capable of allowing it to complete a specific mission whilst following a set of rules during flight. The most basic example of this would simply be examining if a UAV is capable of flying a set distance whilst minimising its fuel consumption. As such, the scope of this thesis focuses predominantly on the aerodynam- ics, with the engine and propeller performance information being limited based on a lack of information available. Additionally, as one of the goals of the thesis is to have a method of simulating UAV performance with the capability to be built upon in the future, some features have been left out of scope for this preliminary iteration of the simulation.

The parameters considered in scope for the thesis as a whole are outlined below. Note that more detailed parameters are provided in the methodology (Section 3) for the parameters directly relevant to the simulation, as the parameters presented here are for the project as a whole. • Wing aerodynamics (effects of geometry on lift and drag, finite wing effects).

• Fuselage aerodynamics (lift and drag, skin friction).

• Engine performance (gasoline-powered piston engines only).

• Propeller performance. (fixed-pitch propellers only).

• Mass of wings, fuselage, engine, payloads and fuel. Conversely, the parameters that were deemed out of scope of the thesis are outlined below. • On-board electronics (completely out of scope).

• Complex mission requirements (custom cost functions, environmental parameters and waypoints can be defined).

• 6-axis flight (5-axis flight is incorporated; no vehicle rolling).

• Relative positioning of UAV components (completely out of scope).

• Controllability of the craft (control surfaces, design balancing). By intentionally limiting the scope of the thesis, a less complex and faster-running sim- ulation can be created. As long as the data used is accurate, this will still facilitate the completion of the thesis objectives. The simulation will also still provide meaningful results, since as long as the input data is correct, the aerodynamic performance of the design will be accurate enough for a meaningful design feasibility estimate, after which more detailed design can be undertaken by hand or other software to determine design specifics (such as the actual electronics used on-board and the positioning of the compo- nents relative to each other), after having fast-tracked the feasibility stage of the design process.

4 1.3 Objectives

There are a number of objectives for this thesis. The first objective is to develop the capability to automatically simulate the performance of a UAV over the course of a mission to determine its feasibility. The second is to develop the capability to automatically optimise a design based on a given set of criteria. The third is to gain insight into the performance of fixed-wing UAVs and understand trends in design and performance by analysing a range of designs over a range of conditions. The final objective is to validate the methods used for the first three objectives, by investigating the performance of real UAVs in the simulation, conducting an example design cycle to determine if the results are logical and in-line with what is expected from literature, and examining the effects of variations in an optimised design or mission on the vehicle’s performance to determine if the results are as expected. These objectives culminate to the outcome of developing an open-source tool that is capable of automatically simulating and optimising a design for a given mission.

5 2 Literature Review

Given the amount of research that has been conducted relating to aircraft design and performance in the past, as well as the goals of the thesis being to gain knowledge and create a simulation which can be used to generate new insight, the research conducted serves less to identify current gaps in the wider knowledge of aircraft design, and more to provide a basis of information from which designs can be generated and a simulation can be created.

2.1 Past UAVs

Three main UAVs have been examined for the purpose of this thesis. All three UAVs typically serve as high-endurance and long-range craft with varying payload capacities. These three UAVs are the General Atomics MQ-1B Predator, Textron Systems Aerosonde, and the Insitu ScanEagle. These UAVs were chosen as they all fit into the role of high-endurance, fixed-wing UAVs, while each of the UAVs is a different size and weight, which will allow validation of the simulation across a range of different designs. The specifications of these UAVs are elaborated in Section 4.1.

The MQ-1B was first created in 1994 as a reconnaissance platform and flew its first mis- sions in 1995 [77]. The MQ-1B has a maximum range of approximately 1240 kilometres, a maximum endurance of approximately 24 hours, and a maximum payload of 204 kilograms (approximately 20% of its maximum takeoff weight) [28].

The first recorded flight of the Aerosonde was in 1997, with the achievement of the first crossing of the North Atlantic by a robotic aircraft being taken by the Aerosonde in 1998 [10]. The Aerosonde can carry a payload of up to 4.5 kilograms (25% of its maximum takeoff weight) [43] with a range of up to 3000 kilometres and endurance of 26 hours unladen [58].

The ScanEagle was first created in 2002 as a portable, long range reconnaissance platform [12]. It can carry a maximum combination of fuel and payload of up to 6 kilograms (approximately 33% of its maximum takeoff weight) [48], with an endurance of over 24 hours [42] and range of 1500 kilometres [41].

6 2.2 Alternate Design and Simulation Options

ADS (Aircraft Design Software) is a design and simulation tool created by Didier Breyne, which advertises itself as having different options to appeal to different target groups [13]. The cheapest version of ADS costs $60 USD, while the most expensive version costs $1147 USD. All versions come with a yearly maintenance fee of 20% of the purchase price, providing the latest program version and databases. The cheapest version of ADS locks the user out of some modules, essentially leaving the user with design modules but no simulation or analysis options, which require a more expensive version to be purchased (the next cheapest version is $225 USD, which includes an analysis module but doesn’t feature wing optimisation). Unlocking all features (including wing optimisation) requires the most expensive version be purchased. Therefore, while ADS is a promising option in terms of program breadth, the price necessary to gain access to both the design and simulation tools is not suitable for typical hobbyists.

Cart3D is an inviscid analysis program created by NASA for computational fluid dynamics (CFD) simulations of aircraft and spacecraft [15]. Cart3D does not include any simulations or analyses beyond the CFD results. It is uncertain what the cost of using Cart3D is, since the NASA Software Catalog was inaccessible at the time of writing, requesting the software through NASA required a license to be obtained (with no price specified) and third-party distributors also didn’t provide a price or download link. Search results seemed to indicate that the software is free, but even if this is the case, the software is targeted for professional use, and only contains the CFD solver.

MachUp is a free, online aerodynamic analysis tool created by Doug Hunsaker at the Utah State University [36]. MachUp is able to calculate a range of aerodynamic parameters for the aircraft given (such as stall velocity, lift and drag forces and the aerodynamic centre) but requires the aerodynamic performance of the geometries used to be defined by the user. Additionally, MachUp can currently only simulate the performance of wings and propellers, and thus has limited use in simulating aircraft, and features no calculations for parameters such as range and endurance.

CEASIOM is a free aircraft design tool created by CFS Engineering [23]. CEASIOM is able to conduct CFD and structural analyses on a 3D model and determine its aerody- namic performance (including stability). However, the program does not feature mission simulations (including calculations for range or endurance), and requires a MATLAB li- cense in order to run (which costs $219 AUD for a personal license [45]). Given that the average hobbyist likely won’t already have a MATLAB license, this is essentially another expensive CFD solver.

7 Advanced Aircraft Analysis (AAA) is an aircraft design and simulation tool created by the Design, Analysis and Research Corporation [17]. AAA is able to calculate the aerody- namic performance of an aircraft and determine its predicted range. However, the pricing for AAA is not specifically listed, but the prices for DARcorporation’s other software range from $350 USD (for an add-on to another DARcorporation product) to $2295 USD for the main software. If these prices are indicative of the price of AAA, then this tool, while being one of the most versatile examined, will be too expensive for a hobbyist. In addition, the interface for the program is not particularly user-friendly, and would require a considerable amount of time to be invested to become proficient in the use of the tool.

It can be seen that the number of tools which incorporate both design and simulation of aircraft is quite low, and for those that do exist, the pricing is typically too expensive for a hobbyist to justify paying. Even if someone was to purchase one of these programs, it is likely that it would still take a considerable amount of time to become proficient with it. As a result, a tool that is easy to use and provides both design simulation and optimisation would be very useful for hobbyists who would typically otherwise not have access to this kind of software. While the simulation created as part of this project does not determine the stability or structural integrity of the craft, as well as leaving more complex effects that would be captured by CFD out of scope, it does allow for rapid feasibility estimates and can be easily upgraded.

8 2.3 Wing Parameters

A broad overview of different wing parameters and their effects is presented below. This information is provided in a general sense in order to provide context into the operations of the simulation and parameters associated with flight that are currently modelled or may be modelled in the future.

NACA Airfoils

The NACA family of airfoils is one of the most common and one of the oldest airfoil families [39]. The NACA family consists of a number of different series’ (4-digit, 5-digit, 1-, 6-, 7- and 8-series). Each series has a designation defined by the characteristics of the airfoil (whether aerodynamic performance or geometric characteristics) [16]. Currently, only the NACA 4-digit series airfoils are modelled within the simulation, but further airfoil geometries can be modelled in the future as long as geometry data is provided to XFOIL. The NACA 4-digit series is designated based on its geometry, and is specified as NACA MPTT, where M is the camber of the airfoil (% chord), P is the position of maximum camber (tenths of a chord) and TT is the maximum thickness (% chord). As such, a NACA 4610 airfoil has a maximum camber of 4% located 60% of the chord length from the leading edge, with a maximum thickness of 10% of the chord. The surface geometry of the NACA 4-digit series airfoils can be determined using their designations and equations developed by NACA [16], which are not listed here due to their length. However, XFOIL is able to internally calculate the geometry of the NACA 4-digit series airfoils, and as such doesn’t require additional geometry data, which is why the 4-digit series is used in this thesis.

Wing Height

The mounting height of the wing is found to play a moderate role in aerodynamic perfor- mance. A high-wing configuration (positioned near the top of the fuselage) experiences higher maximum lift and reduced longitudinal (pitching) instabilities [29], while decreas- ing directional (yaw) control due to disturbed flow over the vertical stabilizer [32] but increasing directional stability (see Appendix A), as well as experiencing increased rolling instabilities [30] and increased drag [53]. A low-wing configuration was found to increase drag with negligible effects on lift [53]. A mid-wing configuration was found to have the highest lift-to-drag ratio [34] of the possible configurations. However, all wing configu- rations were found to cause significant pitching instabilities at varying angles of attack, when flow disturbed by the wing passes over the tail surfaces [61] [32]. As such, depending on the ideal angle of attack, the wing height may need to be altered to keep the disturbed flow away from the tail surfaces. However, ignoring these flow-induced instabilities, a mid-wing configuration is ideal for high endurance or high range flight, while a high-wing configuration is ideal for heavy lifting and increased pitching stability. A low-wing con-

9 figuration is generally inferior in most circumstances, but it is expected that commercial airliners use low-wing configurations to allow the wing structure to pass through the fuse- lage unobstructed, increasing strength and reducing weight. Note that the effect of wing position is not currently included in the simulation.

Wing Sweep

Increasing the sweep of the wings is found to decrease the effectiveness of lifting surfaces (such as wings and flaps) by reducing the gradient of the lift-curve slope [52]. This is because the effective velocity of the flow passing over the wing is proportional to the cosine of the wing sweep [49] [71] (see Appendix D), and therefore increasing sweep reduces the effective flow velocity, reducing the lift generated. However, increasing sweep when operating at high speeds (approaching and exceeding the critical Mach number of the airfoil, see Appendix C) provides significant reductions in wave drag [54] (which occurs due to flow separation as the flow reaches supersonic speeds). Increasing sweep also generates span-wise flow along the wing (flow from the root to tip), which thickens the boundary layer and promotes wing tip stalling, which is unfavourable due to the common location of control surfaces near the wing tips, as well as rolling instabilities induced by this stalling [68] [71]. Swept wings provide an increase in the effective dihedral of the wing, increasing lateral stability [38] and directional stability [46] [69] (see Appendix D), while decreasing longitudinal stability [46] and often causing Dutch rolls (see Appendix E). Wing sweep is also found to maintain a relatively constant lift-to-drag ratio, since the effective velocity plays a role in both lift and drag generation [46]. Therefore, wing sweep is most beneficial when operating at high speed (approaching or exceeding Mach 1) as the reduction in wave drag significantly reduces losses. However, for most subsonic aircraft, unswept wings are ideal due to the maximised lift and reduced likelihood of wing tip stalling. Note that while the simulation incorporates a decrease in lift and drag with the cosine of sweep angle, wave drag and tip stalling are currently not modelled.

Wing Dihedral

Positive wing dihedral (wing tip up) is found to provide a noticeable increase to the damping lateral (rolling) forces on an aircraft as it rolls [55] [30]. Positive wing dihedral also causes the aircraft wings to return to a level position during a sideslip [56] (see Appendix F). Wing dihedral (whether positive or negative) causes a reduction in lift generation approximately equal to the cosine of the dihedral angle [56], as the direction of the lift generated points further away from the vertical axis of the craft as the dihedral is increased (as the lift force is generated normal to the wing surface). Positive wing dihedral is also found to provide increased lateral (rolling) stability [9] [67] [44] [49]. Therefore, wing dihedral serves solely to improve lateral stability at the cost of lift generation. Note that while the effect of wing dihedral on lift generation is modelled in the simulation, stability effects are not. As such, zero dihedral is ideal for designs in the simulation.

10 Wing Twist

Twisting a wing along its span (whether by geometric or aerodynamic twisting, see Ap- pendix G) is used to adjust the span-wise lift distribution as desired (typically to achieve an elliptical lift distribution to minimise losses) [7]. Negatively twisting the wing (reduc- ing the angle of attack of the wing tip) can be used to avoid tip stalling (so the wing root stalls first, aiding recovery) and reduce bending moments within the wing (due to the reduced loading near the tip) [71]. Therefore, twisting the wing is used predominantly to reduce losses, avoid tip stalling and decrease wing weight. Note that wing twisting is currently not featured in the simulation (but changing the angle of incidence of entire wing is possible).

High Lift Devices

High lift devices (leading and trailing edge flaps and slots) are used to modify the lift- curve of the wing at different stages of flight (usually to increase lift generation when landing, thus reducing the necessary velocity). The effects of the different high lift devices are shown in Appendix H [33]. In general, trailing edge flaps increase the maximum lift coefficient and decrease stall angle, leading edge flaps increase the maximum lift coefficient and stall angle, while leading and trailing edge slots increase the lift-curve slope, maximum lift coefficient and stall angle [33]. Flaps serve to increase the effective camber of the wing (increasing the potential to generate lift) while slots re-energize the boundary layer, introducing turbulence and allowing it to remain attached to the wing surface longer [66]. Note that the presence of variable slots is predicated by the extension of flaps, which serves to increase the effective wing area, improving lift generation [70]. Note that all improvements in lift also have subsequent increases in drag, otherwise variable flaps wouldn’t exist (and highly cambered wings would be used more). Therefore, variable flaps can provide highly beneficial effects for aircraft operating at low speeds by reducing the necessary velocity and angle of attack, while stowing away during higher speed flight when they are not needed. Note that flaps and slots are not currently modelled in the simulation.

Aspect Ratio

Increasing the aspect ratio of a wing (ratio between wingspan and chord length) reduces the induced drag of the wing and increases the slope of the lift-curve [59]. This decreases the angle of attack necessary and improves flight efficiency. The effect of aspect ratio on lift and drag (as a result of finite-wing effects) is well documented, and is demonstrated

11 in the following equations from NASA [50] [51]:

C C = L∞ L C 1 + L∞ πAR C2 (2.3.1) C = L D,induced πARe

CD,total = CD∞ + CD,induced

Where CL∞ and CD∞ are the infinite-span lift and drag coefficients for the airfoil. The efficiency factor e is given by Howe [35], who provides a relation for wings with an aspect ratio greater than 5 (where Ne in this context is the number of engines mounted on the wing, and t/c is the relative airfoil thickness [TT from the NACA MPTT designation]).

f(λ) = 0.005(1 + 1.5(λ − 0.6)2) 1 e = (2.3.2) 0.142 + f(λ)AR(10t/c)0.33 0.1(3N + 1) (1 + 0.12M 6)(1 + + e (cos(ϕ))2 (4 + A)0.8

Therefore, increasing the aspect ratio of the wing increases the lift coefficient and decreases the induced drag coefficient. This is particularly important for aircraft that operate at low speeds (and therefore with high lift coefficients), as they would generate significant induced drag with a low aspect ratio wing (due to the squared-relation between induced drag and lift coefficient). Therefore, a higher aspect ratio is always better for improving aerodynamic performance, but the increasing wing mass will provide a limit on the actual optimal aspect ratio (as wing mass grows approximately with wingspan squared [76]). These effects (finite span lift and drag, efficiency factor, and the growth of wing mass with wingspan squared) are modelled within the simulation (with the wing mass information outlined further in Section 2.6).

Taper

The main purposes of wing tapering are to modify the lift distribution of the wing to approach an elliptical lift distribution (see Appendix I) and to reduce the necessary wing thickness (as the wing is then thicker relative to the tip, reducing the need for additional strengthening) [71] [59]. It was found that a taper ratio of 0.45 (tip chord being 45% of the length root chord) provides a lift distribution that causes an induced drag less than 1% greater than that of an elliptical lift distribution [59]. However, tapering the wing also reduces the wing area, which decreases the total lift generation of the wing. Tapering also increases the local lift coefficient of the wing tip, promoting tip stalling. Therefore, the optimal wing taper will depend on the specific craft size and operation, but it is typically kept above 0.3 to avoid tip stalling. The effects of taper are modelled within the simulation in the form of a wing mass reduction and reduced induced drag, while tip stalling is not modelled.

12 Winglets

The purpose of winglets is to obstruct the formation of wing tip vortices (increasing the effective aspect ratio of the wing), which increases lift and reduces induced drag [59]. Winglets cause an improvement in lift at all angles of attack, and at worst break even in total drag (i.e. reducing the induced drag by an amount equal to the drag generated by the winglet) [57]. Winglets also improve the lateral and directional stability of an aircraft, by increasing the effective dihedral of the wing [60]. Negative-dihedral winglets (positioned below the wing as opposed to above) provide slightly larger improvements in lift gain and drag reduction and improved lateral stability over positive-dihedral winglets [75] [62]. Therefore, the addition of winglets provides significant benefits to the aerodynamic performance (increased lift, reduced drag, improved lateral and directional stability) of an aircraft, and should be included whenever feasible. Winglets mounted below the wing are slightly more beneficial than winglets mounted above the wing, but clearance issues between the wing and ground will often necessitate the winglets being mounted above the wing. The effects of winglets are currently not modelled within the simulation, due to the lack of an equation to describe the increase in effective aspect ratio from a winglet based on its geometry.

Thickness

The main effect of wing thickness is the variation in speed of airflow over the top and bottom surfaces [59]. As the wing thickness is increased, the flow over the top surface typically accelerates, which may achieve supersonic speeds if the aircraft is travelling near its critical Mach number. Therefore, decreasing the airfoil thickness is a viable method for increasing the critical Mach number of an aircraft. However, given that this thickness causes the flow to accelerate over the top surface, it is part of the reason that the wing can generate lift (as the flow being accelerated causes the pressure on the top surface to drop, increasing lift). However, making the wing too thick causes it to lose its aerodynamic shape and spoils performance (as the wing approaches the shape of a cylinder as opposed to the streamlined shape of a wing). Therefore, the wing thickness is particularly important for transonic or supersonic aircraft, as an increased thickness will reduce the critical Mach number. While the thickness is not as important for subsonic aircraft, it should still be kept to a relatively low value (typically between 8% and 15% of the chord length [39]) to avoid spoiling the aerodynamics of the wing, by keeping its planform area high with its frontal projected area low.

13 Wing Modelling and Data Source

The infinite-span lift and drag coefficients for the wings were provided by the program XFOIL [20], created by Dr. Mark Drela and Harold Youngren. XFOIL is an airfoil potential flow solver (that can also incorporate viscous effects, such as boundary layer generation and flow separation) released under the GNU General Public License. Its purpose in this simulation is to generate infinite-span lift and drag coefficients for wings with varying airfoil shapes and Reynolds numbers. While XFOIL can analyse any wing shape given a file containing the geometry of the wing, it is able to natively calculate the shape of any NACA 4- or 5-digit series airfoil purely from the NACA designation (given the relation between the geometry and the 4- and 5-digit series designations). However, XFOIL does occasionally have problems converging to a solution for some unusual airfoil shapes (typically, very thin airfoils do not converge to a solution), which must be worked around by careful airfoil selection. After XFOIL determines the infinite-span lift and drag coefficients, the finite-span coefficients are calculated using the equations outlined in the Aspect Ratio section.

XFOIL is released under the GNU General Public License, which allows for the free usage, modification and redistribution of the program in any form, and is available online on the GNU website [31]. The license also stipulates that anyone to whom you redistribute the program must be given the same rights that you received when receiving the program. As such, this coincides with the plan to release this simulation code publicly for free use.

14 2.4 Propulsion

Propellers

There are two main types of propellers, which are fixed-pitch and variable-pitch pro- pellers. Fixed-pitch propellers have a fixed geometry and operate using this constant geometry for the entirety of the flight. Variable-pitch propellers have the capability of altering the angle of the propeller blades in order to change the shape of the propeller’s performance curve (see Appendix Item J for propeller performance curves at a range of blade angles). A variation of a variable-pitch propeller is the constant-speed propeller, which changes the blade angle so that the engine constantly operates at an RPM near its peak efficiency (much like shifting into a higher gear in a car when travelling at high speeds, as engines typically perform best at low RPMs and high loading [21]). As such, variable-pitch and constant-speed propellers are typically much more fuel-efficient than a fixed-pitch propeller, due to their ability to always operate at peak performance. How- ever, for the current scope of the simulation, only fixed-pitch propellers are used. This reduces the simulation complexity and allows the usage of the Propel program created by the University of Sydney, which outputs performance data for fixed-pitch propellers when given the propeller geometry.

Propeller Modelling and Data Source

The propeller performance coefficients (CQ, CT and ηprop) were calculated and tabulated by a program created by the University of Sydney [63] called Propel, which takes the geo- metric parameters of the propeller (diameter, number of blades, pitch, chord length, taper and setting angle) and calculates the efficiency, torque coefficient and thrust coefficient over a range of advance ratios. As such, a very wide range of propellers can be created for simulation. This is the only source of propeller data used, but it is expected to be sufficiently accurate, as the curves generated match the data found by McCormick [47], and uses the same underlying theories to calculate the propeller performance. The main limitations of this program are that the airfoil used for the propeller can’t be modified, and the program can only calculate the performance of a fixed-pitch propeller, and thus data files for a number of setting angles would need to be made to allow for interpolation between the data sets to imitate a variable-pitch propeller, which has been left outside the current scope of the simulation. However, given that the propeller is not a param- eter that is currently automatically optimised, all designs using a specific propeller (i.e. designs created automatically for optimisation) will experience the same effects.

Propel was released for free distribution by the School of Aerospace, Mechanical and Mechatronic Engineering at the University of Sydney, and was found hosted on a website run by Auld and Srinivas [63]. However, the original hosting location from the University of Sydney could not be found, since the program only provides the URL for the main University of Sydney student login page.

15 Engines

There are two main engine archetypes used for UAV propulsion, which are electric and internal combustion engines. Electric engines use power supplied by batteries or other power sources to drive an electric motor, which has been excluded from the current scope of the thesis. Within the internal combustion engine archetype, the engine subtypes used by UAVs are piston, turboprop, turbofan and turbojet engines. Note that only piston engines are kept within the scope of the thesis and modelled in the simulation. This is due to the complexity of modelling the performance of the other engine types, as well as the fact that using the piston engine performance curves does demonstrate the ability of the simulation to accept user-provided data. Piston engines can run on a range of different fuels (including aviation gasolines, jet fuels, and ”glow” fuel - only used by hobby engines). Only gasoline-consuming engines are used within the simulation, as it is unknown if the performance curves will follow the same shape for different fuels, and the Rotax 914 used for the baseline engine performance curves uses AVGAS 100LL [37] (low lead, 100 octane aviation gasoline). Piston engines without gearboxes typically have an increase in fuel consumption and power output as the engine RPM increases. As such, it is relatively simple to model the performance curves and implement them into the simulation.

Engine Modelling and Data Source

Only a limited amount of data could be found for engine performance curves. Addition- ally, the engine performance data used (power output and fuel consumption) cannot be published with the simulation code due to the copyright policy on the documents from which the Rotax 914 (which provided the performance curves that formed the basis for all engines examined) performance curves originated, which was the Operators Manual [37]. The performance curves from this manual were modified in order to imitate the performance of different engines based on their maximum power and fuel consumption. The steps taken to modify the Rotax performance curves were as follows:

1. The power output and fuel consumption curves were ”stretched” to match the RPM range of the new engine.

2. The power output curves were scaled linearly based on the ratio between the maxi- mum power of the Rotax 914 and the new engine, such that the new power output curves peaked at the maximum output power of the new engine.

3. The fuel consumption curves were scaled linearly based on the ratio between the maximum fuel consumption of the Rotax 914 and the new engine, such that the new fuel consumption curves peaked at the maximum fuel consumption of the new engine.

Note that the Rotax 914 Operators Manual provides two curves for each of the graphs, one curve for maximum power output and fuel consumption, and one for partial loading (based

16 on using a constant-speed propeller that draws maximum power at the engines maximum RPM). As such, the fuel consumption of the engine was interpolated based on the power draw. At the required RPM, the power requirement of the design being simulated was compared against the full- and partial-loading power output values. If the required power fell between these values, then the fuel consumption was linearly interpolated between the corresponding full- and partial-loading fuel consumption values. If the required power fell below the partial-loading power, the fuel consumption was set to the partial-loading value, to roughly imitate the fact that engines get less fuel-efficient as the loading is decreased [21]. If the required power exceeded the full-loading output power, then the specific flight configuration being checked was skipped. If all flight configurations checked for a specific design were skipped, then the design returned a failure and was marked as such.

This method of engine performance scaling makes the assumption that the performance curves of all piston engines has the same shape, which is very unlikely to be true. This method arose out of necessity given the stark lack of performance information for smaller engines (particularly hobby aircraft engines). The lack of information was so severe that for most cases, the fuel consumption of the engines examined had to also be extrapolated based on tabulated data from O.S. Engines [25] for other engine sizes, with its fuel con- sumption assumed to be a function of engine displacement (table not shown for copyright reasons). By using the information provided by O.S. Engines for fuel consumption and taking the steps listed above, approximated performance curves can be generated for any engine with a specified power output, RPM range and engine displacement in the absence of performance graphs.

2.5 Fuselage Data Source

For the current iteration of the simulation, data is only provided for one fuselage geometry. This is due to the essentially limitless variations of fuselage shape possible, and as such providing this data would either involve the collection of a very wide range of fuselage geometries, or the ability to calculate the aerodynamics of a fuselage shape during the simulation, via some internal fluid simulation. Given that neither of these approaches is particularly feasible, one fuselage geometry was chosen to be included. The fuselage shape chosen is that of a spherically blunt tangent-ogive nose projectile, more colloquially known as a blunt bullet-esque shape (see Appendix M), as analysed by Lijin and Jothi [40]. This was chosen due to its smooth, rounded shape, such that it would be reason- ably representative of an aerodynamic UAV shape. The usage of the fuselage data is less to provide specific, accurate information on the aerodynamics of the UAV’s fuselage (especially given the number of assumptions made to intentionally limit the scope of this thesis), but instead to provide representative data and confirm the correct usage of the data within the simulation, validating its functions.

17 2.6 Mass Data Sources

For the list of craft components currently available for simulation, only the ogive cylinder (fuselage), dead weight, fuel and engine components have standard mass-finding calcu- lations (for the fuselage, it is assumed the mass of the ogive cylinder is similar to that of an equivalent length and radius cylinder without ends, while the dead mass, fuel and engine components are natively defined by their masses in the design file). The propeller is assumed to be ”massless” (such that its mass forms a part of the dead mass value). The ”dead mass” parameter serves to provide a means of simulating the effects of items on board the UAV that aren’t otherwise simulated, such as avionics, sensors and payloads. The dead mass parameter can also serve as a ”differentiator”, such that the dead mass can be varied in order to investigate the effects of different payloads, electronics or other overall mass changes (such as simply examining how the craft flies with a different mass, potentially examining the effects of using more or less dense materials).

The wing, horizontal and vertical tail and landing gear have their masses estimated using NASA’s Flight Optimization System Weights Estimation Method [76]. The equations presented within this document are used in NASA’s Flight Optimization System, which is used for the design and simulation of aircraft. However, while the program is available as a general public release for individual use, the program itself cannot be redistributed, and thus can’t be wholly integrated with this simulation. However, the documentation for the weight estimation equations is available freely online and can be used within this simulation for weight estimation only. These equations use the geometry of the wings, tail, landing gear size and estimated design gross mass alongside user-defined constants that define the ”efficiency” of the materials and structural designs used. The three constants are FSTRT (strut bracing factor, where a value of 0 is no strut bracing, and 1 is maximum strut bracing, where a higher value reduces wing weight), FAERT (aeroelastic tailoring factor, where 0 is no aeroelastic tailoring and 1 is maximum aeroelastic tailoring, which is the use of directional strength of materials in order to minimise wing weight, where a higher value reduces the wing mass) and FCOMP (composites usage factor, where 0 represents no composite usage and 1 represents maximum composite usage, where again a higher value results in reduced wing weight). As such, these values have all currently been fixed in the low-mid range (0.5, 0.3 and 0.4 for FSTRT, FAERT and FCOMP respectively) to approximate the design capabilities of a relatively knowledgeable hobbyist. While these values aren’t defined within the design file (as all designs created by the user would be expected to have similar constant values), they are defined within the simulation code, but can be easily changed.

18 3 Methodology

The methodology section outlines the creation of the simulation code. Firstly, the scope of the simulation is defined. Next, the equations for relating to equilibrium flight are then derived, followed by a description of the simulation creation process and concluding with an outline of the code structure and data flow.

3.1 Simulation Scope

The simulation scope specifically looks at what parameters were included in the simulation and what parameters were not. The parameters that were taken in scope are:

• Gasoline-powered piston engine performance.

• Fixed-pitch propeller performance.

• Wing finite lift and drag coefficients.

• NACA 4-digit series airfoils.

• Fuselage form drag and skin friction.

• 3D mission waypointing (5 axis flight).

The parameters that were left out of scope for the simulation are:

• Airfoils other than the NACA 4-digit series.

• Non-gasoline engines.

• Turboprop, turbofan, turbojet and electric engines.

• Aircraft rolling/banking.

• Gradual changes in flight conditions (i.e. accelerating, decelerating, progressively pitching up or down).

• Variable-pitch and constant-speed propellers.

• Skin friction on any components other than the fuselage.

• Other sources of drag (wave drag and interference drag).

• Complete assembly of the craft (such as relative positioning of the components and structural integrity).

• Aircraft controllability (control surfaces and stability).

• Engine performance at different altitudes.

• Effects of angle of attack on advance ratio.

19 3.2 Equations of Flight

Equilibrium Flight Velocity

In order to solve for the velocity associated with a given angle of attack, the force summa- tions in the x (horizontal) and y (vertical) directions were used in order to derive usable equations (see Appendix L for a free-body diagram of the forces on a fixed-wing UAV). For a craft in equilibrium, the sum of forces in each direction is zero.

ΣFx = 0 = FT cos(β) − FL sin(θ) − FD cos(θ) (3.2.1) ΣFy = 0 = FT sin(β) + FL cos(θ) − FD sin(θ) − mg

Using the summation of forces in the x direction equation, an expression for thrust can be obtained: F sin(θ) + F cos(θ) F = L D (3.2.2) T cos(β) Equation 3.2.2 can be substituted into the sum of y forces equation in Equation 3.2.1 above.

FL sin(θ) + FD cos(θ) 0 = ( ) sin(β) + FL cos(θ) − FD sin(θ) − mg cos(β) (3.2.3)

mg = FL(tan(β) sin(θ) + cos(θ)) + FD(tan(β) cos(θ) − sin(θ))

Replacing the lift and drag forces with their relevant equations:

2 X FL = 0.5ρV (CLA) (3.2.4) 2 X FD = 0.5ρV ( CDA)

2mg X X = V 2[( C A)(tan(β) sin(θ) + cos(θ)) + ( C A)(tan(β) cos(θ) − sin(θ))] ρ L D (3.2.5) Given the dependence of lift and drag coefficients on the Reynolds number of the compo- P P nent, there are a number of terms dependent on the flight velocity (V , CLA, CDA). As the functions for lift and drag coefficient are creating using interpolation functions from the Python module SciPy, which doesn’t provide function for explicit solving, an iterative solver is used which progressively increases the velocity until the error between the left- and right-hand sides of the equation falls below a given tolerance.

20 Equilibrium Flight Thrust

The thrust required for equilibrium flight was used as an interim equation above (in Equation 3.2.2). Once the flight velocity is found for a given angle of attack, that velocity and angle of attack can be used to find the lift and drag forces and solve for the thrust required to maintain equilibrium flight.

F sin(θ) + F cos(θ) F = L D (3.2.6) T cos(β)

Propeller Performance

The thrust generated by a propeller is given by the following equation:

2 4 FT = CT ρn D (3.2.7)

The torque and power required by the propeller are given by the following:

2 5 Qprop = CQρn D

Pprop = 2πnQ (3.2.8) 3 5 Pprop = 2πCQρn D

The propulsive efficiency of the propeller is then given by the ratio between propulsive power and power required: FT V J CT ηprop = = · (3.2.9) Pprop 2π CQ Iteratively solving the equation for propeller thrust provides the necessary rotation rate of the propeller and engine, which can be used to calculate the power required by the propeller. This power requirement is then used to calculate the fuel consumption based on the method outlined in Section 2.4.

Energy Requirement

The power consumption of the craft is given from the engine performance curves, while determining the energy requirement for the flight leg requires an additional step, shown below. Erequired = Pconsumedtflightleg d (3.2.10) E = P × flightleg required consumed V As such, the energy requirement for the flight leg (used to maximise range) is also depen- dent on the velocity, such that increasing the velocity at a greater rate than the associated power consumption increases will improve the range of the craft.

21 3.3 Simulation Creation

The creation of the simulation occurred in six primary steps, outlined below. Note that descriptions of the code modules can be found in Appendix K, with the names of these modules being in bold when referenced. Note that throughout the course of the simula- tion creation, the utility modules (convert, interpos and angsolver) were progressively built upon with new functions when necessary. The general order of activities was the progressive building upon of the core flight configuration solver, followed by upgrades to incorporate new features.

1. Research was conducted to determine what parameters would be necessary to model, as well as to determine the effects of these parameters.

2. The aerodynamic performance function generating module (cogen) functions for the lift and drag of the craft, which are merged into singular functions by compiler.

3. The flight configuration solver (efficientflight) was created using the crafts aero-

dynamics to determine the required flight power (FD × V ).

4. The design discretization, mission discretization and automatic flight simulation modules (designparam, missionpath, controller and associated sub-modules) were created, to facilitate the discretization of a design into components and to simulate the performance of the design throughout the course of a mission.

5. The automatic batch simulation, sensitivity analysis and results processing modules (batch, sensitivity, resultsprocessing and relevant sub-modules) were created in order to generated varied designs and display their performances so that the optimal design could be found.

6. The flight configuration solver was upgraded with both propeller and engine perfor- mance models added in using the data and methods outlined in Section 2.4.

22 3.4 Simulation Data Flow

Figure 3.4.1: Flowchart for data within the simulation.

Figure 3.4.1 above shows a flowchart of the overall simulation processes and flow of data. In the flowchart, circles represent files, rectangles represent code modules and rectangles with inner lines represent external programs. Dashed lines represent file creation while solid lines represent information being passed around. Filled-in circles represent file names being passed without the file itself being read, while arrows indicated the movement of the actual data. Finally, if a line begins with a double perpendicular lines, it represents that information calculated within a module is moved, whereas a line ending in an arrow that doesn’t begin with double perpendicular lines represents the information explicitly stored with a file being used (i.e. double perpendicular lines indicate the flow of infor- mation found implicitly from the files). Double-arrowed lines represent repeated running of a module, with the larger arrowhead pointing to the module that is repeatedly run. In addition, the colour of the lines represent the family of data being moved around.

23 Black lines relate to overall simulation processes (such as the general overarching order of operations, as well as intermediate files used for score-keeping). Red lines are related to mission-specific characteristics (such as the mission file, flight waypoints, cost functions and environmental parameters). Green lines are related to design-specific characteristics (such as the design file, design mass, and aerodynamic, propeller and engine performance). Finally, yellow lines are related to the specific control information given to the analysis (which consists of the sensitivity control file and the simulation control file automatically generated as part of the sensitivity analysis). Finally, the isolated code modules ang- solver and convert are utility modules which are used in a number of different code modules to provide convenience (such as unit conversions).

While the flowchart may seem confusing at first, there are four main data processes that exist within the simulation that operate using each other to acquire the necessary information.

1. Global overarching data flow, beginning with the sensitivity module, followed by batch and then culminating with resultsprocessing.

This is the process that controls the entirety of the simulation. First, the sen- sitivity module is run, which takes the sensitivity control file as the input. It uses the sensitivity control file to locate the baseline design and mission files, then cre- ates variations of the baseline design as per the criteria provided and moves all files (including the varied designs, as well as copies of the baseline design and mission) to a new directory. Batch then simulates the flight of each of the designs, using the second data process (which begins with controller). The results of the simulations are stored, which are passed to resultsprocessing alongside a ”design keeper” file (which keeps track of what variations are made for each design), which allows the creation of a normalised parallel axis plot.

2. Individual design simulation, beginning with controller and repeatedly using effi- cientflight to simulate the entirety of a mission.

This is the process which handles the actual simulation of a single design. Con- troller utilises the second and third data processes to turn the design and mission files into usable data, which is passed to efficientflight at different points within the mission in order to determine the performance of the design (where efficient- flight calculates the local cost at each point, while controller sums the local costs and calculates the global and custom costs).

24 3. Design discretization within controller.

This process handles the conversion between a design file and information usable within the simulation (performance functions and mass characteristics). Design- param controls the discretization of the design file, beginning with the generation of lift and drag functions for each component using cogen (where ldgen and XFOIL are used for simulating wing performance, and tabulated data is used for other geometries). These lift and drag functions are merged into singular functions us- ing compiler. The mass of the design (separated into dead mass, which is fixed throughout the flight, and fuel mass, which changes during the mission) is found using massfinder, and finally the engine and propeller performance functions are read directly in controller using interpos.

4. Mission discretization within controller.

This process deals with the conversion of the mission file into usable cost func- tions, environmental parameters and flight path information. First, the mission file is given to missionpath, which calculates a range of information (including the distance and heading of each flight leg, turn angles and arc distances, climb angles and changes in position), utilising csolver and side when necessary to calculate the radius and arc length of turns. The enviro module (acting as an interface between the main simulation and tables) is then used whenever efficientflight is run, in or- der to determine the local atmospheric conditions at the point in the mission being simulated.

These four overarching processes form the simulation, and by isolating the internal per- formance of these processes from each other, the processes behave as ”black boxes”. This allows internal modifications to be made for the purposes such as code optimisation or upgrades without needing to worry about data flow being adversely affected (so long as the same inputs and outputs are maintained). Additionally, even if the input or output parameters of a process are changed, these parameters only need to align where the pro- cesses interact with each other, reducing the likelihood of errors within the code due to the simplicity of the process interactions.

25 3.5 Choices Made

A number of choices have been made relating to the operation of the code, which are outlined below with their justifications. Note this section specifically covers choices made during the creation of the simulation, which may or may not fit under the category of scope.

1. Isolating overall processes as much as possible, turning the processes into ”black boxes” with inputs and outputs, and the internals essentially ”hidden”.

This choice was made to reduce the complexity of having the processes and mod- ules interact with each other. By combining different modules into their respective ”families”, only the high-level inputs (such as the design file) and outputs (such as aerodynamic, engine and propeller performance functions and vehicle masses) need to be taken into account for other processes, which allows for changes to be made internally without breaking other processes so long as the input and output structure is preserved.

2. Iteratively checking every angle of attack within a given range for the optimal flight configuration, instead of using some form of root-finding method.

This choice was made for two reasons. Firstly, it was found that this method was more robust against typical causes of simulation failure, such as the craft being too heavy to fly and therefore having no optimal flight configuration. Iteratively checking every angle allows for a definitive result to be provided stating that the design has failed, as opposed to guessing whether the root-finding method is just taking a long time to converge or if there is no actual solution. Secondly, checking all angles within the range allow for the global minimum (within the defined range) to be found, whereas a root-finding method may find a local minimum and present this as the optimal flight configuration.

3. Complete lack of interaction between components (outside of the summation of their aerodynamic effects).

This decision was made to reduce the complexity of the simulation, and is a rea- son why the simulation could essentially be called a glorified ”fuel calculator” as opposed to an actual simulation. Since interactions between components were in- tentionally ignored, this eliminates the possibility to examine the controllability of the craft, which limits the simulation to simply checking the high-level aerodynamic performance of the design. This decision was made as the simulation was intended to fast-track preliminary design sizing and feasibility estimates, which it can do, but more complex aspect of aircraft design (such as the locations of the centres of mass, lift and thrust) will need to be analysed by some other method.

26 4. Iterative solving of flight velocity and propeller/engine rotation rate.

This choice was made out of necessity. Since all performance functions (aerody- namic, engine and propeller performance) are stored as SciPy interpolation func- tions, it is impossible to explicitly reverse solve for the independent variables used to define the functions. As such, iterative solving is used to bypass this problem. Also note that custom iterative solving functions were used instead of built-in root- finding methods as this allows for greater control over the solution-finding process (such as initial guess and step sizes, which can be changed based on the knowledge of the user to speed up simulations) and allows for easy customisation if desired.

5. Optimisation of the propeller and engine has been ignored.

This choice has been made for a number of reasons. Firstly, the information used to model the engine performance (performance curves and fuel consumption) is pro- tected from redistribution by copyright law. As such, adding methods for optimising these parameters would be of limited use for third-party users of this simulation, as they would not have access to the exact same engine data used here. While they are within their rights to seek out the information used within this simulation of their own volition and use it for their own personal uses, they too would be forbidden from redistributing the information. Secondly, the data used disables the capability of optimising based on engine and propeller geometry. The engine performance data is read from engine product information (including brochures and operator manuals), with no clear function relating power output and engine mass to engine displace- ment. As a result, all engine performance data was created by hand-modifying the Rotax 914 performance curves using information provided by engine manufacturers. A similar problem arises for the propeller performance. While the Propel program is capable of automatically determining the performance of a propeller given its geometry, the Propel program cannot be directly interfaced with via Python, which means that optimisation of a propeller would entail manually creating a large range of different propellers to check, which was deemed unnecessary for the current scope of the simulation.

27 6. Generating all engine performance curves based on the Rotax 914 performance curves and O.S. Engines fuel consumption data.

This was another decision made out of necessity. Due to a serious lack of informa- tion available relating to the performance of hobby aircraft engines, it was neces- sary to create some kind of extrapolation method for creating performance curves for small engines. Given that the scales of the hobby engines and the Rotax 914 are significantly different (1-2kW compared to >73kW), it is not expected that the performance curves are a particularly good representation of the engine’s true per- formance. However, without more accurate data, this option was the most viable found.

7. Allowing designs that run out of fuel to continue flying.

This was allowed to happen as it provides an opportunity to estimate variations in craft parameters that would allow the design to complete the mission. For example, a design that runs out of fuel just short of its final waypoint would otherwise be marked as a complete failure, whereas this choice would allow the additional fuel required to be found, with adjustments made to the cost of the design to estimate what its true cost would be if modified to meet the design requirements. Alongside this, it was decided that while the total energy consumption of the vehicle can continue to grow after the vehicle runs out of fuel, the fuel mass cannot drop below zero. This allows a metric of true fuel usage to be recorded whilst avoiding the possibility of a craft attaining negative mass.

28 4 Validation

In order to validate the simulation code, a range of tests were conducted. Firstly, real UAVs were discretized and imported into the simulation to check if the simulated perfor- mance was similar to the real-life performance of the UAV. Additionally, the operating characteristics of the UAVs were tracked and plotted on a performance map generated prior to the main simulation, to check if the optimiser finds the correct solution. Fol- lowing this, an example design process was conducted to validate the ability of the code to correctly optimise a design based on given criteria. Finally, the performance of a set of variations of the optimised design was analysed, while the optimised design was sim- ulated using a different mission, to also see the effects of mission parameters on vehicle performance whilst determining if the results found coincide with the research conducted.

4.1 Performance of Real UAVs

The first stage of validating the simulation included the importing and simulating of real UAVs. By investigating the performance of these designs within the simulation, and comparing the results found to the performance characteristics given for the UAVs, the validity of the simulation can be determined. Note that for all three designs, the flight configuration was found by minimising fuel consumption, thus maximising endurance.

4.1.1 Limitations of Validation

It is important to note that the specific propeller geometry could not be found for any of the three designs analysed. Additionally, the MQ-1B uses a variable-pitch propeller (which currently can’t be modelled within the simulation). Since the performance of the designs is highly dependent on the propeller, attempts were made to mimic the performance of the UAVs by modifying the propeller pitch and angle to yield results similar to those produced by the real UAVs. Doing this does limit the ability to ”validate” the designs, as the results are forced towards the expected results, but given the lack of propeller data found for these designs, modifying the propeller to yield results similar to those which are expected at least helps validate that the simulation can provide results within the expected range of performance of the designs simulated.

It is also worth noting that given the lack of specific information on the aerodynamic characteristics of these designs (as all three designs analysed here use the same generic fuselage shape, as it is the only fuselage shape currently implemented), the performance of the simulated designs is expected to vary from the real world characteristics. This effect is also compounded by the lack of additional drag sources (such as specific drag effects, including interference drag, skin friction from anything other than fuselage, and wave drag, or geometric causes of increased drag such as drag caused by the landing gear or other protrusions). These potential limitations are further outlined in Section 3.1.

29 4.1.2 MQ-1B Predator

Characteristics

The general physical characteristics of the MQ-1B Predator are outlined below in Table 4.1.1, while the dimensions of the MQ-1B can be see in Appendix N. Note that while the airfoils used on the MQ-1B (Drela GW-19, GW-25, GW-27, created by Dr. Mark Drela) are proprietary material of General Atomics, Dr. Drela personally stated on a hobbyist remote-control drone forum that a scale model should use a SD7032 wing (similar shape to a NACA 3510), while the full-scale MQ-1B airfoils ”...have LOTS of top surface camber.” [19]. As such, since Dr. Drela specifies that the GW- series airfoils are designed for high Reynolds numbers (which wouldn’t work for scale models due to flow separation) a NACA 4412 airfoil was chosen to be simulated (due to its high camber). Note that similar performance was observed for other heavily cambered airfoils (ranging from NACA 4410 to NACA 6514). The discretized file can be seen in Appendix O.

Parameter Value Wingspan (m) 16.84 [1] Airfoil NACA 4412 [19] Fuselage length (m) 8.23 [1] Fuselage diameter (m) 1.1 [1] Aspect ratio 22.5 [1] Engine Rotax 914 [28] Engine power (kW) 73.5 kW [37] Fuel used AVGAS 100 LL [37] Fuel energy density (MJ/kg) 44.0 [5] Fuel capacity (kg) 300 [28] Dry mass (kg) 512 [28] Endurance (hours) 24 - 35 [28] [64] Range (return trip) (km) 1240 [28] Velocity (m/s) 27.7-36.1 [18] [28]

Table 4.1.1: MQ-1B physical and performance characteristics.

30 Performance Comparison

The overall performance characteristics of the MQ-1B are shown below in Table 4.1.2, shown as a comparison between the real performance characteristics and those found by the simulation.

Parameter Real Value Simulated Value Average fuel consumption (kg/hour) 8.6-12.5 8.7 Flight velocity (m/s) 27.7 - 36.1 18.9 - 23.5 Endurance (hours) 24-35 36 Range (return trip) (km) 1240 1350

Table 4.1.2: Performance characteristics of the real and simulated MQ-1B.

The results shown above in Table 4.1.2 are approximately what were expected. The average fuel consumption of the simulated design falls just within the lower bound of the real MQ-1B (the endurance value associated to this - 35 hours - being for a variant of the MQ-1B specifically designed for low payload, high endurance flight). Given the lack of potential sources of drag, it was expected that the MQ-1B would perform better than its real-life counterpart. This same trend is shown for both the endurance and range, where the simulated design outperforms both metrics.

However, one important piece of information to note is that the flight velocity for the simulated design is significantly slower than that of the real design (between 8.8 and 12.6 m/s slower). This could be the result of a number of different causes, with two predominant reasons being expected. The first could be that the combination of propeller and engine performances is such that it is most efficient to operate at a lower airspeed (as propeller performance depends on velocity and rotation rate, while engine performance depends on the propeller power requirement and rotation rate). Should the most efficient operating points of the propeller and engine align at lower velocities (requiring less thrust, lower rotation rate and less power), then the craft will naturally fly at a lower velocity (increasing its angle of attack to compensate for the reduced lift generation associated with flying slower). The second is that, as a result of the lower drag of the simulated craft, it may be more efficient to generate the necessary lift by increasing angle of attack (as the maximum lift-to-drag ratio of the design may lie at a higher angle) and reducing velocity.

The first reason (that the combined engine and propeller performance changes the optimal flight velocity and angle of attack) is likely to have played a relatively large role in this result. Due to the limitations in the engine and propeller models (outlined in Section 2.4), the modelling of the engine and propeller has been made conservative, such that the design may choose to fly at a configuration requiring a higher shaft power, but using the same or less fuel due to how the engine is modelled.

31 Figure 4.1.1: Performance map of the MQ-1B showing the combined engine and propeller efficiency at a range of angles of attack and velocities, with the optimised flight overlaid.

Figure 4.1.1 above shows that the combined efficiency of the propeller and engine reduces as the flight progresses (moving down along the optimal performance dots). However, the optimal flight configuration does not change any specific way to avoid reducing the efficiencies, which initially seems strange as this current configuration doesn’t seem to optimise the flight. The reason for the strange behaviour of this graph is due to the way engine efficiency is calculated, which is the ratio between the power required for the propeller and the power input to the engine (in the form of fuel). As such, low ratios between shaft power requirement and the maximum power available at a given RPM result in poor efficiencies, because while the propeller power requirement decreases, the engine input power requirement doesn’t decrease as quickly. The graph of propeller efficiency shown below demonstrates this reasoning for the behaviour shown more clearly.

Figure 4.1.2: MQ-1B propeller efficiency map.

32 Figure 4.1.2 above shows that the propeller is operating near its peak efficiency for the duration of the flight. However, once again, the optimal flight configuration doesn’t shift to improve flight efficiency. The use of an additional graph is able to provide the explanation.

Figure 4.1.3: MQ-1B lift/drag ratio performance map.

Figure 4.1.3 above shows that the design is operating slightly off of its peak lift-to-drag ratio. This is the reason that the angle of attack of the craft isn’t increased to improve the propeller efficiency, which is because increasing the propeller efficiency in this way would worsen the lift-to-drag ratio, increasing the drag force relative to the lift force, increasing thrust requirements and therefore power and fuel requirements. As such, it can be seen that the propeller and engine performance (predominantly the propeller performance) play a significant role in the optimal flight configuration. This validates the reason that the engine and propeller performance models significantly influenced the optimised result, as the design should attempt to fly at its maximum lift-to-drag ratio in order to minimise drag if the engine and propeller weren’t present, but instead it flies slightly off of the peak lift-to-drag point due to improvements in the overall fuel consumption due to improved propeller performance. However, the full extent of the impact that the propeller and engine performance has on the UAV cannot be quantitatively determined, as the engine and propeller models incorporated into the simulation are limited in their accuracy.

The combination of engine, propeller and aerodynamic performance of the craft also influenced the low flight velocity via another means, which is the local cost function used for the optimisation. The simulation was run with the optimiser minimising the power consumption. However, if the optimiser is run to maximise range, then the MQ- 1B flies at a maximum velocity of 25 m/s and improves its round trip range to 1400 km, while reducing its endurance to 32 hours. This brings its flight velocity much closer

33 to the expected value (27.7 m/s) and endurance to within the expected range (24-35 hours), while moving the range further away from the expected value (1240 km). These changes in results are expected, as the maximum range and maximum endurance flight configurations don’t necessarily overlap, particularly as drag is related to velocity squared (such that doubling velocity to arrive in half the time would impart four times the drag force if all other parameters are held constant, increasing the ideal power consumption by a factor of 8 and the energy consumption by a factor of 4).

The second reason (reduced drag of the craft changing the optimal lift-to-drag point) is also expected to have played a noticeable role in these results. The actual drag coefficient of the MQ-1B could not be found, but given the low fuel consumption and increased endurance of the simulated design, it is relatively safe to say that the drag wasn’t as high as it should be (which is expected). The engine and propeller should theoretically be operating less efficiently in the simulation than they would in the real MQ-1B due to the conservative assumptions made, and as a result the drag of the simulated design would be significantly lower than that of the real design in order to result in the offset of these effects shown. This is expected, given not only the lack of drag types modelled (completely disregarding ram drag, interference drag and wave drag, and only modelling skin friction along the fuselage), but also the lack of additional drag sources (in the form of physical additions to the design, including landing gear, mounting pylons and external sensors). Due to a lack of data relating to the aerodynamics of the MQ-1B, it would be difficult to validate this reason quantitatively, but a qualitative analysis does support the theory that a lack of sources of drag would yield the results found. Note that it is not expected that an overestimation in lift would be the cause of these results, as it was found that the simulated MQ-1B is generating just enough lift to fly horizontally, and is unable to ascend along any meaningful climb angle. As a result, the lift of the simulated design is actually expected to be lower than the real MQ-1B, with the drag disproportionately lower.

34 Performance Analysis

Figure 4.1.4: MQ-1B engine power performance map based on craft mass and angle of attack.

Figure 4.1.5: MQ-1B engine power performance map based on craft mass and velocity.

35 Figures 4.1.4 and 4.1.5 above show the performance of the simulated MQ-1B across a range of masses, angles of attack and velocities, with the engine power requirement shown in the contour plots. For these graphs, the independent variable was set as the vehicle mass, as this is fed as the input to the flight configuration optimiser, with the angle of attack, velocity and engine power arising as results. In both graphs it can be seen that there are distinct contours representing engine power consumption (which is fuel consumption multiplied by the fuel energy density). Figure 4.1.4 shows that the the optimal angle of attack stays constant despite changes in mass, which matches the contours shown for engine input power (as the simulation was set to find the minimum engine input power flight configuration). However, as the mass of the vehicle decreases, the necessary lift force decreases, which culminates as a reduction in velocity. Figure 4.1.5 shows that the optimal velocity decreases as the mass of the craft decreases throughout the flight (as a result of the angle of attack staying constant).

The reason that the angle of attack stays constant while velocity decreases is for two reasons, which appear in Figures 4.1.2 and 4.1.3 above. Both of those graphs show their respective parameters (propeller efficiency and lift-to-drag ratio) being nearly indepen- dent of velocity. The propeller efficiency is isolated from velocity due to the fact that an increased velocity increases drag, which in turn increases the thrust requirement and the RPM required to generate the necessary thrust, which happens to essentially cancel out v for the propeller performance (controlled by the advance ratio J = ). The lift-to-drag nD ratio is nearly independent of velocity due to the large chord length of the wings. The wings experience Reynolds numbers on the order of approximately one million, which is double the transition Reynolds number. As a result, the flow over the wing is turbulent, which delays flow separation and reduces the effect of velocity on wing performance (as flow separation, i.e. stalling, is the main cause of changes in wing performance as velocity changes). Increasing the Reynolds number further (by increasing velocity) has a limited effect on the performance of the wing, which is shown in the graph. Note that the ”arti- facting” shown in Figure 4.1.5 is the result of how the plots were generated. To generate the contour plot, a mass was set, then the range of angles (0 to 20 degrees) was swept, finding the performance characteristics. This resulted in a high velocity at zero angle of attack, which progressively decreased as the angle of attack was increased, until the stall point. From this point, increasing the angle of attack increased the required velocity, which ended up being plotted over the data already present. This is why this ”artifact- ing” is only present on the mass versus velocity graph, since the velocity information only ”folds over” itself when kept on on the same x-point (which is the case for mass).

Ultimately, in both Figures 4.1.4 and 4.1.5, the optimiser is shown to be correctly finding the lowest power configuration, which is demonstrated by the black points (the actual optimised solutions) lying in the ”valley” of the contours shown, which is the fuel re- quirement. The solutions found also align with what is expected based on the research conducted.

36 4.1.3 Aerosonde

Characteristics

The general characteristics of the Aerosonde are outlined below in Table 4.1.3. Note that the airfoil used by the Aerosonde is an SD7037 airfoil [6], the closest NACA airfoil to which is the NACA 3510. Note that the fuselage diameter was modified to achieve the same zero-angle-of-attack drag coefficient (0.043), as found by Benghezal et al. [11]. The discretized design file can be found in Appendix P

Parameter Value Wingspan (m) 2.9 [10] Airfoil NACA 3510 [6] Fuselage length (m) 1.7 [26] Fuselage diameter (m) 0.26 [11] Aspect ratio 15.33 [8] Engine EL-005 [65] Engine power (kW) 2.98 [24] Fuel used AVGAS 100LL [24] Fuel energy density (MJ/kg) 44.0 [5] Fuel capacity (kg) 4.9 [10] Dry mass (kg) 8.2 [10] Endurance (hours) 26 (unladen)[58] Range (one way) (km) 3000 [26] [73] Velocity (m/s) 22.3 - 25.7 [26] [43]

Table 4.1.3: Aerosonde physical and performance characteristics.

Note that range estimates found for the Aerosonde were highly variable and highly de- pendent on payload mass, and as such the 3000km estimate will be used as the upper boundary for performance.

Performance Comparison

Parameter Real Value Simulated Value Average fuel consumption (kg/hour) 0.19 0.20 Flight velocity (m/s) 22.3-25.7 19.8-21.0 Endurance (hours) 26 24.5 Range (one way) (km) 3000 1800

Table 4.1.4: Performance characteristics of the real and simulated Aerosonde.

37 The simulated Aerosonde yields results that quite closely match those found for the real design. The only significant discrepancy is the difference in range between the simulation and real Aerosonde. There are two main reasons that are expected to have played a role in this result. The first is that the estimate given for range was for a varied version of the Aerosonde. The second is that a combination of the engine and propeller performance, and the aerodynamics of the simulated design combined to provide suboptimal flight configurations and power consumption.

The first reason is expected to be a relatively significant factor. The first source for the 3000km flight range [26] provides dimensions for an Aerosonde that is markedly heavier (25kg versus the current 8.2kg) despite having the same outer dimensions, which may be the result of a larger fuselage and larger fuel carrying capacity (as this source doesn’t con- tain an estimate for endurance, fuel capacity or fuselage size; only length, width, height, mass, speed and range). The second source [73] outlines the same exterior dimensions and mass of the Aerosonde examined, but its only references are to Wikipedia, and the Wikipedia article on the Aerosonde has no references for the specifications given. How- ever, an alternate source [10] details the record-breaking flight of the Aerosonde ”Laima” across the North Atlantic Ocean, spanning a distance of 3270km in a time of 26 hours 45 minutes, consuming approximately 3.9kg of fuel. However, this has an average speed of 120km/h (approximately 33.3 m/s), which is much faster than the quoted speeds from other sources, and as such likely used a different engine and potentially modified airframe compared to the more commercially-available Aerosonde UAVs.

The second reason is in-line with those presented for the MQ-1B, such that the engine, propeller and aerodynamic performance of the simulation are likely different to the char- acteristics of the real Aerosonde, which isn’t helped by the largely conflicting information available for the Aerosonde (and often does not specify what variant of the Aerosonde is being discussed). While attempts were made to congregate performance information pertaining to one variant of the Aerosonde (by comparing the dimensions and physical characteristics of the different sources), it is possible that incorrect data was allowed into the discretized design for the simulation. Attempts were made to correlate the simulated and real zero-angle-of-attack drag coefficients, but the drag at different angles of attack may have differed between the simulation and real performance. Similar effects can be expected from the wing aerodynamics (using a NACA airfoil instead of the SD airfoil), engine performance (using a scaled Rotax power curve for the EL-005 engine as no perfor- mance curves could be found), propeller performance (diameter found from the Russian Unmanned Vehicle Systems Association [4], number of blades found from images and all other parameters estimated based on resulting performance) and fuselage aerodynamics (using the same generic ogive cylinder fuselage shape).

38 The simulation of the Aerosonde was rerun, but instead of optimising for maximum en- durance, the flight was instead optimised for maximum range. However, it was found that the maximum range flight characteristics (fuel consumption, flight velocity, endurance and range) were the same for both methods of flight optimisation. This is because the Aerosonde propeller is operating at the engine’s stall RPM, as the optimal RPMs for maximum range and maximum endurance flight are both below the stall RPM, but the simulation disallows solutions that require RPMs outside of the engine’s allowable range. This forces both optimisation methods back to the stall RPM, which causes their opti- mised flight configurations to overlap. This effect is shown in Figure 4.1.8 below. Ad- justing the engine models to allow for RPMs between zero and the stall RPM found that the Aerosonde actually flies even slower for both optimisation methods (with the maxi- mum endurance optimisation flying slower than the maximum range optimisation). This further highlights the probability that the simulated Aerosonde’s propeller, engine and aerodynamic performances are notably different to those for the real Aerosonde. However, most of the results obtained are of the approximate magnitudes expected, which essen- tially demonstrates that inputting average-accuracy data into the simulation will yield average-accuracy results.

Overall, the performance of the simulated Aerosonde is mostly in-line with what is ex- pected. The simulated range falls short of the specified range, but given that the fuel consumption, velocity and endurance values all approximately align, it can be assumed that the range estimates were either incorrect or for variations of the Aerosonde UAV.

39 Performance Analysis

Figure 4.1.6: Aerosonde performance map based on craft angle of attack and mass.

Figure 4.1.7: Aerosonde performance map based on craft velocity and mass.

40 Figure 4.1.8: Aerosonde performance map based on craft velocity and angle of attack.

Figures 4.1.6, 4.1.7 and 4.1.8 above all show that the optimiser is once again correctly finding the lowest power operating point for the design. Figure 4.1.6 shows that as the vehicles mass decreases, the angle of attack decreases in order to keep the operating point in the ”valley” of lowest power consumption. Figure 4.1.7 shows that as the vehicles mass decreases, it gradually increases its velocity in order to stay at the lower power operating point. It is interesting to note that the power requirement throughout the flight is nearly constant, which is a result of the conservative engine model overestimating fuel requirements for low propeller power requirements. This is shown in Figure 4.1.8, which illustrates that the optimal flight configuration constantly lies on the lower flight velocity boundary of the operating envelope. Figure 4.1.8 also shows that the power consumption of the flight is essentially constant, as the operating points all lie approximately on the bottom of the velocity band at each angle of attack, which has an approximately constant power consumption along the length of the potential flight configuration band. The reason for the sharp cutting and constant power requirement of the flight configuration band is the result of the engine having a minimum RPM, below which it will stall. If the engine performance curves were linearly extrapolated down to zero RPM, zero fuel consumption, then the performance charts presented would look more like those seen for the MQ-1B (which operated within a narrow band of RPMs, and thus never reached its stall RPM during simulation).

The optimal performance of the Aerosonde provides an interesting comparison to the optimal performance of the MQ-1B. While the MQ-1B operated at a constant angle of attack and varied its velocity to meet lift requirements, the Aerosonde instead keeps its velocity relatively constant and reduces its angle of attack. This comes as a result of the

41 engine model used. Figure 4.1.8 shows that the optimal flight configuration consistently lies on the lower bound of the potential flight envelope. This a result of the ideal RPM of the Aerosonde being lower than its stall RPM for the propeller used, such that as the mass decreases and lift requirements decrease, the angle of attack is decreased to maintain flight velocity to prevent the engine from stalling (operating below its minimum RPM). If the engine curve for the Aerosonde continued to zero RPM, the Aerosonde would operate at a lower RPM. This was found in testing; if the engine performance curves were linearly extrapolated to zero RPM, zero power, then the craft flew at an approximately constant 10 degree angle of attack and around 1200 RPM, which is below the stall RPM of 2200. This flight configuration more closely mimicked the operation of the MQ-1B (maintaining a constant angle of attack and reducing velocity), but the performance of the engine forced the design to a new optimal configuration, which further demonstrates the validity of the optimiser.

The performance maps created for the Aerosonde once again confirm that the optimiser correctly finds the lowest power solution (velocity and angle of attack) at each vehicle mass. The optimiser also finds new, novel solutions as a result of constraints imposed onto it (such as minimum and maximum engine RPMs). These facts help validate the performance of the optimiser in finding the lowest cost flight configuration. Figure 4.1.7 also shows the ”artifacting” that was present in the MQ-1B’s velocity versus mass perfor- mance chart, and this is once again happening for the same reasons (increasing angle of attack beyond the stall point requires a higher velocity to fly, which ends up being plotted over the older data).

42 4.1.4 ScanEagle

Characteristics

The general characteristics of the ScanEagle are outlined below in Table 4.1.5. The chord of the main wing and the dimensions of the vertical stabilisers were measured using pictures produced by Insitu Pacific [42]. No information relating to the airfoil of the ScanEagle could be found, so it is assumed to be using the same airfoil as the Aerosonde (due to being a similar size and filling a similar role), which is the NACA 3510 airfoil. The discretized design file can be found in Appendix Q.

Parameter Value Wingspan (m) 3.1m [42] Airfoil NACA 3510 Fuselage length (m) 1.6 [42] Fuselage diameter (m) 0.178 [78] Aspect ratio ≈13 Engine 3W 2-stroke piston engine [27] Engine power (kW) 1.12 [27] Fuel used ”C-10” gasoline [42] Fuel energy density (MJ/kg) 44.24 [22] Fuel capacity (kg) 5.4 [41] [48] Dry mass (kg) 16 [42] Endurance (hours) 24 [42] Range (one way) (km) 1500 [41] Velocity (m/s) 22.2-30 [41][42]

Table 4.1.5: ScanEagle physical and performance characteristics.

43 Performance Comparison

Parameter Real Value Simulated Value Average fuel consumption (kg/hour) 0.23 0.24 Flight velocity (m/s) 22.3-30 17.7-20.8 Endurance (hours) 24 23 Range (one way) (km) 1500 1400

Table 4.1.6: Performance characteristics of the real and simulated ScanEagle.

The results for the simulated ScanEagle are the closest match to its real-life counterpart out of all of the real UAVs examined. The fuel consumption, endurance and range all closely match the expected values. However, as was also the case for the other simu- lated UAVs, the flight velocity is slower than expected. However, this discrepancy is explained when the local cost function given to the simulation is changed from minimis- ing power consumption to minimising energy requirement over a given distance (changing from maximum endurance to maximum range).

While the range and flight velocity of the simulated ScanEagle fall short of the expected values when optimising for minimum power consumption, the velocity and range rise to 22.8 m/s and 1500km respectively when optimising for range, while causing the endurance to drop to 21 hours. However, given that the flight configurations for maximum endurance and maximum range don’t necessarily coincide, finding this result actually further vali- dates the simulation, as it is able to correctly adjust the flight configuration based on the desired results. This change in the optimised parameter allows the simulated ScanEagle to meet all of the performance criteria found from research, and provides strong validation for the simulation, as it has managed to yield accurate results when given sufficiently accurate input data. This accuracy must be viewed with caution, however, since the assumptions made throughout the creation of the simulation naturally limit its accuracy. However, this result does prove that the simulation is able to find results within the expected range, and can find results that provide good agreement with the expected parameters.

Therefore, the performance of the ScanEagle is in-line with the expected results, which highlights the capability of the simulation to provide good results as long as good data is used initially.

44 Performance Analysis

Figure 4.1.9: ScanEagle performance map based on craft angle of attack and mass.

Figure 4.1.10: ScanEagle performance map based on craft velocity and mass.

45 Figure 4.1.11: ScanEagle performance map based on craft angle of attack and velocity.

The three graphs above show the optimised flight configuration of the ScanEagle on top of its performance map. The ScanEagle behaves in a manner similar to the MQ-1B, in that it maintains a relatively constant angle of attack for the majority of its flight, which is likely for the same reasons outlined for the MQ-1B. It can also be seen in all three graphs that as the flight progresses (decrease in mass, and subsequently decreased velocity) that the power requirement of the ScanEagle decreases, which is as expected given the reduced weight requiring less power to keep in the air. Figures 4.1.9 and 4.1.10 also show the positioning of the optimised flight configurations within the ”valley” of lowest power flight, which once again demonstrates the capability of the optimiser to find the lower power solution for a given set of inputs (aerodynamic, engine and propeller performance, as well as craft mass).

Overall, the ScanEagle simulation provides the most accurate results of the three UAVs examined, which demonstrates the potential accuracy of the simulation as long as accurate data is used for the input information. It is also able to clearly demonstrate the difference between maximum endurance and maximum range flight, while also clearly demonstrating that the optimiser is able to find the optimal flight configuration given a certain set of inputs. The ScanEagle simulation has been able to meet many criteria for the validation of both the optimiser and the simulation as a whole, and demonstrates the potential of the simulation to generate useful results.

46 4.1.5 Overall Real UAV Performance Analysis

The three UAVs examined have had varying levels of success in generating results that match the results found from literature. The MQ-1B’s fuel consumption, endurance and range all aligned between the simulation and expected results, while the flight velocity was significantly lower when optimising for endurance, and only slightly lower than expected when optimising for range. However, these variations in data are expected qualitatively given the potential sources of error identified, which were predominantly variations in aerodynamic, engine and propeller performance between the simulated and real MQ-1B. After taking these factors into account, the results found for the MQ-1B lie within the expected ranges as found from research.

On the other hand, the Aerosonde’s simulated fuel consumption, flight velocity and en- durance were found to be similar to the expected results, while the simulated range was found to be significantly shorter than expected. While variations in performance are ex- pected to have played a role in this result, it is expected that these sources of error are not significant enough to yield the difference in results found (1800km versus 3000km range). It is expected that the range estimates for the Aerosonde of 3000km were for altered ver- sions, with the specific modifications not detailed (as the sources for this range outlined either a significantly heavier design, or a significantly faster design, both of which didn’t align with data found from other sources). As such, the true range of the Aerosonde is expected to align with the simulated result relatively well once performance of the craft is taken into account, which leaves all of the results found for the Aerosonde within acceptable ranges.

The ScanEagle’s results were the most accurate of the three UAVs. Its fuel consumption and endurance closely aligned with expected values when optimised for endurance, while its velocity and range aligned with the expected values when optimised for range. Not only does this validate the data used and the way in which the simulation processes and simulates it, this also validates the optimiser, as it is able to correctly identify different ”optimal” solutions based on what the desired results are (i.e. whether maximum range or endurance is desired). The ScanEagle simulation provides good validation for the simulation and optimiser, as all results were naturally within the expected ranges without additional justification, and the finding of different solutions based on the desired goal highlights the robustness of the optimiser.

Where possible, all three UAVs operated in the same fashion; flying at a relatively constant angle of attack whilst decreasing velocity to minimise power usage as the vehicle mass decreased. However, the Aerosonde was attempting to operate at engine RPMs below the stall RPM, and thus had its optimal flight configuration forced back into the engine’s operating range, yielding the result of a constant decrease in angle of attack and increase in velocity as the vehicle mass decreased.

47 4.2 Example Design Process

An example design process was conducted in order to further validate the simulation. The results of the design process will provide insight into more nuanced effects associated with aircraft design, as well as provide insight into the performance of the optimiser.

4.2.1 Pre-Simulation

Mission Description

The mission file used for the example design process can be seen in Appendix R. The mission chosen for the example design process is a 500km straight line flight at an altitude of 100m. This was chosen due to its simplicity as a mission, and to provide a mission requiring a relatively long-range aircraft. The environmental parameters for the mission were defined at sea level as a temperature of 300K, air pressure of 101.25kPa and air density of 1.225 kg/m3 (fairly standard sea level values).

The global cost function for the mission (i.e defining the ”optimal” design) was given by the following: design static dead weight plus the initial fuel mass (dependent on geometry) plus five times the amount by which the design exceeded its fuel capacity. This was chosen in order to minimise the takeoff weight of the craft, whilst making full use of the designs fuel capacity (based on geometry). Additionally, it was decided to heavily penalise designs incapable of completing the mission (by adding on five times the amount of extra fuel needed), since it has been found in the past that having cost functions that don’t adequately penalise designs that cannot complete the mission yields essentially random-appearing results. This is because a design that might have used less fuel due to operating at zero-fuel-mass (elaborated in Section 3.5) will be unfairly benefited compared to a design that had to actually carry the extra fuel mass. Even taking this into account by means of equations that calculated the extra fuel required, as well as the extra structural mass to carry it, the results were still unfair as the increase in wing area to operate at the same performance was unknown, and increasing the wing area would also further increase mass. The global cost function chosen allows designs that barely run out of fuel to still have reasonable costs, providing cleaner-looking results.

The local cost function used for this optimisation was the energy requirement of the craft (minimising fuel consumption for a given distance and maximising range). This was chosen as it would minimise the fuel required for the mission and allow for the takeoff mass to be minimised as much as possible. Finally, the custom cost function was chosen to be the total fuel consumption (expressed as the sum of energy usage divided by the fuel energy density), which is only there to serve as a reference metric for comparisons between takeoff mass and fuel used.

48 Design Description

The full baseline design file can be seen in Appendix S. The geometries that were opti- mised were the wing and fuselage, with the specific parameters that were optimised being wingspan, root chord, tip chord, fuselage radius and fuselage length. These were chosen as they have the largest impact on the craft’s aerodynamics out of the geometries present. The baseline design had a wingspan of 1.5m, root and tip chord lengths of 0.15m, fuselage outer radius of 0.1m (with a fixed wall thickness of 4mm) and fuselage length of 0.6m. The wing mass was calculated using NASA’s Weight Estimation Methods for an estimated design gross weight of 5kg, while the fuselage had its mass calculated using a material density of 700kg/m3 to represent some form of light plastic (see Section 2.6 for an expla- nation of the mass data and calculations used). All other design parameters (including the engine and propeller used) kept constant throughout the optimisation process.

The parameters of the baseline design were chosen based on a few criteria. Firstly, the wings had to be at an average aspect ratio (which began at 10), as this isn’t at any particular extreme and will avoid the optimiser always being forced in one direction. Secondly, the fuselage size was chosen such that the fuel carried was approximately 3kg. This was because past simulations and research had indicated that this would be a fairly average fuel requirement for the given flight, which would allow design optimisation to either reduce or increase this value based on the possible variations in craft dead mass. This is related to the third criteria, which is the equation used for calculating fuel carrying capacity. The mass of fuel carried is defined by Equation 4.2.1 below. This equation gives the mass of fuel that can be carried in the fuselage assuming 30% of the fuselage length (the nose of the ogive cylinder) is taken up by electronics, and another 28.5cm is taken up by potential payload (assuming the engine is mounted externally on the rear of the fuselage, otherwise assuming the engine is part of this length). For the baseline design, this yields the desired 3kg fuel capacity. The airfoil was chosen to be the NACA 4510 airfoil, due to its effectiveness at low speeds as a result of its high cambering. Also note that all designs carry a fixed 2kg of dead mass to represent electronics and payload.

2 mfuel = π(Router − Twall) × (0.7 × L − 0.285) × ρfuel (4.2.1)

49 4.2.2 Optimisation Process

With the initial design, mission and goals set out, optimisation of the design could com- mence. It was decided that the fuselage geometry would be optimised on its own first, followed by the optimisation of just the wing, ending with an optimisation of both the wing and fuselage to determine if a local or global minimum has been found. Note that for each round of optimisations, the parameters being optimised are varied within a range of ±50% (with a normalised value of 1 corresponding to +50% and a normalised value of -1 corresponding to -50%), while the costs are normalised relative to the value of the baseline design for that optimisation round (such that the baseline design will always have normalised costs of 0, while a design with a true cost of 0 will have a normalised cost of -1, and a design with a true cost double that of the baseline will have a normalised cost of +1, corresponding to -100% and +100% respectively relative to the cost of the baseline design). Note that for the plots presented, the lines representing the top 100 designs are coloured based on their normalised cost values (with the lowest cost design being bright yellow, and the highest cost design of the 100 highlighted designs being black). All designs outside of the top 100 are coloured black. Note that all of the preliminary optimisations tested 200 randomly generated designs, while the final optimisation (optimising both the wing and fuselage simultaneously) tested 500 designs to ensure adequate coverage of the possible combinations.

50 Figure 4.2.1: Results of the first simulation (fuselage only).

Figure 4.2.1 above shows the results of the first optimisation. The colour bar on the right displays the normalised costs of the 100 best-performing vehicles, and indicates a reduction in global cost of up to around 15% is possible for this optimisation stage. The plot itself shows a clear trend in the variations that result in optimum performance, with a 50% reduction in fuselage radius and 50% increase in fuselage length being the optimal, with progressively smaller variations having a less noticeable effect on the global cost. It is also worth noting that the optimal design of this optimisation has a fuel consumption 25% lower than that of the baseline design (shown by its custom cost being at -0.25). This is because the reduced fuselage radius greatly decreases form drag, while the increased fuselage length slightly increases skin friction shear stress (by approximately 40% assuming other parameters are kept constant), but this is offset by the reduced circumference of the fuselage, resulting in a net decrease in skin friction of approximately 30% (as a 50% reduction in fuselage radius equals a 50% reduction in circumference, then FD ∝ Shear stress · L × radius = 1.4 × 0.5 = 0.7). It is worth noting that a 50% reduction in fuselage radius and 50% increase in fuselage length results in a net decrease in fuel capacity of approximately 40%. However, given the significant reduction in drag experienced by the craft, it is able to use less fuel and avoid being penalised for running out of fuel. Following this, the fuselage radius was decreased from 0.1m to 0.05m, and the fuselage length was increased from 0.6m to 0.9m.

51 Figure 4.2.2: Results of the second simulation (fuselage only).

Figure 4.2.2 above shows the results of the second optimisation. Based on the colour bar on the right indicating the potential reduction in global cost function, the current fuselage geometry is optimised based around overall design (before adjusting the wings). The penalty of the global cost function can be clearly seen taking effect in this graph, as some designs consume approximately 10% less fuel than the current baseline design while having normalised global costs of up to +0.8. This is because these designs further decreased the size of the fuselage, which resulted in insufficient fuel being carried, and thus they were heavily penalised for running out of fuel. The designs with the lowest cost functions besides the current baseline design have some opposing combination of increased fuselage length and decreased fuselage radius, or vice versa. It can also be clearly seen that a design with a 25% reduction in fuselage radius required a 50% increase in fuselage length. With the way fuel capacity has been delegated, this results in an approximately equal fuel capacity to the current baseline design, which is to be expected since the fuel consumption of the craft can’t be improved by too large a margin at this stage. This effect is maintained for designs with reductions in radii and increases in length. However, for designs with an increased radius and decreased length, fuel capacity is increased in order to offset the increased drag experienced by making the fuselage wider. For example, a design with a 50% increase in fuselage radius and 25% decrease in fuselage length can carry an additional 28% of fuel mass. However, this by definition increases takeoff mass (as the majority of the fuselage and fuel mass is comprised of the fuel), which worsens the global cost of the design. Following this, since the fuselage is as optimised as possible for this stage, the design was left unmodified and an optimisation was run on the wings.

52 Figure 4.2.3: Results of the third optimisation (wings only).

Figure 4.2.3 above shows the results of the first optimisation of the wings. The colour bar indicates that a reduction in global cost of just over 2.5% can be attained by reducing wingspan slightly, and reducing the root chord by around 35% and reducing the tip chord by around 45%. Reducing the size of the wing in this way can be seen to increase the fuel consumption slightly due to the reduction in lift generation from the reduced wing area. This effect would be offset slightly by the increased efficiency factor (as a result of the increased tapering and aspect ratio), but evidently not enough to maintain or improve fuel efficiency. Given the limited variations in global score, it can be predicted that the mass of the wings is low compared to the total vehicle mass, which is what is found when the designs are inspected. The wings are found to comprise 0.64kg of the 4.6kg dry mass of the current baseline design. As such, any relatively minor variations in wing mass will have little direct effect on the takeoff mass. However, reducing the wing size too much will result in too much fuel being consumed and a penalty being applied by the global cost function. This is what is found in the cost storage files, with the designs that have significantly reduced wingspans without sufficient increases in the chord lengths consuming over 2.1kg of fuel when only 1.77kg of fuel is available, resulting in a penalty to the global cost function of +1.65, which is a 25% increase in the normalised global cost on its own. For the sake of analysing a second optimisation round for the wings, the wingspan was reduced from 1.5m to 1.35m, the root chord was decreased from 0.15m to 0.1m and the tip chord was reduced from 0.15m to 0.08m.

53 Figure 4.2.4: Results of the fourth optimisation (wings only).

Figure 4.2.4 above shows the results of the second wing optimisation. The colour bar indicates that a reduction in global cost of 0.5% can be obtained, which would be ineffec- tual to try to obtain as this level of precision is undoubtedly beyond the accuracy of the simulation. It can be seen that, for the most part, designs with similar or improved global costs relative to the current baseline design feature opposing changes in root chord and tip chord, with varying magnitudes of wingspan increasing. It is interesting that at this stage of the optimisation an increase in wingspan of potentially up to 50% is recommended, given that the previous optimisation stage recommended a reduction in wingspan. This is likely because, having reduced the root and tip chords after the previous optimisation, the root and tip chords can now be reduced to even lower values. This has the effect of allowing the wing to be driven to extremely high aspect ratios if the wingspan is increased, with the highest aspect ratio wing that has an improved global cost having an aspect ratio of 35, which is a typical value for sailplanes, and usually requires high strength composite materials to attain without excessively increasing the mass of the wing. As such, it is infeasible to accept this design as the optimal design for a hobbyist, as they likely won’t have access to these materials. Therefore, in order to confirm that the current design is the most optimised design for the given criteria, an optimisation will be run, varying both the wing and fuselage parameters without changing the baseline design, in order to confirm if there are any superior designs.

54 Figure 4.2.5: Results of the fifth optimisation (wings and fuselage).

Figure 4.2.5 above shows the results of the final optimisation. Note that this optimisation simulated 500 designs in order to ensure good coverage of the possible geometry combi- nations, given that all of the geometries being optimised were varied for this iteration. The colour bar indicates that an improvement in global cost of approximately 2% can be obtained. The figure shows that, for the most part, any variation in one parameter is countered by an opposite variation in a corresponding parameter (with the most notable example of this being the variations in fuselage radius and length, with a clear opposing effect being visible). A similar trend extends to the wing parameters for the most part, but given the low mass of the wings compared to the mass contributed by the fuselage and fuel, the effect of the wings on the global cost is somewhat negligible until the wing area is reduced sufficiently enough that the design is penalised by the global cost function for running out of fuel. In the case of this optimisation, the variations that result in the maximum reduction of global cost do so by the means of reducing the fuel consumption and fuel carried, as it can be seen that all designs that have reduced global costs (bright yellow lines) fall below the 0.00 mark for the custom cost, which indicates reduced fuel consumption. The typical examples of this shown are from reduced fuselage radius and increased fuselage length, with variations in wing parameters made to ensure that the optimal amount of lift is generated (keeping the wings big enough so that high speeds aren’t necessary, but keeping them small enough to keep mass low). Therefore, it given that the global cost can only be reduced by an additional 2% at this stage, it is relatively safe to say that the design has been sufficiently optimised given the level of accuracy of the simulation.

55 4.2.3 Final Results

The optimised parameters of the wing are outlined below in Table 4.2.1, alongside the global and custom costs at the stages where the design was actually varied. It is interesting that the design happened to able to be essentially completely optimised (in terms of fuselage and wing geometry) after one optimisation round for each of the geometries modified, with the final optimisation showing that the final accepted design had a global cost within 2% of the true optimal design, the accuracy for which is beyond the capability of the simulation at this point. This rapid optimisation comes as a result of the ±50% variations specified for the optimisation, alongside the fact that the initial design was relatively similar to the final design.

Parameter Initial 1 Final Wingspan (m) 1.5 1.5 1.35 Root chord (m) 0.15 0.15 0.1 Tip chord (m) 0.15 0.15 0.08 Fuselage radius (m) 0.1 0.05 0.05 Fuselage length (m) 0.6 0.9 0.9 Global cost (kg) 8.28 6.76 6.59 Custom cost (kg) 2.51 1.72 1.75

Table 4.2.1: Parameters of the optimised design at each unique iteration of the optimi- sation process. Parameters that changed are shown in bold. The global cost is takeoff weight with a penalty for running out of fuel, and the custom cost is fuel consumed.

Some interesting trends can be observed from the data gathered over the course of the optimisation. Aside from the expected results such as increasing wing area and reducing fuselage radius resulting in reduced fuel consumption, there are some more nuanced effects being displayed.

The first is that it can sometimes be beneficial to use more fuel by reducing the size of the wings, as the reduction in wing mass can offset the mass gained as extra fuel required. This would typically be an unexpected result, as the wings are essentially the only practical source of lift for the aircraft. However, given that wing mass approximately scales with wingspan squared, there is a hard limit as to when increasing wingspan stops becoming beneficial to the performance of the craft, as the wing adds more weight than it can lift. However, when there are other sources of mass, this limit arrives much sooner, as the wing needs to not only lift itself but also the rest of the vehicle, causing the point at which increasing the wing size becomes detrimental to arrive sooner (as the wing needs to generate enough lift to essentially carry a multiple of its own weight). This effect is particularly evident when there is more than sufficient fuel available in the fuselage (which is why the fuselage was optimised first), as the design can use more fuel without causing an increase in the global cost.

56 The second more intricate effect is the sacrificing of fuel capacity in order to require less fuel. While this may seem more obvious for needlessly large designs that carry significant amounts of excess fuel, when optimising a small design that is often carrying just enough fuel to complete the mission, it isn’t such an obvious conclusion. As shown in Table 4.2.1, the first modified version of the baseline design has a reduced fuselage radius and increased fuselage length. This reduced its fuel capacity from 3kg to 1.77kg, a reduction of 41%. However, this reduction came from the shrinking of the vehicle fuselage, which not only reduced the mass of fuel it had to carry, but also decreased the drag it experienced, the effects of both culminating in reducing the fuel consumption required, which allows the takeoff mass to be reduced. As such, at this stage of the optimisation, the global cost was reduced by 1.52kg while the fuel consumption was reduced by 0.79kg, which are significant reductions given the scale of the aircraft.

The third less obvious effect is the leverage of wing efficiency parameters in order to offset losses in other areas. The fourth optimisation iteration highlights this, in that it recommends the wingspan be increased by 50%, with the root and tip chords being reduced by between 25% and 40%. This would cause the wing area to either be held constant or reduced depending on the chord length chosen, which would typically worsen performance, especially since the wing mass scales with wingspan squared. However, the reason this effect is found is because increasing the wingspan while decreasing the chord lengths increases the aspect ratio, which increases the lift and reduces the drag generated by the wing (due to finite wing effects). The tip chord is also typically reduced by a greater amount than the root chord, which also takes advantage of the benefits of tapering the wing for the efficiency factor, which has an effect on the induced drag, reducing fuel requirements. It seems that the reduction in the chord lengths after the third optimisation iteration pushed the aspect ratio range examined in the next optimisation iteration over some kind of boundary, where the chord lengths could be shortened enough relative to the wingspan such that the wing area could be reduced while still improving performance due to the extremely high aspect ratio. This effect was likely only observed due to the fact that the chord lengths were shortened after the third optimisation, as the wingspan was also shortened slightly after that iteration, while it would have been expected to see an increase in wingspan recommended for both wing optimisation stages.

Ultimately, all of the more nuanced effects found from the optimisation process are related to trade-offs that would conventionally be unexpected but yield beneficial results under the right conditions. However, after examining relevant literature and with the information outlined in the literature review (Section 2), these effects are valid and serve to validate the simulation and optimisation process, as it is able to reproduce typically unconventional results correctly. Therefore, the example design process as a whole has served to validate the functions of the simulation and optimisation, and demonstrate the capability of the system.

57 4.3 Off-Design Performance

The optimised design found from Section 4.2 has been simulated under conditions different to those under which it was optimised. Firstly, this entails examining the effects of variations on the design to determine how robustly it can complete its mission. This is followed by examining variations in the mission, to analyse if the design is capable of completing a wide range of missions or if it is limited to a very narrow range of missions.

4.3.1 Design Variations

The first off-design analysis conducted analysed variations in the design to determine how robust the design is to factors such as errors in manufacturing. This will also provide an opportunity to analyse if the effects of these parameters being varied falls in-line with what is expected. The overall results of this analysis can be found in Table 4.3.1 below. Note that the same mission is used for this analysis as was used for the optimisation, with an increased simulation resolution, which is the reason that the results for the baseline design are different here than in the example design process. Note that ”big” and ”small” prefixes have their associated parameters (all parameters that were optimised in the example design process) increased or decreased respectively by 10%, while the heavy and light designs have their dead masses adjusted by 1kg. While the overall results are shown in the table below, a discussion on the performance of the designs can be found below the table. Note that, as was the case for the example design process, the designs examined here use the energy requirement for a given distance as their local cost (therefore the flight solver will attempt to maximise the range of the design).

Angle of Velocity Global Custom Design attack (deg) (m/s) cost (kg) cost (kg) Baseline 1.9-2.6 23.8-26.2 6.59 1.70 Big fuselage 1.9-3.2 25.8-27.5 7.61 1.84 Small fuselage 0.5-1.9 24.8-25.4 8.28 1.62 Big wings 0.5-1.3 23.8-26.0 6.64 1.68 Small wings 2.7-3.4 24.9-27.9 6.54 1.75 Heavy 1.9-2.6 25.9-28.2 7.63 1.77 Light 0.5-1.9 23.3-25.0 5.59 1.65

Table 4.3.1: Results from the off-design design variation analysis. Note that angle of attack and velocity values are given as the range experienced over the course of the flight.

The baseline design achieves the same global score as it did during optimisation, with a slightly reduced fuel consumption due to the increased simulation resolution due to the lower number of designs being simulated. This baseline design serves as a comparison for the performance of the other designs, while an in-depth analysis of the performance of the baseline design over the course of a mission is examined in Section 4.3.2.

58 Figure 4.3.1: Performance map of the ”big fuselage” design.

The ”big fuselage” design can be seen to fly at a slightly higher maximum angle of attack and at a higher velocity than the baseline design. This is to be expected, as the increased mass of the design requires additional lift force to be generated, while also competing with the increased drag of the larger fuselage. Figure 4.3.1 shows a performance map for the design of the energy requirement for a given flight leg, as a function of vehicle mass and angle of attack, with the flight configuration plotted on top. This shows that as the flight progresses (and the vehicle mass decreases), the angle of attack of the craft decreases in order to keep operating at the most energy efficient configuration, shown by the tracking of the optimal performance points along the bottom the ”valley” of peak efficiency shown. It is also shown that the ”big fuselage” design doesn’t use all of its fuel, which is demonstrated by the fact that the design optimal performance points don’t reach the minimum mass plotted (note that all of these performance maps have the mass range defined between the dry mass and the takeoff mass of the vehicle, showing the potential masses at different fuel levels). This is as expected, since the increased fuselage size allows the craft to carry an additional 0.84kg of fuel, while only consuming an additional 0.14kg (shown by the custom cost). Therefore, while the craft does require additional fuel to overcome the increase in drag and mass, it isn’t so significant as to result in the design running out of fuel (using only 1.84kg of its available 2.61kg). An interesting effect to note is the steep increase in energy requirement shown in Figure 4.3.1 at an angle of attack of approximately 12.5 degrees. This comes as a result of the fact that the wings for all designs examined have a fixed incidence angle of 3 degrees. Therefore, when reaching an angle of attack of 12.5 degrees, the wing is effectively at an angle of attack of 15.5 degrees, which would be expected to be in the range of stalling, thus causing a sharp increase in energy requirements to maintain flight (this effect is seen for all designs examined here as they all use the same airfoil). Therefore, the performance of the ”big fuselage” design is as expected, and also demonstrates the ability of the flight optimiser to minimise the local cost function.

59 Figure 4.3.2: Performance map of the ”small fuselage” design.

The ”small fuselage” design can be seen to fly at lower angles of attack than the baseline design, with a reduced velocity range (with a higher minimum velocity and lower maxi- mum velocity). This is as expected, since the smaller fuselage limits the amount of fuel that can be carried, reducing the lift required. The reduced fuselage size also reduces the drag that the craft experiences, allowing it to fly faster with less penalty. Additionally, since the mass of the craft changes less than the baseline design (due to carrying less fuel), the overall range of flight configurations it covers is reduced. This combination of effects has the result of reducing the angle of attack (due to the required lift) and maintaining a similar velocity (due to the reduced lift generation by the lower angle of attack being offset by the reduced mass). Figure 4.3.2 shows that the optimal angle of attack for the craft is fairly low, once again with the craft operating at its most efficient points. However, as demonstrated by the increase in global cost of this design, it does run out of fuel (using 1.62kg whilst only carrying 1.12kg), which heavily penalises its global cost. This justifies the example design process as it validates that further decreasing the fuselage size has detrimental effects on the global cost that was examined. Therefore, the performance of the ”small fuselage” design is as expected given its variations, with the results aligning with those expected from literature, while also verifying the performance of the design optimisation process.

60 Figure 4.3.3: Performance map of the ”big wing” design.

From Table 4.3.1, the ”big wing” fuselage can be seen to fly at a lower angle of attack and velocity than the baseline design. This is because the increased wing area enhances its lifting capabilities, allowing both the angle of attack and velocity to be reduced whilst still generating sufficient lift, which shows good agreement with prior research. The table also shows that the design uses 0.02kg less fuel than the baseline design (1.68kg vs 1.7kg) while having an increase in global cost of 0.05kg due to the increase in wing mass. This validates the performance of the optimisation process, as it specifically examines a design with a larger wing and demonstrates how its global cost is negatively affected. Figure 4.3.3 shows the flight configuration of the vehicle over the course of this mission. It can be seen that the design does not run out of fuel (due to the absence of black circles on the left boundary), and shows that it operates at a relatively constant angle of attack for the majority of the flight. This corresponds to the velocity range shown in Table 4.3.1, as the reduction in required lift manifests as a reduction in velocity as opposed to a decrease in angle of attack, up until the reduction in mass is significant enough to warrant reducing the angle of attack and increasing velocity in order to reduce induced drag (as induced drag scales with the square of lift coefficient). Therefore, the results of the ”big wing” design align with what is expected, while the flight configurations found also show the correct operation of the flight solving module.

61 Figure 4.3.4: Performance map of the ”small wing” design.

From Table 4.3.1, it can be seen that the ”small wings” design has a minor (<1%) decrease in global cost and a 0.05kg increase in fuel consumption when compared to the baseline design. The second last optimisation round in Section 4.2 above showed that there were potential combinations of slightly smaller wings that showed marginal improvements in global cost, but these variations weren’t implemented due to how small the improvement was. Therefore, this improvement in global cost doesn’t contradict what was found during the design optimisation process. The table also shows that the design flies at a higher angle of attack and higher velocity than the baseline design. It’s interesting to note that the same ”cancelling of effects” shown by the ”big wings” design to maintain similar velocities to the baseline design isn’t shown operating in reverse here. It is expected that this was not seen here because it was essentially a coincidence for the ”big wings” design, such that it just happened to be operating under certain conditions that allowed the velocity-maintaining effect to be observed, which isn’t present at other conditions. It was expected that the ”small wings” design would fly at a higher angle of attack and velocity, as the mass of the craft is still quite similar to the baseline design whilst having a smaller lifting area, necessitating an increase in specific lift, which agrees with the results found. Figure 4.3.4 shows the design flying at relatively constant angles of attack, with a sudden decrease at approximately half fuel (halfway between the minimum and maximum masses examined). Based on the performance maps examined so far, there seems to be some kind of ”critical point” in craft mass, where it becomes more efficient to decrease the angle of attack rather than to decrease velocity. It is expected that this is due to fluctuations in the lift and drag data generated by XFOIL and in the linear interpolation used, which is demonstrated by Figure 4.3.5 below. However, overall performance of the craft is as expected from both its variation relative to the baseline design and its performance over the course of the mission.

62 Figure 4.3.5: Lift-to-drag ratio of the NACA 4510 airfoil, with a velocity of 30m/s and chord length of 0.09m.

Figure 4.3.5 shows the points used for interpolation of the lift-to-drag ratio for the NACA 4510 airfoil, as well as the interpolated values between the points. The airfoils are sim- ulated at intervals of 0.25 degrees within XFOIL. There is clearly visible ”jitter” within the curve for the lift-to-drag ratio, which explains why the ideal angle of attack changes in larger steps than the 0.1 degree steps analysed within the simulation, as the change in gradient makes it more efficient to lower the velocity more, until the point where velocity is low enough that it becomes feasible to decrease the angle of attack by a larger amount and increase velocity slightly. It can also be seen that the fluctuations are more significant at lower angles of attack, as the lower magnitude of the lift and drag coefficients results in equal values of fluctuations having a larger impact on the data. It is not expected that this has a significant impact on the overall performance of the designs, but instead it only slightly changes the current optimal configuration (as the velocity is still decreasing to try to reduce energy consumption).

63 Figure 4.3.6: Performance map for the ”heavy” design.

Table 4.3.1 shows that the ”heavy” design (increased mass by 1kg, carrying the same amount of fuel) has an increase in fuel consumption of 0.07kg and an increase in global cost of 1.04kg. This suggests that the design runs out of fuel and is penalised by the global cost function, since the global cost should otherwise only be increased by 1kg. This is indeed found to be the case, with the design over expending its fuel by approximately 8 grams. This demonstrates the reasoning for the global cost function chosen: a design that just barely runs out of fuel is not immediately ruled out, but instead heavily punished so that only designs with just barely insufficient fuel are left with reasonable cost values. The table also shows that the design flies at a similar angle of attack and higher velocity than the baseline design, which matches the expected results as an additional 1kg of mass needs to be carried for the entire duration of the flight. It is interesting however that the angle of attack range doesn’t change. This is presumably due to the fact that the mass doesn’t directly affect the vehicles aerodynamics, and thus a certain lift-to- drag ratio peak fluctuation (explained by Figure 4.3.5 above) will remain. Since the design ran out of fuel in the final step of the simulation, it is not explicitly shown to be out of fuel on its performance map (as the fuel mass is calculated after determining the flight configuration and plotting). The performance map (Figure 4.3.6) shows the trend of tending to operate at a constant angle of attack before suddenly decreasing that was demonstrated in previous performance maps, jumping from 2.6 degrees to 1.9 degrees, presumably for the same reasons (slight fluctuations in the data produced by XFOIL resulting in sudden variation in aerodynamic performance as opposed to a smooth curve). Overall, the craft performs as expected and provides further validation to both the simulation and optimisation processes.

64 Figure 4.3.7: Performance map of the ”light” design.

From Table 4.3.1, the ”light” design can be seen to fly at a lower angle of attack and lower velocity than the baseline design, with a 1kg reduction to the global cost and 0.05kg reduction in fuel consumed. The lower angle of attack and velocity are naturally expected due to the reduction in lift required to maintain flight. The reduction of global cost is also in-line with what is expected, as the global cost only factors in the fuel available at the beginning and how much additional fuel is needed, as opposed to just the fuel consumed. Therefore, reducing the dry weight by 1kg only reduces the global cost by 1kg because the initial fuel mass is the same. The fuel consumption is reduced by 0.05kg however, which is also as expected given the reduced craft mass. Figure 4.3.7 shows the discrete stepping down of angle of attack as the mission progresses, with the design clearly not using all of its available fuel (as expected due to its reduced mass). The performance of this design over the course of its flight is similar to that of the other designs analysed, and is also in-line with what would be expected (a reduction in lift generation over the course of the mission as the mass of fuel remaining decreases).

Results Analysis

It can be seen on all performance maps presented that the energy requirement for flight sharply increases at approximately 12 degrees. This is because of the angle of incidence of the wing (3 degrees) causing the wing to be operating at an angle of attack of 15 degrees, which causes stalling, resulting in significant losses and an increase in the energy required to maintain flight. It can also be seen that the stall angle has a weak dependence on the velocity, as the increase in flow turbulence delays the flow separation that causes stalling. These results are expected and demonstrate the ability of the simulation to capture stalling effects.

65 Additionally, it was found that all designs appeared to have some sort of ”critical mass” where it became more efficient to decrease angle of attack than to decrease velocity. It was then found that the cause for this was fluctuations in the aerodynamic performance data created by XFOIL at a resolution of 0.25 degrees, with the linear interpolation between these points causing there to be more optimal pathways of reducing the energy requirement (by decreasing only the velocity, until such a point where it is more efficient to decrease angle of attack by a larger margin, resulting in velocity being slightly increased). While a smooth reduction in both angle of attack and velocity would typically be expected to maximise range, the angle of attack was instead found to discretely step between angles larger than the resolution simulated, due to the interpolation between the original points provided. It is not expected that this has had a meaningful effect on the overall results provided, especially since all designs would suffer from the same effects, as well as the fact that the velocity is still correctly reduced to account for the delay in reducing angle of attack.

As expected, the designs with the smallest fuselage, biggest wings and lowest masses con- sumed the least fuel, given their more favourable aerodynamic characteristics. However, it was found that the design with the small fuselage was penalised heavily by the global cost function for not carrying sufficient fuel (and thus had the highest global cost of the designs analysed), as the reduction in fuel capacity greatly outweighed the reduction in fuel consumption. The ”heavy” design was found to be barely incapable of completing the mission fully, and was penalised by the global cost function by +0.04kg as a result. However, this provided validation for the cost function chosen, as it demonstrates how a design with good potential that is unable to complete the mission doesn’t need to be completely ignored, as it still had a reasonable global cost and could be subsequently modified to carry sufficient fuel.

All designs were found to be consistently operating at their lowest energy consumption points, validating the function of the flight solver and its ability to determine the lowest cost flight configuration. The results found for each design also align with those that would be expected, which validates the overall simulation functions as operating correctly.

Overall, the design variation analysis provided good support for the successful and correct functioning of the optimiser, flight solver and simulation as a whole, and provided useful insight into more nuanced effects.

66 4.3.2 Mission Variation

The second off-design analysis conducted analysed the performance of the optimised de- sign when tasked with a more complex mission, including operation at different altitudes, ascents and descents. The mission file can be seen in Appendix T, but the main variations made are in the flight path taken. The mission can be described as the following:

1. 100km horizontal distance at a constant altitude of 100m.

2. 20km horizontal distance and ascent of 2km.

3. 100km horizontal distance at a constant altitude of 2.1km.

4. 20km horizontal distance and ascent of 1km.

5. 100km horizontal distance at a constant altitude of 3.1km.

6. 30km horizontal distance and a descent of 3km.

7. 30km horizontal distance at a constant altitude of 100m.

This mission covers a horizontal distance of 400km and features different climb rates and different straight line flights at different altitudes, to examine the effects of differing climb rates and atmospheric properties on the craft.

Figure 4.3.8: Flight parameters over the course of a mission.

67 Figure 4.3.8 shows how the parameters of the craft vary over the course of a mission. The air density and climb angle are controlled directly by the current position along the flight path, as the vehicle is fixed to a certain location and climb angle to force it to follow the waypoints. Note that the structure of the mission was level flight, followed by a climb, level flight, climb, level flight, descent and level flight.

The power requirement can be seen to increase from an average level of around 4200W to up to around 6500W for the first climb (5.7 degree slope for the first climb, and around 3 degrees for the second climb). The power required to climb also increases as the altitude is increased, as the reduction in air density reduces the lift generated, requiring an increase in velocity to overcome the reduction in density, requiring increased propeller RPM. The power requirement during descent can be seen to drop to around 3000W, which indicates that the descent angle is not sufficiently large to allow the craft to glide (descent angle of -5.7 degrees). Given that the craft has a peak lift-to-drag ratio of approximately 9.5 (see Figure 4.3.9 below), this corresponds to a zero-power glide slope of approximately 1 6 degrees (given by atan( )). Therefore, if the glide slope was slightly steeper, the L/D craft wouldn’t have to consume any fuel. This result was corroborated by testing, by manually changing the the slope of a test mission file, with zero power being consumed for a descent of 1040 metres over a horizontal distance of 10km, equalling a zero-power glide slope of 5.94 degrees. The reason the power consumption is still so significant (around 3000W when the craft is about 0.25 degrees from zero power usage) is due to the engine model, which intentionally overestimates fuel consumption for very low propeller power requirements, to mimic the effect of the reduced efficiencies engines operate at when under partial loading. Therefore, the power consumption of the craft aligns with what would be expected.

Figure 4.3.9: Lift-to-drag ratio of the vehicle at various angles of attack.

68 The vehicle velocity can be seen to steadily decrease over the course of level flight, with an increase in velocity during ascents and a decrease in velocity during descent. It can also be seen that velocity is increased in regions of lower density, as the reduced air density decreases the lift generation of the vehicle, which must be offset by either increasing the angle of attack or velocity. As Figure 4.3.9 shows, the peak lift-to-drag ratio of the vehicle occurs at around 2.5-4 degrees angle of attack. As such, since the vehicle flies at an angle of attack of 2.6 degrees for the majority of the flight (due to it being the peak lift-to-drag ratio), the velocity is instead increased to maintain lift. This effect in reverse is seen for the steady level flight periods, where the mass of the vehicle drops, which causes a reduction in flight velocity whilst maintaining angle of attack. During periods of climb or descent, the velocity is essentially controlled by the air density, as the climb and descent angles are quite minor (up to 5.7 degrees maximum in either ascent or descent). As such, the lift and drag vectors are still quite close to their level-flight orientations, reducing the need to change the velocity and increase thrust to balance the changing vector orientations. Instead, only the thrust is changed in order to provide the potential energy to change altitude, whilst maintaining a roughly constant velocity for a given altitude (it can be seen from interpolation that the craft velocity would decrease linearly from the first level flight period to the last level flight period if no climbs were present, by inspecting the gradient of the velocity curve for the first and last steady flight periods). Therefore, the velocity of the craft over the course of the flight aligns with what would be expected from literature.

The angle of attack of the craft during most stages of level flight remains at a constant 2.6 degrees, with the velocity being used to trim the vehicle’s lift generation. During the first climb, the angle of attack drops to 1.9 degrees (in order to align the thrust vector more closely with the direction of travel in order to climb effectively) and approximately holds steady until the climb is levelled-out. During the second climb, the angle of attack is kept constant, with it jumping to a higher angle of attack upon levelling out, which gradually returns back to 2.6 degrees over the course of the level flight. Finally, during the descent period near the end of the mission, the angle of attack is initially increased, with it decreasing steadily to 1.3 degrees over the course of the descent, then returning to 2.0 degrees for the final level flight. It is expected that for the second climb, the air density and craft mass have become low enough that it is no longer more efficient to point the thrust vector closer to the velocity vector, and instead, upon levelling out at the new, higher altitude, it is actually more efficient to pitch up beyond the 2.6 degree point due to the velocity required to maintain flight, which gradually returns back to 2.6 degrees over time. It is interesting then that a similar pattern occurs for the final descent, beginning with an initial angle of attack increase, with a steady decrease to 1.3 degrees before the craft levels out at 2.0 degrees. It is expected that this occurs because of the further decrease in craft mass, such that a given force can cause greater acceleration. As such, the craft increases its angle of attack in order to increase the drag experienced (as

69 the craft always maintains equilibrium flight to ensure linear travel between waypoints), with a very minor amount of thrust used to maintain forwards velocity (less than 0.4 Newtons for the entirety of the descent phase, whilst level flight required between 5.4 and 6.7 Newtons depending on mass). As such, after inspection, the angle of attack of the craft over the course of the mission aligns with what is expected, with the likely reasons for the angles of attack seen presented.

Finally, it can be seen that the mass of the craft decreases fairly steadily over the entire duration of the flight, with the gradient of the curve decreasing very slightly over the course of the mission, with slight variations experienced during climbs and descents (proportional to the power consumption at those points in time). As such, the mass of the craft over the course of the mission aligns with what is expected.

Results Analysis

The variations in craft parameters (power consumption, angle of attack, velocity and mass) over the course of a more complex mission all align with what would be expected from literature. One of the more interesting aspects of the simulation was how the velocity was used to trim the lift generation of the craft, such that the design stayed at its peak lift-to-drag angle of attack for nearly the entirety of the flight. It is also interesting to examine the effects of operating at different altitudes (note that the engine performance functions are altitude-independent), such that the velocity was again used to trim the necessary lift generation, with the velocity being approximately inversely proportional to air density. It was also found that the simulated zero-power glide slope of the design aligns with its analytically-found value based on its aerodynamics, which validates the simulation as it is able to correctly model unpowered gliding.

Therefore, the simulation and flight solving processes have been given further validation, as not only do the macroscopic results of a mission (such as total fuel consumption, range and endurance) align with the expected results, the time-dependent parameters are also shown to agree with the expected results, with likely explanations available for all of the effects seen.

70 5 Discussions and Recommendations

5.1 Trends Observed

A number of unique trends have been observed as being reproduced by the simulation, with further inspection being able to provide plausible reasons for the causes of these effects.

It has been noticed that low-speed flight is typically ideal for craft endurance, whilst an increase in speed will often improve the vehicle’s range. This is because while the endurance depends solely on the rate of fuel consumption (such that minimising fuel consumption at the cost of all other factors will improve endurance), range depends on a combination of the rate of fuel consumption and velocity (such that using extremely little fuel but not moving at all doesn’t provide a particularly good range). This effect is reproduced within the simulation and agrees with literature, as commercial aircraft are often more fuel efficient for a given distance by travelling faster, reducing angle of attack and the induced drag coefficient, while maintaining lift, resulting in a slightly increased power consumption but shorter travel times, resulting in a net decrease in total fuel consumption.

It was also noted (predominantly in the validation of real UAVs, Section 4.1) that the overall performance of a craft is not typically dominated by either one of engine/propeller performance or aerodynamic characteristics. The performance maps presented show the optimal flight configuration lying slightly off of the peak engine/propeller efficiency as well as the peak lift-to-drag ratio, with their combined near-peak efficiencies being more beneficial than maximising either one. This occurs due to the increase in fall-off rate of the parameters as you move away from the peak (as the peak is a local maximum or minimum and therefore has a local gradient of zero), such that picking a point halfway between the two peaks is more beneficial than picking an operating point on one peak. One instance where the engine performance dominated was for the Aerosonde UAV, which had its operating ranges limited due the tendency of its engine to operate below its stall RPM. As flight configurations that operated below the stall RPM were discarded, the optimal flight configuration of the Aerosonde was forced to the lower RPM boundary for the entire duration of the flight.

Another interesting trend that was observed for most designs was the tendency to use the velocity of the craft as a form of trim to keep the lift generation just sufficient to maintain equilibrium flight, as a result of the angle of attack being held constant for most cases, or otherwise decreasing slightly over time. This is because the vehicles would operate at their peak lift-to-drag angle of attack (which is dependent solely on aerodynamic characteristics and not mass). As such, the most efficient configuration to operate at (before taking into account the associated engine and propeller performances) would be at the angle of attack that maximises the lift-to-drag ratio (as this allows the least drag force for the given lift

71 force, where the lift force must equal the vehicle weight for level flight and therefore is fixed).

A trend that was identified as part of the design optimisation process was the trade-off between parameters. For example, the most optimal design found in the first fuselage iteration had a 50% reduction in fuselage radius and a 50% increase in fuselage length. This caused a 40% reduction in fuel capacity, but decreased the fuel required by 25-30% as a result of a reduction in skin friction and form drag. Given that the pre-optimisation design had fuel to spare, this trade-off was highly beneficial, since not only did the design use less fuel (allowing a reduction in size and reducing takeoff mass) but it also had a reduced capability to carry fuel (thus having less fuel left over at the end). Since the designs were always assumed to begin with the maximum fuel possible, this provided benefits to the global cost from two separate sources.

Another trade-off that provided benefits to the global cost was the reduction in wing size recommended by the third optimisation (which was the first optimisation of the wings). This had the expected result of increasing fuel consumption as a result of the peak lift- to-drag ratio being reduced (since the lift and drag of the wings were reduced, while the drag from the fuselage stayed constant, resulting in a lower lift-to-drag ratio). However, the reduction in wing mass (due to the wing mass scaling approximately with wingspan squared) lowered the total weight of the vehicle, with the reduction amount tuned so that the fuel consumed was marginally less than the fuel capacity, making full use of the fuel on board.

Yet another trade-off that was identified was the reduction in wing area in order to improve the efficiency of the wing. The second wing optimisation showed that an increase in wingspan of 50% and a reduction in chord lengths of between 25-40% provided a reduction in global cost and fuel consumption. This is because, having reduced the chord lengths in the previous iteration, a subsequent reduction of chord lengths and increase in wingspan could drive the aspect ratio to extremely high values (up to 35). The taper of the wings was also increased (taper ratio reduced) by shortening the tip chord more than the root chord. These effects combined increased the lift and reduced the induced drag enough that a smaller wing area was sufficient to maintain flight without running out of fuel, whilst decreasing the mass of the wing by a small amount.

A trend that was noted during the off-design analysis of a varied mission was the rela- tionship between air density, flight velocity and power requirement. The graph displaying the changes in key parameters over the course of the mission (Figure 4.3.8) consistently demonstrated that a reduction in air density results in an increase in velocity and power requirement (when flying to maximise range). The increase in power first seems counter- intuitive, as it is known that airliners fly at high altitudes in order to reduce their costs and reduce travel time. However, the reason that this is the case is because of the higher

72 velocity. Due to the reduction in air density, either an increase in the coefficient of lift or velocity is required. Since the vehicle spent the majority of its mission operating at its peak lift-to-drag angle of attack (2.6 degrees), the velocity was increased in order to maintain lift generation. As a result, the advance ratio of the propeller was changed. This effect, alongside the reduction in thrust as a result of the reduced air density, neces- sitated that the propeller RPM be increased (both to counteract the change in advance ratio and to generate the necessary thrust). This results in an increase in the rate of fuel consumption (expressed as power). However, the increased velocity serves to offset the power consumption (power × time) and reduce the energy requirement for a given dis- tance. It is worth noting that here, however, the energy requirement for a given distance was increased by approximately 10% at a higher altitude, but this is the result of how the engine and propeller are modelled. The engine model was designed to be conservative, and the propeller used is a fixed-pitch propeller, while nearly all propeller-powered pas- senger aircraft use variable-pitch and constant-speed propellers due to their significantly increased efficiency.

These trends have been observed without having intentionally programmed their existence into the simulation. All that was added to the simulation is the underlying ”rules”, such as lift and drag coefficient generation, calculations for the masses of components and the means of reading and understanding simulation and optimisation criteria. The fact that these more subtle results have managed to surface over the course of normal simulation operation provides good support for the accuracy and validity of the simulation created, as well as showing the high potential that can be realised should the simulation be improved and refined.

73 5.2 Problems Encountered

A number of problems were encountered over the course of this thesis, particularly in the area of information availability. These problems and their solutions or workarounds are outlined below.

A glaring lack of information relating to the performance of small-to-mid sized engines caused significant problems relating to modelling the performance of the typical engine sizes examined within this thesis. Most hobby aircraft engine manufacturers provide gen- eral geometric information for their engines (such as size, mass and displacement), but usually provide very little in the way of performance information (typically just power out- put and RPM range). As a result, engine performance maps have had to be extrapolated from an engine with performance curves available (which was the Rotax 914), with fuel consumption values extrapolated based on an indicative table provided by O.S. Engines that relates engine displacement to fuel consumption. Given the scales associated with these extrapolations (in that the Rotax 914 outputs over 73kW of power, while the typical hobby engines examined output 1-2kW), it is very unlikely that the performance curves of the Rotax are indicative of the performance of the hobby engines. However, given the lack of available information, this method was necessitated to allow smaller engines to be modelled.

In a similar vein to the problem above, a lack of information relating aerodynamic per- formance of standard shapes was encountered. While standardised values exist for ”the drag coefficient of a cylinder”, there was significant difficulty finding geometries that had their lift and drag characteristics presented whilst being dependent on the angle of attack and Reynolds number of the geometry. While standard Reynolds number and angle of attack independent drag coefficients could have been used (and were used during the ini- tial creation stages to recognise faults in the code), it was deemed unacceptable to leave this in as part of the full simulation. This is because these geometries would typically function as a fuselage or other appendage to the vehicle, which have significant effects on the overall aerodynamics. As such, making such sweeping simplifications was seen as tarnishing the accuracy and validity of the simulation, which is why considerable effort was put into finding good aerodynamic data for a somewhat aerodynamic fuselage shape. While this generic shape is the only fuselage implemented, which limits the accuracy of the simulation in its own way since alternate fuselages can’t be modelled correctly using it, it serves to validate the functions of the simulation (such as how angle of attack and Reynolds number affect the lift and drag of bodies).

As with any code-oriented project, a large number of problems within the code (ranging from inconvenient to code-breaking) were encountered over the course of the project. Problems were often encountered when completing upgrades of the code (such as creating the automatic mass-simulation of a set of designs, or incorporating new engine or propeller

74 models), which sometimes required a number of hours to correctly diagnose and solve. These problems sometimes stemmed from user error, but other, more difficult to solve problems arose from bugs within Python. For example, a two-dimensional interpolation function within the native SciPy module was incorrectly interpolating between points, such that instead of providing interpolated values in a straight line between the two points, it functioned as if there was a point with a value of zero between them, such that the interpolated value went from the first user-defined value, down to zero, then up to the second user-defined value. This required a different interpolation function be used, requiring a rewrite of the code that reads, processes and generates interpolation functions from the relevant data.

Another problem that was encountered during the project was the change in thesis goals. The original goal of the thesis was to create a single design that is optimised for a specific mission, with the simulation being a means to an end. However, the simulation (and associated knowledge gained) ended up becoming the focus of the thesis, which required a shift in the direction of work. For example, a reasonable portion of the literature review that had been conducted up until the point of changing the goals became essentially irrelevant, as these features weren’t modelled within the simulation, and the design of the craft outside of the simulation became out of scope (such as craft balancing, avionics and other electronics). This caused a minor setback in that new research had to be conducted into other areas to align with the new goal, in order to cover knowledge gaps that were previously not important to the thesis.

Overall, the main problems encountered over the course of the project were related to a lack of information relating to parameters relevant to the simulation (such as aerodynamic characteristics of different geometries and engine performance). This lack of information has resulted in a number of assumptions being made, some of which have had significant impacts on the potential accuracy of the simulation (most notably the engine performance extrapolation method adopted).

75 5.3 Validity

The main work undertaken has been the creation and validation of the simulation, such as to demonstrate not only the correct functionality but as to also demonstrate good accuracy and agreement with expected results. The results of the validity analyses are presented below.

5.3.1 Performance of Real UAVs

The discretization and simulation of real UAVs demonstrated strong potential for the simulation and flight solver, especially when considering the assumptions made over the course of the simulation creation, the factors that were left out of scope and the generic aerodynamic data used. All UAVs were consistently kept at their lowest local cost configu- ration (for this analysis, minimising power usage to maximise endurance), which provides a strong argument for the proper functioning of the flight solver module.

The MQ-1B showed good agreement for its fuel consumption, endurance and range, whilst flying significantly slower than reported. This was found to be the result of the local cost function chosen, as optimising the flight for range as opposed to endurance produces comparable velocities. The discrepancies in the compared performance were justifiable due to the assumptions made in the discretization process, and as a result the simulation of the MQ-1B is able to provide support for the validity and accuracy of the simulation created.

The Aerosonde showed good agreement for its fuel consumption and endurance, with reasonable agreement for its flight velocity and poor agreement for its range. Given that the endurance and fuel consumption are directly linked, it is not surprising that having one in agreement causes the other to be in agreement. The flight velocity was found to be lower than the reported values for the same reason as the MQ-1B; that flying to maximise endurance significantly reduces the flight velocity compared to flying for maximum range. On that note, the severe discrepancy in range is attributed in part to the assumptions made in the discretization process and the accuracy of the simulation, but the main cause for this is expected to be differing circumstances around the range values reported for the Aerosonde. Widely varying range values were found during research (from anywhere between 140km and 3000km), and the range was found to be highly dependent on payload mass. As a result, choosing a ”correct” range to compare to proved difficult, and the 3000km estimate was used as an upper bound. After providing reasonable justifications for the discrepancies seen for the Aerosonde’s results, it is also able to serve as validation for the simulation, as the majority of its overarching flight results showed good agreement, with its one questionable result likely being attributed to reporting error.

The ScanEagle showed the best agreement to the reported results out of the three UAVs examined. The fuel consumption, endurance and range were all very similar to the re-

76 ported values, while the velocity was once again slower than reported due to the fact that these simulations were optimised for minimising power consumption, which benefits from reducing velocity. The ScanEagle is able to serve as validation for the simulation without much additional justification, as the results obtained are essentially exactly what was expected.

As a result, all three UAVs examined were able to serve as the first round of validation for the simulation. All three had results that aligned with that which was expected, and any discrepancies have logical justifications. Therefore, the analysis of the performance of UAVs has been successful in validating both the internal functions and accuracy of the simulation and associated data.

5.3.2 Example Design Process

The purpose of the example design process was twofold. Firstly, it was intended to demonstrate the steps taken to optimise a given design for the sake of context to the user. Secondly, an analysis of the designs that are reported as being optimised would serve to determine whether the optimiser was producing logical results.

Over the course of the optimisation process, a number of unexpected results were pro- duced. However, after inspection, it was found that these results were logical as a result of a complex combination of effects culminating in typically unpredicted results. This served as strong validation for the simulation process, as not only is the simulation able to model the standard, individual effects within the data (such as mass calculations, vari- ations in aerodynamics and engine/propeller performance), it is also able to capture the more subtle interactions, often in the form of unexpected trade-offs (such as reducing wing area while increasing specific lift, or decreasing fuselage size and therefore fuel capacity in order to use less fuel). The presence of these effects is likely the strongest single source of validation of the simulation analysed in this thesis, as it demonstrates the correct fun- damental workings of the simulation, such that subtle, unexpected effects are correctly captured.

5.3.3 Off-Design Performance

Off-Design Performance: Design Variation

The off-design analysis of variations of the optimised design found was conducted in order to not only validate the results found from the optimiser (such as validating that the optimal design found is indeed the optimal) but also to search for the presence of more nuanced effects that would arise from the forced variations made to the baseline design.

The off-design performance found the dependence of stall angle on velocity, as well as showing the stall angle to be in the expected range, validating the ability of the simulation to model stall effects. The analysis also found fluctuations in the aerodynamic data

77 provided by XFOIL, which was the cause of the designs maintaining a constant angle of attack while decreasing velocity, followed by increasing velocity and decreasing angle of attack by an amount larger than the simulation resolution (whereas expected behaviour would be a smooth, continuous decrease in both angle of attack and velocity). This behaviour is not intended, but arises due to slight fluctuations in the data from XFOIL and the linear interpolation used. However, it is not expected that this has any meaningful effect on the overall results of the simulation (such as fuel consumption or range), but does provide an interesting effect of reducing velocity by more than it typically would, followed by increasing it and stepping down by a moderate angle of attack. This validates that the simulation processes are functioning correctly, with the input data having slight issues. Finally, this analysis found that the effects of variations on the designs were in-line what what was expected, as well as demonstrating that the flight solver was correctly picking the flight configurations to minimise energy use.

Therefore, the design-variation off-design analysis provided insight into the stall mechanics of a wing, whilst bringing potential issues with input data to light. The results obtained were in-line with what was expected, and as a result, served to provide further validation to the simulation.

Off-Design Performance: Mission Variation

This analysis featured the simulation of the optimised design over the course of a mission that it was not optimised for, featuring ascents, descents and level flight at varying alti- tudes. The purpose of this analysis was to investigate how the parameters of the craft (such as angle of attack, power requirement and velocity) change as a result of varying flight conditions (such as air density and climb angle).

The analysis correctly found that a reduction in air density requires a higher velocity, which increases the power consumption of the vehicle. It also correctly used the governing criteria of the flight solver (maintaining equilibrium flight) to maintain the velocity of the vehicle during descent (before taking into account the air density effects), whilst requiring minimal thrust to maintain forwards velocity. An analysis of the lift-to-drag ratio of the craft predicted that the zero-power glide slope of the craft would be approximately 6 degrees, while testing found it to be 5.94 degrees, showing good agreement between the simulation- and analytically-found results. The other flight parameters also showed good agreement with what would be expected based on literature, which assists in validating the operation of the simulation on more complex missions and flight scenarios.

5.3.4 Overall Validity

Based on the continual agreement between analytical results predicted based on liter- ature and the results created independently by the simulation, it has been shown that the simulation does function correctly, and is able to correctly capture a wide range of

78 effects, such as obvious effects including air density reducing lift generation, to more com- plex effects such as trade-offs between wing area and specific lifting capabilities. The constant agreement shown without any real discrepancies serves to justify that the simu- lation is functioning correctly, while the specific comparisons between real UAVs and their discretized counterparts demonstrated the surprisingly good accuracy of the simulation given the assumptions made.

5.4 Future Potential

The simulation code created does have good potential for improvements and modifica- tions in the future. The simulation was created such that parts were kept separated as much as possible, confining code modules into their respective ”families” and strictly controlling the input and output data (such as having an input be only the design file name, as opposed to passing all of the design parameters). This allows for new modules to be integrated where necessary (as they can easily interface with the existing code), while modifications internal to a code module or code ”family” can be made without much worry of adversely affecting other areas of the code. As long as the input/output structure is maintained and the modifications don’t affect the purpose of the code (for example, optimising the code to run faster would be simple, since it shouldn’t affect the input/output structure), then there should be minimal data-flow related issues.

On a similar note, direct upgrades to the code (incorporating the aerodynamics of differ- ent geometries, or engine/propeller models) can be made without much difficulty. The aerodynamic-function generating module cogen has the lift and drag functions for each geometry strictly separated, such that a new geometry could be added without impacting the others at all. Tabulated data can also easily be added into the simulation, as the interpos module contains a large number of data processing and interpolation options, which should be sufficient for most data that would be added. As long as the function name for the geometry within cogen is consistent with its name in the design file, adding the aerodynamics of new geometries should be very simple and easy. Data used for the aerodynamics can also either be tabulated (which would allow for CFD results to be used) or in the form of an explicitly defined function, both of which can be added in without much difficulty.

Overall, the simulation code does show good promise for future improvements, and it is likely that it will be built upon in the future to further improve the accuracy of the simulation, as well as improving the variety of geometries that can be simulated. The scope of the simulation may also be widened in order to take into account effects that have currently been ignored, such as craft balancing, on-board electronics and control surfaces.

79 5.5 Recommendations

Having concluded the creation of the current version of the simulation and its associated studies, a number of recommendations can be made relating to the work completed.

Firstly, it would be recommended that engine models for a wider range of engine types be added to the simulation. Given that the current engine model is only for gasoline-powered piston engines, adding in other engine models (such as electric motors, turboprops, tur- bofans, turbojets and possibly gearboxes) would greatly widen the range of designs that can be simulated, allowing the code to be used for a wider range of applications.

Relating to the previous recommendation, it is recommended that if new engine mod- els are to be added, significant research into accurate performance modelling should be conducted. While the current iteration of the simulation provides surprisingly good ac- curacy given the assumptions made (especially for the engine model), it would almost be redundant to add in new engine models that are poorly researched. As a part of this, pertaining specifically to the lack of data on hobby aircraft engines, it could almost be deemed worthwhile to purchase a hobby engine and experimentally examine its perfor- mance, which could either be converted into empirical functions or left as tabulated data for the code to interpolate. The information gained by an experimental analysis could then be retroactively applied to the current engine model in place to improve its accuracy.

Another recommendation would be to add additional components and geometries into the simulation alongside their associated aerodynamic data. If research is found to be unfruitful, CFD simulations could be set to automatically examine the aerodynamics of custom shapes at a range of configurations (such as varying the fineness ratio or bluntness of a geometry, alongside the angle of attack) and generate data that could be tabulated and interpolated within the simulation, or converted into an empirical function to bypass the use of interpolation within the code and allow for explicit reverse-solving.

Yet another recommendation for an addition to the code (and is also related to the engine modelling) would be to add the modelling of variable-pitch and constant-speed propellers into the simulation. Given that these propellers are used essentially whenever possible (as long as size permits) due to their ability to maintain consistent good performance of the propeller at a range of flight conditions, it would be highly beneficial to be able to model them within the simulation, as it would drastically expand the range of aircraft that could be simulated accurately. If possible, it is recommended to use equations that define the propeller performance based on geometry and current blade angle as opposed to using third-party programs. If a search for equations that are capable of being incorporated into the simulation is found to be fruitless, then some means of interfacing with the Propel program could be used to automatically generate data sets for interpolation. However, it is not currently believed that Python has a method for doing this, and as such it may

80 be necessary to examine alternate interfacing methods for the Propel program to avoid having to manually generate hundreds of data sets.

It is also suggested that range of potential mission criteria be widened so as to allow more complex missions to be optimised for. This could include the deployment of payloads or full 6-axis simulation (including the effects of vehicle banking). Given that the current missions allow for 5-degree of freedom flight with no pre-defined changes in conditions available (such as the dropping of a payload mid-flight), the range of missions that can be simulated is slightly limited, but does meet the initial criteria of allowing rapid preliminary design and feasibility estimates.

A possible recommendation for future work would be the widening of the simulation scope by introducing entire function areas not present in the current simulation. This could include the functioning of on-board electronics and sensors, design balancing and structural integrity, integration of stability and control surfaces, analysis of alternate vehicle types (such as rotorcraft), or the implementation of a true 6-axis simulation (using a time-step-based simulation where the aerodynamics of the craft at one point in time are numerically integrated to the next, and so on). Since the simulation was designed to be modular, it is likely that interfacing new modules to the current simulation would be simple, with the vast majority of the work to be completed falling under actually creating the module itself.

Overall, as the project was focused on the research and implementation of said research into a simulation for fixed-wing UAVs, the recommendations for future work consist of further research to both improve the modelling of current features, as well as to add in additional features and widen the scope of the simulation, to allow for a wider range of designs and missions to be simulated, increasing the range of applications for which the simulation is suitable.

81 6 Conclusions

In this study, research was conducted into the key aerodynamic and performance char- acteristics of fixed-wing UAVs, which were subsequently implemented into a simulation software capable of correctly simulating and optimising designs based on user-defined cri- teria. The functionality and accuracy of the simulation have been validated by multiple means. The objectives of the project were also met. Simulation software was developed to evaluate the performance of a UAV over the course of a mission. The capability to au- tomatically optimise a design is also built into the software. Insight has also been gained into not only the overarching performance parameters of fixed-wing UAVs, but also into more nuanced results that arise from a combination of effects. While the current scope of the simulation software is limited, it shows strong potential for future additions and improvements.

6.1 Contributions

This thesis makes the following contributions to the field of fixed-wing UAV design and simulation:

• Aggregated information relating to the performance of wings, engines and propellers.

• Insight into the effects of certain parameters on the macroscopic performance of an aircraft, such as the relationship between angle of attack and velocity for maximising range or endurance.

• Insight into the less-common effects associated with aerodynamics, such as the de- pendence of stall angle on velocity, beneficial effects arising as a by-product of two counteracting parameters (such as a reduction in wing area whilst increasing aspect ratio resulting in higher total lift), and the mutual-detriment taken for each of the engine/propeller performance and aerodynamic performance, in order to maximise the combined-parameter performance.

• Insight into design sizing and performance estimation, such that performance cal- culations and optimisation could be performed by hand should the relevant data be available.

• The open-source release of the simulation code created, particularly intended for use by hobbyists and small companies that would otherwise not have access to, or not be the intended audience of alternative design, simulation and optimisation software. This simulation, being comprised of design, simulation and optimisation features, does assist in filling a void in ”full-package” design and simulation software, given a lack of available options for completing entire design cycles (see Appendix U for a link to the software).

82 References

[1] Air Force Civil Engineer Support Agency. ETL 09-1 Airfield Planning and Design Criteria for Unmanned Aircraft Systems (UAS). en. Sept. 2009. url: http://www.wbdg.org/ccb/AF/AFETL/ etl_09_1.pdf (visited on 10/20/2009).

[2] AltiGator. Drones for search and rescue missions. 2018. url: https://altigator.com/drones- for-search-rescue-missions/ (visited on 05/29/2018).

[3] Amazon. Amazon Prime Air. 2018. url: https://www.amazon.com/Amazon-Prime-Air/b?ie= UTF8&node=8037720011 (visited on 05/29/2018).

[4] Russian Unmanned Vehicle Systems Association. Aerosonde MK 4.7. 2011. url: http://en. ruvsa.com/catalog/aerosonde_mk_4_7/?ELEMENT_CODE=aerosonde_mk_4_7&PAGEN_6=2 (visited on 10/20/2018).

[5] Shell . Shell AVGAS 100LL. 1999-02-19. url: https://www.shell.com.au/motorists/ shell - fuels / sds - tds / _jcr _ content / par / textimage _ 278c . stream / 1519809888867 / 1fd2a443b48ce24dec1b995f7c5e6fd8e4f675f2c6923b0031e3e6eac4d1ee6a/avgas-100ll-pds. pdf (visited on 10/20/2018). [6] Nayan Avalakki et al. “Design, Development and Manufacture of a Search and Rescue ”. PhD thesis. Adelaide: The University of Adelaide, Oct. 18, 2007. 323 pp. url: http://data.mecheng.adelaide.edu.au/robotics/projects/2007/iSOAR/finalreport.pdf (visited on 10/20/2018). [7] J. A. Bagley. SOME AERODYNAMIC PRINCIPLES FOR THE DESIGN OF SWEPT WINGS. Tech. rep. Royal Aircraft Establishment, Farnborough: Aerodynamics Department, Royal Aircraft Establishment, 2002-11-01. (Visited on 05/29/2018). [8] Parvathavadhani Krishna Bahumanyam. “Evaluation of Novel Wing design for UAV”. Masters Thesis. University of Alabama, 2014-09-10. url: https://www.comsol.dk/paper/download/ 194633/bahumanyam_presentation.pdf (visited on 10/20/2018). [9] M. J. Bamber and R. O. House. WIND-TUNNEL INVESTIGATION OF EFFECT OF YAW ON LATERAL-STABILITY CHARACTERISTICS I - FOUR N.A.C.A 23012 WINGS OF VARIOUS PLAN FORMS WITH AND WITHOUT DIHEDRAL. Techincal Note 703. Langley Aeronautical Laboratory, Langley AFB, Virginia: NACA, Apr. 1939. (Visited on 05/29/2018). [10] Joseph A. Barnard. Unmanned Air Vehicle Features, Applications and Technologies. 2006-11-01. url: http://www.barnardmicrosystems.com/media/presentations/UAV_Features_Apps_ and_Tech_V25.pdf (visited on 10/20/2018). [11] Amar Benghezal et al. “Trajectory generation for a fixed-wing UAV by the potential field method”. In: 2015 3rd International Conference on Control, Engineering & Information Technology (CEIT). 2015 3rd International Conference on Control, Engineering & Information Technology (CEIT). Tlemcen, Algeria: IEEE, May 2015, pp. 1–6. isbn: 978-1-4799-8212-7. doi: 10.1109/CEIT.2015. 7233049. url: http://ieeexplore.ieee.org/document/7233049/ (visited on 10/20/2018). [12] Boeing. Historical Snapshot: ScanEagle Unmanned Aerial Vehicle. 2018. url: https : / / www . boeing . com / history / products / scaneagle - unmanned - aerial - vehicle . page (visited on 10/20/2018).

[13] Didier Breyne. ADS - Aircraft Design Software. 2016. url: http://www.pca2000.com/en/index. php (visited on 10/22/2018).

[14] R. L. Carmichael and R. J. Kwan. Download the Atmosphere Programs. 2018. url: http://www. pdas.com/atmosdownload.html (visited on 10/15/2018).

83 [15] NASA Ames Research Center. Cart3D. 2018-10-05. url: https://www.nas.nasa.gov/publications/ software/docs/cart3d/pages/cart3Dhome.html (visited on 10/22/2018). [16] Clarkson University. The NACA Airfoil Series. Tech. rep. Clarkson University: Clarkson Univer- sity, 2004-01-20. (Visited on 05/29/2018).

[17] Analysis Design and Research Corporation. AAA. 2018. url: http : / / www . darcorp . com / Software/AAA/ (visited on 10/22/2018).

[18] Henock Dory. Design and Specifications. 2013. url: https : / / mq - 1predator . weebly . com/ (visited on 10/20/2018).

[19] Mark (markdrela) Drela. Predator Airfoil. 2010-05-15. url: https://www.rcgroups.com/forums/ showthread.php?1227417-Predator-Airfoil/page3 (visited on 10/20/2018).

[20] Mark Drela and Harold Youngren. XFOIL Subsonic Airfoil Development System. 2013. url: https://web.mit.edu/drela/Public/web/xfoil/ (visited on 10/14/2018).

[21] Julian Edgar. AutoSpeed - FuelSmart, Part 1. 2016-08-02. url: http://www.autospeed.com/ cms/article.html?&title=FuelSmart-Part-1&A=113297 (visited on 10/22/2018). [22] “Energy and Energy Types”. In: Ya¸sarDemirel. Energy. London: Springer-Verlag London Limited, 2012, pp. 27–70. isbn: 978-1-4471-2371-2 978-1-4471-2372-9. doi: 10.1007/978-1-4471-2372- 9_2. url: http://link.springer.com/10.1007/978-1-4471-2372-9_2 (visited on 10/20/2018). [23] CFS Engineering. CEASIOM - Conceptual Aircraft Design Tool. 2018. url: https : / / www . ceasiom.com/wp/ (visited on 10/22/2018).

[24] Lycoming Engines. EL-005 Engine. 2016. url: https://www.lycoming.com/engines/el-005 (visited on 10/20/2018).

[25] O.S. Engines. Product Frequently Asked Questions (FAQ). 2018. url: https://www.osengines. com/faq/faq-q900.html (visited on 10/14/2018).

[26] Military Factory. AAI MQ-19 Aerosonde Unmanned Aerial Vehicle. 2018. url: https://www. militaryfactory.com/aircraft/detail.asp?aircraft_id=1042#specs (visited on 10/20/2018).

[27] Air Force. Factsheets: Scan Eagle. 2011-09-15. url: https://web.archive.org/ web/20130710112005/http://www.af.mil/information/factsheets/factsheet.asp?id= 10468 (visited on 10/21/2018).

[28] . MQ-1B Predator. 2015. url: https://www.af.mil/About-Us/Fact- Sheets/Display/Article/104469/mq-1b-predator/ (visited on 10/14/2018). [29] Paul G Fournier and William C Jr. Sleeman. EFFECTS OF WING HEIGHT ON LOW-SPEED AERODYNAMIC CHARACTERISTICS OF A MODEL HAVING A 42deg SWEPT WING, A SUPERCRITICAL AIRFOIL, DOUBLE-SLOTTED FLAPS, AND A LOW TAIL. Techni- cal Memorandum. Langley Research Center, Hampton, Virginia: NASA, Sept. 1973. (Visited on 05/29/2018). [30] Clarence L Gillis and Rowe Jr. Chapman. “EFFECT OF WING HEIGHT AND DIHEDRAL ON THE LATERAL STABILITY CHARACTERISTICS AT LOW LIFT OF A 45deg SWEPT- WING AIRPLANE CONFIGURATION AS OBTAINED FROM TIME-VECTOR ANALYSES OF ROCKET PROPELLED-MODEL FLIGHTS AT MACH NUMBERS FROM 0.7 TO 1.3”. en. In: (1956-09-14), p. 71.

[31] GNU. The GNU General Public License v3.0. 2016. url: https://www.gnu.org/licenses/gpl- 3.0.en.html (visited on 10/15/2018).

84 [32] Alex Goodman. EFFECTS OF WING POSITION AND HORIZONTAL-TAIL POSITION ON THE STATIC STABILITY CHARACTERISTICS OF MODELS WITH THE UNSWEPT AND 45deg SWEPTBACK SURFACES WITH SOME REFERENCE OT MUTUAL INTERFERENCE. Techincal Note. Langley Aeronautical Laboratory, Langley AFB, Virginia: NACA, Oct. 1951. (Vis- ited on 05/29/2018). [33] Hamburg University of Applied Sciences. High Lift Systems and Maximum Lift Coefficients. 2016- 01-17. (Visited on 05/29/2018). [34] John C Heitmeyer. EFFECT OF VERTICAL POSITION OF THE WING ON THE AERODY- NAMIC CHARACTERISTICS OF THREE WING-BODY COMBINATIONS. Research Memo- randum. Langley Aeronautical Laboratory, Langley AFB, Virginia: NACA, Feb. 1953. (Visited on 05/29/2018). [35] Denis Howe. Aircraft Conceptual Design Synthesis: Howe/Aircraft Conceptual Design Synthesis. en. Chichester, UK: John Wiley & Sons, Ltd, Oct. 2000. isbn: 1 86058 301 6. doi: 10.1002/ 9781118903094. url: http://doi.wiley.com/10.1002/9781118903094 (visited on 10/14/2018). [36] Doug Hunsaker. USU Aero Lab — MachUp. 2018. url: http://aero.go.usu.edu/machup/ (visited on 10/22/2018).

[37] BRP-Powertrain GmbH&Co KG. Rotax 914 Operators Manual. Apr. 2010. url: https://www. rotax-owner.com/en/support-topmenu/engine-manuals#914-series-engines (visited on 10/20/2018). [38] Bill Kuhlman and Bunny Kuhlman. Swept Wings and Effective Dihedral. Jan. 2000. (Visited on 05/29/2018).

[39] David Lednicer. The Incomplete Guide to Airfoil Usage. 2010. url: http : / / m - selig . ae . illinois.edu/ads/aircraft.html (visited on 05/29/2018). [40] J Lijin and T J S Jothi. “Aerodynamic characteristics of an ogive-nose spinning projectile”. en. In: S¯adhan¯a 43.4 (Apr. 2018). issn: 0256-2499, 0973-7677. doi: 10.1007/s12046-018-0857-3. url: http://link.springer.com/10.1007/s12046-018-0857-3 (visited on 10/14/2018). [41] Verdict Media Limited. ScanEagle - Mini-UAV. 2018. url: https://www.naval-technology. com/projects/scaneagle-uav/ (visited on 10/20/2018).

[42] Insitu Pacific Pty Ltd. ScanEagle Product Card. 2017. url: http://insitupacific.com.au/wp- content/uploads/pdf/ScanEagle_SubFolder_IPL_PR080315.pdf (visited on 10/20/2018).

[43] Verdict Media Ltd. Aerosonde Mk 4.7 Small Unmanned Aircraft System. 2018. url: https:// www.naval- technology.com/projects/aerosonde- mark- 47- small- unmanned- aircraft- system-suas/ (visited on 10/20/2018). [44] Bernard Maggin and Robert E Shanks. THE EFFECT OF GEOMETRIC DIHEDRAL ON THE AERODYNAMIC CHARACTERISTICS OF A 40deg SWEPT-BACK WING OF ASPECT RA- TIO 3. Techincal Note. Langley Aeronautical Laboratory, Langley AFB, Virginia: NACA, Dec. 1946. (Visited on 05/29/2018).

[45] MathWorks. Pricing and Licensing. 2017. url: https://au.mathworks.com/pricing-licensing. html?prodcode=ML&intendeduse=home (visited on 10/22/2018). [46] Gerald M McCormack and Victor I. Jr. Stevens. AN INVESTIGATION OF THE LOW-SPEED STABILITY AND CONTROL CHARACTERISTICS OF SWEPT-FORWARD AND SWEPT- BACK WINGS IN THE AMES 40 - BY 80 - FOOT WID TUNNEL. en. Research Memorandum. AMES Aeronautical Laboratory, Moffett Field, California: NACA, Jan. 1952, p. 182. (Visited on 05/29/2018).

85 [47] Barnes Warnock McCormick. Aerodynamics, aeronautics, and flight mechanics. en. New York: Wiley, 1979. isbn: 978-0-471-03032-4. [48] Barnard Microsystems. ScanEagle. 2014. url: http://www.barnardmicrosystems.com/UAV/ uav_list/scaneagle.html (visited on 10/20/2018). [49] Max M Munk. NOTE ON THE RELATIVE EFFECT OF THE DIHEDRAL AND SWEEP BACK OF AIRPLANE WINGS. Techincal Note. Langley Aeronautical Laboratory, Langley AFB, Vir- ginia: NACA, Jan. 1924. (Visited on 05/29/2018).

[50] NASA. Downwash Effects on Lift. 2015. url: https://www.grc.nasa.gov/www/k-12/airplane/ downwash.html (visited on 05/30/2018).

[51] NASA. Induced Drag Coefficient. 2015. url: https://www.grc.nasa.gov/www/k-12/airplane/ induced.html (visited on 05/30/2018). [52] John W Jr. Paulson and Scott O. Kjelgaard. An Experimental and Theoretical Investigation of Thick Wings at Various Sweep Angles In and Out of Ground Effect. Technical Paper. Langley Research Center, Hampton, Virginia: NASA, Oct. 1982. (Visited on 05/29/2018). [53] L Prandtl. EFFECTS OF VARYING THE RELATIVE VERTICAL POSITION OF WING AND FUSELAGE. Techincal Note. NACA, Dec. 1921. (Visited on 05/29/2018). [54] Ning Qin and Spiridon Siouris. Study of the effects of wing sweep on the aerodynamic perfor- mance of a blended wing body aircraft. Article. University of Sheffield, Sheffield, UK: University of Sheffield, Oct. 2006. (Visited on 05/29/2018). [55] M. J. Queijo and Byron M Jaquet. CALCULATED EFFECTS OF GEOMETRIC DIHEDRAL ON THE LOW-SPEED ROLLING DERIVATIVES OF SWEPT WINGS. Techincal Note. Langley Aeronautical Laboratory, Langley AFB, Virginia: NACA, Oct. 1948. (Visited on 05/29/2018). [56] M. J. Queijo and Byron M Jaquet. INVESTIGATION OF EFFECTS OF GEOMETRIC DI- HEDRAL ON LOW-SPEED STATIC STABILITY AND YAWING CHARACTERISTICS OF AN UNTAPERED 45deg SWEPTBACK-WING MODEL OF ASPECT RATIO 2.61. Techincal Note. Langley Aeronautical Laboratory, Langley AFB, Virginia: NACA, Sept. 1948. (Visited on 05/29/2018). [57] Phil R Rademacher. “WINGLET PERFORMANCE EVALUATION THROUGH THE VORTEX LATTICE METHOD”. PhD thesis. Daytona Beach, Florida: Embry-Riddle Aeronautical Univer- sity, May 2014. (Visited on 05/29/2018).

[58] Army Recognition. Aerosonde UAS. 2015-02-10. url: https : / / www . armyrecognition . com / us_american_unmanned_aerial_ground_vehicle_uk/aerosonde_uas_unmanned_aerial_ system_textron_technical_data_sheet_specifications_pictures_video.html (visited on 10/20/2018). [59] Dieter Scholz. Wing Design. 2016-02-17. (Visited on 05/29/2018). [60] JOSEPH A. SHORTAL. “EFFECT OF TIP SHAPE AND DIHEDRAL ON LATERAL-STABILITY”. en. In: (1937-01-01), p. 10. (Visited on 05/29/2018). [61] M Leroy Spearman. EFFECTS OF WING AND TAIL LOCATION ON THE AERODYNAMIC CHARACTERISTICS OF AN AIRPLANE FOR MACH NUMBERS FROM 0.25 TO 4.63. Tech- nical Memorandum. Langley Research Center, Hampton, Virginia: NASA, Mar. 1983. (Visited on 05/29/2018). [62] M Leroy Spearman and Robert E Becht. THE EFFECT OF NEGATIVE DIHEDRAL, TIP DROOP, AND WING-TIP SHAPE ON THE LOW-SPEED AERODYNAMIC CHARACTER- ISTICS OF A COMPLETE MODEL HAVING A 45deg SWEPTBACK WING. Research Mem-

86 orandum. Langley Aeronautical Laboratory, Langley AFB, Virginia: NACA, Dec. 1948. (Visited on 05/29/2018).

[63] Auld & Srinivas. Blade Element Propeller Theory. 2018. url: http://www.aerodynamics4students. com/propulsion/blade-element-propeller-theory.php (visited on 10/14/2018).

[64] Beth Stevenson. Export-licensed Predator makes maiden flight. 2014-07-09. url: https://www. flightglobal.com/news/articles/export- licensed- predator- makes- maiden- flight- 400992/ (visited on 10/20/2018).

[65] Textron Systems. TS US Aerosonde Datasheet. 2016. url: http://www.barnardmicrosystems. com/media/presentations/UAV_Features_Apps_and_Tech_V25.pdf (visited on 10/20/2018). [66] J. Tang. High-Lift Systems.pdf. 2003-10-28. (Visited on 05/29/2018). [67] Erika R S Teixeira et al. “The Study and Analysis of Using Wing Dihedral on the Side of an Aircraft’s Static Stability”. In: Proceedings of the World Congress on Engineering 2 (July 2015). (Visited on 05/29/2018). [68] JEROME TEPLITZ. EFFECTS OF SMALL ANGLES OF SWEEP AND MODERATE AMOUNTS OF DIHEDRAL ON STALLING AND LATERAL CHARACTERISTICS OF A WING-FUSELAGE COMBINATION EQUIPPED WITH P ARTIAL- AND FULL-SPAN DOUBLE SLOTTED FLAPS. en. Tech. rep. Langley Research Center, Hampton, Virginia: NACA, 1944, p. 27. (Visited on 05/29/2018). [69] Egbert Torenbeek. Advanced Aircraft Design. Tech. rep. Delft University of Technology, 1988. (Visited on 05/30/2018). [70] Lance Traub and Mashaan Kaula. “Effect of Leading-Edge Slats at Low Reynolds Numbers”. en. In: Aerospace 3.4 (Nov. 2016), p. 39. issn: 2226-4310. doi: 10.3390/aerospace3040039. url: http://www.mdpi.com/2226-4310/3/4/39 (visited on 05/29/2018). [71] E G Tulapurkara. Chapter 5 Wing design - selection of wing parameters - 3 Lecture 21 Topics. en. 2013-10-04. (Visited on 05/29/2018). [72] United States Government Accountability Office. Assessments of Selected Weapon Programs. Eco- nomic Report. United States Government Accountability Office, Mar. 2013. (Visited on 05/29/2018).

[73] FOP SHVACHKO V. V. Aerosonde UAV. 2014-01-31. url: https://shvachko.net/?p=1545& lang=en (visited on 10/20/2018).

[74] Verdict Media Ltd. Predator UAV. 2018. url: https : / / www . airforce - technology . com / projects/predator-uav/ (visited on 05/29/2018). [75] Karen E Washburn and Blair B Gloss. EFFECT OF WING-TIP DIHEDRAL ON THE LON- GITUDINAL AND LATERAL AERODYNAMIC CHARACTERSTICS OF A SUPERSONIC CRUISE CONFIGURATION AT SUBSONIC SPEEDS. en. Technical Memorandum. Langley Research Center, Hampton, Virginia: NASA, Aug. 1976, p. 43. (Visited on 05/29/2018). [76] Douglas P Wells, Bryce L Horvath, and Linwood A McCullers. “The Flight Optimization System Weights Estimation Method”. en. In: NASA/TM-2017-219627 I (June 2017), p. 91. [77] Richard Whittle. Predator: The Secret Origins of the Drone Revolution (First Ed.) New York: Henry Holt and Co., 2014. isbn: 978-0805099645. [78] Carol Wilke. ScanEagle Overview. 2007-03-02. url: http://www.csdy.umn.edu/acgsc/Meeting_ 99/SubcommitteeE/SEpubrlsSAE.PDF (visited on 10/21/2018).

87 Appendices

A Example of the Effect of Wing Position

Figure A.1: Effect of wing position on a craft experiencing side-slip. For a high-wing configuration, the wing towards the direction of slip experiences a higher effective angle of attack (due to flow coming from below), increasing the lift and induced drag, causing the craft to yaw in the direction of the sideslip. Image courtesy of Kuhlman and Kuhlman [38].

B Effective Flow Velocity Over a Swept Wing

Figure B.1: Effective flow over the chord of a swept wing. The decrease in effective velocity delays the onset of supersonic flow over the airfoil, increasing the critical mach number for the craft. The normal component of the velocity manifests as spanwise flow, promoting tip vortex generation and tip stalling. Image courtesy of the Hamburg University of Applied Sciences [59].

88 C Supersonic Flow Over a Wing

Figure C.1: Critical flow over an airfoil. The region of supersonic flow manifests as sig- nificant wave drag and causes early flow separation, significantly decreasing the efficiency of the airfoil. Image courtesy of Hamburg University of Appplied Sciences [59].

D Example of the Effect of Wing Sweep

Figure D.1: Effect of wing sweep on yawed flight. The right wing experiences greater lift and drag due to its larger effective span relative to the incoming airflow, causing the yaw of the craft to turn back towards its direction of travel. Image courtesy of Kuhlman and Kuhlman [38].

89 E Dutch Roll

Figure E.1: Diagram of a Dutch roll (with spiral divergence included). Out-of-phase motion of yaw and roll causes a repeated pattern of unstable flight until corrective inputs are made. Image courtesy of Kuhlman and Kuhlman [38].

90 F Effect of Wing Dihedral on Lateral Stability

Figure F.1: The effect of wing dihedral on the rolling stability and induced sideslip of a craft. As the craft rolls, it begins to slip sideways due to the wings non-vertical lift generation. As the craft slips sideways, the sideways flow combined with the dihedral angle of the wings causes asymmetric lift generation between the two wings, causing a restorative rolling moment that returns the craft to a level configuration. Image courtesy of the Hamburg University of Applied Sciences [59].

G Wing Twisting

Figure G.1: Geometric and aerodynamic twisting. Geometric twisting involves changing the angle of attack of the chord along the span, while aerodynamic twisting involves changing the shape of the airfoil in order to change the zero-lift angle of attack, whilst keeping the chord line constant. Image courtesy of the Hamburg University of Applied Sciences [59].

91 H Effects of Leading and Trailing Edge Flaps and Slots

Figure H.1: The effects of leading and trailing edge flaps and slots on the lift-curve of a wing. Image courtesy of the Hamburg University of Applied Sciences [33].

92 I Effect of Wing Taper on Lift Distribution and Local Coefficient of Lift

Figure I.1: Total lift generated versus position along wing for varying tapers (taper ratio of 1 is untapered). It can be seen that as the taper ratio is decreased, the lift distribution moves away from the ’rounded-rectangular’ shape and approaches a more ’triangular’ shape. Image courtesy of the Hamburg University of Applied Sciences [59].

Figure I.2: Local lift coefficient versus position along wing for varying tapers. It can be seen that for taper ratios approaching zero, the local lift coefficient near the tip is much higher than other areas of the wing, promoting tip stalling. As such, taper ratios are nearly always kept above 0.3 for both tip-stalling and size requirements (to facilitate the installation of ailerons and flaps and other control surfaces). Image courtesy of the Hamburg University of Applied Sciences [59].

93 J Variable-Pitch Propeller Performance Curves

Figure J.1: Propeller effiency at varying advance ratios and blade angles, courtesy of McCormick [47].

94 K Code Description

Module Description angsolver Determines the heading (compass) angle and standard unit circle angle of a vector batch Controls the simulation and scoring of groups of design files cogen Creates lift and drag functions for individual geometries compiler Merges sets of aerodynamic functions into one equation for each of lift and drag controlgen Processes the simulation control file, filling in the optional gaps with standard values if gaps are present controller Controls the simulation and recording of overall parameters (such as time taken and fuel consumption) for a single design convert Provides unit conversion functions (such as between radians and degrees, or pounds and kilograms) csolver Solves for the radius and arc length of circular arcs for flight path generation when given waypoints designparam Controls the reading and processing of a design file into usable data (including the reading of fuel carried and total design mass) efficientflight Solves for the optimal (lowest cost) flight configuration for a craft at a given point in the mission enviro Interface for the tables module, providing inputs in metres and sea level atmo- spheric parameters and outputs in SI units (as opposed to ratios) interpos Collection of data reading and interpolation functions, used for reading tabu- lated data for aerodynamic, engine or propeller performance ldgen Interfaces with XFOIL to generate lift and drag functions for an airfoil at a range of angles of attack and velocities. massfinder Solves for the masses of craft components missionpath Controls the discretization of the mission file into usable information, including finding the distance travelled by the craft (using csolver when turns are present) Propel Propeller performance analysis program that accepts geometric parameters of the propeller as inputs and returns tabulated data for thrust coefficient, torque coefficient, and efficiency at a range of advance ratios resultsprocessing Reads the cost and design variation record files to generate parallel axis plots for analysis sensitivity Controls the automatic generation of design variations based on given criteria and starts the process of simulation and results processing (using batch and resultsprocessing) side Used by csolver to determine which direction (left or right) the next waypoint is to calculate turn distance tables U.S. Standard Atmosphere information converted into a Python module by Ralph Carmichael and Richard Kwan [14] XFOIL Inviscid and viscous potential flow solver for airfoils, written by Dr Mark Drela and Harold Youngren of MIT [20].

Table K.1: Description of modules used within the simulation code. Bold names are for Python code files, while names not in bold are for external programs.

95 L Forces on an Airbourne Fixed-Wing UAV

Figure L.1: Forces acting on a fixed-wing UAV in flight at an ascent angle of θ and angle of attack of α, comprising of lift, drag, thrust and weight.

M Spherically Blunt Tangent-Ogive Nose Projectile

Figure M.1: Spherically blunt tangent-ogive nose projectile diagram, as examined by Lijin and Jothi [40].

96 N MQ-1B Dimensions

Figure N.1: Dimensions of the MQ-1B Predator, image provided by the Air Force Civil Engineer Support Agency [1]. All dimensions in feet and degrees.

O MQ-1B Discretization

G. name=’MQ−1B Predator ’ G.wing=[[’NACA 4412’,16.84,1.1,0.4,0,0,5,500]] G.eng=[[’R914’ ,60 ,1]] G.dead=[167] G. fuel=[300,44000000] G.ocyl=[[0.005,0.55,8.23,700,False ]] G. prop=[’MQ−1B ’ ] G.ht=[[’NACA 0012’,5.1,1,1,0,30,0,500]] G.lg=[[1.4,500]]

Propeller parameters:

Diameter = 1.8m Number of blades = 2 Blade pitch = 1.2m Blade setting angle = −4 degrees Blade chord = 0.15m Blade taper ratio = 1

97 P Aerosonde Discretization

G.name=’Textron Aerosonde ’ G.wing=[[’NACA 3510’,2.9,0.19,0.19,0,0,0,9]] G.eng=[[’EL−005 ’ ,1 ,1]] G. dead =[0] G. fuel=[4.9,42800000] G.ocyl=[[0.005,0.13,1.7,700,False ]] G.prop=[’aerosonde ’] G.ht=[[’NACA 0012’,1.15,0.1,0.1,0,30,0,9]]

Propeller parameters:

Diameter = 0.5m Number of blades = 2 Blade pitch = 0.5m Blade setting angle = 7 degrees Blade chord = 0.04m Blade taper ratio = 0.9

Q ScanEagle Discretization

G.name=’Textron Aerosonde ’ G.wing=[[’NACA 3510’,2.9,0.19,0.19,0,0,0,9]] G.eng=[[’EL−005 ’ ,1 ,1]] G. dead =[0] G. fuel=[4.9,42800000] G.ocyl=[[0.005,0.13,1.7,700,False ]] G.prop=[’aerosonde ’] G.ht=[[’NACA 0012’,1.15,0.1,0.1,0,30,0,9]]

Propeller parameters:

Diameter = 0.5m Number of blades = 2 Blade pitch = 0.5m Blade setting angle = 7 degrees Blade chord = 0.04m Blade taper ratio = 0.9

98 R Example Design Process Mission

M. temp=300 M. pres=101250 M. dens=1.225 M.locs=[[0,0,100],[500000,0,100]] M. localcosts=[’Ereq ’] M. globalcost=’deadmass+initfuelmass+5∗max(0 ,Eusagesum/fuelEdensity − initfuelmass)’ M. globalreturn=’Eusagesum/fuelEdensity ’

This is the mission file used for the example design process. This contains the environmen- tal parameters at sea level (temperature of 300K, air pressure of 101.25kPa, air density of 1.225 kg/m3), the waypoints of the mission ([0, 0]m to [500000, 0]m at an altitude of 100m) and the cost functions. The global cost function is the static dead mass of the vehicle plus the starting fuel mass (defined by geometry) plus five times how much extra fuel was needed (to heavily punish designs incapable of completing the mission). The local cost function is the energy requirement (to maximise range), while the custom cost function is fuel used. S Example Design Process Baseline Design

G.name=’Example Design Process ’ G.wing=[[’NACA 4510’,1.5,0.15,0.15,0,0,3,5]] G.eng=[[’GGT15’ ,0.788 ,1]] G. dead =[2] G.ocyl=[[0.004,0.1,0.6,700,False ]] G.prop=[’newprop ’] G.ht=[[’NACA 0012’,0.4,0.1,0.1,0,0,2,5]] G.vt=[[’NACA 0012’,0.2,0.1,0.1,0,0,2,5,1]] G.lg=[[0.5,5]] G. fuel=[3.14159∗(G.ocyl [0][1] − G.ocyl[0][0]) ∗∗2 ∗ (G.ocyl [0][2] ∗ 0 . 7 − 0 . 2 8 5 ) ∗770,46400000]

This is the baseline design file used at the start of the example design process. This uses a NACA 4510 airfoil with a wingspan of 1.5m and chord length of 0.15m (with no tapering), with no sweep or dihedral, and a 3 degree wing incidence angle, with the mass estimated based on a design mass of 5kg. The fuselage (ocyl) has a wall thickness of 4mm, outer radius of 0.1m, length of 0.6m, material density of 700kg/m3 and is not aerodynamically shielded. The fuel mass is defined as the fuel density multiplied by the ”available volume” of the fuselage, which is given by the inner radius squared multiplied by the ”available length”, given by 0.7 times the total length, minus 0.285m. This was chosen as it approximates the effects of having avionics in the nose of the fuselage, and a 28.5cm payload bay. This payload bay length was chosen as it results in a fuel mass of 3kg for the baseline design. The design also features a horizontal tail, vertical tail, landing gear, GGT15 (15 cubic centimetre) gasoline engine and a custom propeller.

99 T Off-Design Mission Variation Mission File

M. temp=300 M. pres=101250 M. dens=1.225 M.locs=[[0,0,100],[100000,0,100],[120000,0,2100],[220000,0,2100], [240000,0,3100], [340000,0,3100],[370000,0,100],[400000,0,100]] M. localcosts=[’Ereq ’] M. globalcost=’deadmass+initfuelmass+5∗max(0 ,Eusagesum/fuelEdensity − initfuelmass)’ M. globalreturn=’Eusagesum/fuelEdensity ’

100 U Simulation Code

This software can be found at: https://bitbucket.org/tim-ab/airframe-design-and-validation/src/default/.

U.1 Angsolver

from convert import rtd, dtr import math d e f heading(x,y):#find actual heading (0 degrees is north, 90 degrees is east) i f x==0 andy >= 0 : r e t u r n0 e l i f x==0 andy < 0 : r e t u r n 180 ang = rtd(math.atan(y/x)) i fx > 0 andy >= 0 : r e t u r n 90 − ang i fx < 0 andy >= 0 : r e t u r n 270 − ang i fx > 0 andy < 0 : r e t u r n 90 − ang i fx < 0 andy < 0 : r e t u r n 270 − ang d e f standard(x,y):#finds the angle in the standard mathmematical unit circle − 0 degrees i s right(east) and 90 degrees is up(north) i f x==0 andy >= 0 : r e t u r n 90 e l i f x==0 andy < 0 : r e t u r n −90 ang = rtd(math.atan(y/x)) i fx > 0 andy >= 0 : r e t u r n ang i fx < 0 andy >= 0 : r e t u r n 180+ang i fx > 0 andy < 0 : r e t u r n ang i fx < 0 andy < 0 : r e t u r n −180+ang U.2 Batch import os import time import controller import controlgen keepername =’keeper.txt’ scorername =’scorer.txt’ d e f main(controlfile ,extended=False): partwayflag=False starttime = time.clock()#keep track of time taken

controlclass = controlgen.main(controlfile)#loads the sim control class and reads a l l the relevant information controlname = controlclass .name missionnum = controlclass .mission designfolder = controlclass.designs goodfolder = controlclass.good badfolder = controlclass.bad resultsfolder = controlclass.results

f o ri in [designfolder ,goodfolder ,badfolder ,resultsfolder ]: i f not os.path.isdir(i): os.mkdir(i)

beginningstring =”Beginning simulation batch using simulation controller:”+ controlname+”. \ nSimulating mission:”+missionnum+”.”

101 p r i n t(beginningstring) d e s i g n s = next(os.walk(designfolder))[2]#reads the designs to be checked i f os.path. isfile (resultsfolder+keepername):#if the progress keeping file already e x i s t s − i.e. sim stopped partway through the batch p r e v f i l e = open( resultsfolder+keepername ,’r’)#read the current keeper file and determine what designs have already been simulated l i s t d a t a = list(prevfile) prevfile.close() names = [i.replace(’ \n’,’’) fori in listdata] donefiles = [i+’.txt’ fori in names] partwayflag = True#flag the batch as already having been started e l s e: donefiles = [] keeper = open( resultsfolder+keepername ,’a’)#open the keeper and scorer files for w r i t i n g s c o r e r = open(resultsfolder+scorername ,’a’) i f partwayflag == False:#if startinga brand new batch, writea header to the s c o r i n g file header =”Scoring for mission”+str (missionnum)+” − ”+str(len(designs))+” designs to be checked. \ n” scorer .write(header) designsleft = [des for des in designs if not des in donefiles]#the designs that have not yet been simulated f o ri in range(len(designsleft)):#for the designs that haven’t been simulated: istarttime = time.clock()#start time for current design filename = designsleft[i] loc = designfolder+filename designation = filename.replace(’.txt’,’’)#remove the file extension for the d e s i g n name progressstring =”Design”+str( i+1)+”/”+str(len(designsleft))+” − ”+designation# s t r i n g that tells the user the current sim progress p r i n t(progressstring)#print the progress string score = controller .main(loc ,missionnum ,extended=extended)#run the simulation and get the score for the design scoreout = designation+’=’+str(score) +’ \n’#add the design and its score to the s c o r e file in the format design=score(i.e. custom 4510=123123) scorer.write(scoreout)#write the design and score to the scorer file keeper.write(designation+’ \n’)#immediately after, write down the design to the keeper file so it won’t get checked again designfile = open(designfolder+filename ,’a’)#open the file for the design that was checked designfile .write(’ \n#’+missionnum+’=’+str(score))#write its score − w i l l bea2 element list if it faileda check designfile.close()#close the file to avoid problems i f type(score) == list:#if the score isa2 element list, then it failed i f len(score) == 2: reason = score[1]#reason it failed p r i n t(reason)#print the reason os.rename(designfolder+filename , badfolder+filename)#move it to the bad s u b f o l d e r p r i n t(’’)#adda blank line in the output continue#check the next design globalscore = score[0] sumlocalscore = score[1] customscore = score[2] scoreprinter =”Global score=”+str(globalscore)+” \nSum of local scores=”+str( sumlocalscore)+”\nCustom score=”+str(customscore)#string to be printed for the u s e r p r i n t(scoreprinter) os.rename(designfolder+filename , goodfolder+filename) iendtime = time.clock() telapsed = iendtime − s t a r t t i m e itelapsed = iendtime−i s t a r t t i m e t o t a l h = int(telapsed //3600) totalm = int((telapsed − t o t a l h ∗3600) // 60) t o t a l s = int((telapsed − t o t a l h ∗3600 − totalm ∗60) ) currh = int(itelapsed//3600) currm = int((itelapsed − currh ∗3600) // 60) c u r r s = int((itelapsed −currh ∗3600−currm ∗60) ) totaltimestring = str(totalh)+’:’+str(totalm)+’:’+str(totals) currtimestring = str(currh)+’:’+str (currm)+’:’+str(currs) p r i n t(’Total elapsed time=’+totaltimestring+’, previous design time=’+ currtimestring +’. Current time:’+time. strftime(”%H:%M:%S”,time.localtime())) p r i n t(’’)

102 endtime = time.clock() finalelapsed = endtime−s t a r t t i m e f i n a l h = int(finalelapsed //3600) finalm = int((finalelapsed − f i n a l h ∗3600) // 60) f i n a l s = int((finalelapsed − f i n a l h ∗3600 − finalm ∗60) ) finalstring =”The time taken to check the”+str(len(designsleft))+” designs remaining was”+str(finalh)+”:”+str(finalm)+”:”+str(finals)+”.” p r i n t(finalstring) keeper.close() scorer.close() os.remove( resultsfolder+keepername) U.3 Cogen import numpy as np import ldgen from convert import rtd, dtr from math import cos, sin from interpos import digidatanew , csvinterp1d

#−−−−−−−−−−−−−−− OGIVE CYLINDER −−−−−−−−−−−−−−−−−−− d e f ocyl(ins): i f ins[4] == True: p r i n t(’sh’) d e f blankfunc(inputs): r e t u r n0 r e t u r n blankfunc ,blankfunc v i s c = 1 . 4 8 e−5 T = i n s [ 0 ] OR = i n s [ 1 ] L = i n s [ 2 ] AR = L/OR/2 #fCn= digidatanew(1) #fCa= digidatanew(2) fCl ,fCd = csvinterp1d(’fuselage/bulletscaledrag’) CA = np . p i ∗ OR∗∗2 W = 2∗np . p i ∗OR d e f cdaocyl(ins): aoar = ins[0] aoa = rtd(aoar) v = i n s [ 1 ] Re T = 5 e5#transition reynolds x T = Re T/v∗ v i s c#transition distance i fL < x T: L1 = 0 L2 = L L3 = L e l i fL >= x T: L1 = 0 L2 = x T L3 = L C f d s k i n = W∗ 0 . 6 6 4 ∗ ( v i s c /v ) ∗∗(1/2) ∗2∗( L2 ∗∗0.5 − L1 ∗ ∗ 0 . 5 ) + W∗0.027 ∗ ( v i s c /v ) ∗∗(1/7) ∗ 7/6∗( L3 ∗∗(6/7) − L2 ∗∗(6/7) ) Cd = fCd(aoa) r e t u r n Cd∗CA+C f d s k i n d e f claocyl(ins): aoar = ins[0] aoa = rtd(aoar) v = i n s [ 1 ] Cl = fCl(aoa) r e t u r n Cl∗CA r e t u r n cdaocyl, claocyl

#−−−−−−−−−−−−−−−−−− WING −−−−−−−−−−−−−−−−−− d e f wing(ins): wingtype = ins[0] basespan = ins[1] rootchord = ins[2] tipchord = ins[3] sweep = ins[4] TCA = int(wingtype[ − 2 : ] ) /100 avchord = (rootchord+tipchord)/2 avchord = round(avchord ,2) A = avchord ∗ basespan taper = tipchord/rootchord dihedral = ins[5]

103 dAOA = ins[6] span = basespan ∗ cos(dtr(sweep)) AR = span ∗∗2/A Ne = 0 f = 0.005∗(1+1.5∗( taper −0.6) ∗∗2)#f ande being found using equation from Howe, 2000 fcl , fcd = ldgen.main(wingtype,avchord) d e f clawing(inps): aoa = rtd(inps[0]) v = i n p s [ 1 ] cLfinite = fcl (aoa+dAOA,v)/(1+fcl (aoa+dAOA,v)/np. pi/AR) mod = cos(dtr(dihedral)) ∗ cos(dtr(sweep)) r e t u r n cLfinite ∗A∗mod d e f cdawing(inps): aoa = rtd(inps[0]) v = i n p s [ 1 ] M = v/347 e = 1 / ( (1+0.12∗M∗∗6) ∗ (1 + (0.142+f ∗AR∗(10∗TCA) ∗ ∗ 0.33)/(cos(dtr(sweep))) ∗∗2 + 0 . 1 ∗ ( 3 ∗ Ne+1)/(4+AR) ∗ ∗ 0 . 8 ) ) cLfinite = fcl (aoa+dAOA,v)/(1+fcl (aoa+dAOA,v)/np. pi/AR) cDfinite = fcd(aoa+dAOA,v) + cLfinite ∗∗2/np. pi/AR/e mod = cos(dtr(sweep)) r e t u r n cDfinite ∗A∗mod r e t u r n cdawing,clawing

#−−−−−−−−−−−−−−− H o r i z o n t a l Tail −−−−−−−−−−−−− d e f ht(ins): wingtype = ins[0] TCA = float(wingtype[ − 2 : ] ) /100 basespan = ins[1] rootchord = ins[2] tipchord = ins[3] sweep = ins[4] avchord = (rootchord+tipchord)/2 avchord = round(avchord ,2) A = avchord ∗ basespan taper = tipchord/rootchord dihedral = ins[5] dAOA = ins[6] span = basespan ∗ cos(dtr(sweep)) AR = span ∗∗2/A f = 0.005∗(1+1.5∗( taper −0.6) ∗∗2) Ne = 0 fcl , fcd = ldgen.main(wingtype,avchord) d e f claht(inps): aoa = rtd(inps[0]) v = i n p s [ 1 ] cLfinite = fcl (aoa+dAOA,v)/(1+fcl (aoa+dAOA,v)/np. pi/AR) mod = cos(dtr(dihedral)) ∗ cos(dtr(sweep)) r e t u r n cLfinite ∗A∗mod d e f cdaht(inps): aoa = rtd(inps[0]) v = i n p s [ 1 ] M = v/347 e = 1 / ( (1+0.12∗M∗∗6) ∗ (1 + (0.142+f ∗AR∗(10∗TCA) ∗ ∗ 0.33)/(cos(dtr(sweep))) ∗∗2 + 0 . 1 ∗ ( 3 ∗ Ne+1)/(4+AR) ∗ ∗ 0 . 8 ) ) cLfinite = fcl (aoa+dAOA,v)/(1+fcl (aoa+dAOA,v)/np. pi/AR) cDfinite = fcd(aoa+dAOA,v) + cLfinite ∗∗2/np. pi/AR/e mod = cos(dtr(sweep)) r e t u r n cDfinite ∗A∗mod r e t u r n cdaht,claht

#−−−−−−−−−−−−V e r t i c a l tail −−−−−−− d e f vt(ins): wingtype = ins[0] TCA = float(wingtype[ − 2 : ] ) /100 basespan = ins[1] rootchord = ins[2] tipchord = ins[3] sweep = ins[4] avchord = (rootchord+tipchord)/2 avchord = round(avchord ,2) A = avchord ∗ basespan taper = tipchord/rootchord dihedral = ins[5] dAOA = ins[6]

104 span = basespan ∗ cos(dtr(sweep)) AR = span ∗∗2/A numtail = ins[8] f = 0.005∗(1+1.5∗( taper −0.6) ∗∗2) Ne = 0 fcl , fcd = ldgen.main(wingtype,avchord) d e f clavt(inps): r e t u r n0 d e f cdavt(inps): aoa = 0 v = i n p s [ 1 ] M = v/347 e = 1 / ( (1+0.12∗M∗∗6) ∗ (1 + (0.142+f ∗AR∗(10∗TCA) ∗ ∗ 0.33)/(cos(dtr(sweep))) ∗∗2 + 0 . 1 ∗ ( 3 ∗ Ne+1)/(4+AR) ∗ ∗ 0 . 8 ) ) c L f i n i t e = 0 cDfinite = fcd(aoa+dAOA,v) + cLfinite ∗∗2/np. pi/AR/e mod = cos(dtr(sweep)) r e t u r n cDfinite ∗A∗mod∗ numtail r e t u r n cdavt,clavt U.4 Compiler d e f main(funcs):#Callable function d e f fused(mainvar):#Returned function containing all input functions merged = 0#by default, function does nothing f o ri in range(len(funcs)):#For each function passed into compiler merged += funcs[ i ](mainvar)#Sum them together r e t u r n merged#Returns the merged function equation back to main r e t u r n fused#Returns the merged functions to the caller asa callable function U.5 Controlgen expected = [’parent’,’new’,’mission’,’designs’,’name’,’good’,’bad’,’results’] d e f main(controlfile): i f type(controlfile) == str: cfile = controlfile e l i f type(controlfile) == float or type(controlfile) == int: c f i l e = str(controlfile) e l s e: errorstring =”The simulation control class”+str(controlfile)+”, of type”+str( type(controlfile))+” is nota valid type.” r a i s e TypeError(errorstring) mod1 =’.txt’ i f mod1 in cfile: mod1 =’’ i f’/’ not in cfile: path =”simcontrol/”+cfile+mod1 e l i f’/’ in cfile: path = cfile+mod1 c l a s s simcontrol: pass C = simcontrol exec(open(path).read() , {} ,locals()) a t t s = [ a t t for att in dir(C) if not att.startswith(’ ’)] f o ri in expected: i fi not in atts: i f i ==’new’: C. new = True i f i ==’mission’:#if the control class has no mission defined, raise error r a i s e ImportError(’Sim control class has no mission specified.’) i f i ==’name’:#if the control class has no name, nota big deal but recommended p r i n t(’Sim control class has no name defined. Suggest adding name.’) i f i ==’designs’:#if the control class has no design folder to check, raise e r r o r r a i s e ImportError(’Sim control class has no design folder specified.’) i f i ==’name’: C. name =”No name defined” i f i ==’parent’:#if the control class has no parent results folder, default to the designs folder(no file movement) C. parent=C. designs i f i ==’good’:#if the control class has no subfolders for good/bad/failed designs, default to the parent folder C.good = C.parent

105 i f i ==’bad’: C.bad = C.parent i f i ==’results’: C.results = C.parent+’/results’ e l i fi in atts: mid =’’ i f C.parent[ −1] !=’/’: mid =’/’ i f i ==’good’: C. good=C. parent+mid+C. good i f i ==’bad’: C. bad=C. parent+mid+C. bad i f i ==’results’: C. results = C.parent+mid+C. results

i f C.designs[ −1] !=’/’:#for each of the folders stored within the class, ensure they end witha/ to append the file names to for file referencing C.designs +=’/’ i f C.parent[ −1] !=’/’: C. parent +=’/’ i f C.good[ −1] !=’/’: C. good +=’/’ i f C.bad[ −1] !=’/’: C. bad +=’/’ i f C.results[ −1] !=’/’: C.results +=’/’ r e t u r nC U.6 Controller import designparam import missionpath import efficientflight from enviro import dens from convert import dtr, rtd from interpos import propperf , digidatanew , newengine, enginedata import math import numpy as np import matplotlib.pyplot as plt from matplotlib import cm import matplotlib.colors as colours d e f main(designation ,missionnum ,extended=False):#Main control function for each s i m u l a t i o n run sumlocals = 0 maxdist = 1001#Maximum distance between checks for quasi equilibrium geomclass = designparam.geomload(designation)#Loads the geometry class name, geoms, geomparams= designparam. geomsplit(geomclass)#Finds the geometry name, geometry types, parameters for geometry and engine dragf , liftf = designparam.paramgen(geoms,geomparams)#Finds the CdA and ClA equations f o r the design missionclass = missionpath.main(missionnum)#Loads the mission class db = missionclass.dens#Finds the base density from the mission class flightlegs = missionclass.paths#Reads the mission class for the flight leg data deadmass, initfuelmass , fuelEdensity , initstoredE = designparam.masscalc(geomclass)# Finds the dead mass, fuel mass, fuel density and stored energy of the design t r y:#Try to read the engine data numeng = int(math. ceil(geomclass.eng[0][2]))#Number of engines − rounded up and s e t to integer propname = geomclass.prop[0] fct , fcq , feta ,propdiam = propperf(propname) proprad = propdiam/2 engname = geomclass.eng[0][0] i f’oldengs’ in engname: engeffmap = engname+’eff’ feng = digidatanew(’engs/’+engeffmap ,extrap=0,fillval=10) e l i f’old’ in engname: feng = enginedata(engname) e l i f’oldengs’ not in engname: p r i n t (engname) feng = newengine(engname) except:#If the design has no engine, fail it noenginestring =”Design”+designation+” failed checks. Design has no engine” f a i l t y p e =”No Engine” r e t u r n [failtype ,noenginestring]

106 i f initstoredE == False:#If designparam.masscalc returns False for initial stored energy, there is no energy storage on the design. Return the failure to batch c o n t r o l l e r. noEstring =”Design”+designation+” failed checks. Design has no stored energy.” #Failure reporting string f a i l t y p e =”No Energy”#Failure type r e t u r n [failtype , noEstring]#If designparam.masscalc finds the design has no s t o r e d energy, fail the design maxclimb = 0 f o ri in range(len(flightlegs)):#Find the maximum climb angle for the mission i f flightlegs[i][2][2] > maxclimb : maxclimb = flightlegs[i ][2][2]

fuelmass = initfuelmass#Variable fuel mass hypfuelmass = initfuelmass Eusagesum = 0 totaltime = 0 Eremaining = initstoredE#Variable energy remaining initialise = missionclass.custominit customise = missionclass.custom returner = missionclass.globalreturn

i f extended == True:#generating the initial performance map localcostf = missionclass.localcosts[0] minmass = deadmass maxmass = (deadmass+initfuelmass) minaoa = 0 maxaoa = 20 masses = np. linspace(minmass,maxmass,5) aoas = np. linspace(minaoa,maxaoa) p a s s e r =’None’ aoastorage = [] Estorage = [] Festorage = [] vstorage = [] cdastorage = [] clastorage = [] pshaftstorage = [] penginestorage = [] nstorage = [] Jstorage = [] Qstorage = [] engeffstorage = [] propeffstorage = [] timetakenstorage = [] localcoststorage = [] f o ri in range(len(masses)): p r i n t(’Extended progress=’+str(int(i+1))+’/’+str(len(masses))) aoastore , Estore, Festore, vstore , cdastore , clastore , pshaftstore , penginestore ,nstore ,Jstore ,Qstore ,engeffstore ,propeffstore ,timetakenstore , localcoststore = efficientflight .main(liftf ,dragf,0,1000,proprad,1.225,masses[i],fct , fcq ,feta ,feng ,numeng, localcostf ,passer ,2) aoastorage .append(aoastore) Estorage .append(Estore) Festorage .append(Festore) vstorage .append(vstore) cdastorage .append(cdastore) clastorage .append(clastore) pshaftstorage .append(pshaftstore) penginestorage .append(penginestore) nstorage .append(nstore) Jstorage .append(Jstore) Qstorage .append(Qstore) engeffstorage .append(engeffstore) propeffstorage .append(propeffstore) timetakenstorage .append(timetakenstore) localcoststorage .append(localcoststore) Fmasslist = [] Faoalist = [] Fpenginelist = [] Fvstoragelist = [] Fldratiolist = [] Fcombinedefflist = [] Fpropefflist = [] FEreqlist = [] f o ri in range(len(masses)):

107 Iaoalist = aoastorage[i] Ivstoragelist = vstorage[i] Ipenginelist = penginestorage[i] cdalist = cdastorage[i] clalist = clastorage[i] Ildratiolist = [clalist[j]/cdalist[j] forj in range(len(clalist))] l i s t l e n = len(Iaoalist) engefflist = engeffstorage[i] propefflist = propeffstorage[i] Icombinedefflist = [engefflist[i] ∗ propefflist[i] fori in range(len( engefflist))] IEreqlist = Estorage[i] FEreqlist += IEreqlist tmass = masses[i] Fmasslist += [tmass] ∗ l i s t l e n Faoalist += Iaoalist Fpenginelist += Ipenginelist Fvstoragelist += Ivstoragelist Fldratiolist += Ildratiolist Fcombinedefflist += Icombinedefflist Fpropefflist += propefflist v1storage = [] v2storage = [] v3storage = [] v4storage = [] v5storage = [] v6storage=[] v7storage=[] v8storage=[] varpassflag = False i f type(missionclass.passers) == list: varpassflag = True exec(initialise , {} ,locals())#execute the custom initialisation command − must be one s t r i n g, use \n if you want to use multiple commands f o ri in range(len(flightlegs)):#For each major leg i f varpassflag == True: passer = missionclass.passers[i] e l s e: passer = missionclass.passers i f len(missionclass.localcosts) == 1: localcostf = missionclass.localcosts[0] e l s e: localcostf = missionclass.localcosts[i] legdata = flightlegs[i]#Load the leg data legdist = legdata[0][0]#Read the true distance to be covered climb = dtr(legdata[2][2])#Read the climb angle altbase = legdata[1][0][2]#Read the base altitude for the leg dalt = legdata[1][4][2]#Read how much the altitude changes across the leg n s t e p s = int(legdist//maxdist + 1)#Check how many steps will be necessary to avoid violating the maxdist constraint(integer) stepdist = legdist / nsteps#Find the distance of each step startxloc = legdata[1][0][0] f o rj in range(nsteps):#For each step in the current leg vehmass = fuelmass + deadmass#Read the full vehicle mass alt = altbase + dalt ∗ j / n s t e p s#Read the current altitude localdens = dens(alt/1000,db)#Find the current density xloc = startxloc+stepdist ∗ j i f extended == True: lcost , Euse, passed , timetaken , rminaoa,rm, rminV, rminpshaft ,rminpengine ,rminpropeff ,rminengeff , rminJ = efficientflight .main(liftf ,dragf ,climb,stepdist , proprad ,localdens ,vehmass,fct ,fcq ,feta ,feng ,numeng, localcostf ,passer ,1) v1storage .append(rminaoa) v2storage .append(rm) v3storage .append(rminV) v4storage .append(rminpengine) v5storage .append(Euse) v6storage .append(localdens) v7storage .append(xloc) v8storage .append(rtd(climb))

e l s e: lcost , Euse, passed, timetaken = efficientflight.main(liftf ,dragf ,climb, stepdist ,proprad ,localdens ,vehmass,fct ,fcq ,feta ,feng ,numeng, localcostf ,passer ,0) i f Euse ==’Fail’: noflightstring =”Design”+designation+” failed mid −f l i g h t(leg”+str(i

108 +1)+”/”+str(len(flightlegs))+”, step”+str (j+1)+”/”+str(nsteps)+”)” f a i l t y p e =”Mid −f l i g h t” r e t u r n [failtype ,noflightstring] totaltime += timetaken exec(customise , {} ,locals())#just like initialise, must be one string sumlocals += lcost Eusagesum += Euse Eremaining −= Euse#Find how much energy remains fue lmass −= Euse/fuelEdensity#Reduce the fuel mass based on how much energy i s consumed hypfuelmass −= Euse/fuelEdensity#hypothetical fuel mass that will continue to drop below0 − not used for vehicle mass calculations i f fuelmass < 0 : fue lmass = 0#stops fuel mass from going below 0, since the fuel mass only matters to vehmass, it stops the vehicle mass from decreasing more than it should s c a l e = 0 . 5 i f extended == True: i f localcostf ==’Ereq’: plt.figure(figsize=(15∗ s c a l e , 1 0 ∗ s c a l e ) ) plt. tricontourf(Fmasslist ,Faoalist ,FEreqlist ,30,cmap=cm. viridis) cb = plt.colorbar() cb . s e t l a b e l (’Craft performance map(Energy usage)(J)’) plt. scatter(v2storage ,v1storage ,color=’k’,label=’Design optimal performance’) plt.xlabel(’Vehicle mass(kg)’) plt.ylabel(’Angle of attack(deg)’) plt . title (name+’ Performance Map(Energy)(Mass versus Angle of Attack)’) p l t . xlim (min(Fmasslist) ,max(Fmasslist)) p l t . ylim (min(Faoalist),max(Faoalist)) plt.legend() p l t . show ( )

plt.figure(figsize=(15∗ s c a l e , 1 0 ∗ s c a l e ) ) plt. tricontourf(Fmasslist ,Faoalist ,Fpenginelist ,30,cmap=cm. viridis) cb = plt.colorbar() cb . s e t l a b e l (’Craft performance map(power consumption)(W)’) plt. scatter(v2storage ,v1storage ,color=’k’,label=’Design optimal performance’) plt.xlabel(’Vehicle mass(kg)’) plt.ylabel(’Angle of attack(deg)’) plt . title (name+’ Performance Map(Mass versus Angle of Attack)’) p l t . xlim (min(Fmasslist) ,max(Fmasslist)) p l t . ylim (min(Faoalist),max(Faoalist)) plt.legend() p l t . show ( )

plt.figure(figsize=(15∗ s c a l e , 1 0 ∗ s c a l e ) ) plt. tricontourf(Fmasslist ,Fvstoragelist ,Fpenginelist ,30,cmap=cm. viridis) cb = plt.colorbar() cb . s e t l a b e l (’Craft performance map(power consumption)(W)’) plt. scatter(v2storage ,v3storage ,color=’k’,label=’Design optimal performance’) plt.xlabel(’Vehicle mass(kg)’) plt.ylabel(’Flight velocity(m/s)’) plt . title (name+’ Performance Map(Mass versus velocity)’) p l t . xlim (min(Fmasslist) ,max(Fmasslist)) p l t . ylim (min(Fvstoragelist),max(Fvstoragelist)) plt.legend() p l t . show ( )

plt.figure(figsize=(15∗ s c a l e , 1 0 ∗ s c a l e ) ) plt. tricontourf(Faoalist ,Fvstoragelist ,Fpenginelist ,30,cmap=cm. viridis) cb = plt.colorbar() cb . s e t l a b e l (’Craft performance map(power consumption)(W)’) plt. scatter(v1storage ,v3storage ,color=’k’,label=’Design optimal performance’) plt.xlabel(’Angle of attack(deg)’) plt.ylabel(’Flight velocity(m/s)’) plt . title (name+’ Fuel Consumption Map(AOA versus Velocity)’) p l t . xlim (min(Faoalist),max(Faoalist)) p l t . ylim (min(Fvstoragelist),max(Fvstoragelist)) plt.legend() p l t . show ( )

plt.figure(figsize=(15∗ s c a l e , 1 0 ∗ s c a l e ) ) plt. tricontourf(Faoalist ,Fvstoragelist , Fldratiolist ,30,cmap=cm. viridis)

109 cb = plt.colorbar() cb . s e t l a b e l (’Craft performance map(L/D ratio)’) plt. scatter(v1storage ,v3storage ,color=’k’,label=’Design optimal performance’) plt.xlabel(’Angle of attack(deg)’) plt.ylabel(’Flight velocity(m/s)’) plt . title (name+’L/D Map(AOA versus Velocity)’) p l t . xlim (min(Faoalist),max(Faoalist)) p l t . ylim (min(Fvstoragelist),max(Fvstoragelist)) plt.legend() p l t . show ( )

plt.figure(figsize=(15∗ s c a l e , 1 0 ∗ s c a l e ) ) plt. tricontourf(Faoalist ,Fvstoragelist ,Fcombinedefflist ,30,cmap=cm. viridis) cb = plt.colorbar() cb . s e t l a b e l (’Craft performance map(combined efficiency)’) plt. scatter(v1storage ,v3storage ,color=’k’,label=’Design optimal performance’) plt.xlabel(’Angle of attack(deg)’) plt.ylabel(’Flight velocity(m/s)’) plt . title (name+’ Combined Efficiency Map’) p l t . xlim (min(Faoalist),max(Faoalist)) p l t . ylim (min(Fvstoragelist),max(Fvstoragelist)) plt.legend() p l t . show ( )

plt.figure(figsize=(15∗ s c a l e , 1 0 ∗ s c a l e ) ) plt. tricontourf(Faoalist ,Fvstoragelist , Fpropefflist ,30,cmap=cm. viridis) cb = plt.colorbar() cb . s e t l a b e l (’Craft performance map(propeller efficiency)’) plt. scatter(v1storage ,v3storage ,color=’k’,label=’Design optimal performance’) plt.xlabel(’Angle of attack(deg)’) plt.ylabel(’Flight velocity(m/s)’) plt . title (name+’ Propeller Efficiency Map’) p l t . xlim (min(Faoalist),max(Faoalist)) p l t . ylim (min(Fvstoragelist),max(Fvstoragelist)) plt.legend() p l t . show ( )

vs = np.linspace(10,40,30) finalaoastorage=[] finalvstorage = [] ldratiostorage=[] f o ri in aoas: f o rj in vs: liftval = liftf([dtr(i),j]) dragval = dragf([dtr(i),j]) ldratio = liftval/dragval finalaoastorage .append(i) finalvstorage .append(j) ldratiostorage .append(ldratio) plt.figure(figsize=(15∗ s c a l e , 1 0 ∗ s c a l e ) ) plt. tricontourf(finalaoastorage ,finalvstorage ,ldratiostorage ,30,cmap=cm. viridis) cb = plt.colorbar() cb . s e t l a b e l (’Lift −to−drag ratio’) plt. scatter(v1storage ,v3storage ,color=’k’,label=’Design optimal performance’) plt.xlabel(’Angle of attack(deg)’) plt.ylabel(’Flight velocity(m/s)’) plt . title (name+’ Lift −to−Drag Ratio Map’) plt.xlim(0,20) plt.ylim(10,40) plt.legend() p l t . show ( )

globalcoststr = missionclass.globalcost globalcost = eval(globalcoststr) r e t u r n [globalcost ,sumlocals ,eval(returner)] U.7 Code: Convert import numpy as np d e f dtr(ang): r e t u r n ang∗np . p i /180 d e f rtd(ang): r e t u r n ang ∗180/np . p i d e f ftm(foot): r e t u r n foot ∗0.3048

110 d e f mtf(metre): r e t u r n metre ∗3.28084 d e f lbkg(pounds): r e t u r n pounds ∗0.453592 d e f kglb(kilograms): r e t u r n kilograms ∗2.20462 U.8 Csolver d e f curvesolver(xc,yc,x1,y1,x2,y2): import math import numpy as np from convert import rtd,dtr from angsolver import standard as sdd sd = sdd ( ( x1−xc ) , ( y1−yc ) ) e r r o r = 5 t o l = 1e−5 s t e p = 1 mod = 0 . 1 d e f dsolve(x1,y1,x2,y2): r e t u r n ((x2−x1 ) ∗∗2 + ( y2−y1 ) ∗∗2) ∗∗0.5

d e f side(x1,y1,x2,y2,xc,yc): t o t a l = ( x2−xc ) ∗( y1−yc ) − ( y2−yc ) ∗( x1−xc ) lencontrol = dsolve(xc,yc,x1,y1) r e t u r n total/lencontrol

dside = side(x1,y1,x2,y2,xc,yc) i f dside > 0 : angmodder = −90 dr =’right’ e l i f dside < 0 : angmodder = 90 dr =’left’ e l i f dside == 0: r a i s e ValueError(’Called circle solving module when the end points lies on the l i n e created from control to start points’)

startang = sdd((x1−xc ) , ( y1−yc ) ) starttoendang = sdd((x2−x1 ) , ( y2−y1 ) ) d i f f a n g = abs(starttoendang −s t a r t a n g ) interiorang = abs(90 − d i f f a n g ) dist = dsolve(x1,y1,x2,y2) r = dist/2/math.cos(dtr(interiorang)) x f = x1+r ∗math. cos(dtr(sd+angmodder)) y f = y1+r ∗math. sin (dtr(sd+angmodder)) dang = abs(sdd((x2 −x f ) , ( y2−y f ) )−sdd ( ( x1−x f ) , ( y1−y f ) ) ) estd = sdd((x2−x f ) , ( y2−y f ) ) − 90∗ d s i d e /abs(dside) ecx = x2 + math.cos(dtr(estd+180)) ecy = y2 + math.sin(dtr(estd+180)) c l e n g t h = 2∗np . p i ∗ r ∗dang /360 scstd = sdd((x1−x f ) , ( y1−y f ) ) ecstd = sdd((x2−x f ) , ( y2−y f ) ) r e t u r n r,[xf,yf] ,[ecx,ecy],dr,dang,clength ,scstd ,ecstd ,estd U.9 Designparam import cogen#Imports the coefficient generation functions import compiler#Imports the function merger function import massfinder#Import the function to determine component masses d e a d l i s t = [’name’,’dead’,’eng’,’fuel’,’batt’,’prop’,’lg’]#List of parameters that won’t a f f e c t lift/drag notmasslist=[’name’,’fuel’,’batt’,’cust1’,’prop’]#List of parameters that don’t get t h e i r mass auto calculated as dead mass d e f geomload(geomnumber) :#Loads the desired geometry intoa class i f type(geomnumber) != str: n = str (geomnumber)#Converts the input number toa string for file path finding e l s e: n = geomnumber mod1 =’.txt’ i f mod1 in geomnumber: mod1 =’’ i f’/’ not in geomnumber: path =”designs/”+n+mod1#Finds the file

111 e l i f’/’ in geomnumber: path = geomnumber+mod1 c l a s s geomdata:#Creates an empty class for filling pass G = geomdata#Createsa class calledG that is of type geomdata \ exec(open(path).read() , {} ,locals())#Executes the code within the file specified, f i l l i n g the class r e t u r nG#Returns the filled class d e f geomsplit(geomclass):#Splits the geometry class into separate parts for Cd,Cl f i n d i n g atts= [param for param in dir(geomclass) if not param.startswith(’ ’)]#Find all a t t r i b u t e s of the class(i.e. won’t return rectangle if the geometry has no r e c t a n g l e s) name = geomclass.name#Finds geometry name geoms = [ a t t for att in atts if att not in deadlist]#Find each geometry that might c o n t r i b u t e to aerodynamics geomparams = []#Empty list for storing the actual geometry parameters f o ri in range(len(geoms)):#For each geometry type geomparams. append(getattr(geomclass ,geoms[ i ]))#Add its geometry data to the list r e t u r n name, geoms, geomparams#Return the name, geometry types and geometry parameters

#For paramgen, returning functions for Cl ∗A and Cd∗A instead of just Cl, Cd so that they can be summed together, as they are all multiplied by 0.5 ∗ rho ∗vˆ2(when ignoring skin f r i c t i o n) d e f paramgen(geoms ,geomparams) :#Using the geometry types and corresponding geometric parameters − f i n d i n gC (d,L) ∗A funcstoredrag = []#Empty function storage list for CdA funcstorelift = []#Same for ClA f o ri in range(len(geoms)):#For each geometry type f o rj in range(len(geomparams[ i ])):#For each instance of that geometry type calledfunc = getattr(cogen ,geoms[ i ])#determine the function to call −> cogen .”geometry” −> i.e. cogen.cyl filledfuncdrag , filledfunclift = calledfunc(geomparams[i ][ j])#call the fun cti on, passing the geometric parameters to geta function for cd,cl funcstoredrag.append(filledfuncdrag)#Add the function for cd to the storage l i s t funcstorelift .append(filledfunclift) fusedfuncdrag = compiler.main(funcstoredrag)#Pass the storage list into the compiler f u n c t i o n to geta single function for cdA fusedfunclift = compiler.main(funcstorelift) r e t u r n fusedfuncdrag , fusedfunclift#Return the fused Cd function d e f masscalc(geomclass): atts = [param for param in dir(geomclass) if not param.startswith(’ ’)]#For e v e r y t h i n g that’s an actual class parameter masses = [att for att in atts if att not in notmasslist]#Find all the parameters that contribute to dead mass massedparams = []#storage for the actual values for the parameters that contribute deadmass = 0 f o ri in range(len(masses)):#For each mass −contributing parameter(i.e. cyl, rect, dead, etc.) massedparams .append(getattr(geomclass ,masses[ i ]))#Add the parameters values to the storage list f o ri in range(len(masses)):#For each mass −contributing parameter type f o rj in range(len(massedparams[ i ])):#For each instance of that parameter type i n the vehicle functocall = getattr(massfinder ,masses[ i ])#Determine the correct function to c a l l in the massfinder script(i.e. cyl, rect, etc.) calledfunc = functocall(massedparams[i ][ j])#Call the function, passing in the parameters values([i][j]) − typei, instancej deadmass += calledfunc#Sum up the non −changing masses i f’fuel’ in atts: initfuelmass = geomclass.fuel [0]#If the craft uses fuel, read off the initial f u e l mass fuelEdensity = geomclass.fuel [1] initstoredE = initfuelmass ∗ fuelEdensity e l i f’batt’ in atts:#If the craft uses batteries, fuel mass=0 initfuelmass = 0 deadmass += geomclass.batt [1] fuelEdensity = 1e10#arbitrarily high to represent the fact that mass doesnt change with battery energy use, this doesnt really matter since controller.main changes fuelmass to0 if fuelmass < 0

112 initstoredE = geomclass.batt[0] e l s e: p r i n t(”The design has no energy source. Aborting check for this design”) r e t u r n deadmass, initfuelmass , fuelEdensity , False p r i n t(’Design dry mass=’+str(round(deadmass ,2) )+’ kg, initial fuel mass=’+str( initfuelmass)+’ kg.’) r e t u r n deadmass, initfuelmass , fuelEdensity , initstoredE U.10 Efficientflight import numpy as np from convert import dtr,rtd import time import math d e f itVsolver(m,rho,fcla ,fcda ,aoa,aof):#Iteratively solve forv given the inability to s o l v e directly, as ClA and CdA contain wing lift/drag information, which doesnt vary i n any real trend withv g = 9 . 8#pre definition stuff LHS = m∗g ∗2/ rho e r r o r = 1 v = 10#initial velocity guess t o l = 1e−5 s t e p = 5 count = 0 while abs(error) >= t o l :#while the error is too large RHS = v∗∗2 ∗ (fcla ([aoa,v]) ∗ (np.sin(aof) ∗np.tan(aof+aoa) +np.cos(aof)) + fcda([ aoa , v ] ) ∗ (np.cos(aof) ∗np.tan(aof+aoa) − np.sin(aof))) e r r o r = RHS − LHS i f abs(error) <= t o l :#if error is good, break out of loop break i f error < 0 :#if RHS 0 :#If RHS >LHS v −= s t e p#Step back once s t e p ∗= 0 . 5#Reduce step size v += s t e p#Step forward(as the solution must lie somewhere between the p r e v i o u s and current RHS when checking) count += 1 r e t u r nv

#Calculates the force output required from the engine given certain flight conditions d e f Fengine(ClA,CdA,aoa,aof ,v,rho):#directly calculate required thrust r e t u r n 0.5 ∗ rho ∗v ∗∗2∗(ClA([aoa,v]) ∗np.sin(aof) + CdA([aoa,v]) ∗np.cos(aof))/(np.cos(aof +aoa ) )

#solves for the propeller spin rate in revolutions per second, and returns it plus the advance ratio d e f nsolver(Fe,fct ,proprad ,v,rho=1.225,start=5,step=5): D = proprad ∗2#prop diameter e r r o r = 1#initial error − arbitrarily set greater than tolerance t o l = 1e−5#error tolerance count = 0#number of loops n = s t a r t#note thatn is revolutions per second LHS = Fe#LHS of Thrust= rho ∗ Ct(J) ∗ nˆ2 ∗ Dˆ4 warn1, warn2 = True, True#makes warning messages only happen once s i g n = s t e p /abs(step)#sign of the step value while abs(error) >= t o l :#while error is unsatisfactory J = v/n/D#calculate the new advance ratio RHS = rho ∗ f c t ( J ) [ ( ) ] ∗ n∗∗2 ∗ D∗∗4#calculate the thrust at this velocity+ rpm/ advance ratio #print(n,round(J,2),round(LHS,2),round(RHS,2),round(fct(J)[()],2)) e r r o r = LHS − RHS#find the error i f abs(error) <= t o l :#if the error is acceptable, break the loop break i f error ∗ s i g n >= 0 :#if LHS > RHS(for sign+ve) n += s t e p#step up e l i f error ∗ s i g n < 0 :#if RHS > LHS(for sign+ve) n −= s t e p#step back down s t e p ∗=0.1#reduce step size n += s t e p#step up count += 1#add one to count i f count > 500 & warn1 == True:#generic warning messages warn1 = False p r i n t(’nsolver seems to be non −converging’)

113 i f count > 2000 & warn2 == True: warn2 = False p r i n t(’nsolver has failed to converge. Returning zeroes to continue the s i m u l a t i o n.’) r e t u r n 0,0 r e t u r n n,J

#Finds the energy required for the leg d e f main(ClAf,CdAf,aof ,dist ,proprad ,rho,m,fct ,fcq ,feta ,feng ,numeng, localcoststr ,passers , extended=0):#main(ClAf,CdAf,aof,dist,proprad,rho,m, Fmax,eff): i f extended != 2: p r i n t(”Craft current mass=” ,m) resolution = 0.1#Resolution of angles to sweep e l i f extended == 2: resolution = 0.5 amax = 20#Maximum angle to sweep to amin = 0 a s t o r e = [ ]#Storage of angles checked, only really needed for troubleshooting Estore = [ ]#Storage of energy required, needed to find minimum, alternatively could j u s t do ifE new < E currentmin,E currentmin=E new? v s t o r e =[] F e s t o r e = [ ] pshaftstore = [] penginestore = [] n s t o r e = [ ] J s t o r e = [ ] Qstore = [ ] engeffstore = [] propeffstore = [] FePerstore = [] timetakenstore = [] cdastore = [] clastore = [] localcosts = [] aoastore=[] f o ri in np. linspace(amin,amax,int ((amax −amin)/resolution+1)):#For each angle to be checked aoa = dtr ( i )#convert angle of attack to radians v = itVsolver(m,rho,ClAf,CdAf,aoa,aof)#iteratively solve for velocity timetaken = dist/v ClA = ClAf([aoa,v])#[0] CdA = CdAf([aoa,v])#[0] i f math.isnan(Fe): continue i f Fe <= 0 : Fe = 0 FePer = Fe/numeng n , J = 0 ,0 p s h a f t=0 Q = 0 e n g e f f = 1 p r o p e f f = 1 pengine=0 Ereq = 0 e l i f Fe > 0 : FePer = Fe/numeng#thrust per engine required n,J = nsolver(FePer,fct ,proprad ,v,rho, start=5,step=10)#iteratively solves f o r the RPM that gives the necessary thrust p s h a f t = rho ∗ n∗∗3 ∗ ( proprad ∗2) ∗∗5 ∗ f c q ( J ) ∗ 2 ∗ np . p i Q = rho ∗ n∗∗2 ∗ ( proprad ∗2) ∗∗5 ∗ f c q ( J )#shaft torque propeff = feta(J)#propeller efficiency, not actually used for calculations Fd = 0 . 5 ∗ rho ∗v∗∗2∗CdA#drag force, not used for real calculations i f type(feng) == list:#this stuff is for the new engine model powerf,torquef ,preqf = feng#reads the performance curves poweravail = powerf(n ∗60) [ ( ) ]#available power, takes RPM input torqueavail = torquef(n ∗60) [ ( ) ]#available torque, takes RPM input i f pshaft < poweravail andQ < torqueavail :#checks if the power/torque i s sufficiently available pengine = preqf(n ∗60) [ ( ) ]#reads the power consumption of the engine (just theg/min value ∗ 4 6 . 4 MJ/kg/ 60 to geta power) engeff = pshaft/pengine#engine efficiency, purely for reference( s h a f t power divided by input power) e l s e: continue e l i f type(feng) != list:#otherwise if using the old engine model rpm = n∗60

114 pengine = feng(rpm,pshaft) pe = pengine i f pe == None: pe = 0 i f pengine == None: continue e l s e: engeff = pshaft/pengine

Ereq = pengine ∗ d i s t /v ∗ numeng#energy requirement is power per engine ∗ time ∗ number of engines

i f pengine != None: clastore .append(ClA) cdastore .append(CdA) l o c a l c o s t = eval(localcoststr)#evaluate the local cost string from the mission file localcosts .append(localcost)#store the local cost astore .append(aoa)#Stores the other parameters as well aoastore .append(i) vstore .append(v) Festore .append(Fe) FePerstore .append(FePer) Estore .append(Ereq)#Stores the energy required pshaftstore .append(pshaft) penginestore .append(pengine) nstore .append(n) Jstore .append(J) Qstore .append(Q) engeffstore .append(engeff) propeffstore .append(propeff) timetakenstore .append(timetaken) t r y: mincost = min(localcosts) except ValueError: r e t u r n’Fail’,’Fail’,’Fail’,’Fail’ num = localcosts .index(mincost) minEreq = Estore[num] minFe = Festore[num]#finds the parameters associated with the lowest cost flight configuration minV = v s t o r e [ num ] minaoar = astore[num] minaoa = aoastore[num] mincda = cdastore[num] mincla = clastore[num] minpshaft = pshaftstore[num] minpengine = penginestore [num] minn = nstore[num] minJ = Jstore[num] minQ = Qstore [ num ] minengeff = engeffstore[num] minpropeff = propeffstore [num] mintimetaken = timetakenstore [num] i f extended != 2: p r i n t(’AOA=’,round(minaoa,2) ,’V=’,round (minV , 2 ) ,’n=’,round(minn,2) ,’Q=’,round( minQ , 2 ) ,’engeff=’,round(float(minengeff) ,3) ,’Propeff=’,round(float(minpropeff) ,3) ,’J= ’,round(float(minJ) ,2) ,’Fe=’,round(float(minFe) ,2) ,’minE=’,round(minEreq,2) ,’cla=’, round(mincla ,3) ,’cda=’,round(mincda,3) ,’power in=’,round(minpengine ,2) ,’p used=’, round(minpshaft ,2))

p a s s e d v a l = eval(passers) i f extended == 0: r e t u r n mincost , minEreq, passedval , mintimetaken#Returns the minimised cost f u n c t i o n and its associated energy usage e l i f extended == 1: r e t u r n mincost ,minEreq,passedval ,mintimetaken , minaoa,m, minV, minpshaft , minpengine ,minpropeff ,minengeff , minJ e l i f extended == 2: r e t u r n aoastore, Estore, Festore, vstore, cdastore, clastore , pshaftstore , penginestore ,nstore ,Jstore ,Qstore ,engeffstore ,propeffstore ,timetakenstore , localcosts U.11 Enviro from tables import Atmosphere d e f pres(alt ,pbase): r e t u r n pbase ∗ Atmosphere(alt) [1]

115 d e f dens(alt ,dbase): r e t u r n dbase ∗ Atmosphere(alt) [0] d e f temp(alt ,tbase): r e t u r n tbase ∗ Atmosphere(alt) [2] U.12 Interpos d e f digidata1d(name,kind=’linear’,fillval=0): from scipy.interpolate import interp1d i f type(name) == int or type(name) == float:#reads the name, if itsa float or int then turn it toa string name = str(int (name)) e l i f type(name) != str:#if its not float,int,str then raise an error r a i s e TypeError(’File name is wrong. digidata1d received type’+str(type(name))) f i l e l o a d = open(’data/’+name+’.csv’,’r’)#load the file l d a t a = list(fileload)#turn the fileload.close() m1 = [i.replace(’ \n’,’’) fori in ldata] m2 = [i.split(’,’) fori in m1] nrow = len (m2) n c o l = len(m2[0]) xs = [ ] ys = [ ] f o ri in range(nrow): xs . append (float(m2[i ][0])) ys . append (float(m2[i ][1])) interpfunc = interp1d(x=xs,y=ys, fill value=fillval ,bounds error=False , kind=kind) r e t u r n interpfunc d e f digidata(name,mode=’cubic’ ,extrap=1,fillval=0): import numpy as np from scipy.interpolate import griddata i f type(name) == int or type(name) == float: name = str(int (name)) e l i f type(name) != str: r a i s e TypeError(’File name is wrong. digidata received type’+str(type(name))) f i l e l o a d = open(’data/’+name+’.csv’,’r’) l d a t a = list(fileload) fileload.close() y f i l e = open(’data/’+name+’y.csv’,’r’) yldata = list(yfile) yfile.close() xm1 = [i.replace(’ \n’,’’) fori in ldata] xm2 = [i.split(’,’) fori in xm1 ] ym1 = [i.replace(’ \n’,’’) fori in yldata] ym2 = [i.split(’,’) fori in ym1 ] x l s = [ [ float(i) fori in xm2t] for xm2t in xm2 ] y l s = [ [ float(i) fori in ym2t] for ym2t in ym2 ] ys = y l s [ 0 ] nrow = len(xls) n c o l = len(xls[0]) xs = [ ] zs = [ ] i f len(ys) != ncol −1: r a i s e ValueError(”Not enoughy’s provided in accompanying data file”) f o ri in range(ncol −1) : c o l = i +1 f o rj in range(nrow): i f i ==0: xs.append(xls[j ][0]) zs.append(xls[j ][ col]) pts = np.array([]) f o ri in ys: f o rj in xs: coord = [j,i] pts = np.append(pts ,coord) pts = np.array s p l i t ( pts ,len(pts)/2) pts = np.array(pts) minx = min(xs) maxx = max(xs) miny = min(ys) maxy = max(ys) d e f interpofunc(x,y): i f extrap == 0: aval = griddata(pts ,zs ,(x,y) ,method=mode, fill value=fillval) i f extrap == 1:

116 i fx < minx : x = minx i fx > maxx : x = maxx i fy < miny : y = miny i fy > maxy : y = maxy aval = griddata(pts ,zs ,(x,y) ,method=mode) r e t u r n float(aval) r e t u r n interpofunc d e f digidatanew(name,extrap=1,fillval=0): import numpy as np from scipy.interpolate import CloughTocher2DInterpolator as cti i f type(name) == int or type(name) == float: name = str(int (name)) e l i f type(name) != str: r a i s e TypeError(’File name is wrong. digidata received type’+str(type(name))) f i l e l o a d = open(’data/’+name+’.csv’,’r’) l d a t a = list(fileload) fileload.close() y f i l e = open(’data/’+name+’y.csv’,’r’) yldata = list(yfile) yfile.close() xm1 = [i.replace(’ \n’,’’) fori in ldata] xm2 = [i.split(’,’) fori in xm1 ] ym1 = [i.replace(’ \n’,’’) fori in yldata] ym2 = [i.split(’,’) fori in ym1 ] x l s = [ [ float(i) fori in xm2t] for xm2t in xm2 ] y l s = [ [ float(i) fori in ym2t] for ym2t in ym2 ] ys = y l s [ 0 ] nrow = len(xls) n c o l = len(xls[0]) xs = [ ] zs = [ ] i f len(ys) != ncol −1: r a i s e ValueError(”Not enoughy’s provided in accompanying data file”) f o ri in range(ncol −1) : c o l = i +1 f o rj in range(nrow): i f i ==0: xs.append(xls[j ][0]) zs.append(xls[j ][ col]) pts = np.array([]) f o ri in ys: f o rj in xs: coord = [j,i] pts = np.append(pts ,coord) pts = np.array s p l i t ( pts ,len(pts)/2) pts = np.array(pts) minx = min(xs) maxx = max(xs) miny = min(ys) maxy = max(ys) func = cti(pts,zs,fill value=fillval) d e f interpofunc(x,y): i f extrap == 0: aval = func(x,y) i f extrap == 1: i fx < minx : x = minx i fx > maxx : x = maxx i fy < miny : y = miny i fy > maxy : y = maxy aval = func(x,y) r e t u r n float(aval) r e t u r n interpofunc d e f propperf(designation): from scipy.interpolate import interp1d f i l e= open(’data/props/’+designation+’.txt’,’r’) l s = list(file)

117 f i l e .close() m1 = [i.replace(’ \n’,’’) fori in ls] m2 = [ ] checks = [’Diameter=’,’Number of Blades=’,’Blade Pitch=’,’Blade Setting Angle=’,’ Blade Chord=’,’Taper Ratio’,’Advance Ratio’] indexstore = [None,None,None,None,None,None,None] f o ri in range(len(m1)): f o rj in checks: i fj in m1[i]: indexstore[checks.index(j)] = i f o ri in m1: b a s e l i n e = i brokenlist = baseline.split(’’) cleanlist = [j forj in brokenlist if j!=’’] m2.append(cleanlist) diam = float(m2[indexstore [0]][ − 1 ] ) nblades = float(m2[indexstore [1]][ − 1 ] ) p i t c h = float(m2[indexstore [2]][ − 1 ] ) s e t a n g l e = float(m2[ indexstore [3]][ − 1 ] ) rootchord = float(m2[ indexstore [4]][ − 1 ] ) t a p r a t = float(m2[ indexstore [5]][ − 1 ] ) m3 = [ ] f o ri in range(indexstore[6]+1,len(m2)): m3.append(m2[ i ]) f o ri in range(len(m3)): m3[ i ] = [float(j) forj in m3[i]] advs = [ ] c t s = [ ] cqs = [ ] e t a s = [ ] f o ri in m3: advs.append(i [0]) cts.append(i [1]) cqs.append(i [2]) etas.append(i [3])

fct = interp1d(advs,cts ,kind=’cubic’ ,bounds error=False , fill v a l u e =0) fcq = interp1d(advs,cqs ,kind=’cubic’ ,bounds error=False , fill v a l u e =0) feta = interp1d(advs,etas ,kind=’cubic’ ,bounds error=False , fill v a l u e =0) #print(’Propeller used:’, designation,’ \ n P r o p e l l e r diameter =’,diam,’ \ nNumber of b l a d e s =’,nblades,’ \ nPitch =’,pitch,’ \ n S e t t i n g angle =’,setangle,’ \ nRoot chord =’, rootchord,’ \ nTapering ratio =’,taprat) r e t u r n fct ,fcq,feta ,diam d e f csvinterp1d(fileloc ,forcesearch=False ,kind=’cubic’): from scipy.interpolate import interp1d i f’data’ not in fileloc and forcesearch == False: f i l e l o c =’data/’+fileloc i f’.csv’ not in fileloc: f i l e l o c +=’.csv’ f i l e= open(fileloc ,’r’) d a t a l i s t = list(file) datalist = [i.replace(’ \n’,’’) fori in datalist] datalist = [i.split(’,’) fori in datalist] f i l e .close() nrow = len(datalist) n c o l = len(datalist [0]) xdata = [ ] ydatas = [ ] f o ri in range(ncol): tempdata = [] f o rj in range(nrow): v a l = float(datalist[j][i]) i f i ==0: xdata.append(val) e l s e: tempdata.append(val) i f i != 0: ydatas .append(tempdata) funcstores = [] f o r yset in ydatas: tempfunc = interp1d(xdata ,yset ,kind=kind) funcstores .append(tempfunc) r e t u r n funcstores d e f enginedata(name):

118 i f’/’ not in name: name +=’/’ powerfilename =’data/engs/’+name+’power.csv’ torquefilename =’data/engs/’+name+’torque.csv’ preqfilename =’data/engs/’+name+’preq.csv’ p o w e r f i l e = open(powerfilename ,’r’) powerdata = list(powerfile) powerfile.close() torquefile = open(torquefilename ,’r’) torquedata = list(torquefile) torquefile.close() p r e q f i l e = open(preqfilename ,’r’) preqdata = list(preqfile) preqfile.close() powerdata = [i.replace(’ \n’,’’).split(’,’) fori in powerdata] torquedata = [i.replace(’ \n’,’’).split(’,’) fori in torquedata] preqdata = [i.replace(’ \n’,’’).split(’,’) fori in preqdata] f o ri in [powerdata ,torquedata ,preqdata ]: f o rj in range(len(i)): f o rk in range(len(i[j])): i [ j ] [ k ] = float(i[j][k]) powerxs, powerys = [] ,[] torquexs, torqueys = [] ,[] preqxs, preqys = [] ,[] f o ri in powerdata: powerxs.append(i [0]) powerys.append(i [1]) f o ri in torquedata: torquexs.append(i [0]) torqueys.append(i [1]) f o ri in preqdata: preqxs.append(i [0]) preqys.append(i [1]) from scipy.interpolate import interp1d powerfunc = interp1d(powerxs ,powerys ,kind=’linear’ ,bounds error=False , fill v a l u e =0) torquefunc = interp1d(torquexs ,torqueys ,kind=’linear’ ,bounds error=False , fill v a l u e =0) preqfunc = interp1d(preqxs ,preqys ,kind=’linear’ ,bounds error=False , fill v a l u e =0) r e t u r n [powerfunc ,torquefunc ,preqfunc] d e f newengine(name,kind=’linear’): i f’/’ not in name: name +=’/’ poutfilename =’data/engs/’+name+’pout.csv’ pinfilename =’data/engs/’+name+’pin.csv’ p o u t f i l e = open(poutfilename ,’r’) p i n f i l e = open(pinfilename ,’r’) poutdata = list(poutfile) pindata = list(pinfile) poutfile.close() pinfile.close() pout = [i.replace(’ \n’,’’).split(’,’) fori in poutdata] pin = [i.replace(’ \n’,’’).split(’,’) fori in pindata] pout = [ [ float(i) fori in j] forj in pout] pin = [ [ float(i) fori in j] forj in pin] poutrpms = [i[0] fori in pout] poutfull = [i[1] fori in pout] poutpart = [i[2] fori in pout] pinrpms = [i[0] fori in pin] pinfull = [i[1] fori in pin] pinpart = [i[2] fori in pin] import scipy.interpolate as scp fpoutfull = scp.interp1d(poutrpms,poutfull ,kind=kind , fill value=0,bounds error=False) fpoutpart = scp.interp1d(poutrpms,poutpart ,kind=kind , fill value=0,bounds error=False) fpinfull = scp.interp1d(pinrpms,pinfull ,kind=kind, fill value=0,bounds error=False) fpinpart = scp.interp1d(pinrpms,pinpart ,kind=kind , fill value=0,bounds error=False) d e f econsumption(rpmval,preq): fullout = fpoutfull(rpmval)[()] partout = fpoutpart(rpmval)[() ] fullin = fpinfull(rpmval)[()] partin = fpinpart(rpmval)[() ] i f preq > f u l l o u t : r e t u r n None e l i f preq >= partout and preq <= f u l l o u t : perc = ( preq−partout)/(fullout −partout ) vtoreturn = partin + perc ∗( f u l l i n −p a r t i n )

119 r e t u r n vtoreturn e l i f preq < partout : r e t u r n partin r e t u r n econsumption U.13 Ldgen import scipy.interpolate as scp import numpy as np import os import subprocess as sp import matplotlib.pyplot as plt import time d e f main(wing=’NACA 0009’ ,chord=0.1): tstart = time.clock() i f’xftemp.txt’ in next(os.walk(’quarantine’))[2]:#If the temp file already exists, remove it os . remove (’quarantine/xftemp.txt’) liftfilename = wing+’ chord’+str(chord)+’ lift.npy’ dragfilename = wing+’ chord’+str(chord)+’ drag.npy’ w i n g f i l e s = next(os.walk(’data/wings’))[2] i f liftfilename in wingfiles and dragfilename in wingfiles: loadedfCl = np.load(’data/wings/’+liftfilename).item() loadedfCd = np.load(’data/wings/’+dragfilename).item() t2 = time.clock() p r i n t(’XFOIL function loading for’+wing+’ chord’+str(chord)+’ took’+str(round( t2−tstart ,5))+’ seconds.’) r e t u r n loadedfCl , loadedfCd

v i s c = 1 . 4 8 e−5#kinematic viscosity of air spsound = 347#sonic speed of air AOAmin = 0#minimum AOA AOAmax = 25#maximum AOA AOAres = 0.25#AOA resolution numAOA = int ( (AOAmax−AOAmin)/AOAres + 1)#number of AOAs being checked AOAs = np. ndarray . tolist (np. linspace (AOAmin,AOAmax,numAOA))#List of AOAs being checked, for indexing later Cls = [ ]#Cl list for use in scipy Cds = [ ]#Cd list for use in scipy a l l a o a s = [ ] a l l c l s = [ ] a l l c d s = [ ] a l l v s = [ ] Vs = [1,10,20,30,40,50,70,100]#Velocities to be checked f o rv in Vs:#For each velocity Cltemp = [None] ∗ numAOA#Createa temporary Cl list full of zeros(baseline r e s u l t for stall) Cdtemp = [None] ∗ numAOA#Createa temporary Cd list full of tens(baseline r e s u l t for stall) Re = int(v ∗ chord/visc)#Find Reynolds/Mach number Ma = round(v/spsound ,3) xfoilstring = wing+’ \nPLOP\nG\n\nPANE\nOPER\nITER 500\nVISC’+str (Re)+’ \nMACH’+ s t r (Ma)+’ \nPACC\ nquarantine/xftemp.txt \n\nASEQ’+str (AOAmin)+’’+str (AOAmax)+’’+str( AOAres)+’ \nPACC\n\ nquit \n’ xf = sp.Popen([’xfoil.exe’ ] , stdin=sp.PIPE, stdout=None, stderr=None)#Create the x f o i l subprocess t r y:#Try communicating the input string, then kill the process to avoid doubleups xf.communicate(xfoilstring .encode(’utf −8’) ,timeout=90) x f . k i l l ( ) except:#If it times out, kill the process anyway p r i n t(’Warning: XFOIL is timing out onV=’,v) x f . k i l l ( ) t e m p f i l e = open(’quarantine/xftemp.txt’,’r’)#Load the temporary file produced lines = tempfile.readlines()#Read the lines of the temp file f o ri in range(len(lines)):#For each line i f’ −−−− ’ in lines[i]:#Find the line with −−−− i n it, as this is just before the actual data linenum = i+1#Save the index break#Stop checking d e l lines[0:linenum]#Delete the lines with useless information f o rj in range(len(lines)):#For each line with data line = lines[j]#temporary line assignment

120 line.replace(’ \n’,’’)#remove \n from each string broken = line.split(’’)#Break the string intoa list of strings based on s p a c e s c l e a ne d = [float(n) forn in broken if n!=’’]#createa new list with only f l o a t values AOA = cleaned[0]#Read the AOA Cl = cleaned[1]#Read the Cl Cd = cleaned[2]#Read the Cad allaoas .append(AOA) allcls .append(Cl) allcds .append(Cd) allvs .append(v) tempfile.close() os . remove (’quarantine/xftemp.txt’)

pts = [[allaoas[i],allvs[i]] fori in range(len(allaoas))] fCl = scp.CloughTocher2DInterpolator(pts , allcls) fCd = scp.CloughTocher2DInterpolator(pts , allcds) np . save (’data/wings/’+liftfilename ,fCl ,allow pickle=True) np . save (’data/wings/’+dragfilename ,fCd, allow pickle=True) tend = time.clock() p r i n t(’XFOIL function generation for’+wing+’ chord’+str(chord)+’ took’+str(round( tend−tstart ,3))+’ seconds.’) r e t u r n fCl,fCd U.14 Massfinder import numpy as np from convert import mtf, ftm, lbkg, kglb, dtr import math d e f wing(ins):#main wing estimated weight − based on NASA FLOPS Weight Estimation Methods for transport aircraft main wing wingtype = ins[0] TCA = int(wingtype[ − 2 : ] ) /100#read the last two digits of the naca designationi.e.’ NACA 4510’ −> 10 for thickness to chord ratio= 0.1 wingspan = ins[1] rootchord = ins[2] tipchord = ins[3] sweep = ins[4] dihedral = ins[5] angle = ins[6] DG = i n s [ 7 ] avchord = (tipchord+rootchord)/2 wingarea = wingspan ∗ avchord AR = wingspan ∗∗2/ wingarea taper = tipchord/rootchord A1 = 8 . 8 A2 = 6 . 2 5 A3 = 0 . 6 8 A4 = 0 . 3 4 A5 = 0 . 6 A6 = 0.035 A7 = 1 . 5

FSTRT = 0 . 5#wing strut bracing factor,0 for no strut bracing,1 for full benefit, assumed mid−range EMS = 1 −0.25∗FSTRT#wing strut bracing factor

TLAM = math.tan(dtr(sweep)) − (2∗(1 − taper))/(AR∗(1+ taper ) )#tangent of 3/4 chord wing sweep, sweep given at 1/4 chord SLAM = TLAM/(1+TLAM∗∗2) ∗∗0.5#sin of 3/4 chord wing sweep angle FAERT = 0 . 3#Aeroelastic tailoring factor,0 for no aeroelastic tailoring,1 for maximum − assumed low range C4 = 1 − 0 . 5 ∗FAERT CAYA = max(0 ,AR−5) C6 = 0 . 5 ∗FAERT − 0.16∗FSTRT CAYL = (1−SLAM∗∗2) ∗(1+C6∗SLAM∗∗2+0.03∗CAYA∗C4∗SLAM)#wing sweep and aeroelastic f a c t o r

BT = 0.215 ∗ (0.037+0.7∗ taper ) ∗(mtf(wingspan) ∗∗2/mtf(mtf(wingarea))) ∗∗(EMS) /CAYL/TCA #wing equivalent bending material factor

FCOMP = 0 . 4#usage of composites in wing,0 for no use,1 for maximum use. hobby −i s t/ non−m i l i t a r y craft likely not overly high usage

121 VFACT = 1#variable sweep wing penalty −> no variable sweep=1 ULF = 3#ultimate load factor, NASA says default 3.75 but for hobby −i s t craft, likely lower CAYF = 1#multiple fuselage factor,1 for1 fuselage, 0.5 for >1 fuselage PCTL = 1#fraction of load carried by defined wing − f o r current tests, only1 main wing is used, assume all load is carried by it

W1NIR = A1 ∗ BT ∗ (1+(A2/mtf(wingspan)) ∗ ∗ 0 . 5 ) ∗ULF∗mtf(wingspan) ∗(1 −0.4∗FCOMP) ∗(1 −0.1∗ FAERT) ∗ CAYF ∗VFACT∗PCTL/1000000#wing bending material weight, not including e f f e c t s of intertia relief

SFLAP = 0 . 1 ∗ mtf(mtf(wingarea))#assume control surfaces(i.e. flaps) take up 10% of the wing area W2 = A3∗(1 −0.17∗FCOMP) ∗SFLAP∗∗A4∗ kglb (DG) ∗∗A5#wing shear material and control s u r f a c e weight W3 = A6∗(1 −0.3∗FCOMP) ∗mtf(mtf(wingarea)) ∗∗A7#Wing miscellaneous item weight NEW = 0#number of wing mounted engines CAYE = 1 − 0.03∗NEW#propulsion pod intertia relief factor W1 = ( kglb (DG) ∗CAYE∗W1NIR+W2+W3) /(1+W1NIR) − W2 − W3#bending material weight of wing WWING = W1+W2+W3 r e t u r n lbkg (WWING) d e f ht(ins):#horizontal tail estimated weight − based on NASA FLOPS Weight Estimation Methods for transport aircraft horizontal tail htailtype = ins[0] hTCA = int(htailtype[ − 2 : ] ) /100#read the last two digits of the naca designationi.e. ’NACA 4510’ −> 10 for thickness to chord ratio= 0.1 htailspan = ins[1] hrootchord = ins[2] htipchord = ins[3] hsweep = ins[4] hdihedral = ins[5] hangle = ins[6] DG = i n s [ 7 ] htaper = htipchord/hrootchord havchord = (hrootchord+htipchord)/2 htailarea = htailspan ∗ havchord WHT = 0 . 5 3 ∗ mtf(mtf(htailarea)) ∗ kglb (DG) ∗ ∗ 0 . 2 ∗ (htaper+0.5)#weight of horizontal t a i l(lb) r e t u r n lbkg (WHT) d e f vt(ins):#vertical tail estimated weight − based on NASA FLOPS Weight Estimation Methods for transport aircraft vertical tail vtailtype = ins[0] vTCA = int(vtailtype[ − 2 : ] ) /100#read the last two digits of the naca designationi.e. ’NACA 4510’ −> 10 for thickness to chord ratio= 0.1 vtailheight = ins[1] vrootchord = ins[2] vtipchord = ins[3] vsweep = ins[4] vdihedral = ins[5] vangle = ins[6] DG = i n s [ 7 ] num = i n s [ 8 ] vtaper = vtipchord/vrootchord vavchord = (vtipchord+vrootchord)/2 vtailarea = vavchord ∗ vtailheight WVT = 0.32∗ kglb (DG) ∗∗0.3 ∗ (vtaper+0.5) ∗num∗∗0.7∗ mtf(mtf(vtailarea)) ∗∗0.85#weight of v e r t i c a l tail(lb) r e t u r n lbkg (WVT) d e f lg(ins):#landing gear estimated weight − based on NASA FLOPS Weight Estimation Methods for landing gear extendedlength = ins[0] rampweight = ins[1]

DFTE = 0#1 for fighter aircraft,0 for all others CARBAS = 0#1 for carrier based aircraft,0 for others WMAIN = (0.0117 −0.0012∗DFTE) ∗ kglb(rampweight) ∗∗0.95∗ mtf(extendedlength) WNOSE = (0.048 −0.008∗DFTE) ∗ kglb(rampweight) ∗∗0.67∗ mtf(extendedlength) ∗(1+0.8∗CARBAS) r e t u r n lbkg (WMAIN+WNOSE) d e f dead(ins): r e t u r n ins

122 d e f eng(ins): r e t u r n ins[1] ∗ i n s [ 2 ] d e f ocyl(ins): r e t u r n np.pi ∗ ( i n s [ 1 ] ∗∗2 − ( i n s [1] − i n s [ 0 ] ) ∗∗2) ∗ i n s [ 2 ] ∗ i n s [ 3 ] U.15 Missionpath import math from angsolver import standard as sd from convert import dtr, rtd from csolver import curvesolver as cslv from side import side t o l = 1e−3 d e f missionimport(missionnum): #Loads the desired mission file and returnsa class containing the data i f type(missionnum) == str: mnum = missionnum e l i f type(missionnum) == float or type(missionnum) == int: mnum = str (missionnum) e l s e: inputtype = type(missionnum) errorstring =”The mission number”+str (missionnum)+”, of type”+str(inputtype)+” i s nota recognized type.” r a i s e TypeError(errorstring) mod1 =’.txt’ i f mod1 in mnum: mod1 =’’ i f’/’ not in mnum: path =”missions/” + mnum +mod1#Read the filepath for the desired mission e l i f’/’ in mnum: path = mnum+mod1 c l a s s mission:#Define an empty mission class pass M = mission#Create the empty class exec(open(path).read() , {} ,locals())#Read the mission file and execute the code within, filling the empty class i f’passers’ not in dir (M) :#if the mission file doesn’t have custom execution parameters, set them to’None’ so that upon evaluation, nothing will happen M. p a s s e r s =’None’ i f’custominit’ not in dir (M) : M.custominit =’None’ i f’custom’ not in dir (M) : M. custom =’None’ i f’globalreturn’ not in dir (M) : M.globalreturn =’None’ r e t u r nM#Return the class with the mission information d e f pathgen(missionclass):#Determines flight leg information and adds to to the existing c l a s s coords = missionclass.locs#List of waypoint coordinates ncoords = len(coords)#Number of coordinates npath = ncoords − 1#Number of flight legs paths =[]#Empty list for appending e s t d =’placeholder’#placeholder std(standard angle argument of unit circle), will r e c o r d what the previous legs std was to see if the current leg isa turn f o ri in range(npath):#For each flight leg sx = coords[i ][0];sy=coords[i ][1];sz = coords[i ][2];ex = coords[i+1][0];ey=coords [i+1][1];ez = coords[i+1][2]#start and endx,y,z of the current leg dx = ex−sx#Findx distance covered(longitude) dy = ey−sy#Findy distance covered(latitude dz = ez−sz#Findz distance covered(altitude) h d i s t = ( dx∗∗2 + dy ∗∗2) ∗∗0.5#Finds the horizontal straight line distance covered s d i s t = ( dx∗∗2+dy∗∗2+dz ∗∗2) ∗∗0.5#Finds the total straight line distance covered elev = sd(hdist ,dz)#climb angle in standard unit circle i f estd ==’placeholder’:#if its the first leg, estd= placeholder, which t r i g g e r s here to define the std angle and control point based on the geometry of the f i r s t leg − must bea straight line to ensure sstd= estd estd = sd(dx,dy)#the first flight leg must bea straight line(can be sloped up/down) ecpx = sx + math.cos(dtr(estd+180))#defining the control points based on the standard angle of the first leg, following legs will have scpx/scpy based on the ecpx/ecpy of the previous leg ecpy = sy + math.sin(dtr(estd+180))#cp is control point,s is start/e is end ,x isx/y isy −

123 scpx = ecpx#reads the last legs end point control point as this legs start point c o n t r o l point scpy = ecpy sstd = sd((sx−scpx ) , ( sy−scpy ) )#defines the start point heading using the start point and control point − u n i t circle orientation (0 right 90 up) sidefinder = side(sx,sy,ex,ey,scpx,scpy) i f abs(sidefinder) < 1e −3: e s t d = s s t d ecpx = ex+math.cos(dtr(estd+180)) ecpy = ey+math. sin(dtr(estd+180)) tdist = sdist r r = None#turn radius cc = None#turn circle centre turnang = 0#total turn angle s c s t d = None#centre of circle to start of leg std angle e c s t d = None#centre of circle to end of leg std angle i f dz == 0: ptype =’cruise’ i f dz > 0 : ptype =’ascent’ i f dz < 0 : ptype =’descent’ e l i f abs(sidefinder) > 1e −3:#if the start heading is different to the end heading rr ,cc ,[ecpx,ecpy],ptype,turnang,tdist ,scstd ,ecstd ,estd = cslv(scpx,scpy,sx,sy , ex , ey ) toappend = [[tdist ,sdist ,hdist] ,[[sx,sy,sz] ,[scpx,scpy] ,[ex,ey,ez] ,[ecpx,ecpy] ,[ dx,dy,dz]] ,[sstd ,estd ,elev],ptype ,[rr ,turnang,cc,scstd ,ecstd ]] paths .append(toappend) missionclass.paths = paths#Createa new attribute in the missionclass containing path data r e t u r n missionclass#Returns the updated class d e f main(missionnum):#Reads the mission number and generatesa class with flight path data r e t u r n (pathgen(missionimport(missionnum))) U.16 Resultsprocessing import matplotlib.pyplot as plt from mpl toolkits .mplot3d import Axes3D from matplotlib import cm from copy import deepcopy import numpy as np wingnames = [’Wing type’,’Wingspan’,’Root chord’,’Tip chord’,’Wing sweep’,’Wing dihedral’ ,’Wing angle’,’Design gross weight’] ocylnames = [’Ocyl thickness’,’Ocyl radius’,’Ocyl length’,’Ocyl density’,’Ocyl shielded’] htnames = [’HT wing type’,’HT wingspan’,’HT root chord’,’HT tip chord’,’HT wing sweep’,’ HT wing dihedral’,’HT wing angle’,’Design gross weight’] vtnames = [’VT wing type’,’VT wingspan’,’VT root chord’,’VT tip chord’,’VT wing sweep’,’ VT wing dihedral’,’VT wing angle’,’Design gross weight’] d e f normaliser(parlist):#normalises the relative variation values into+ −1 scale based on maximum increase/decrease in the data set run parentlist = deepcopy(parlist) indicativevars = deepcopy(parentlist [0][1])#baseline values − assumes design0 is the baseline maxstorage = deepcopy(indicativevars)#lists to store the maximum and minimum v a r i a t i o n s minstorage = deepcopy(indicativevars) f o ri in range(len(parentlist)):#for each design drow = parentlist[i]#the data row variants = drow[1]#the variation data f o rj in range(len(variants)):#for each parameter being varied varstring = variants[j]#read the current variation, as well as the max and min maxcomp = maxstorage [ j ] mincomp = minstorage[ j ] i f’ ∗ ’ in varstring:#if itsa multiplicative scaling i f eval(’1’+varstring) > e v a l(’1’+maxcomp) :#if it’sa larger scaling than the current max, overwrite it maxstorage[j] = varstring e l i f eval(’1’+varstring) < e v a l(’1’+mincomp) :#or if itsa lower scaling than the current min, overwrite it

124 minstorage[j] = varstring e l i f’ ∗ ’ not in varstring:#if its just an additive/subtractive scaling, do the same thing but don’t need the1 in front of ∗ 1 . 5 when it’s given as +1.5 for example i f eval(varstring) > e v a l (maxcomp) : maxstorage[j] = varstring e l i f eval(varstring) < e v a l (mincomp) : minstorage[j] = varstring f o ri in range(len(parentlist)):#for each design(row) f o rj in range(len(parentlist[i][1])):#for each variation varstr = parentlist[i][1][j]#current variation, as well as max/min/mid v a l u e s maxval = maxstorage[j] minval = minstorage[j] midval = indicativevars[j] i f’ ∗ ’ in varstr:#ifa multiplicative scaling i f eval(’1’+varstr) == eval(’1’+midval) :#if it equals the mid, the normalised value is0 normalisedval = 0 e l i f eval(’1’+varstr) > e v a l(’1’+midval) :#if its larger than the mid, f i n d how much larger ona0 −1 scale normalisedval = (eval(’1’+varstr) − e v a l(’1’+midval))/(eval(’1’+ maxval ) − e v a l(’1’+midval)) e l i f eval(’1’+varstr) < e v a l(’1’+midval) :#likewise if smaller than the mid normalisedval = (eval(’1’+varstr) − e v a l(’1’+midval))/(eval(’1’+ midval )−e v a l(’1’+minval)) e l i f’ ∗ ’ not in varstr:#same as above but for absolute scaling i f eval(varstr) == eval(midval): normalisedval = 0 e l i f eval(varstr) > e v a l(midval): normalisedval = (eval(varstr) −e v a l(midval))/(eval(maxval) −e v a l(midval )) e l i f eval(varstr) < e v a l(midval): normalisedval = (eval(varstr) − e v a l(midval))/(eval(midval) − e v a l( minval ) ) parentlist[i ][1][ j] = normalisedval#overwrite the old string value with the new normalised value r e t u r n parentlist#return the new, normalised data set d e f scorenormaliser(varnormeddata ,mode=’based’): variationnormeddata = deepcopy(varnormeddata) i f mode ==’relative’: midval = variationnormeddata [0][2] maxval = midval minval = midval e l i f mode ==’based’: midval = variationnormeddata [0][2] maxval = 0 minval = 0 e l i f mode ==’absolute’ or mode ==’scaled’: midval = 0 maxval = 0 minval = float(”inf”) f o ri in range(len(variationnormeddata)): currscore = variationnormeddata[i ][2] i f currscore > maxval : maxval = currscore e l i f currscore < minval : minval = currscore

i f mode ==’relative’: upperdiff = maxval−midval lowerdiff = midval−minval i f upperdiff == lowerdiff: upperscale = 1 lowerscale = 1 e l i f upperdiff > l o w e r d i f f : upperscale = 1 lowerscale = lowerdiff/upperdiff e l i f upperdiff < l o w e r d i f f : upperscale = upperdiff/lowerdiff lowerscale = 1

f o ri in range(len(variationnormeddata)): currscore = variationnormeddata[i ][2]

125 i f currscore == midval: normalisedval = 0 e l i f currscore > midval : normalisedval = (currscore −midval)/(maxval−midval ) ∗ u p p e r s c a l e e l i f currscore < midval : normalisedval = (currscore −midval)/(midval−minval ) ∗ l o w e r s c a l e variationnormeddata[ i ][2] = normalisedval e l i f mode ==’based’: f o ri in range(len(variationnormeddata)): currscore = variationnormeddata[i ][2] normalisedval = currscore/midval − 1 variationnormeddata[ i ][2] = normalisedval e l i f mode ==’absolute’: f o ri in range(len(variationnormeddata)): currscore = variationnormeddata[i ][2] normalisedval = currscore/maxval variationnormeddata[ i ][2] = normalisedval e l i f mode ==’scaled’: f o ri in range(len(variationnormeddata)): currscore = variationnormeddata[i ][2] normalisedval = (currscore −minval)/(maxval−minval ) variationnormeddata[ i ][2] = normalisedval r e t u r n variationnormeddata d e f multiscorenormaliser(varnormeddata ,mode=’based’): variationnormeddata = deepcopy(varnormeddata) f o r stc in range(len(varnormeddata[0][2]) ): i f mode ==’relative’: midval = variationnormeddata [0][2][ stc] maxval = midval minval = midval e l i f mode ==’based’: midval = variationnormeddata [0][2][ stc] maxval = 0 minval = 0 e l i f mode ==’absolute’ or mode ==’scaled’: midval = 0 maxval = 0 minval = float(”inf”) f o ri in range(len(variationnormeddata)): currscore = variationnormeddata[i ][2][ stc] i f currscore > maxval : maxval = currscore e l i f currscore < minval : minval = currscore

i f mode ==’relative’: upperdiff = maxval−midval lowerdiff = midval−minval i f upperdiff == lowerdiff: upperscale = 1 lowerscale = 1 e l i f upperdiff > l o w e r d i f f : upperscale = 1 lowerscale = lowerdiff/upperdiff e l i f upperdiff < l o w e r d i f f : upperscale = upperdiff/lowerdiff lowerscale = 1

f o ri in range(len(variationnormeddata)): currscore = variationnormeddata[i ][2][ stc] i f currscore == midval: normalisedval = 0 e l i f currscore > midval : normalisedval = (currscore −midval)/(maxval−midval ) ∗ u p p e r s c a l e e l i f currscore < midval : normalisedval = (currscore −midval)/(midval−minval ) ∗ l o w e r s c a l e variationnormeddata[i ][2][ stc] = normalisedval e l i f mode ==’based’: f o ri in range(len(variationnormeddata)): currscore = variationnormeddata[i ][2][ stc] normalisedval = currscore/midval − 1 variationnormeddata[i ][2][ stc] = normalisedval e l i f mode ==’absolute’: f o ri in range(len(variationnormeddata)): currscore = variationnormeddata[i ][2][ stc]

126 normalisedval = currscore/maxval variationnormeddata[i ][2][ stc] = normalisedval e l i f mode ==’scaled’: f o ri in range(len(variationnormeddata)): currscore = variationnormeddata[i ][2][ stc] normalisedval = (currscore −minval)/(maxval−minval ) variationnormeddata[ i ][2] = normalisedval r e t u r n variationnormeddata d e f main(resultsfilepath , dkeeperfilepath=None,dscore=’global’ ,mode=’based’ ,show=’all’): i f’.txt’ not in resultsfilepath:#add.txt to the ends of the file paths if they dont already have it resultsfilepath +=’.txt’ i f dkeeperfilepath != None: i f’.txt’ not in dkeeperfilepath: dkeeperfilepath +=’.txt’ resultsfile = open(resultsfilepath ,’r’)#open the score and design mod keeper files dkeeperfile = open(dkeeperfilepath ,’r’) allresults = list(resultsfile)#convert them to lists and close the files resultsfile .close() dkeeper = list(dkeeperfile) dkeeperfile.close() #allresults=[i fori in allresults if’Mid −f l i g h t’ not ini]

f o ri in range(len(allresults)):#for each element in the scorer file(i.e. each line ) allresults[i] = allresults[i].replace(’ \n’,’’)#remove \n i f’Scoring for’ in allresults[i]:#if its the header line, set the whole thing to None allresults[i] = None rawresults = [i fori in allresults if i != None]#read the results without the header line f o ri in range(len(rawresults)): rawresults[i] = rawresults[i]. split(’=’)#split the results at the= cleanedlist = [] f o ri in range(len(rawresults)):#turn the weird list with strings for both the d e s i g n number and scores into one list, each element isa list of[”design number”, g l o b a l, sumlocal, custom] cleanedlist .append([rawresults[ i ][0]]+eval(rawresults[i ][1])) originalsorted = sorted(cleanedlist ,key=lambda x:int(x[0]))#sort by design number so i t should be in the same order as dkeeper

f o ri in range(len(dkeeper)):#for each line of dkeeper, remove \n dkeeper[i] = dkeeper[i ].replace(’ \n’,’’) geometriesstring = dkeeper[0]#the line detailing the geometries being adjusted is s e p a r a t e d from the rest of the actual modification data geometrieslist = geometriesstring.split(’=’)#split the line containing the geometry names geoms = eval(geometrieslist[ −1])#set the variable geoms to equal the list containing the geometry names,i.e. this will look like geoms=[’wing’,’ocyl’] geommods = dkeeper [1:]#the actual geometry modifications are the rest of the list elements f o ri in range(len (geommods)) :#for each geometry modification geommods[ i ] = geommods[ i ]. split(’=’)#split it at the= geommods[i ][1] = eval(geommods[ i ][1])#change the string containinga list into an actual list geommodssorted = sorted (geommods, key=lambda x:int(x[0]))#sort by design number, this shouldn’t actually do anything as it should be written in dkeeper in ascending order combined = [] f o ri in range(len(originalsorted)): i f len(originalsorted[i]) == 4: tupletoadd = (originalsorted[i],geommodssorted[i ]) combined.append(tupletoadd)

rawplotdata = [] f o ri in combined: designname = i [0][0] scores = i[0][1:] mods = i[1][1] rawplotdata .append([designname]+[scores]+[mods]) i f show !=’all’: i f dscore ==’global’: r e f = 0 e l i f dscore ==’sumlocals’: r e f = 1 e l i f dscore ==’custom’:

127 r e f = 2 e l s e: r a i s e TypeError(”Score name not recognized. Please enter’global’,’sumlocals ’ or’custom’.”)

indicativeslice = rawplotdata[0] paramnamelist = [] f o ri in geoms: i f i.startswith(’ ’): newvarname = i [1:] exec(i+”names=[’”+newvarname+”’]”) f o ri in range(len(indicativeslice [2])): geomname = geoms[ i ] grabstring =”deepcopy(”+geomname+”names)” grabbeddata = eval(grabstring) f o rj in range(len(indicativeslice [2][i])): i f indicativeslice[2][i][j] == False: grabbeddata[j] = None paramnamelist += grabbeddata paramnamelist = [i fori in paramnamelist if i != None] parentmodstoragelist = [] f o ri in range(len(rawplotdata)): dataslice = rawplotdata[i] modificationstoragelist = [] f o rj in range(len(dataslice[2])): f o rk in range(len(dataslice[2][j])): i f dataslice[2][j][k] != False: modificationstoragelist.append(dataslice [2][ j ][k]) i f show !=’all’: scoretoappend = dataslice [1][ ref] e l i f show ==’all’: scoretoappend = dataslice [1] parentmodstoragelist.append([ dataslice [0] , modificationstoragelist ,scoretoappend]) partialnormed = normaliser(parentmodstoragelist) i f show !=’all’: fullnormed = scorenormaliser(partialnormed ,mode=mode) e l i f show ==’all’: fullnormed = multiscorenormaliser(partialnormed ,mode=mode) i f show !=’all’: paramnamelist .append(’Cost’) e l i f show ==’all’: paramnamelist .append(’Global Cost’) paramnamelist .append(’Sum Local Costs’) paramnamelist .append(’Custom Cost’) i f show ==’all’: cnames = [’global’,’sumlocals’,’custom’] scorehighlightref = cnames.index(dscore) nhighlights = min(len(fullnormed) ,100) name = resultsfilepath.replace(’results’,’’).replace(’scorer.txt’,’’).replace(’/’,’’)

i f show !=’all’: sortednorm = sorted(fullnormed ,key=lambda x:x[2]) cutoffnorm = sortednorm[nhighlights −1][ −1] minnorm = min([i[ −1] fori in sortednorm]) maxnorm = max([i[ −1] fori in sortednorm]) sm = plt .cm. ScalarMappable(cmap=cm.magma r, norm=plt . Normalize(vmin=minnorm, vmax =cutoffnorm)) sm . A = [ ] nrows = len(sortednorm) numparams = len(fullnormed[0][1]) + 1 xs = np. linspace(0,numparams−1,numparams) s c a l e =2 plt.figure(figsize=(11∗ s c a l e , 3 ∗ s c a l e ) ) f o ri in range(nrows −1,−1,−1) : i fi < nhighlights : currnorm = sortednorm[i ][2] percdone = (cutoffnorm−currnorm)/(cutoffnorm−minnorm ) colour = cm.magma(percdone) e l s e: c o l o u r =’black’ plt.plot(xs,sortednorm[i ][1] + [sortednorm[i ][2]] , color=colour ,linewidth=1.5)

plt . xticks(xs ,paramnamelist) plt . xlim(0 ,numparams−1) p l t . ylim ( −1 ,1)

128 plt . colorbar(sm) titlestring = name+’’+dscore plt.title(titlestring)

e l i f show ==’all’: sortednorm = sorted(fullnormed ,key=lambda x:x[2][ scorehighlightref]) cutoffnorm = sortednorm[nhighlights − 1][2][ scorehighlightref] minnorm = min([i [2][ scorehighlightref] fori in sortednorm]) maxnorm = max([i [2][ scorehighlightref] fori in sortednorm]) sm = plt .cm. ScalarMappable(cmap=cm.magma r, norm=plt . Normalize(vmin=minnorm, vmax =cutoffnorm)) sm . A = [ ] nrows = len(sortednorm) numparams = len(fullnormed[0][1]) + 3 xs = np. linspace(0,numparams−1,numparams) xs = list(xs) s c a l e =1 plt.figure(figsize=(11∗ s c a l e , 3 ∗ s c a l e ) ) f o ri in range(nrows −1,−1,−1) : i fi < nhighlights : currnorm = sortednorm[i ][2][ scorehighlightref] percdone = (cutoffnorm−currnorm)/(cutoffnorm−minnorm ) colour = cm.magma(percdone) e l s e: c o l o u r =’black’ ys = sortednorm[i ][1] + sortednorm[i ][2] plt.plot(xs,ys, color=colour ,linewidth=1.5)

plt . xticks(xs ,paramnamelist) plt . xlim(0 ,numparams−1) p l t . ylim ( −1 ,1) cb = plt.colorbar(sm) cb . s e t l a b e l (’Normalised cost’) titlestring = name+’ Parallel Axis Plot − ’+dscore+’ cost highlighting’ plt.title(titlestring) #plt.title(’Example Parallel Axis Plot − Global Cost Highlighting’) plt . grid(which=’both’) plt.ylabel(’Normalised value’) ax2 = plt.twinx() ax2 . s e t y t i c k s ( [ − 1 . 0 0 , − 0 . 7 5 , − 0 . 5 0 , − 0.25,0.00,0.25,0.50,0.75,1.00]) p l t . t i g h t layout(pad=0.5) r e t u r n U.17 Sensitivity import os import shutil from designparam import geomload import itertools import batch from copy import deepcopy import numpy as np import resultsprocessing orderedatts= [’name’,’wing’,’cyl’,’ocyl’,’rect’,’ht’,’vt’,’lg’,’eng’,’dead’,’fuel’,’batt’ ,’prop’] d e f filegen(geomclass , infolist ,actualgeometries):#writesa geometry class toa string that can be written toa file a t t r s = [ i fori in dir(geomclass) if not i.startswith(’ ’)]#read what attributes the geometry has priorityatts = [i fori in attrs if i.startswith(’ ’)] mainatts = [i fori in orderedatts ifi in attrs] i n i t s t r =’’ f o ri in priorityatts: i fi not in actualgeometries: f i n d e r =’G.’+i+’=’ stradd = [infostring for infostring in infolist if finder in infostring][0] i f’ \n’ not in stradd: stradd +=’ \n’ e l s e: stradd =”G.”+i+”=”+str(getattr(geomclass , i))+” \n” initstr += stradd f o ri in mainatts:#for each attribute i fi not in actualgeometries: f i n d e r =’G.’+i+’=’ stradd = [infostring for infostring in infolist if finder in infostring][0]

129 i f’ \n’ not in stradd: stradd +=’ \n’ e l s e: i f i ==’name’:#if its the name, it needs’’ around the name to make ita s t r i n g when it gets read, so its done specially stradd =”G.name=’”+geomclass .name+”’ \ n” e l s e:#otherwise just doG. geomtype=geomvalues all asa string stradd =”G.”+i+”=”+str(getattr(geomclass , i))+” \n” initstr += stradd r e t u r n initstr d e f sensmodder(modstring , steps=1):#takesa string for the sensitivity analyses and r e t u r n s string usable in eval() i f modstring == False: r e t u r n [False] i f’%’ in modstring:#if the values are given asa percentage i f’+ − ’ in modstring:#if its given asa+ − stripped = modstring.replace(’+ − ’,’’).replace(’%’,’’) rawval = float(stripped)#float val reduced = rawval/100#0.5 mods = np.linspace(1−reduced,1+reduced ,int(2 ∗ s t e p s +1) ) sortedmods = sorted(mods, key=lambda x:abs(x −1) ) sortedmods = [’ ∗ ’+str(round(i,5)) fori in sortedmods] r e t u r n sortedmods#return ∗1 , ∗1+percentage, ∗1− percentage with extra steps i f steps >1 e l i f’+’ in modstring:#if its just +, just return ∗1 , ∗1+percentage stripped = modstring.replace(’+’,’’).replace(’%’,’’) rawval = float(stripped) reduced = rawval/100 mods = np. linspace(1,1+reduced ,int(steps+1)) sortedmods = sorted (mods,key=lambda x:abs(x −1) ) sortedmods = [’ ∗ ’+str(round(i,5)) fori in sortedmods] r e t u r n sortedmods e l i f’ − ’ in modstring:#likewise for −% stripped = modstring.replace(’ − ’,’’).replace(’%’,’’) rawval = float(stripped) reduced = rawval/100 mods = np.linspace(1−reduced , 1 ,int(steps+1)) sortedmods = sorted (mods,key=lambda x:abs(x −1) ) sortedmods = [’ ∗ ’+str(round(i,5)) fori in sortedmods] r e t u r n sortedmods e l i f’%’ not in modstring:#if its justa raw value addition/subtraction i f’+ − ’ in modstring:#if its given as+ −, do +0,+val, −v a l stripped = modstring.replace(’+ − ’,’’) v a l = float(stripped) mods = np.linspace(−val , val , 2 ∗ s t e p s +1) sortedmods = sorted (mods,key=lambda x:abs(x)) sortedmods = [’+’+str(round(i,5)) fori in sortedmods] r e t u r n sortedmods e l i f’+’ in modstring or’ − ’ in modstring:#otherwise just do +0,+val or +0, − v a l v a l = float(modstring) mods = np.linspace(0,val ,steps+1) sortedmods = [’+’+str(round(i,5)) fori in mods] r e t u r n sortedmods d e f randomiser(plistslice): returnercopy = deepcopy(plistslice) f o ri in range(len(plistslice)): paramvals = plistslice[i] f o rj in range(len(paramvals)): strval = paramvals[j] i f strval == False: continue i f’%’ in strval: i f’+ − ’ in strval: reducedval = float(strval.replace(’%’,’’).replace(’+ − ’,’’))/100 newval = np.random.uniform(low=1−reducedval , high=1+reducedval) newvalstr =’ ∗ ’+str(round(newval ,5)) e l i f’+’ in strval: reducedval = float(strval.replace(’%’,’’).replace(’+’,’’))/100 newval = np.random.uniform(low=1,high=1+reducedval) newvalstr =’ ∗ ’+ str(round(newval ,5)) e l i f’ − ’ in strval: reducedval = float(strval.replace(’%’,’’).replace(’ − ’,’’))/100 newval = np.random.uniform(low=1−reducedval ,high=1)

130 newvalstr =’ ∗ ’+str(round(newval ,5)) e l i f’%’ not in strval: i f’+ − ’ in strval: reducedval = float(strval.replace(’+ − ’,’’)) newval = np.random.uniform(low=−reducedval ,high=reducedval) newvalstr =’+’+str(round(newval ,5)) e l i f’+’ in strval: reducedval = float(strval.replace(’+’,’’)) newval = np.random.uniform(low=0,high=reducedval) newvalstr =’+’+str(round(newval ,5)) e l i f’ − ’ in strval: reducedval = float(strval.replace(’ − ’,’’)) newval = np.random.uniform(low=−reducedval ,high=0) newvalstr =’+’+str(round(newval ,5)) returnercopy[i ][ j] = newvalstr r e t u r n returnercopy d e f main(controlfilename ,way=’random’):#main sensitivity analysis function i f type(controlfilename) == int or type(controlfilename) == float:#check file name type and convert to string if appropriate controlfilename = str(controlfilename) i f type(controlfilename) != str: r a i s e ImportError(’Sensitivity control file name type not recognized.’) mod1 =’.txt’#ifa full folder path is given, use the folder path. If justa file is given, use senscontrol/file. If the file doesn’t have.txt, add it i f’.txt’ in controlfilename: mod1 =’’ i f’/’ not in controlfilename: controlfilepath =’senscontrol/’+controlfilename+mod1 e l i f’/’ in controlfilename: controlfilepath = controlfilename+mod1 c l a s s senscontrol:#define the empty class pass S = senscontrol#createa new sensitivity control class exec(open(controlfilepath).read() , {} ,locals())#execute the code in the sensitivity c o n t r o l file to fill the class g i v e n s = [ i fori in dir(S) if not i.startswith(’ ’)]#all parameters within the sensitivity control class s c p r i o = [ i fori in givens if i.startswith(’ ’)] i f’basedesign’ not in givens:#if no base design is given, raise an error r a i s e ImportError(’No base design given for the sensitivity analysis.’) i f’mission’ not in givens:#if no mission is given, raise an error r a i s e ImportError(’No mission given for the sensitivity analysis.’) i f’stype’ not in givens: p r i n t(”Sensitivity analysis type not provided. Defaulting to testing individual parameters(stype= single)”) S . stype=’single’ i f’parent’ not in givens:#if no parent results folder is given, default to results/ −− note that numbered subfolders are used for individual analyses p r i n t(’No parent sensitivity analysis results folder given. Defaulting to results /’) S . parent=’results’ i f’name’ not in givens:#if no name is defined, suggest adding one p r i n t(’No sensitivity analysis name defined. Suggest addinga name. Defaulting to sensanalysis #’) S . name=’sensanalysis ’ i f’designs’ not in givens: S . d e s i g n s=’designs’ i f’results’ not in givens: S . r e s u l t s=’results’ i f’steps’ not in givens: S . s t e p s = 1 i f’varia’ not in givens: S.varia = 500 i f S.name[ −1] ==’/’:#if the name given hasa/ at the end, get rid of it becausea number gets added after the name S.name = S.name[: − 1 ] i f S.parent[ −1] !=’/’:#if the parent folder name directory doesn’t end witha/, add one S . parent +=’/’ i f not os.path.isdir(S.parent):#if the parent directory doesn’t exist, make it os.mkdir(S.parent)

foldergenflag = False#prepare for subfolder generation

131 foldergencount = 0 while foldergenflag == False: childfolderstr = S.parent+S.name+str(foldergencount) +’/’#create the string for the child folder directory i f os.path.isdir(childfolderstr):#if the folder already exists, count up by1 foldergencount += 1 e l i f not os.path.isdir(childfolderstr):#if the folder doesn’t exist, make it, f l a g foldergenflag as true and break the loop os.mkdir(childfolderstr) foldergenflag = True break

possiblesubfolders=[’good’,’bad’,’results’,’designs’]#possible subfolders that might need to be made actualsubfolders=[i fori in dir(S) ifi in possiblesubfolders]#of the possible s u b f o l d e r s, what ones are actually wanted f o ri in actualsubfolders:#for any subfolder that needs to be made, make it(and add / to the end if it doesnt have it) refdfolder = getattr(S,i) i f refdfolder[ −1] !=’/’: s e t a t t r(S,i,refdfolder +’/’) os.mkdir(childfolderstr+getattr(S,i))

#copying the mission file −> M. i f’/’ not in S.mission:#finding where the desired mission is stored − i f it was r e f e r e n c e d with just the file name(no/) then check missions/filename.txt missionfileloc =’missions/’+S. mission e l i f’/’ in S.mission:#otherwise if it is given asa filepath, check that path missionfileloc = S.mission i f’.txt’ not in missionfileloc: missionfileloc +=’.txt’ endmissionfileloc = childfolderstr+’mission.txt’#end location − copied to the root o f the analysis root folder shutil.copy(missionfileloc ,endmissionfileloc)

#writing the sim control file −> C. simcontrol = open(childfolderstr+’simcontrol.txt’,’w’)#opena new file in the a n a l y s i s root folder simcontrol.write(”C.name=’”+S . name+str(foldergencount)+”’ \ n”)#write the analysis name simcontrol.write(”C.mission=’”+endmissionfileloc+”’ \ n”)#write the mission file l o c a t i o n simcontrol.write(”C.parent=’”+childfolderstr+”’ \ n”)#write the parent folder location f o ri in actualsubfolders:#for each of the defined subfolders, write their location i f i ==’designs’: simcontrol.write(”C.designs=’”+childfolderstr+”designs’ \ n”) e l s e: simcontrol.write(”C.”+i+”=’”+getattr(S,i)+”’ \ n”) simcontrol. close()

#copying the design file to the new root analysis folder i f’/’ not in S.basedesign:#check the location of the base design folder, if it’s j u s t given asa filename and nota filepath, look in designs/filename.txt, otherwise look at filepath.txt designfileloc =’designs/’+S. basedesign e l i f’/’ in S.basedesign: designfileloc = S.basedesign i f’.txt’ not in designfileloc: designfileloc +=’.txt’ enddesignfileloc = childfolderstr+’design.txt’ shutil.copy(designfileloc ,enddesignfileloc)#copy the base design to the sensitivity a n a l y s i s parent folder

shutil .copy(controlfilepath , childfolderstr+’senscontrol.txt’)

originaldesign = geomload(enddesignfileloc)#load the base design

possiblegeometries = [’wing’,’eng’,’dead’,’fuel’,’ocyl’,’prop’]#all possible g e o m e t r i e s actualgeometries = [i fori in possiblegeometries ifi in dir(S)]#what geometries the sensitivity analysis is being conducted on actualgeometries = scprio + actualgeometries f o ri in actualgeometries:#for each geometry used in the sensitivity analysis i fi not in dir(originaldesign):#if the original design doesn’t have it, raise an error r a i s e ImportError(”Geometry modification defined fora geometry that isn’t in

132 the base design.”) i f way ==’structured’: parentlist = [] f o ri in actualgeometries:#for the geometries being modified s t r v a l s = getattr(S,i)#get the value of the geometry geomlist = [] f o rj in strvals:#for the values of the geometry geomlist .append(sensmodder(j ,S. steps))#convert from ’+ −50%’ to [’ ∗ 1 ’ , ’ ∗ 1 . 5 ’ , ’ ∗ 0 . 5 ’ ] for the eval() parentlist .append(geomlist)

i f S.stype==’single’:#if looking at single modifications(i.e. all parameters other than the one being examined are baseline) baselist = [] f o ri in range(len(parentlist)): temp = [t1[0] for t1 in parentlist[i]]#reads the baseline geometry configurationi.e. index0 for each parameter of each geometry baselist .append(temp)

donelistduplicates = []#finding all combinations, will have duplicates due to how each(for example) ’+ −50%’ will have[’ ∗ 1 ’ , ’ ∗ 1 . 5 ’ , ’ ∗ 0 . 5 ’ ] , so it will do ∗1 of the first, ∗ 1 . 5 of the first, ∗ 0 . 5 of the first, then ∗1 of the second= duplicate f o ri in range(len(parentlist)):#for each geometry being examined dataset1 = parentlist[i] f o rj in range(len(dataset1)):#for each parameter of that geometry dataset2 = dataset1[j] f o rk in range(len(dataset2)):#for each possible variation of that parameter newdataset = deepcopy(baselist)#makea copy of the baseline geometry for modification newval = dataset2[k]#read what value will be inserted newdataset[i ][ j] = newval#modify the value to the desired value (i.e.’ ∗1 ’ to’ ∗ 1 . 5 ’ ) donelistduplicates .append(newdataset)#append it to the list f o ri in range(len(donelistduplicates)):#remove all duplicates dataset3 = donelistduplicates[i] i f dataset3 in donelistduplicates[:i]:#if the specific geometry configuration has occured before, set the whole thing to None donelistduplicates[i] = None donelist = [i fori in donelistduplicates if i != None]#createa new list of geometry configurations without the None’s

i f S.stype==’combined’:#if doinga combined sensitivity analysis(i.e testing each combination of each parameter variation with each other variation) −− warning: significant number of designs will be created even if onlya few parameters,i.e.2 v a r i a t i o n s of 10 parameters= 2ˆ10 designs fulllist = [] f o ri in parentlist:#for each geometry toappend = list(itertools .product( ∗ i ) )#find all combinations of v a r i a t i o n s within that geometry fulllist .append(toappend)#and append those combinations toa master list d o n e l i s t = list(itertools .product( ∗ f u l l l i s t ) )#find all combinations between a l l geometries

f o ri in range(len(donelist)):#convert the tuples to lists donelist[i] = list(donelist[i]) f o rj in range(len(donelist[i])): donelist[i][j] = list(donelist[i][j]) i f way ==’random’: parentlist = [] f o ri in actualgeometries: s t r v a l s = getattr(S,i) parentlist .append(strvals) donelist = [] f o ri in range(S.varia): donelist .append(randomiser(parentlist))

basedeslist = deepcopy(parentlist) f o ri in range(len(basedeslist)): f o rj in range(len(basedeslist[i])): i f basedeslist[i][j] == False: continue i f’%’ in basedeslist[i][j]:

133 basedeslist[i][j] =’ ∗1’ e l i f’%’ not in basedeslist[i][j]: basedeslist[i][j] =’+0’ donelist = [basedeslist] + donelist

infodesignfile = open(enddesignfileloc ,’r’) i n f o l i s t = list(infodesignfile) infodesignfile.close() designkeeperfile = open(childfolderstr+getattr(S,’results’)+’/dkeeper.txt’,’w’)# c r e a t ea file for storing the geometry modification information designkeeperfile .write(’geoms=’+str(actualgeometries)+’ \n’)#writea header detailing what geometries are being modified and the order they information is stored in f o ri in range(len(donelist)):#for each geometry configuration fullconfiguration = donelist[i]# the full configuration information(for all g e o m e t r i e s) baseclass = geomload(enddesignfileloc)#reload the base class for modification − can’t deepcopy classes − information was being remembered and this resulted ine −24 f o r parameters due to repeated multiplications, etc. f o rj in range(len(fullconfiguration)):#for each of the blocks to get modified( wing/ocyl/etc) geomtype = actualgeometries[j]#geometry type being modifiedi.e. wing geomconfiguration = fullconfiguration[j]#the specific configuration to be used for that geometry,i.e. wing type, span, chord, etc. variation information currentdata = getattr(baseclass ,geomtype)#the current base design geometry parameter values f o rk in range(len(geomconfiguration)):#for each value in the geometry configuration to be applied strmodval = geomconfiguration[k]#the string outlining the modification( i.e.’ ∗ 1 . 5 ’ or ’+3’) i f strmodval == False:#if the values is defined as False, then it doesn’ t undergo modification continue e l s e:#otherwise if itsa string outlininga variation in the value oldval = currentdata[0][k]#load the baseline value o l d s t r v a l = str(oldval)#change it toa string to be used in eval() moddedval = eval(oldstrval+strmodval)#evaluate the string of the old value and the modificationi.e. ’5’+’ ∗ 1 . 5 ’ −> ’ 5 ∗ 1 . 5 ’ −> e v a l(’5 ∗ 1 . 5 ’ )= 7.5 currentdata[0][k] = round(moddedval ,6)#set the new value s e t a t t r(baseclass ,geomtype,currentdata)#apply the value toe the class − not s u r e if this is necessary due to the currentdata beinga reference to the info in b a s e c l a s s soi think it got set already, but sometimes it didnt work? baseclass .name =’variation’+str(i)#change the name of the class − w i l l be w r i t t e n in the design file, doesn’t matter if it loses the original name because the base class stored in the sensitivity analysis folder has the original name designkeeperstring = str(i)+”=”+str(donelist[i])+’ \n’#write the geometry modification information to the designkeeper file designkeeperfile .write(designkeeperstring) writestring = filegen(baseclass ,infolist ,actualgeometries)#turn the class information intoa string to be written toa new design file filetowriteto = open(childfolderstr+getattr(S,’designs’)+’/’+str(i)+’.txt’,’w’)# load up the design file − note that because designkeeper and design both have their names referenced asi, they are correctly numbered to match each other − important f o r parallel plot filetowriteto .write(writestring)#write the design file filetowriteto.close()#close the design file designkeeperfile.close()#close the design keeper file

e l s e: batch.main(childfolderstr+’simcontrol.txt’)#run the simulation batch using the custom simcontrol file written resultsprocessing .main(childfolderstr+getattr(S,’results’)+’scorer.txt’, childfolderstr+getattr(S,’results’)+’dkeeper.txt’ ,mode=’based’)

r e t u r n U.18 Side d e f dsolve(x1,y1,x2,y2): r e t u r n ((x2−x1 ) ∗∗2 + ( y2−y1 ) ∗∗2) ∗∗0.5 d e f side(x1,y1,x2,y2,xc,yc): t o t a l = ( x2−xc ) ∗( y1−yc ) − ( y2−yc ) ∗( x1−xc ) lencontrol = dsolve(xc,yc,x1,y1) r e t u r n total/lencontrol

134 U.19 Tables

#!/usr/bin/env python

””” Tables.py − Make tables of atmospheric properties(Python 3)

Adapted by RichardJ. Kwan, Lightsaber Computing from original programs by RalphL. Carmichael, Public Domain Aeronautical Software

Revision History Date Vers Person Statement of Changes 2004 Oct 04 1.0 RJK Initial program 2017 Jun 04 1.1 RLC All indents are with spaces; all prints in() New version for Python3 that does integer div with// ””” import math d e f Atmosphere(alt): ””” Compute temperature, density, and pressure in standard atmosphere. Correct to 86 km. Only approximate thereafter. Input: a l t geometric altitude, km. Return:(sigma, delta, theta) sigma density/sea −l e v e l standard density d e l t a pressure/sea −l e v e l standard pressure theta temperature/sea −l e v e l std. temperature ”””

REARTH = 6369.0# radius of the Earth(km) GMR = 34.163195

htab = [ 0.0, 11.0, 20.0, 32.0, 47.0, 51.0, 71.0, 84.852 ] ttab = [ 288.15, 216.65, 216.65, 228.65, 270.65, 270.65, 214.65, 186.946 ] ptab = [ 1.0, 2.2336110E−1, 5.4032950E−2, 8.5666784E−3, 1.0945601E−3, 6.6063531E−4, 3.9046834E−5, 3.68501E−6 ] gtab = [ −6.5, 0.0, 1.0, 2.8, 0, −2.8 , −2.0 , 0 . 0 ]

h = a l t ∗REARTH/( a l t+REARTH)# geometric to geopotential altitude

i =0; j=len(htab) while (j > i +1) : k = ( i+j ) //2# this is floor division in Python3 i fh < htab [ k ] : j = k e l s e: i = k tgrad = gtab[i]# temp. gradient of local layer tbase = ttab[i]# base temp. of local layer d e l t a h=h−htab [ i ]# height above local base tlocal=tbase+tgrad ∗ d e l t a h# local temperature theta = tlocal/ttab[0]# temperature ratio

i f 0.0 == tgrad: delta=ptab[ i ] ∗ math . exp(−GMR∗ deltah/tbase) e l s e: delta=ptab[ i ] ∗ math .pow(tbase/tlocal , GMR/tgrad) sigma = delta/theta r e t u r n ( sigma, delta, theta )

135