[Python] Design & build airplanes from your specifications.
Proper package structure
Changed files
__init__.py
creator/__init__.py
@@ -0,0 +1,1 @@
1
Added:
__all__ = ['base', 'fuselage', 'propulsion', 'wing']
creator/base.py
@@ -0,0 +1,59 @@
1
Added:
"""The base.py module contains parent classes for components."""
2
Added:
import numpy as np
3
Added:
import sys
4
Added:
import os.path
5
Added:
import logging
6
Added:
7
Added:
logging.basicConfig(filename='log.txt',
8
Added:
level=logging.DEBUG,
9
Added:
format='%(asctime)s - %(levelname)s - %(message)s')
10
Added:
11
Added:
12
Added:
class Component:
13
Added:
"""Basic component providing coordinates and tools."""
14
Added:
15
Added:
# TODO: define defaults in separate module
16
Added:
def __init__(self):
17
Added:
self.x = np.array([])
18
Added:
self.z = np.array([])
19
Added:
self.material = str()
20
Added:
self.mass = float()
21
Added:
22
Added:
def set_material(self, material):
23
Added:
"""Set the component bulk material."""
24
Added:
self.material = material
25
Added:
26
Added:
def info_print(self, round):
27
Added:
"""Print all the component's coordinates to the terminal."""
28
Added:
name = f' CREATOR DATA FOR {str(self).upper()} '
29
Added:
num_of_dashes = len(name)
30
Added:
print(num_of_dashes * '-')
31
Added:
print(name)
32
Added:
for k, v in self.__dict__.items():
33
Added:
if type(v) != list:
34
Added:
print('{}:\n'.format(k), v)
35
Added:
print(num_of_dashes * '-')
36
Added:
for k, v in self.__dict__.items():
37
Added:
if type(v) == list:
38
Added:
print('{}:\n'.format(k), np.around(v, round))
39
Added:
return None
40
Added:
41
Added:
def info_save(self, save_path, number):
42
Added:
"""Save all the object's coordinates (must be full path)."""
43
Added:
file_name = f'{str(self).lower()}_{number}.txt'
44
Added:
full_path = os.path.join(save_path, file_name)
45
Added:
try:
46
Added:
with open(full_path, 'w') as sys.stdout:
47
Added:
self.info_print(6)
48
Added:
# This line required to reset behavior of sys.stdout
49
Added:
sys.stdout = sys.__stdout__
50
Added:
logging.debug(f'Successfully wrote to file {full_path}')
51
Added:
except IOError:
52
Added:
print(f'Unable to write {file_name} to specified directory.\n',
53
Added:
'Was the full path passed to the function?')
54
Added:
return None
55
Added:
56
Added:
57
Added:
class Aircraft:
58
Added:
"""This class tracks all sub-components and is fed to the evaluator."""
59
Added:
pass
creator/wing.py
@@ -11,65 +11,16 @@
11
11
plot_geom(airfoil): generates a 2D plot of the airfoil & any components.
12
12
"""
13
13
14
Removed:
import sys
15
Removed:
import os.path
14
Added:
import creator.base as base
15
Added:
16
16
import logging
17
17
import numpy as np
18
18
from math import sin, cos, atan
19
19
import bisect as bi
20
20
import matplotlib.pyplot as plt
21
21
22
Removed:
logging.basicConfig(filename='log.txt',
23
Removed:
level=logging.DEBUG,
24
Removed:
format='%(asctime)s - %(levelname)s - %(message)s')
25
22
26
Removed:
27
Removed:
class Component:
28
Removed:
"""Basic component providing coordinates and tools."""
29
Removed:
30
Removed:
# TODO: define defaults in separate module
31
Removed:
def __init__(self):
32
Removed:
self.x = np.array([])
33
Removed:
self.z = np.array([])
34
Removed:
self.material = str()
35
Removed:
self.mass = float()
36
Removed:
37
Removed:
def set_material(self, material):
38
Removed:
"""Set the component bulk material."""
39
Removed:
self.material = material
40
Removed:
41
Removed:
def info_print(self, round):
42
Removed:
"""Print all the component's coordinates to the terminal."""
43
Removed:
name = f' CREATOR DATA FOR {str(self).upper()} '
44
Removed:
num_of_dashes = len(name)
45
Removed:
print(num_of_dashes * '-')
46
Removed:
print(name)
47
Removed:
for k, v in self.__dict__.items():
48
Removed:
if type(v) != list:
49
Removed:
print('{}:\n'.format(k), v)
50
Removed:
print(num_of_dashes * '-')
51
Removed:
for k, v in self.__dict__.items():
52
Removed:
if type(v) == list:
53
Removed:
print('{}:\n'.format(k), np.around(v, round))
54
Removed:
return None
55
Removed:
56
Removed:
def info_save(self, save_path, number):
57
Removed:
"""Save all the object's coordinates (must be full path)."""
58
Removed:
file_name = f'{str(self).lower()}_{number}.txt'
59
Removed:
full_path = os.path.join(save_path, file_name)
60
Removed:
try:
61
Removed:
with open(full_path, 'w') as sys.stdout:
62
Removed:
self.info_print(6)
63
Removed:
# This line required to reset behavior of sys.stdout
64
Removed:
sys.stdout = sys.__stdout__
65
Removed:
logging.debug(f'Successfully wrote to file {full_path}')
66
Removed:
except IOError:
67
Removed:
print(f'Unable to write {file_name} to specified directory.\n',
68
Removed:
'Was the full path passed to the function?')
69
Removed:
return None
70
Removed:
71
Removed:
72
Removed:
class Airfoil(Component):
23
Added:
class Airfoil(base.Component):
73
24
"""This class represents a single NACA airfoil.
74
25
75
26
The coordinates are saved as two lists
@@ -185,7 +136,7 @@
185
136
return None
186
137
187
138
188
Removed:
class Spar(Component):
139
Added:
class Spar(base.Component):
189
140
"""Contains a single spar's data."""
190
141
def __init__(self, airfoil, loc_percent, material):
191
142
"""Set spar location as percent of chord length."""
@@ -214,7 +165,7 @@
214
165
return None
215
166
216
167
217
Removed:
class Stringer(Component):
168
Added:
class Stringer(base.Component):
218
169
"""Contains the coordinates of all stringers."""
219
170
def __init__(self):
220
171
super().__init__()
evaluator/__init__.py
evaluator/evaluator.py
@@ -14,18 +14,11 @@
14
14
15
15
class Evaluator:
16
16
"""Performs structural evaluations for the airfoil passed as argument."""
17
Removed:
def __init__(self, airfoil):
17
Added:
def __init__(self, aircraft):
18
18
# Evaluator knows all geometrical info from evaluated airfoil
19
Removed:
self.airfoil = airfoil
20
Removed:
self.spar = airfoil.spar
21
Removed:
self.stringer = airfoil.stringer
22
Removed:
# Global dimensions
23
Removed:
self.chord = airfoil.chord
24
Removed:
self.semi_span = airfoil.semi_span
25
Removed:
# Mass & spanwise distribution
26
Removed:
self.mass_total = float(airfoil.mass + airfoil.spar.mass +
27
Removed:
airfoil.stringer.mass)
28
Removed:
self.mass_dist = []
19
Added:
self.airfoil = self.get_airfoil(aircraft)
20
Added:
self.spars = self.get_spars(aircraft)
21
Added:
self.stringers = self.get_stringers(aircraft)
29
22
# Lift
30
23
self.lift_rectangular = []
31
24
self.lift_elliptical = []
@@ -40,9 +33,33 @@
40
33
def __str__(self):
41
34
return type(self).__name__
42
35
36
Added:
def get_airfoil(self, aircraft):
37
Added:
"""Get data of spars belonging to aircraft."""
38
Added:
try:
39
Added:
pass
40
Added:
except:
41
Added:
pass
42
Added:
pass
43
Added:
44
Added:
def get_spars(self, aircraft):
45
Added:
"""Get data of spars belonging to aircraft."""
46
Added:
try:
47
Added:
pass
48
Added:
except:
49
Added:
pass
50
Added:
pass
51
Added:
52
Added:
def get_stringers(self, aircraft):
53
Added:
"""Get data of spars belonging to aircraft."""
54
Added:
try:
55
Added:
pass
56
Added:
except:
57
Added:
pass
58
Added:
pass
59
Added:
43
60
def info_print(self, round):
44
61
"""Print all the component's evaluated data to the terminal."""
45
Removed:
name = ' EVALUATOR DATA FOR {} '.format(str(self).upper())
62
Added:
name = f' {print(self)} DATA FOR {str(self).upper()} '
46
63
num_of_dashes = len(name)
47
64
print(num_of_dashes * '-')
48
65
print(name)
example_airfoil.py
@@ -10,8 +10,8 @@
10
10
"""
11
11
12
12
from resources import materials as mt
13
Removed:
from creator import wing, fuselage, propulsion
14
Removed:
# from evaluator import
13
Added:
from creator import *
14
Added:
from evaluator import evaluator
15
15
# from generator import
16
16
17
17
import time
@@ -41,6 +41,8 @@
41
41
42
42
SAVE_PATH = '/home/blendux/Projects/Aircraft_Studio/save'
43
43
44
Added:
# Create aircraft instance
45
Added:
aircraft = base.Aircraft
44
46
# Create airfoil instance
45
47
af = wing.Airfoil(20, 150, mt.aluminium)
46
48
af.add_naca(NACA_NUM)
@@ -69,7 +71,7 @@
69
71
# wing.plot_geom(af, [af.spar1, af.spar2], None)
70
72
71
73
# Evaluator object contains airfoil analysis results.
72
Removed:
# eval = evaluator.Evaluator(af)
74
Added:
eval = evaluator.Evaluator(aircraft)
73
75
# The analysis is performed in the evaluator.py module.
74
76
# eval.analysis(1, 1)
75
77
# eval.info_print(2)