Coverage for /opt/hostedtoolcache/Python/3.11.10/x64/lib/python3.11/site-packages/hypervehicle/hangar/htv.py: 94%
77 statements
« prev ^ index » next coverage.py v7.6.4, created at 2024-10-29 02:51 +0000
« prev ^ index » next coverage.py v7.6.4, created at 2024-10-29 02:51 +0000
1import numpy as np
2from copy import deepcopy
3from hypervehicle import Vehicle
4from scipy.optimize import bisect
5from hypervehicle.components import Wing
6from hypervehicle.generator import Generator
7from hypervehicle.geometry import Vector3, Line, Polyline
10class ParametricHTV(Generator):
11 """Parametric generator for mock-up of the Hypersonic Technology Vehicle 2.
13 Dimensions have been approximated based on vehicle's visual proportions.
15 References
16 ----------
17 https://en.wikipedia.org/wiki/Hypersonic_Technology_Vehicle_2
18 """
20 def __init__(self, **kwargs) -> None:
21 # Vehicle parameters
22 self.L = 1
23 self.body_width = 0.5
24 self.h = 0.1
25 self.t_LE = 0.01
26 self.flap_angle = 15
28 # Nominal parameters for proportional scaling
29 self.L_nom = 1
30 self.body_width_nom = 0.8
31 self.h_nom = 0.2
32 self.t_LE_nom = 0.025
34 # Complete instantiation
35 super().__init__(**kwargs)
37 def create_instance(self) -> Vehicle:
38 # Create Vehicle instance
39 htv = Vehicle()
40 htv.configure(
41 name="Hypersonic Technology Vehicle",
42 verbosity=1,
43 )
45 # Create main body
46 # ================
47 A0 = Vector3(x=0, y=0)
48 A1 = Vector3(x=0.15 * self.L, y=0)
49 TT = Vector3(x=self.L, y=0)
50 B0 = Vector3(x=0, y=self.body_width / 2)
52 B1 = Vector3(x=A1.x, y=B0.y)
53 B0B1 = Line(p0=B0, p1=B1)
54 B1TT = Line(p0=B1, p1=TT)
55 Line_B0TT = Polyline([B0B1, B1TT])
57 def get_local_width(x):
58 """Returns the vehicle width at a given x."""
59 func = lambda t: Line_B0TT(t).x - x
60 t = bisect(func, 0.0, 1.0)
61 return 2 * Line_B0TT(t).y
63 def wing1_tf_top(x, y, z=0):
64 """Thickness function to create the top surface shape
65 of the vehicle."""
66 local_width = get_local_width(x)
68 if y < 0.5 * (local_width - 2 * self.t_LE):
69 z_val = 0.5 * (self.h - self.t_LE) * np.cos(
70 2 * np.pi * y / (local_width - 2 * self.t_LE)
71 ) + 0.5 * (self.h + self.t_LE)
72 elif y == 0.5 * (local_width - 2 * self.t_LE):
73 z_val = self.t_LE
74 else:
75 z_val = self.t_LE
77 # Apply axial tapering
78 z_val *= (self.L - x) + 0.05
80 return Vector3(x=0, y=0, z=-z_val)
82 def wing1_tf_bot(x, y, z=0):
83 """Bottom thickness function."""
84 z_val = 0.2 * self.t_LE
85 return Vector3(x=0, y=0, z=z_val)
87 def lewf(r):
88 """Constant leading edge width function."""
89 le_width = 0.01
90 return le_width
92 # Add wing
93 wing = Wing(
94 A0=A0,
95 A1=A1,
96 TT=TT,
97 B0=B0,
98 Line_B0TT=Line_B0TT,
99 top_tf=wing1_tf_top,
100 bot_tf=wing1_tf_bot,
101 LE_wf=lewf,
102 stl_resolution=5,
103 )
104 htv.add_component(wing, reflection_axis="y")
106 # Create flaps
107 # ================
108 length_scaler = self.L / self.L_nom
109 width_scaler = self.body_width / self.body_width_nom
111 flap_length = 0.2 * length_scaler
112 flap_gap = 0.01 * width_scaler
114 offset = 0.1 * self.t_LE
116 A0f = Vector3(x=flap_length, y=0 + 0.5 * flap_gap)
117 A1f = Vector3(x=flap_length + 0.05 * self.L, y=0 + 0.5 * flap_gap)
118 TTf = Vector3(x=flap_length + 0.1 * self.L, y=0 + 0.5 * flap_gap)
119 B0f = Vector3(x=flap_length, y=0.8 * self.body_width / 2 + 0.5 * flap_gap)
121 B1f = Vector3(x=A1f.x, y=0.5 * B0f.y)
122 B0B1f = Line(p0=B0f, p1=B1f)
123 B1TTf = Line(p0=B1f, p1=TTf)
124 Line_B0TTf = Polyline([B0B1f, B1TTf])
126 def wing2_tf_top(x, y, z=0):
127 return Vector3(x=0, y=0, z=-self.t_LE - offset)
129 def wing2_tf_bot(x, y, z=0):
130 return Vector3(x=0, y=0, z=0.2 * self.t_LE - offset)
132 flap_wing = Wing(
133 A0=A0f,
134 A1=A1f,
135 TT=TTf,
136 B0=B0f,
137 Line_B0TT=Line_B0TTf,
138 top_tf=wing2_tf_top,
139 bot_tf=wing2_tf_bot,
140 flap_length=flap_length,
141 flap_angle=np.deg2rad(self.flap_angle),
142 stl_resolution=5,
143 )
144 htv.add_component(deepcopy(flap_wing))
145 htv.add_component(flap_wing, reflection_axis="y")
147 return htv
150if __name__ == "__main__":
151 # To create the nominal geometry
152 parametric_generator = ParametricHTV()
153 htv = parametric_generator.create_instance()
154 htv.generate()
155 htv.to_stl(prefix="htv")