1+ import numpy as np
12import matplotlib .pyplot as plt
23
34from rocketpy .rocket .aero_surface import Fins , NoseCone , Tail
@@ -105,7 +106,7 @@ def thrust_to_weight(self):
105106
106107 return None
107108
108- def draw (self , vis_args = None ):
109+ def draw2 (self , vis_args = None ):
109110 """Draws the rocket in a matplotlib figure.
110111
111112 Parameters
@@ -117,7 +118,7 @@ def draw(self, vis_args=None):
117118 "background": "#EEEEEE",
118119 "tail": "black",
119120 "nose": "black",
120- "body": "dimgrey ",
121+ "body": "black ",
121122 "fins": "black",
122123 "motor": "black",
123124 "buttons": "black",
@@ -131,144 +132,248 @@ def draw(self, vis_args=None):
131132 "background" : "#EEEEEE" ,
132133 "tail" : "black" ,
133134 "nose" : "black" ,
134- "body" : "dimgrey " ,
135+ "body" : "black " ,
135136 "fins" : "black" ,
136137 "motor" : "black" ,
137138 "buttons" : "black" ,
138- "line_width" : 2 .0 ,
139+ "line_width" : 1 .0 ,
139140 }
140141
141142 # Create the figure and axis
142- _ , ax = plt .subplots (figsize = (10 , 5 ))
143+ _ , ax = plt .subplots (figsize = (8 , 5 ))
143144 ax .set_aspect ("equal" )
144145 ax .set_facecolor (vis_args ["background" ])
145146 ax .grid (True , linestyle = "--" , linewidth = 0.5 )
146147
147148 csys = self .rocket ._csys
148-
149- # Draw rocket body
150149 reverse = csys == 1
151150 self .rocket .aerodynamic_surfaces .sort_by_position (reverse = reverse )
152- y_tube , x_tube = [], []
153- for surface , position in self .rocket .aerodynamic_surfaces :
154- if isinstance (surface , (NoseCone , Tail )):
155- # Append the x and y coordinates of the surface shape_vec to the respective lists
156- x_tube .extend ((- csys ) * surface .shape_vec [0 ] + position )
157- y_tube .extend (surface .shape_vec [1 ])
158- if isinstance (surface , Fins ):
159- pass
160-
161- # Negate each element in the y_tube list using a list comprehension
162- y_tube_negated = [- y for y in y_tube ]
163- plt .plot (
164- x_tube , y_tube , color = vis_args ["body" ], linewidth = vis_args ["line_width" ]
165- )
166- plt .plot (
167- x_tube ,
168- y_tube_negated ,
169- color = vis_args ["body" ],
170- linewidth = vis_args ["line_width" ],
171- )
172151
173- # Get nozzle position (kinda not working for EmptyMotor class)
174- x_nozzle = self .rocket .motor_position + self .rocket .motor .nozzle_position
175-
176- # Find the last point of the rocket
177- idx = - 1 if csys == 1 else 0
178- surface , position = self .rocket .aerodynamic_surfaces [idx ]
179- length = surface .shape_vec [0 ][- 1 ] - surface .shape_vec [0 ][0 ]
180- x_last = position + (- 1 * csys ) * length
181- y_last = surface .shape_vec [1 ][- 1 ]
182-
183- plt .plot (
184- [x_nozzle , x_last ],
185- [0 , y_last ],
186- color = vis_args ["body" ],
187- linewidth = vis_args ["line_width" ],
188- )
189- plt .plot (
190- [x_nozzle , x_last ],
191- [0 , - y_last ],
192- color = vis_args ["body" ],
193- linewidth = vis_args ["line_width" ],
194- )
195-
196- # Draw nosecone
197- nosecones = self .rocket .aerodynamic_surfaces .get_tuple_by_type (NoseCone )
198- for nose , position in nosecones :
199- x_nosecone = - csys * nose .shape_vec [0 ] + position
200- y_nosecone = nose .shape_vec [1 ]
201-
202- plt .plot (
203- x_nosecone ,
204- y_nosecone ,
205- color = vis_args ["nose" ],
206- linewidth = vis_args ["line_width" ] - 0.05 ,
207- )
208- plt .plot (
209- x_nosecone ,
210- - y_nosecone ,
211- color = vis_args ["nose" ],
212- linewidth = vis_args ["line_width" ] - 0.05 ,
213- )
152+ # List of drawn surfaces with the position of points of interest
153+ # and the radius of the rocket at that point
154+ drawn_surfaces = []
214155
215- # Draw transitions
216- tails = self .rocket .aerodynamic_surfaces .get_tuple_by_type (Tail )
217- for tail , position in tails :
218- x_tail = - csys * tail .shape_vec [0 ] + position
219- y_tail = tail .shape_vec [1 ]
156+ # Ideia is to get the shape of each aerodynamic surface in their own
157+ # coordinate system and then plot them in the rocket coordinate system
158+ # using the position of each surface
159+ # For the tubes, the surfaces need to be checked in order to check for
160+ # diameter changes. The final point of the last surface is the final
161+ # point of the last tube
220162
221- plt .plot (
222- x_tail ,
223- y_tail ,
224- color = vis_args ["tail" ],
163+ for surface , position in self .rocket .aerodynamic_surfaces :
164+ if isinstance (surface , NoseCone ):
165+ x_nosecone = - csys * surface .shape_vec [0 ] + position
166+ y_nosecone = surface .shape_vec [1 ]
167+
168+ ax .plot (
169+ x_nosecone ,
170+ y_nosecone ,
171+ color = vis_args ["nose" ],
172+ linewidth = vis_args ["line_width" ],
173+ )
174+ ax .plot (
175+ x_nosecone ,
176+ - y_nosecone ,
177+ color = vis_args ["nose" ],
178+ linewidth = vis_args ["line_width" ],
179+ )
180+ # close the nosecone
181+ ax .plot (
182+ [x_nosecone [- 1 ], x_nosecone [- 1 ]],
183+ [y_nosecone [- 1 ], - y_nosecone [- 1 ]],
184+ color = vis_args ["nose" ],
185+ linewidth = vis_args ["line_width" ],
186+ )
187+
188+ # Add the nosecone to the list of drawn surfaces
189+ drawn_surfaces .append (
190+ (surface , x_nosecone [- 1 ], surface .rocket_radius , x_nosecone [- 1 ])
191+ )
192+
193+ elif isinstance (surface , Tail ):
194+ x_tail = - csys * surface .shape_vec [0 ] + position
195+ y_tail = surface .shape_vec [1 ]
196+
197+ ax .plot (
198+ x_tail ,
199+ y_tail ,
200+ color = vis_args ["tail" ],
201+ linewidth = vis_args ["line_width" ],
202+ )
203+ ax .plot (
204+ x_tail ,
205+ - y_tail ,
206+ color = vis_args ["tail" ],
207+ linewidth = vis_args ["line_width" ],
208+ )
209+ # close above and below the tail
210+ ax .plot (
211+ [x_tail [- 1 ], x_tail [- 1 ]],
212+ [y_tail [- 1 ], - y_tail [- 1 ]],
213+ color = vis_args ["tail" ],
214+ linewidth = vis_args ["line_width" ],
215+ )
216+ ax .plot (
217+ [x_tail [0 ], x_tail [0 ]],
218+ [y_tail [0 ], - y_tail [0 ]],
219+ color = vis_args ["tail" ],
220+ linewidth = vis_args ["line_width" ],
221+ )
222+
223+ # Add the tail to the list of drawn surfaces
224+ drawn_surfaces .append (
225+ (surface , position , surface .bottom_radius , x_tail [- 1 ])
226+ )
227+
228+ # Draw fins
229+ elif isinstance (surface , Fins ):
230+ num_fins = surface .n
231+ x_fin = - csys * surface .shape_vec [0 ] + position
232+ y_fin = surface .shape_vec [1 ] + surface .rocket_radius
233+
234+ # Calculate the rotation angles for the other two fins (symmetrically)
235+ rotation_angles = [2 * np .pi * i / num_fins for i in range (num_fins )]
236+
237+ # Apply rotation transformations to get points for the other fins in 2D space
238+ for angle in rotation_angles :
239+ # Create a rotation matrix for the current angle around the x-axis
240+ rotation_matrix = np .array ([[1 , 0 ], [0 , np .cos (angle )]])
241+
242+ # Apply the rotation to the original fin points
243+ rotated_points_2d = np .dot (
244+ rotation_matrix , np .vstack ((x_fin , y_fin ))
245+ )
246+
247+ # Extract x and y coordinates of the rotated points
248+ x_rotated , y_rotated = rotated_points_2d
249+
250+ # Project points above the XY plane back into the XY plane (set z-coordinate to 0)
251+ x_rotated = np .where (
252+ rotated_points_2d [1 ] > 0 , rotated_points_2d [0 ], x_rotated
253+ )
254+ y_rotated = np .where (
255+ rotated_points_2d [1 ] > 0 , rotated_points_2d [1 ], y_rotated
256+ )
257+
258+ # Plot the fins
259+ ax .plot (
260+ x_rotated ,
261+ y_rotated ,
262+ color = vis_args ["fins" ],
263+ linewidth = vis_args ["line_width" ],
264+ )
265+
266+ # Add the fin to the list of drawn surfaces
267+ drawn_surfaces .append (
268+ (surface , position , surface .rocket_radius , x_rotated [- 1 ])
269+ )
270+
271+ # Draw tubes
272+ for i , d_surface in enumerate (drawn_surfaces ):
273+ # Draw the tubes, from the end of the first surface to the beggining
274+ # of the next surface, with the radius of the rocket at that point
275+ surface , position , radius , last_x = d_surface
276+
277+ if i == len (drawn_surfaces ) - 1 :
278+ # If the last surface is a tail, do nothing
279+ if isinstance (surface , Tail ):
280+ continue
281+ # Else goes to the end of the surface
282+ else :
283+ x_tube = [position , last_x ]
284+ y_tube = [radius , radius ]
285+ y_tube_negated = [- radius , - radius ]
286+ else :
287+ # If it is not the last surface, the tube goes to the beggining
288+ # of the next surface
289+ next_surface , next_position , next_radius , next_last_x = drawn_surfaces [
290+ i + 1
291+ ]
292+ x_tube = [last_x , next_position ]
293+ y_tube = [radius , radius ]
294+ y_tube_negated = [- radius , - radius ]
295+
296+ ax .plot (
297+ x_tube ,
298+ y_tube ,
299+ color = vis_args ["body" ],
225300 linewidth = vis_args ["line_width" ],
226301 )
227- plt .plot (
228- x_tail ,
229- - y_tail ,
230- color = vis_args ["tail " ],
302+ ax .plot (
303+ x_tube ,
304+ y_tube_negated ,
305+ color = vis_args ["body " ],
231306 linewidth = vis_args ["line_width" ],
232307 )
233308
234- # Draw fins
235- fins = self .rocket .aerodynamic_surfaces .get_tuple_by_type (Fins )
236- for fin , position in fins :
237- x_fin = - csys * fin .shape_vec [0 ] + position
238- y_fin = fin .shape_vec [1 ] + self .rocket .radius
239-
240- plt .plot (
241- x_fin ,
242- y_fin ,
243- color = vis_args ["fins" ],
244- linewidth = vis_args ["line_width" ],
245- )
246- plt .plot (
247- x_fin ,
248- - y_fin ,
249- color = vis_args ["fins" ],
250- linewidth = vis_args ["line_width" ],
251- )
309+ # TODO - Draw motor
310+ nozzle_position = (
311+ self .rocket .motor_position
312+ + self .rocket .motor .nozzle_position
313+ * self .rocket ._csys
314+ * self .rocket .motor ._csys
315+ )
316+ ax .scatter (
317+ nozzle_position , 0 , label = "Nozzle Outlet" , color = "brown" , s = 10 , zorder = 10
318+ )
319+ # Check if nozzle is beyond the last surface, if so draw a tube
320+ # to it, with the radius of the last surface
321+ if self .rocket ._csys == 1 :
322+ if nozzle_position < last_x :
323+ x_tube = [last_x , nozzle_position ]
324+ y_tube = [radius , radius ]
325+ y_tube_negated = [- radius , - radius ]
326+
327+ ax .plot (
328+ x_tube ,
329+ y_tube ,
330+ color = vis_args ["body" ],
331+ linewidth = vis_args ["line_width" ],
332+ )
333+ ax .plot (
334+ x_tube ,
335+ y_tube_negated ,
336+ color = vis_args ["body" ],
337+ linewidth = vis_args ["line_width" ],
338+ )
339+ else : # if self.rocket._csys == -1:
340+ if nozzle_position > last_x :
341+ x_tube = [last_x , nozzle_position ]
342+ y_tube = [radius , radius ]
343+ y_tube_negated = [- radius , - radius ]
344+
345+ ax .plot (
346+ x_tube ,
347+ y_tube ,
348+ color = vis_args ["body" ],
349+ linewidth = vis_args ["line_width" ],
350+ )
351+ ax .plot (
352+ x_tube ,
353+ y_tube_negated ,
354+ color = vis_args ["body" ],
355+ linewidth = vis_args ["line_width" ],
356+ )
252357
253358 # Draw rail buttons
254359 buttons , pos = self .rocket .rail_buttons [0 ]
255360 lower = pos
256361 upper = pos + buttons .buttons_distance * csys
257- plt .scatter (
258- lower , - self .rocket .radius , marker = "s" , color = vis_args ["buttons" ], s = 10
362+ ax .scatter (
363+ lower , - self .rocket .radius , marker = "s" , color = vis_args ["buttons" ], s = 15
259364 )
260- plt .scatter (
261- upper , - self .rocket .radius , marker = "s" , color = vis_args ["buttons" ], s = 10
365+ ax .scatter (
366+ upper , - self .rocket .radius , marker = "s" , color = vis_args ["buttons" ], s = 15
262367 )
263368
264369 # Draw center of mass and center of pressure
265370 cm = self .rocket .center_of_mass (0 )
266- plt .scatter (cm , 0 , color = "black" , label = "Center of Mass" , s = 30 )
267- plt .scatter (cm , 0 , facecolors = "none" , edgecolors = "black" , s = 100 )
371+ ax .scatter (cm , 0 , color = "black" , label = "Center of Mass" , s = 30 )
372+ ax .scatter (cm , 0 , facecolors = "none" , edgecolors = "black" , s = 100 )
268373
269374 cp = self .rocket .cp_position
270- plt .scatter (cp , 0 , label = "Center Of Pressure" , color = "red" , s = 30 , zorder = 10 )
271- plt .scatter (cp , 0 , facecolors = "none" , edgecolors = "red" , s = 100 , zorder = 10 )
375+ ax .scatter (cp , 0 , label = "Center Of Pressure" , color = "red" , s = 30 , zorder = 10 )
376+ ax .scatter (cp , 0 , facecolors = "none" , edgecolors = "red" , s = 100 , zorder = 10 )
272377
273378 # Set plot attributes
274379 plt .title (f"Rocket Geometry" )
@@ -278,6 +383,7 @@ def draw(self, vis_args=None):
278383 plt .legend (loc = "best" )
279384 plt .tight_layout ()
280385 plt .show ()
386+
281387 return None
282388
283389 def all (self ):
0 commit comments