Coverage for /opt/hostedtoolcache/Python/3.11.10/x64/lib/python3.11/site-packages/hypervehicle/hangar/d21.py: 95%

102 statements  

« prev     ^ index     » next       coverage.py v7.6.4, created at 2024-10-29 02:51 +0000

1import numpy as np 

2from hypervehicle import Vehicle 

3from scipy.optimize import bisect 

4from hypervehicle.generator import Generator 

5from hypervehicle.components import Wing, Fin, RevolvedComponent 

6from hypervehicle.geometry import Vector3, Bezier, Line, Polyline 

7 

8 

9class ParametricD21(Generator): 

10 """Parametric generator for mock-up of the Lockheed D-21 drone. 

11 

12 Dimensions have been approximated based on vehicle's visual proportions. 

13 

14 References 

15 ---------- 

16 https://en.wikipedia.org/wiki/Lockheed_D-21 

17 """ 

18 

19 def __init__(self, **kwargs) -> None: 

20 # Vehicle parameters 

21 self.R_b = 1 # Body radius 

22 self.L_b = 20 # Body length 

23 self.L_w = 16 # Wing length 

24 self.W_w = 5 # Wing width, 

25 self.flap_angle = 0 

26 

27 # STL resolutions 

28 self.wing_stl_res = 3 

29 self.te_fin_stl_res = 3 

30 

31 # Complete instantiation 

32 super().__init__(**kwargs) 

33 

34 def create_instance(self) -> Vehicle: 

35 # Initialise 

36 d21 = Vehicle() 

37 d21.configure( 

38 name="Lockhead Martin D-21", 

39 verbosity=1, 

40 ) 

41 

42 # Construct fuselage 

43 # ------------------------ 

44 n = Vector3(x=0, y=0) 

45 b0 = Vector3(x=0, y=self.R_b) 

46 b1 = b0 - Vector3(x=self.L_b, y=0) 

47 b2 = b1 - Vector3(x=0, y=self.R_b) 

48 bL0 = Line(n, b0) 

49 bL1 = Line(b0, b1) 

50 bL2 = Line(b1, b2) 

51 

52 fuseline = Polyline([bL0, bL1, bL2]) 

53 fuselage = RevolvedComponent(revolve_line=fuseline, stl_resolution=20) 

54 d21.add_component(fuselage) 

55 

56 # Construct Aerospike nose 

57 # -------------------------- 

58 shift = Vector3(x=-0.1, y=0.0) 

59 tip = Vector3(x=0.15 * self.L_b, y=0) + shift 

60 top = Vector3(x=0.0, y=1 * self.R_b) + shift 

61 mid_cp = Vector3(x=0.0, y=0.3 * self.R_b) + shift 

62 

63 front_bz = Bezier([tip, mid_cp, top]) 

64 back_cap = Line(p0=top, p1=Vector3(x=-0.5, y=0.0) + shift) 

65 

66 noseline = Polyline([front_bz, back_cap]) 

67 nose = RevolvedComponent(revolve_line=noseline, stl_resolution=20) 

68 d21.add_component(nose) 

69 

70 # Construct wings 

71 # ------------------------ 

72 # --- |---B0------________________B1 

73 # | | | ----____ 

74 # | | | ----_____ 

75 # | | | --____B2 

76 # --- |---A0----------------------A1----------------------TT 

77 # 

78 # |------------------- L_w ---------------------| 

79 

80 wing_thickness = 0.15 * self.R_b 

81 wing_span = self.W_w 

82 flap_length = 0.1 * self.L_w 

83 wing_LE_shift = Vector3(x=0.3, y=0) 

84 

85 # Required points 

86 wing_tip = Vector3(x=0.0, y=0.0) # Tip of wing reference point 

87 A0 = wing_tip - Vector3(x=self.L_w, y=0) 

88 A1 = Vector3(x=A0.x + 0.6 * self.L_w, y=0) 

89 TT = Vector3(x=A0.x + self.L_w, y=0) - wing_LE_shift 

90 B0 = Vector3(x=A0.x, y=wing_span) 

91 

92 # Construction points 

93 B1 = Vector3(x=A1.x, y=0.5 * B0.y) 

94 B2 = Vector3(x=TT.x, y=0.15 * wing_span) 

95 

96 # Leading edge line 

97 B0B1 = Line(p0=B0, p1=B1) 

98 # B1B2 = Line(p0=B1, p1=B2) 

99 

100 # Create Bezier for front edge 

101 a = B1 

102 b = Vector3(x=0.5 * (B1.x + B2.x), y=B1.y) 

103 c = B2 

104 B1B2 = Bezier([a, b, c]) 

105 

106 B2TT = Line(p0=B2, p1=TT) 

107 Line_B0TT = Polyline([B0B1, B1B2, B2TT]) 

108 

109 def local_ws(x): 

110 """Calculates the local wingspan.""" 

111 func = lambda t: Line_B0TT(t).x - x 

112 t = bisect(func, 0.0, 1.0) 

113 return Line_B0TT(t).y 

114 

115 def wing_tf_top(x, y, z=0): 

116 # Get the local wingspan 

117 lws = local_ws(x) 

118 if lws == 0: 

119 lws = 1e-3 

120 

121 # Define a thickness scalar which 

122 thickener = 0.5 * (1 - y / lws) 

123 

124 return Vector3(x=0, y=0, z=-wing_thickness / 2 - thickener) 

125 

126 def wing_tf_bot(x, y, z=0): 

127 return Vector3(x=0, y=0, z=wing_thickness / 2) 

128 

129 wing = Wing( 

130 A0=A0, 

131 A1=A1, 

132 TT=TT, 

133 B0=B0, 

134 Line_B0TT=Line_B0TT, 

135 top_tf=wing_tf_top, 

136 bot_tf=wing_tf_bot, 

137 flap_length=flap_length, 

138 flap_angle=np.deg2rad(self.flap_angle), 

139 stl_resolution=self.wing_stl_res, 

140 ) 

141 d21.add_component(wing, reflection_axis="y") 

142 

143 # Construct tail 

144 # ------------------------ 

145 # |--p1-----p2 

146 # | | \ 

147 # | | \ 

148 # | | \ 

149 # |--p0______________p3 

150 

151 fin_height = 0.15 * self.W_w 

152 fin_thickness = wing_thickness 

153 fin_length = self.L_b - self.L_w 

154 

155 p0 = b2 

156 p1 = p0 + Vector3(x=0, y=fin_height) 

157 p2 = p1 + Vector3(x=0.4 * fin_length, y=0) 

158 p3 = p0 + Vector3(x=fin_length, y=0) 

159 

160 # Thickness functions 

161 def fin_thickness_function_top(x, y, z=0): 

162 return Vector3(x=0.0, y=0.0, z=-fin_thickness / 2) 

163 

164 def fin_thickness_function_bot(x, y, z=0): 

165 return Vector3(x=0.0, y=0.0, z=fin_thickness / 2) 

166 

167 offset_func = lambda x, y, z: Vector3(x=0, y=0, z=-0.95 * self.R_b) 

168 tail = Fin( 

169 p0=p0, 

170 p1=p1, 

171 p2=p2, 

172 p3=p3, 

173 offset_func=offset_func, 

174 fin_thickness=fin_thickness, 

175 fin_angle=np.deg2rad(-90), 

176 top_thickness_function=fin_thickness_function_top, 

177 bot_thickness_function=fin_thickness_function_bot, 

178 stl_resolution=self.te_fin_stl_res, 

179 ) 

180 d21.add_component(tail) 

181 

182 # Construct trailing wings 

183 # ------------------------ 

184 # Straight wings at base of vehicle 

185 # Construct as rectangle fins 

186 fin_height = 0.45 * self.W_w 

187 fin_thickness = wing_thickness 

188 fin_length = 1.3 * (self.L_b - self.L_w) 

189 

190 te_wing_o = b2 

191 p0 = te_wing_o 

192 p1 = p0 + Vector3(x=0, y=fin_height) 

193 p2 = p1 + Vector3(x=fin_length, y=0) 

194 p3 = p0 + Vector3(x=fin_length, y=0) 

195 

196 tew1 = Fin( 

197 p0=p0, 

198 p1=p1, 

199 p2=p2, 

200 p3=p3, 

201 fin_thickness=fin_thickness, 

202 fin_angle=np.deg2rad(0), 

203 top_thickness_function=fin_thickness_function_top, 

204 bot_thickness_function=fin_thickness_function_bot, 

205 stl_resolution=self.te_fin_stl_res, 

206 ) 

207 d21.add_component(tew1) 

208 

209 tew2 = Fin( 

210 p0=p0, 

211 p1=p1, 

212 p2=p2, 

213 p3=p3, 

214 fin_thickness=fin_thickness, 

215 fin_angle=np.deg2rad(180), 

216 top_thickness_function=fin_thickness_function_top, 

217 bot_thickness_function=fin_thickness_function_bot, 

218 stl_resolution=self.te_fin_stl_res, 

219 ) 

220 d21.add_component(tew2) 

221 

222 return d21 

223 

224 

225if __name__ == "__main__": 

226 # To create the nominal geometry 

227 parametric_generator = ParametricD21() 

228 d21 = parametric_generator.create_instance() 

229 d21.generate() 

230 d21.to_stl("d21")