-
-
Notifications
You must be signed in to change notification settings - Fork 257
Expand file tree
/
Copy pathGetting_Started.html
More file actions
295 lines (270 loc) · 66.5 KB
/
Getting_Started.html
File metadata and controls
295 lines (270 loc) · 66.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge,IE=9,chrome=1"><meta name="generator" content="MATLAB 2023b"><title>Getting Started with RocketPy in MATLAB®</title><style type="text/css">.rtcContent { padding: 30px; } .S0 { margin: 3px 10px 5px 4px; padding: 0px; line-height: 28.8px; min-height: 0px; white-space: pre-wrap; color: rgb(192, 76, 11); font-family: Helvetica, Arial, sans-serif; font-style: normal; font-size: 24px; font-weight: 400; text-align: left; }
.S1 { margin: 2px 10px 9px 4px; padding: 0px; line-height: 21px; min-height: 0px; white-space: pre-wrap; color: rgb(33, 33, 33); font-family: Helvetica, Arial, sans-serif; font-style: normal; font-size: 14px; font-weight: 400; text-align: left; }
.S2 { margin: 10px 0px 20px; padding-left: 0px; font-family: Helvetica, Arial, sans-serif; font-size: 14px; }
.S3 { margin-left: 56px; line-height: 21px; min-height: 0px; text-align: left; white-space: pre-wrap; }
.CodeBlock { background-color: #F5F5F5; margin: 10px 0 10px 0; }
.S4 { border-left: 1px solid rgb(217, 217, 217); border-right: 1px solid rgb(217, 217, 217); border-top: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); border-radius: 4px; padding: 6px 45px 4px 13px; line-height: 18.004px; min-height: 0px; white-space: nowrap; color: rgb(33, 33, 33); font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 14px; }
.S5 { border-left: 1px solid rgb(217, 217, 217); border-right: 1px solid rgb(217, 217, 217); border-top: 1px solid rgb(217, 217, 217); border-bottom: 0px none rgb(33, 33, 33); border-radius: 4px 4px 0px 0px; padding: 6px 45px 0px 13px; line-height: 18.004px; min-height: 0px; white-space: nowrap; color: rgb(33, 33, 33); font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 14px; }
.S6 { border-left: 1px solid rgb(217, 217, 217); border-right: 1px solid rgb(217, 217, 217); border-top: 0px none rgb(33, 33, 33); border-bottom: 0px none rgb(33, 33, 33); border-radius: 0px; padding: 0px 45px 0px 13px; line-height: 18.004px; min-height: 0px; white-space: nowrap; color: rgb(33, 33, 33); font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 14px; }
.S7 { border-left: 1px solid rgb(217, 217, 217); border-right: 1px solid rgb(217, 217, 217); border-top: 0px none rgb(33, 33, 33); border-bottom: 1px solid rgb(217, 217, 217); border-radius: 0px 0px 4px 4px; padding: 0px 45px 4px 13px; line-height: 18.004px; min-height: 0px; white-space: nowrap; color: rgb(33, 33, 33); font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 14px; }
.S8 { margin: 3px 10px 5px 4px; padding: 0px; line-height: 20px; min-height: 0px; white-space: pre-wrap; color: rgb(33, 33, 33); font-family: Helvetica, Arial, sans-serif; font-style: normal; font-size: 20px; font-weight: 700; text-align: left; }
.S9 { margin: 20px 10px 5px 4px; padding: 0px; line-height: 20px; min-height: 0px; white-space: pre-wrap; color: rgb(33, 33, 33); font-family: Helvetica, Arial, sans-serif; font-style: normal; font-size: 20px; font-weight: 700; text-align: left; }</style></head><body><div class = rtcContent><h1 class = 'S0'><span>Getting Started with RocketPy in MATLAB®</span></h1><div class = 'S1'><span>In this Live Script, you will learn how to run RocketPy using the MATLAB® environment.</span></div><div class = 'S1'><span>First things first: clone/download RocketPy's repository and set it as your MATLAB® working directory so that you can run this live script without any issues.</span></div><div class = 'S1'><span>After that, we start by configuring our Python environment. You can do so by following the guidelines presented in the MATLAB® documentation:</span><span> </span><a href = "https://www.mathworks.com/help/matlab/matlab_external/install-supported-python-implementation.html?searchHighlight=python&s_tid=srchtitle_python_4"><span>Configure Your System to Use Python - MATLAB & Simulink (mathworks.com)</span></a><span>.</span></div><div class = 'S1'><span>Once the Python environment is configured, RocketPy needs to installed using</span><span> </span><span style=' font-family: monospace;'>pip</span><span> as outlined in RocketPy's documentation:</span><span> </span><a href = "https://docs.rocketpy.org/en/latest/user/installation.html#quick-install-using-pip"><span>Installation — RocketPy documentation</span></a><span>.</span></div><div class = 'S1'><span>Finally, all the prerequisites are complete and you can comeback to MATLAB®! We just need to set the execution mode as out of process and start working. MATLAB® can run Python scripts and functions in a separate process. Running Python in a separate process enables you to:</span></div><ul class = 'S2'><li class = 'S3'><span>Use some third-party libraries in the Python code that are not compatible with MATLAB®.</span></li><li class = 'S3'><span>Isolate the MATLAB® process from crashes in the Python code.</span></li></ul><div class="CodeBlock"><div class="inlineWrapper"><div class = 'S4'><span style="white-space: pre"><span >pyenv(</span><span style="color: rgb(167, 9, 245);">'ExecutionMode'</span><span >,</span><span style="color: rgb(167, 9, 245);">'OutOfProcess'</span><span >);</span></span></div></div></div><div class = 'S1'><span>Note: if MATLAB® is not able to find Python automatically, you may have to run the command line above including a path to the Python exectuable installed on your computer:</span></div><div class="CodeBlock"><div class="inlineWrapper"><div class = 'S4'><span style="white-space: pre"><span style="color: rgb(0, 128, 19);">% pyenv('ExecutionMode','OutOfProcess', 'Version', '/path/to/python/executable');</span></span></div></div></div><div class = 'S1'><span>Now, we will go through a simplified rocket trajectory simulation to get you started. Let's start by importing the rocketpy module and its classes.</span></div><div class="CodeBlock"><div class="inlineWrapper"><div class = 'S5'><span style="white-space: pre"><span >rocketpy = py.importlib.import_module(</span><span style="color: rgb(167, 9, 245);">'rocketpy'</span><span >);</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span >Environment = rocketpy.environment.Environment;</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span >SolidMotor = rocketpy.motors.solid_motor.SolidMotor;</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span >Rocket = rocketpy.rocket.Rocket;</span></span></div></div><div class="inlineWrapper"><div class = 'S7'><span style="white-space: pre"><span >Flight = rocketpy.simulation.flight.Flight;</span></span></div></div></div><h2 class = 'S8'><span>Setting Up a Simulation</span></h2><div class = 'S1'><span>Creating an Environment for Spaceport America</span></div><div class="CodeBlock"><div class="inlineWrapper"><div class = 'S5'><span style="white-space: pre"><span style="color: rgb(0, 128, 19);">% rocketpy.Environment(latitude, longitude, elevation);</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span >env = Environment(pyargs(</span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'latitude'</span><span >, 32.990254, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'longitude'</span><span >,-106.974998, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'elevation'</span><span >, 1400 </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S7'><span style="white-space: pre"><span >));</span></span></div></div></div><div class = 'S1'><span>To get weather data from the GFS forecast, available online, we run the following lines.</span></div><div class = 'S1'><span>First, we set tomorrow's date.</span></div><div class="CodeBlock"><div class="inlineWrapper"><div class = 'S5'><span style="white-space: pre"><span >Tomorrow = datetime(</span><span style="color: rgb(167, 9, 245);">'tomorrow'</span><span >);</span></span></div></div><div class="inlineWrapper"><div class = 'S7'><span style="white-space: pre"><span >env.set_date({int32(Tomorrow.Year), int32(Tomorrow.Month), int32(Tomorrow.Day), int32(12)}) </span><span style="color: rgb(0, 128, 19);">% Hour given in UTC time (noon UTC)</span></span></div></div></div><div class = 'S1'><span>Now, we tell our Environment object to retrieve a weather forecast for our specified location and date using GFS:</span></div><div class="CodeBlock"><div class="inlineWrapper"><div class = 'S5'><span style="white-space: pre"><span >env.set_atmospheric_model(pyargs( </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'type'</span><span >, </span><span style="color: rgb(167, 9, 245);">"Forecast"</span><span >, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'file'</span><span >, </span><span style="color: rgb(167, 9, 245);">"GFS" </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S7'><span style="white-space: pre"><span >))</span></span></div></div></div><div class = 'S1'><span>We can see what the weather will look like by calling the info method!</span></div><div class="CodeBlock"><div class="inlineWrapper"><div class = 'S4'><span style="white-space: pre"><span >env.info()</span></span></div></div></div><div class = 'S1'><span>Plots will open in a separate window, so be sure to run this last cell to see them!</span></div><h2 class = 'S9'><span>Creating a Motor</span></h2><div class = 'S1'><span>A solid rocket motor is used in this case. To create a motor, the SolidMotor class is used and the required arguments are given.</span></div><div class = 'S1'><span>The SolidMotor class requires the user to have a thrust curve ready. This can come either from a .eng file for a commercial motor, such as below, or a .csv file from a static test measurement.</span></div><div class = 'S1'><span>Besides the thrust curve, other parameters such as grain properties and nozzle dimensions must also be given.</span></div><div class="CodeBlock"><div class="inlineWrapper"><div class = 'S5'><span style="white-space: pre"><span >Pro75M1670 = SolidMotor(pyargs( </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'thrust_source'</span><span >, </span><span style="color: rgb(167, 9, 245);">"../../data/motors/cesaroni/Cesaroni_M1670.eng"</span><span >, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'dry_mass'</span><span >, 1.815, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'dry_inertia'</span><span >, py.tuple({0.125, 0.125, 0.002}), </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'nozzle_radius'</span><span >, 33 / 1000, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'grain_number'</span><span >, int32(5), </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'grain_density'</span><span >, 1815, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'grain_outer_radius'</span><span >, 33 / 1000, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'grain_initial_inner_radius'</span><span >, 15 / 1000, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'grain_initial_height'</span><span >, 120 / 1000, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'grain_separation'</span><span >, 5 / 1000, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'grains_center_of_mass_position'</span><span >, -0.85704, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'center_of_dry_mass_position'</span><span >, 0.317, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'nozzle_position'</span><span >, 0, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'burn_time'</span><span >, 3.9, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'throat_radius'</span><span >, 11 / 1000, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'interpolation_method'</span><span >, </span><span style="color: rgb(167, 9, 245);">"linear"</span><span >, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'coordinate_system_orientation'</span><span >, </span><span style="color: rgb(167, 9, 245);">"nozzle_to_combustion_chamber" </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S7'><span style="white-space: pre"><span >));</span></span></div></div></div><div class = 'S1'><span>To see what our thrust curve looks like, along with other import properties, we invoke the info method yet again. You may try the all_info method if you want more information all at once!</span></div><div class="CodeBlock"><div class="inlineWrapper"><div class = 'S4'><span style="white-space: pre"><span >Pro75M1670.info()</span></span></div></div></div><div class = 'S1'><span>Plots will open in a separate window, so be sure to run this last cell to see them!</span></div><h2 class = 'S9'><span>Creating a Rocket</span></h2><div class = 'S1'><span>A rocket is composed of several components. Namely, we must have a motor (good thing we have the Pro75M1670 ready), a couple of aerodynamic surfaces (nose cone, fins and tail) and parachutes (if we are not launching a missile).</span></div><div class = 'S1'><span>Let's start by initializing our rocket, named calisto, supplying it with the Pro75M1670 engine, entering its inertia properties, some dimensions and also its drag curves.</span></div><div class="CodeBlock"><div class="inlineWrapper"><div class = 'S5'><span style="white-space: pre"><span >calisto = Rocket(pyargs( </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'radius'</span><span >, 127 / 2000, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'mass'</span><span >, 14.426, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'inertia'</span><span >, py.tuple({6.321, 6.321, 0.0334}), </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'power_off_drag'</span><span >, </span><span style="color: rgb(167, 9, 245);">"../../data/rockets/calisto/powerOffDragCurve.csv"</span><span >, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'power_on_drag'</span><span >, </span><span style="color: rgb(167, 9, 245);">"../../data/rockets/calisto/powerOnDragCurve.csv"</span><span >, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'center_of_mass_without_motor'</span><span >, 0, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'coordinate_system_orientation'</span><span >, </span><span style="color: rgb(167, 9, 245);">"tail_to_nose" </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span >));</span></span></div></div><div class="inlineWrapper"><div class = 'S6'> </div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span >Rocket.set_rail_buttons(pyargs( </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'self'</span><span >, calisto, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'upper_button_position'</span><span >, 0.0818, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'lower_button_position'</span><span >, -0.618, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'angular_position'</span><span >, 45 </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span >));</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span >Rocket.add_motor(pyargs( </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'self'</span><span >, calisto, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'motor'</span><span >, Pro75M1670, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'position'</span><span >, -1.255 </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span >));</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span style="color: rgb(0, 128, 19);">% Adding Aerodynamic Surfaces</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span style="color: rgb(0, 128, 19);">% Now we define the aerodynamic surfaces. They are really straight forward.</span></span></div></div><div class="inlineWrapper"><div class = 'S6'> </div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span >nosecone = Rocket.add_nose(pyargs( </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'self'</span><span >, calisto, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'length'</span><span >, 0.55829, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'kind'</span><span >, </span><span style="color: rgb(167, 9, 245);">"von karman"</span><span >, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'position'</span><span >, 1.278 </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span >));</span></span></div></div><div class="inlineWrapper"><div class = 'S6'> </div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span >fin_set = Rocket.add_trapezoidal_fins(pyargs( </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'self'</span><span >, calisto, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'n'</span><span >, int32(4), </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'span'</span><span >, 0.110, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'root_chord'</span><span >, 0.120, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'tip_chord'</span><span >, 0.060, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'position'</span><span >, -1.04956 </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span >));</span></span></div></div><div class="inlineWrapper"><div class = 'S6'> </div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span >tail = Rocket.add_tail(pyargs( </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'self'</span><span >, calisto, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'top_radius'</span><span >, 0.0635, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'bottom_radius'</span><span >, 0.0435, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'length'</span><span >, 0.060, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'position'</span><span >, -1.194656 </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span >));</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span style="color: rgb(0, 128, 19);">% Adding Parachutes</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span style="color: rgb(0, 128, 19);">% Finally, we have parachutes! calisto will have two parachutes, Drogue and </span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span style="color: rgb(0, 128, 19);">% Main.</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span style="color: rgb(0, 128, 19);">% </span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span style="color: rgb(0, 128, 19);">% Both parachutes are activated by some special algorithm, which is usually </span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span style="color: rgb(0, 128, 19);">% really complex and a trade secret. Most algorithms are based on pressure sampling </span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span style="color: rgb(0, 128, 19);">% only, while some also use acceleration info.</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span style="color: rgb(0, 128, 19);">% </span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span style="color: rgb(0, 128, 19);">% RocketPy allows you to define a trigger function which will decide when to </span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span style="color: rgb(0, 128, 19);">% activate the ejection event for each parachute. This trigger function is supplied </span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span style="color: rgb(0, 128, 19);">% with pressure measurement at a predefined sampling rate. This pressure signal </span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span style="color: rgb(0, 128, 19);">% is usually noisy, so artificial noise parameters can be given. Call </span></span></div></div><div class="inlineWrapper"><div class = 'S6'> </div></div><div class="inlineWrapper"><div class = 'S7'><span style="white-space: pre"><span style="color: rgb(0, 128, 19);">% py.help(Rocket.add_parachute)</span></span></div></div></div><div class = 'S1'><span>for more details. Furthermore, the trigger function also receives the complete state vector of the rocket, allowing us to use velocity, acceleration or even attitude to decide when the parachute event should be triggered.</span></div><div class = 'S1'><span>Here, we define our trigger functions rather simply using Python. Unfortunately, defining these with MATLAB® code is not yet possible.</span></div><div class="CodeBlock"><div class="inlineWrapper"><div class = 'S5'><span style="white-space: pre"><span style="color: rgb(0, 128, 19);">% Drogue parachute is triggered when vertical velocity is negative, i.e. rocket is falling past apogee</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span >drogue_trigger = py.eval(</span><span style="color: rgb(167, 9, 245);">"lambda p, y: y[5] < 0"</span><span >, py.dict);</span></span></div></div><div class="inlineWrapper"><div class = 'S6'> </div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span style="color: rgb(0, 128, 19);">% Main parachute is triggered when vertical velocity is negative and altitude is below 800 AGL </span></span></div></div><div class="inlineWrapper"><div class = 'S7'><span style="white-space: pre"><span >main_trigger = py.eval(</span><span style="color: rgb(167, 9, 245);">"lambda p, y: (y[5] < 0) and (y[2] < 800 + 1400)"</span><span >, py.dict); </span></span></div></div></div><div class = 'S1'><span>Now we add both the drogue and the main parachute to our rocket.</span></div><div class="CodeBlock"><div class="inlineWrapper"><div class = 'S5'><span style="white-space: pre"><span >Main = Rocket.add_parachute(pyargs( </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'self'</span><span >, calisto, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'name'</span><span >, </span><span style="color: rgb(167, 9, 245);">"Main"</span><span >, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'cd_s'</span><span >, 10.0, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'trigger'</span><span >, main_trigger, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'sampling_rate'</span><span >, 105, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'lag'</span><span >, 1.5, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'noise'</span><span >, py.tuple({0, 8.3, 0.5}) </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span >));</span></span></div></div><div class="inlineWrapper"><div class = 'S6'> </div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span >Drogue = Rocket.add_parachute(pyargs( </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'self'</span><span >, calisto, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'name'</span><span >, </span><span style="color: rgb(167, 9, 245);">"Drogue"</span><span >, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'cd_s'</span><span >, 1.0, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'trigger'</span><span >, drogue_trigger, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'sampling_rate'</span><span >, 105, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'lag'</span><span >, 1.5, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'noise'</span><span >, py.tuple({0, 8.3, 0.5}) </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S7'><span style="white-space: pre"><span >));</span></span></div></div></div><div class = 'S1'><span style=' font-family: monospace;'>Just be careful if you run this last cell multiple times! If you do so, your rocket will end up with lots of parachutes which activate together, which may cause problems during the flight simulation. We advise you to re-run all cells which define our rocket before running this, preventing unwanted old parachutes. Alternatively, you can run the following lines to remove parachutes.</span></div><div class="CodeBlock"><div class="inlineWrapper"><div class = 'S5'><span style="white-space: pre"><span style="color: rgb(0, 128, 19);">% calisto.parachutes.remove(Drogue)</span></span></div></div><div class="inlineWrapper"><div class = 'S7'><span style="white-space: pre"><span style="color: rgb(0, 128, 19);">% calisto.parachutes.remove(Main)</span></span></div></div></div><h2 class = 'S8'><span style=' font-family: monospace;'>Simulating a Flight</span></h2><div class = 'S1'><span style=' font-family: monospace;'>Simulating a flight trajectory is as simple as initializing a Flight class object givin the rocket and environnement set up above as inputs. The launch rail inclination and heading are also given here.</span></div><div class="CodeBlock"><div class="inlineWrapper"><div class = 'S5'><span style="white-space: pre"><span >test_flight = Flight(pyargs(</span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'rocket'</span><span >, calisto, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'environment'</span><span >,env, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'rail_length'</span><span >, 5.2, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'inclination'</span><span >, 85, </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span > </span><span style="color: rgb(167, 9, 245);">'heading'</span><span >, 0 </span><span style="color: rgb(14, 0, 255);">...</span></span></div></div><div class="inlineWrapper"><div class = 'S7'><span style="white-space: pre"><span >));</span></span></div></div></div><h2 class = 'S8'><span style=' font-family: monospace;'>Analyzing the Results</span></h2><div class = 'S1'><span style=' font-family: monospace;'>RocketPy gives you many plots, thats for sure! They are divided into sections to keep them organized. Alternatively, see the Flight class documentation to see how to get plots for specific variables only, instead of all of them at once.</span></div><div class="CodeBlock"><div class="inlineWrapper"><div class = 'S4'><span style="white-space: pre"><span >test_flight.all_info()</span></span></div></div></div><div class = 'S1'><span>Plots will open in a separate window, so be sure to run this last cell to see them!</span></div><h2 class = 'S9'><span>Working with Data Generated by RocketPy in MATLAB®</span></h2><div class = 'S1'><span>You can access the entire trajectory solution matrix with the following line of code. The returned matrix contain the following columns: time</span><span> </span><span style="font-family: STIXGeneral-webfont, serif; font-style: italic; font-weight: 400; color: rgb(33, 33, 33);">t</span><span> (s),</span><span> </span><span style="font-family: STIXGeneral-webfont, serif; font-style: italic; font-weight: 400; color: rgb(33, 33, 33);">x</span><span> (m),</span><span> </span><span style="font-family: STIXGeneral-webfont, serif; font-style: italic; font-weight: 400; color: rgb(33, 33, 33);">y</span><span> (m),</span><span> </span><span style="font-family: STIXGeneral-webfont, serif; font-style: italic; font-weight: 400; color: rgb(33, 33, 33);">z</span><span> (m),</span><span> </span><span texencoding="v_x" style="vertical-align:-6px"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAnCAYAAAAYRfjHAAAAAXNSR0IArs4c6QAAAvlJREFUWEftljtoFFEUhv9/ZpLsxoQURvJ078wShSB2iqIpFGwUg4KI2KhFxAcqijZWEfGFYmGCIogJIuIL46sQxEJUxEKQFCpIyL27QkQRUklizN4jA7uwhGzc3UQtslPP/b9z/vPfM0P8p4f/iYsS+J85X7K6ZPVfc6AUrr9m7UThWW61UqrBcZw11tqlJNsA+CS3a60fZ6yqq6ubE41Gr5NsF5Fuz/OODgwM/Cx0RpNZ7SqldpDsIlkpIseNMZ3Z4MrKypsA2gF8E5ENxpg3MwFGPB6vsdbeJ7laRPqMMVsBjGXE4/H4QmttH8kqa+3aRCLxcUbAoYjv+5dI7hGRfhEJxb9kiZf7vh92/csYsy27qHwLyJnqIAg6AFwRkSERWZ9IJN5lRGOx2CLXdW8BOKy1fpovLPu9nGCl1CaSt0mOA9icFTD6vn+GZIPrujuLCVZYQE5wLBZrcxznAcm5ALZore+kR7AKwCnHcXYMDg5+KqbbKcFKqYDkM5JxEek0xhxvbm5u8jzvHslTWutHk0FbWloqRkdHayORyPeMG+mwRo0xXwHIlODGxsZYRUXFMwALQvDIyMj5aDQaXjGjtT6REcjAgyBQInKI5BIAKwFc1Vrv8n2/g+RZEfllrd2YTCZfTQmur6+fF4lEHpNcJiK9adA3z/OOTTVXpVSr4zhPROS7iFwCsDyVSp1zXbe5rKzsdeZszhlPuMspkr2u6+77U5hqa2urq6ur+0RkNYD+sbGxjUNDQ5/z/khMAPd4nrf3T9As288BOALggNa6e7Is5Ow4rLyqquougA+F7uMgCPYD6BKRC8aYgwWBi70mSqkVJHsAzCf5NpVKhYEaztvqYsBNTU1zy8vLL4vIjdBmki3j4+PrHMcpI1ljjHme0Z32j0D6M3mE5A8RaQXw0hhzzff9i+GuD5eNiATW2pPJZPL9jIGDIKgTkYcAFpM8rbU+DSCVtvwegGGSu7XWL/La1cVYXciZaVtdCKzUcbFuTevc7Jvxby4RPTeeLxlcAAAAAElFTkSuQmCC" width="15" height="19.5" /></span><span> (m/s),</span><span> </span><span texencoding="v_y" style="vertical-align:-6px"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAnCAYAAAAYRfjHAAAAAXNSR0IArs4c6QAAA1NJREFUWEftlU9oXFUUxr/vvjeTzJii0JSkmeHd9wbUhSsXKkIRi3EhGAT/ULvRLixiLVQsVUSkEqToQhQFUyhYRMR/tIpdCFrqSlAQRagKEnLvyzNTJiIuxA46M/fIhRkYQ2YyiZN0Ye5yeHN+9/vud84hrtDhFeJiG7xlzm9bvW31pjmwHa5Ns3Zl4f+51Vrr3UqpaefcTST3AIhJPmyMOdexamJi4qpCofA2yRkReT0Mw2fm5+f/Wu8brWZ1oLU+QPI1kkURmbXWHu8GF4vFdwHMAFgWkXustV8NA4xKpXK1c+4jkntF5Ky1dj+AvzvFK5XKdc65syTHnHN3pWn601DAvkgcx2+QfExEvhcRX/xSV/F8HMdedcNa+1D3pQa9QM9UJ0nyCIBTIlIVkbvTNP2uUzSKohuCIHgPwFFjzGeDwrq/6wnWWt9H8n2STQAPdAWMcRy/SHJ3EAQHNxIsf4Ge4CiK9iilPia5E8A+Y8wH7Se4HcAJpdSBhYWFnzeiti9Ya52QPE+yIiLHrbWz5XK5FIbhGZInjDGfrIB6JyYAXC8iQZqmXwAQL05rvZfkZWvt1+3feiuempqKRkZGzgO41oPr9frLhULBt5g1xrzQKdCG57XWdwC4leRRkr920l4qlcq5XO5zANe0Wq2ZLMu+6at4cnJy1+jo6DmSt4jI6TZoOQzD5/u8q1c9R/JRETlkrZ3zkCiKpoMgeKXZbO7PsuxiX/CKXm6RPB0EweG1wpQkyZ0AzojIhTAM9/nvtdY3kjxWr9cP1mq1P9cDfjMMw0NrQX1BP3ZJfgpgh4hMp2lqtNZPKqX+MMac6uSiZ6rHx8d3jI2NfQjgx3XOYyZJ8paI3Avg/kajcTGXy73UarWOZVlWXRO80TZpt9wRkq8CeEpEin6mW2tPdgdyU/ZxkiS3iYif9Usi8kOj0Ti8tLT020CT678o7mqhXc65BxcXF31b/utsiuKujvjWGPM0gNaWgP0SUUo9W6/Xn6jVasuruTd0xaVSaWc+nz/pnJtL0/RCrycbCjhJkpt9+zSbzXf8xiL5pbXWLxU/q1c9QwFrrWeVUs8B+AXA4+0V2hPad3KtM9VBuVyedM79Xq1WLw/y36EoHgS0Jake5CL/AI+Cajcgjn/cAAAAAElFTkSuQmCC" width="15" height="19.5" /></span><span> (m/s),</span><span> </span><span texencoding="v_z" style="vertical-align:-6px"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAnCAYAAAAcsCj6AAAAAXNSR0IArs4c6QAAAuhJREFUWEftlU1oE0EUx99/ZtN2a0XBSts07k5DFEHwJl4KVfAiKIIiIvjRgx4sCgWl6EGsRbQXoSgoIlihB7+wiooHUfHoQRAPKkrp7G5BScGbptR258lKCmtomgRjLybXybzfzG/+7y1okX9YZB7VgFU3XlNaU1qxgVpoKlZWasN/ptR13TYhxBZjzAYAnUSkABzUWj+eU9XS0rLEtu0RANuZ+bJlWafGxsamS6mcW59PqXRdtxvAJQCNzDzged6ZOLCxsfEWEW0noklm3uF53uu/AVI6nV5mjHkAYDMzj3qet5eIfs4VTafTa4wxowCajDFbfd//+FfAaLNS6gqAI8z8jpmjol9jReuUUtEtZzzPOxA/TClw0ZR2dHQcIqLrzPyFmbf5vv92rpjjOOuklLeJ6LjW+lkpSHy9KNB13V0A7gCYJaLdseBAKTUIoE1KebiSwETgokDHcTqFEA8BrCCiPVrru3nVm4jovBCie3x8/HMlt1sQ6LpuB4DnANLMfMbzvIFUKtVuWdZ9AOe11o8qhS0ITCaTTn19/XMiWh0Bp6amLtq2HbWKp7U+R0RcGCIAO+OHYOYQwNn4/4sqbW1tXdnQ0PAYwEZmHs4DJi3L6i98N6WUIqJrzDw0MzPzPoImEondQoi1uVyuN5vN/lio8X+vFfRidNJhKeXR+UKSTCZXSSlbJiYm3uTfuQvAsVwu15PNZifLSmkB8IZlWT3lJDI/FPrzKj8VvnNRpc3NzUubmpruEdGHcudle3v7irq6usEwDIeCIPittmxgpQnMZDL1s7OzF5j5ie/7L4vtr9b3MBoGfQC+aq1HChL8B7sqQMdx9gkhTgDo01q/IKLwn91QKdVFRDeJaBUASUQj0cibnp5eL6U8aYw5HQTBh5JtUe4bRkGxbft7GIbLmbmfiA4A6DXGfBNCXCWi/fEBXxWl8cOlUqlMIpHoJiI7DMOnQRC8iiuuOrCUmRqwlKGK1xdd6S/j5yo3fQVT/AAAAABJRU5ErkJggg==" width="14" height="19.5" /></span><span> (m/s),</span><span> </span><span texencoding="q_0" style="vertical-align:-6px"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAnCAYAAABuf0pMAAAAAXNSR0IArs4c6QAAA+xJREFUWEftVluIG1UY/r5jJiERVFo07CZkzoS1KBUffVJUVLRotRe1yqottd76VB8KfRBFQfpSUV+s9VIQW3cV2yq1VXGpIlYUBPVBC3XJObOycaMWLOpmk92dX07NyJim6S6tLELyNGTO+f/vfJf/DLHAPy5wf/QA9BjoMdBjoMdAj4H/BwNa60sAPEryWhH5AUAfgGHgxGW2RES+D8PweQAz871duzIwMDCQmZ2dfQzAFhHZX6/XH67Vaj8XCoXFnuftIXm1aygiT1hrn5pvc7f+lABck3Q6vQPAahHZmUqlNo6OjjbiJkEQ7AIwCOB3t8YY89FZA+BOPjMz8wLJ9QBGms3mXePj48fiBv39/blMJvMWgJtF5FsRWRaG4U/ufbFYXOR5nmPjKhH5DsDlIvKG53nPJA8Q1+rIgNZ6E4BtAH6LomjF2NjYZ8nTaa01yQ9b+m+31m5071usDYtIn1JqVaVSOaq1djI5vxxsZ7GjBC3DHSBZFpEd1tpHnMxJAL7vryf5Uuu/QWvtm+5Za72V5BYAm40x7gAnemitt5NcF0XR/WEY7k7WOokBrfXjJJ8EcDyKolVhGB5Kbsjn8+dms9m3Sd4EIIyiyNF/pFAoFNPp9EERKZBcaYz5NN7n+/6gUsp55kCj0bizWq1OdpSgXC6fH0XRvlbcvpyamlo+MTHxS9vpXbFXAWREZK+19m4AzSAIbgCwB8BEo9G4vlqtjsX7SqXSlUqpd0j+EQPuCMD3/UuVUu8D8EVkyFrrXP4P/eVyeUkURXtJLm3Fb5O11uUfQRBsAPCyiJwEPFF3UXti/iVBAuliALuNMffESFsGGxKRy0j2icixpEFj6UTkY6XUykqlcjyRmlImkxkBcDGANcYYl6C/DdJGb5KBL0iuMMbU8vn8Rdls9kVHIYALACwXkc+np6dvjeN5VgA4g+VyuSHXoEXxNyR/FJHrALxL8jkADr3vYmqM2Rwf4DQSBCRHSF7YVQJXzPf9QCnldF0mIiR5RES2WWt3+b6/1sWPpJv5dxhj9icAnLkJk3J0eGYQBK8BuBfAURG50VprE1HrI+kMXGwfXnEMReSDer1+e61W+7OjB7oBSE4/AK8bY9a2D6hugwjABhF5MAzDnV0H0alAaK3XuGSQPAfAA8aYV9rXFovFgud5+0Qk12EUf5JKpda13wdz/SCJx+lDIlIVkVvCMPy6E1iXmFwu9zSAK+LLiOTw5OTks0nq5yVBqVRaqpR6j6QGcLjZbN6WvB1P452ur7sy4Pv+apL3kbwGwHmtaM6SPAzgq0ajsbVarf76nwE4k8Jz3TtXD8y13rzX9QAsOAN/AXKqAkb9bH7gAAAAAElFTkSuQmCC" width="16" height="19.5" /></span><span>,</span><span> </span><span texencoding="q_1" style="vertical-align:-6px"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAnCAYAAABuf0pMAAAAAXNSR0IArs4c6QAAAyhJREFUWEftll+IlFUYxp/nc3eH2UgDFwd3Yc6ZYRFDIfRaUOnCxDRJImMrQQj/XGmgeCH+Q/DGi/IiM1KIlK0oK0xEjG7MKAiqm4RaOedb2XVXV1AUdnd293vkyEwM486uMy5KMN/lzPu9z3N+533O+Yhn/PAZ66NhoEGgQaBBoEGgQeD/QcBauxDATpIrJf0LYD6AL4CHl9kCSX/HcfwhgPFab9cpCXR2dqYmJib2Atgj6dzw8PDWwcHBmx0dHXObm5u/Ibk8CEra770/VKt4qK9qIIi0tLScALBB0qmmpqbtPT09oyWRXC53GkAXgHuhxjl3acYMhJWPj49/RHIzgB8LhcLGvr6+2yWB9vb21lQq9RWANZL+krQ6juMb5QaMMUtJHiF52Tl3uJq5SQlYa3cAOArgTpIk63t7e38ub2CttSQvFvf/uPd+exmZlyTtJrkGwJzptucRA8WBO08yL+mE935b2OaK1W0m+Unxty7v/Zel/9va2p4fGhq6b609QHJfPQb2kTwI4G6SJK/HcfxTuXgmk3kunU5/TfIVAHGSJAH/1UrE1tqHfWoykM/n5yRJ8m0xbr+NjIysHRgYuFWx+q4oik4CSEk6671/C0BhRgwYY16MougCACOp23sfpvw//Pl8fkGSJGdJLirGb4f3PuT/kacuAtlsdlkURd+RnAvgjHPu7VLnYiy7JS0mOV/S7ckGtFRfl4EKAr+SXO+cG8xkMvPS6fTHJO8DeAHAWkm/jI2NrSuPZ0VSap+BMGCtra3dQaCI+E+S1yW9DOB7kh8ACPk3IabOuV3V8l0XgdDMGJOLoijs62pJJHlV0lHv/WljzKYQP5LhzH/DOXduxg1McZwyl8t9BuAdAP9IWuW990/NQPnpB+Bz59ymygPqiWdgqsvEWvtmSAbJWQDec859Ok39wbpOwipNaa09TnKLpH5Jr8Zx/MdktcaYJWF+SL4f4izpGoBjki5P9s5jfRFls9lFURT9QNICuFIoFF6rFr9ar+QpDRhjNpB8l+QKALOL0ZwgeQXA76Ojo0f6+/uHahUtr38sAk8iMN27DQMNAg8AjgSkNz3ZhPkAAAAASUVORK5CYII=" width="16" height="19.5" /></span><span>,</span><span> </span><span texencoding="q_2" style="vertical-align:-6px"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAnCAYAAABuf0pMAAAAAXNSR0IArs4c6QAAA9RJREFUWEftVl1onEUUPWfcbLIRVCi4JBt25ltCUapCXwRB8O9Bi0aL9a/EWqmKtk9REARLxX+QPuiLtaJSaUq0aKvUH0TxqRVFQX2x0MadmUjSrFqw/rDJbvJdGf1WNtvdbRaFIOw87nfvPWfOvefOEit8uML46BLoKtBVoKtAV4GuAv8PBYwxFwB4kORVInIcwACAN4C/HrPVIvKd9/4FAAudvq5tFRgeHu5dXFzcDuARETlULpcfKJVKP+ZyuVU9PT1vk7wiAIrIY865JzoFD/EtCQSQdDq9G8AGEXktlUptm5ycnK+BRFE0DmAUwG8hxlr78X9GINx8YWHhRZJbAHxSqVTumJ6ePlkDGBwc7O/t7d0P4HoR+VZE1nnvT4TvURRdIiKhHZeS7BcRKyJPe+/3AFhsJNlUAWPMGICdAH6J43j91NTU4fpEY4wh+VHS/13OuW3huzEmtGSC5HERmSQZyKxN2rTDe//MGQkkA/c+yYKI7HbObQ1trk/UWm8h+XLy26hz7s1sNnt2f3//BIAvrbVPJTmMomh7mBGS34vItc45V1/rNAWMMTtIPg7gVBzHN3vvP61PCECZTOYtktcB8HEcB/mPaq3XKqUeJXlPsVg8VcvJ5XJD6XT6AxEZbKbmEgKFQuHcOI4PJnb7Ym5ubmR2dvanhtuPKqVeBdArIgeccxsBVMJc9PX19dSDh7y6moUa2ZYKaK0vVEp9CECLyIRzLkz5P/IXCoXVcRwfILkm6euYcy4MXMujtR4gGWqeKJfLt5RKpT9aEsjn85crpd4huQrAPmvtnXVSBltOiMhFJAdE5GQzSRuZaK2vVkpNxHH8kPd+X9shbFDgc5LrrbWlbDZ7fiaTeYnk7wDOAzAiIp9Vq9Ub6+3ZWDxZZOMi8mvjHqnFLpmBukkeSST+huQPInINgHdJPg8g+F8Hm1prH24nvzHmbgC3VavVTa2InuYCrXWklAp9XSciJHlURHY658a11puD/UiGnX+rtfZQKwJRFAWVxpRSW4vF4rFWcZ28hsHTrwPYBOBYM0/XQMJCIvkkyXvbgYf4ZROo334A9lprNzcuqNo2bAaerPfnRGSP9/7rpjNwhn7eHpxB8iwA91lrX2ky8ZeR3AtgCoBdYre/1/Kkcy4Qr3RKgMaYXSTvF5EZEbmh/hah2NDQ0MWpVGo/yfDfodmZj+N4o/f+YMs90EqBfD6/Rin1HkkD4EilUrmpnf3aKdl2DzSRdAPJu0heCeCcxJqLJI8A+Gp+fv7ZmZmZnzsB7IjAvym83Nxlu2C5BTuN6xJYcQX+BIuu0jcaM9OXAAAAAElFTkSuQmCC" width="16" height="19.5" /></span><span>,</span><span> </span><span texencoding="q_3" style="vertical-align:-6px"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAnCAYAAABuf0pMAAAAAXNSR0IArs4c6QAAA+hJREFUWEftVm1oXEUUPWc2X5uCCgWXJmRn3hqKUhEEBX8IKgW1ak1t0RpSLQbEtiJUUFEoioKoNIIiWCvWD2xNq7UqtRVRBMFKBUGLYKGGzLzVjVm1oKjJ5iX7rkx5Kc+Yj90qBGHn55v7cebce+59xCIfLnJ+NAA0GGgw0GCgwUCDgf8HA8aY8wHcS/IqEfkOwDIAe4FTy2y5iHwbhuGzAKbq3a7zMtDd3d1arVa3AXhQRA6Oj49vKpfLP3V2di5tbm5+m+QVPqGIPOKce6ze5N5+TgA+SUtLy04A60Tk5aampi1DQ0MT00mCINgNoA/A797GWvvRfwbAv3xqaup5kv0APo6i6NZSqXRyOkFHR0d7a2vrmwCuF5FjIrIqDMMf/X1XV9d5mUzmcZKrRGQJyePVavWpYrG4x5M1E+SsDBhjtgIYAPBrHMdrisXiZ2lHY4wh+WFS/x3OuS3+3hhzGYBdJF+pVquHM5nMSl8eAFkA/c65fQsCSBruEMmCiOx0zm2eiVxr3U/yxSRYXxK4xRjzHIA3nHOfpkp1H4DtIvKqc+6OWgA8TPJRAL/Fcbw2DMNP0k65XG5JNpvdT/JaAGEcx57+4/57W1vbRWEYHk0DDoLgFgD7RORJ59xD8wIoFApnx3H8TiK3LyqVyurR0dGf005a6z6l1C4ArSJywDnXCyCaowFpjHkawNVKqbXDw8Mn5gWgtb5AKfUBAC0ig8453+WnG6dQKCyP4/gAyRWJ/LY657z+Zzs++SYA95DstdYem9Uo/TGfz1+ulHqX5FIAe6y1G6bvE1kOisiFJJeJyMnZGtRLW2t9E8n7AVxKMuNtSW621r5VDwNHSa6x1pZzudy52Wz2BZJ/ADgHwGoR+XxycvLGtDzTwb2Uoyi6RCk1QNKr45soiq4rlUo/pO3+JkPfSO3t7YM+QULx1yS/F5GVAN4j+QwAr3/tZWqt9a+c9wRBkBMRz+rFAG621h6cE4C/0FoHSilfVz9I6AeJiAw453ZrrTd6+ZH0M/8fweZCEgTBdgBejuuttf4Bp08925BBELwG4DYAJ0TkGuecW4gBf2+M8dK+W0R6nHNepvUDSE8/AK9bazfONlpnAkrNjcmxsbHecrn855kCWO+V4bsawJ3W2pfSgRKJnlrRIrItDMPDAJQx5gGSXhUbFpwD89DpNb2D5F0iMiIiN4Rh+FXaPlnRfhT3+CEFwP83OBHZX6lU9s58+bRvTT2Qz+dXKKXeJ2kAHImiqGcu+dXSEzWXQGu9juTtJK8EcFYizSrJIwC+nJiYeGJkZOSXepPWDODfBK7Vt6YS1BrsTOwaABadgb8APTG6Nweg5pMAAAAASUVORK5CYII=" width="16" height="19.5" /></span><span>, </span><span> </span><span texencoding="\omega_1" style="vertical-align:-6px"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAAnCAYAAACIVoEIAAAAAXNSR0IArs4c6QAAA3JJREFUWEftlk1oHGUYx5//O9lNNoKCrSRmm3l3QqQtgiIIiogg1ottpbUfEIylPRWkxR5EEA9ByEGsB0Xx49ZDQ+3FSlTsoSBoEQU/Th5KQ+adTbMkioiC2R03M395YaYM200y2ebQw8z1feZ9fvt7PmYhd+CDO5BJCqi8VSlMFabyGsgbV/RUYSqvgbxxRU9ttSnHdd2dSqmHAfSR/M4YY5IkZa31M0qp7ST/abfbVxcXF//MC9AtbqPyOVrr40qpKZKLAKbCMLzaaDRWOi+rVqs7SqXS2wCOkHy/r6/v9bm5ubAXuDWhqtXqtnK5/ImIHCJ5rtlsnlpeXv53vSRa691Kqa9J7hCRV40x724ZVAL0qYjsIfkDgAO+7y/bBOPj4/1RFH1A8gSAj33fPy0itGdjY2P3xHF8CcDTIvJVGIZHu1ndCLSbKdRqtbcAvCYiYRzHE0EQXEovqtVqZ0TkHQAOyW+UUgfn5+f/7gJ1PQzDPY1Go56+OzQ0dNfg4ODLInIkDMPD2bMs6C1Qo6OjjzqO8wWAYZKXm83m4bRsHSaE5AVjzItrmLoJZWEqlcokgFMkdwOY7wReF8rzvLO2H2wQyTPGmPfSF7TWjwD4EsBIt/ORkRG3v7//iog8ICLfRlF0oF6v/2VLvrq6CpL3A7gCIMoNNTw8fN/AwIC19BjJBsl9QRD8moE6BOBiUrqlKIr2Lyws/JSee573FEnbU/eS/MgYY0t188lAS26odHpERJP8sdVq7V9aWvojk/SoiFxMLJ0zxpwUkf8y/fYKADtxt/SijekJynXdJ5VSnwPYRvIzY8xENqnneSnUjaQ0P2dElGu12gUAL5D8vt1uP9+5RHuC6uiZGd/3J7P6Pc+zvXa2W2nSARGRuwFM+L4/2zn6PUHZ/VQqlWYBPNFpyvO8nSStxV12mRpjTqRJk911nuRBAG/6vj+dTuRt95S9wHXdSaWU3eS/x3G8r16v/+a67oNKqfMiYveRLyKPJwv1WrJ7bB+9ZC06jjO91uelJ1PJr4LW+jkA0wAGReQaSRfAzMrKyoc2plKpvAHgWQtI8iEA1+M4ngqC4Jf1tvXtQG30Fej5vIDKq05r7W16o+e9fLNxyTDsFZFjIrKXZCQiMyRnW63W5c6/RBv9ydts/i2JL6DyaixMFabyGsgb9z+yxfw3aBZpLwAAAABJRU5ErkJggg==" width="18.5" height="19.5" /></span><span> (rad/s),</span><span> </span><span texencoding="\omega_2" style="vertical-align:-6px"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAAnCAYAAACIVoEIAAAAAXNSR0IArs4c6QAABBtJREFUWEftlW9om1UUxs9z06RtxBW6aUOzvn9GdcpAEURFVJRNQd10c25QnOD0gyCKA/9RRIpSUOc+OBxTvw1dnfuyjenQD1NRh6j454MIztW+901sSBUFBZvGJPeRK3klS5M0lVkm5P1673vO7zznOedCzsIPZyGTdKDa7UpHqY5S7SrQ7r2OpzpKtatAu/c6njrTSsUcx1mtlLoUQBfJj7XWupok4bruWqXUCpK/l0qlE9PT07+0C9Do3kLti7mue49SaozkNICxYrF4IpfLzdYHS6fTK+Px+E4AW0i+1NXVNTo5OVn8N3BNodLp9PJEIvGqiGwmua9QKDw4MzPzR6skruterJR6h+RKEXlUa/3iGYOqAr0pIutIfgpgYxAEMzbB8PBwd6VS2UNyO4BXgiB4SERoz1atWtVnjDkM4AYROVYsFrc2UnUh0EZKwfO85wA8LiJFY8xIGIaHo0Ce5+0QkV0AYiQ/UEptmpqa+q0B1Klisbgul8tlbCGlUukRpdT9IuKQnAVwrFwuj2az2R/qIedBDQ0NXR6Lxd4CkCL5bqFQuDNqW50SQvKA1vquJkr9DZVMJmfK5fJeALeKyHERSZBcC6BfRL4xxtwehmFQCzYPyvf9F6wf7CWSO7TWu6MfXNe9DMDbAAYbnQ8ODjrd3d028QUi8lGlUtkYi8WuJTmmlBqZmpr6vqrohcaYQwDW2DOt9TNNoVKp1Hk9PT1WpStJ5kiuD8Pw6xqozQAOVluXr1QqG7LZ7BfRue/715G0nuon+bLW+gHP83aT/DwMw4naxL7v28KtABNBEGxrChVNj4i4JD+bm5vbkM/nf65JulVEDlZV2qe1th75s8ZvDwOwExd58UgqlVqRz+d/FZFKHVQUa1cQBI81hXIc5xql1BEAy0ke0lqP1Cb1fT8K9KNtTSaT+bImWMLzvAMA7iD5SalUuq3VEvU8zxbwfP0g2XinearOM/NkjSSPWlNbXTQgIrIMwEgQBEdbjL4t4DUROb92eqP7p0HZ/RSPx48CuLpeKd/3V5O0Kl5kl6nWensUpLq79pPcBODpIAjGo4lsBOb7/k0k94rIfVrrDxdcCY7jbFNK2U3+kzFmfSaT+dZxnDVKqf0iYveRHd+rqgv15MDAwDnJZNL66G5r3FgsNt7qeakW/oYx5vVMJmNjzvsaLk/XdW8BMA4gKSInSToAJmZnZ2110tvb+ySAGy0gyUsAnDLGjIVh+FWrbd3f37+sr69vjzHmuzAMn22m5kIPcqscizqLnicRySzU3iWBagXked71InKz1vqJhkZfVOltXrZA5XJ5p4hsAfAeyX/2GoBzReQKY8y9YRi+v1RQCd/3nyI5al+BRnXUv6/z9lSbxf/n15bEU4utogPVrmIdpf7XSv0FVZcVRg9veRcAAAAASUVORK5CYII=" width="18.5" height="19.5" /></span><span> (rad/s),</span><span> </span><span texencoding="\omega_3" style="vertical-align:-6px"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAAnCAYAAACIVoEIAAAAAXNSR0IArs4c6QAABCJJREFUWEftlV1oHFUUx8//zu7mQ1CwSuImO3cmRqr4RUFQRASxvmirrdVAaIX2QYKiWKQWgmIUAorpQ/2g6kOhaEstotVatYggaJUqfiBYsDRk7mySNfELFJpks+z85coOTDebZCot9mHn9Zy5539/53/OhZyHH85DTdIUlbYrTVJNUmkJpM1reqpJKi2BtHlNT51tUo7ruiuVUtcDyJD8whhjakVyWuvblVKXkPy7UqkcnZyc/COtgEZ5y7XP0VpvVkoNkZwEMFQul4+WSqWZ+sO6urq6s9nsCwDuJ/lyJpMZHB0dLf8XcYuK6urqWpHL5V4XkQ0k98zOzj4yPT19aqkiWuurlFIfk+wWkW3GmJ1nTVRN0FsisprkMQDrgiCYtgV6e3tbqtXqKyS3AHgtCIJHRYQ21tPTc1EURQcB3CYiH5bL5b5GVJcT2ogUPM97HsB2ESlHUdQfhuHB+CDP87aKyA4ADsnPlFLrx8bG/mog6mS5XF5dKpWKIhLbYDvJywGcIvnO/Pz8UKlUGq8XuUBUoVC4wXGcDwB0kjwyOzt7X9y2OhJCcr8xZuMipGJRU57nvQQgH0XRTgAzAJ4SkbtIfqKU6osvFYtbIMr3/RHrB5tAcqsx5sU4WWu9CsBhW6BRPJ/Puy0tLZ+KyBUi8nm1Wl0HYJWl6TjOttj4dihyudxHItJB8h5jzLEkrdNEdXZ2Xtra2mop3UiyRHJNGIY/JERtAHCg1rqparW6dnx8/Ns47vv+rSStpy4m+aox5uHu7u5rHcf5PQzDX+K8mLiIaEvMGPPzoqLi6bHJJL+em5tbOzU19VuiaJ+IHKhR2mOMGRCR+YTfHgNgJ26BF5NFC4XCNZlM5rCI7A6CYDhuf8P2ua57i1LqPQArSL5rjOlPFvV9PxY1YVtTLBa/SxTLeZ63H8C9JL+qVCp3N1qi+Xy+kMvl3iT5TRiGgyJSXdLodZ7ZFwTBpuQPvu9br43Eram7/b8DIiIXAugPguBQMq61vkxEBgFstO2txewEDtSLP81Tdj9ls9lDAG6uJ+X7/kqSluKVdpkaY7bERWu7ay/J9QCebdSSRIs7RWQAwOP2AiLyRBAEOxb1lA24rrtJKWU3+a9RFK0pFovHXde9Wim1V0TsPgpE5KbaQj3R0dFxQXt7u/XRA5ai4zjDaZ4X3/cftMQBHKlfsg2Xp9b6TgDDANpF5ARJF8C+mZmZXVZ4W1vbkwDusAJJXgfgZBRFQ2EYfr/ctk5McvwkjSUXsI0v9yCnrXHGefFOI/ll0gr/qyittfXfbgCb64finJPyPO8ZAA+JyNuVSuXpiYmJP+3QiMgbURS9H4bhc0vuqTPuQYoftNb2FRgB4NcG5SeSxwHsCoLgx0ZHnHNSKXQvSGmKSkutSapJKi2BtHn/AJcEB0ZXe+NJAAAAAElFTkSuQmCC" width="18.5" height="19.5" /></span><span> (rad/s).</span></div><div class="CodeBlock"><div class="inlineWrapper"><div class = 'S4'><span style="white-space: pre"><span >solution_matrix = double(py.numpy.array(test_flight.solution))</span></span></div></div></div><div class = 'S1'><span>Support for accessing secondary values calculated during post processing, such as energy, mach number, and angle of attack, is also available for all versions of RocketPy greater than or equal to version 0.11.0.</span></div><div class = 'S1'><span>To showcase this, let's get the angle of attack of the rocket and plot it using MATLAB®:</span></div><div class="CodeBlock"><div class="inlineWrapper"><div class = 'S5'><span style="white-space: pre"><span >angle_of_attack = double(test_flight.angle_of_attack.source)</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span >plot(angle_of_attack(:,1), angle_of_attack(:,2)) </span><span style="color: rgb(0, 128, 19);">% First column is time (s), second is the angle of attack</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span >ylabel(</span><span style="color: rgb(167, 9, 245);">'Angle of Attack (Deg)'</span><span >)</span></span></div></div><div class="inlineWrapper"><div class = 'S6'><span style="white-space: pre"><span >xlabel(</span><span style="color: rgb(167, 9, 245);">'Time(s)'</span><span >)</span></span></div></div><div class="inlineWrapper"><div class = 'S7'><span style="white-space: pre"><span >xlim([test_flight.out_of_rail_time, 10])</span></span></div></div></div><div class = 'S1'><span>You can also convert data from other objects besides the Flight class, such as from the Environment. For example, let's say you want to get the wind velocity, both the x and y component:</span></div><div class="CodeBlock"><div class="inlineWrapper"><div class = 'S5'><span style="white-space: pre"><span >wind_velocity_x = double(env.wind_velocity_x.source) </span><span style="color: rgb(0, 128, 19);">% First column is altitude (ASL m), while the second one is the speed (m/s)</span></span></div></div><div class="inlineWrapper"><div class = 'S7'><span style="white-space: pre"><span >wind_velocity_y = double(env.wind_velocity_y.source) </span><span style="color: rgb(0, 128, 19);">% First column is altitude (ASL m), while the second one is the speed (m/s)</span></span></div></div></div><h2 class = 'S8'><span>Time to Fly!</span></h2><div class = 'S1'><span>This is all you need to get started using RocketPy in MATLAB®! Now it is time to play around and create amazing rockets. Have a great launch!</span></div>
<br>
<!--
##### SOURCE BEGIN #####
%% Getting Started with RocketPy in MATLAB®
% In this Live Script, you will learn how to run RocketPy using the MATLAB®
% environment.
%
% First things first: clone/download RocketPy's repository and set it as your
% MATLAB® working directory so that you can run this live script without any issues.
%
% After that, we start by configuring our Python environment. You can do so
% by following the guidelines presented in the MATLAB® documentation: <https://www.mathworks.com/help/matlab/matlab_external/install-supported-python-implementation.html?searchHighlight=python&s_tid=srchtitle_python_4
% Configure Your System to Use Python - MATLAB & Simulink (mathworks.com)>.
%
% Once the Python environment is configured, RocketPy needs to installed using
% |pip| as outlined in RocketPy's documentation: <https://docs.rocketpy.org/en/latest/user/installation.html#quick-install-using-pip
% Installation — RocketPy documentation>.
%
% Finally, all the prerequisites are complete and you can comeback to MATLAB®!
% We just need to set the execution mode as out of process and start working.
% MATLAB® can run Python scripts and functions in a separate process. Running
% Python in a separate process enables you to:
%%
% * Use some third-party libraries in the Python code that are not compatible
% with MATLAB®.
% * Isolate the MATLAB® process from crashes in the Python code.
pyenv('ExecutionMode','OutOfProcess');
%%
% Note: if MATLAB® is not able to find Python automatically, you may have to
% run the command line above including a path to the Python exectuable installed
% on your computer:
% pyenv('ExecutionMode','OutOfProcess', 'Version', '/path/to/python/executable');
%%
% Now, we will go through a simplified rocket trajectory simulation to get you
% started. Let's start by importing the rocketpy module and its classes.
rocketpy = py.importlib.import_module('rocketpy');
Environment = rocketpy.environment.Environment;
SolidMotor = rocketpy.motors.solid_motor.SolidMotor;
Rocket = rocketpy.rocket.Rocket;
Flight = rocketpy.simulation.flight.Flight;
%% Setting Up a Simulation
% Creating an Environment for Spaceport America
% rocketpy.Environment(latitude, longitude, elevation);
env = Environment(pyargs(...
'latitude', 32.990254, ...
'longitude',-106.974998, ...
'elevation', 1400 ...
));
%%
% To get weather data from the GFS forecast, available online, we run the following
% lines.
%
% First, we set tomorrow's date.
Tomorrow = datetime('tomorrow');
env.set_date({int32(Tomorrow.Year), int32(Tomorrow.Month), int32(Tomorrow.Day), int32(12)}) % Hour given in UTC time (noon UTC)
%%
% Now, we tell our Environment object to retrieve a weather forecast for our
% specified location and date using GFS:
env.set_atmospheric_model(pyargs( ...
'type', "Forecast", ...
'file', "GFS" ...
))
%%
% We can see what the weather will look like by calling the info method!
env.info()
%%
% Plots will open in a separate window, so be sure to run this last cell to
% see them!
%% Creating a Motor
% A solid rocket motor is used in this case. To create a motor, the SolidMotor
% class is used and the required arguments are given.
%
% The SolidMotor class requires the user to have a thrust curve ready. This
% can come either from a .eng file for a commercial motor, such as below, or a
% .csv file from a static test measurement.
%
% Besides the thrust curve, other parameters such as grain properties and nozzle
% dimensions must also be given.
Pro75M1670 = SolidMotor(pyargs( ...
'thrust_source', "../../data/motors/cesaroni/Cesaroni_M1670.eng", ...
'dry_mass', 1.815, ...
'dry_inertia', py.tuple({0.125, 0.125, 0.002}), ...
'nozzle_radius', 33 / 1000, ...
'grain_number', int32(5), ...
'grain_density', 1815, ...
'grain_outer_radius', 33 / 1000, ...
'grain_initial_inner_radius', 15 / 1000, ...
'grain_initial_height', 120 / 1000, ...
'grain_separation', 5 / 1000, ...
'grains_center_of_mass_position', -0.85704, ...
'center_of_dry_mass_position', 0.317, ...
'nozzle_position', 0, ...
'burn_time', 3.9, ...
'throat_radius', 11 / 1000, ...
'interpolation_method', "linear", ...
'coordinate_system_orientation', "nozzle_to_combustion_chamber" ...
));
%%
% To see what our thrust curve looks like, along with other import properties,
% we invoke the info method yet again. You may try the all_info method if you
% want more information all at once!
Pro75M1670.info()
%%
% Plots will open in a separate window, so be sure to run this last cell to
% see them!
%% Creating a Rocket
% A rocket is composed of several components. Namely, we must have a motor (good
% thing we have the Pro75M1670 ready), a couple of aerodynamic surfaces (nose
% cone, fins and tail) and parachutes (if we are not launching a missile).
%
% Let's start by initializing our rocket, named calisto, supplying it with the
% Pro75M1670 engine, entering its inertia properties, some dimensions and also
% its drag curves.
calisto = Rocket(pyargs( ...
'radius', 127 / 2000, ...
'mass', 14.426, ...
'inertia', py.tuple({6.321, 6.321, 0.0334}), ...
'power_off_drag', "../../data/rockets/calisto/powerOffDragCurve.csv", ...
'power_on_drag', "../../data/rockets/calisto/powerOnDragCurve.csv", ...
'center_of_mass_without_motor', 0, ...
'coordinate_system_orientation', "tail_to_nose" ...
));
Rocket.set_rail_buttons(pyargs( ...
'self', calisto, ...
'upper_button_position', 0.0818, ...
'lower_button_position', -0.618, ...
'angular_position', 45 ...
));
Rocket.add_motor(pyargs( ...
'self', calisto, ...
'motor', Pro75M1670, ...
'position', -1.255 ...
));
% Adding Aerodynamic Surfaces
% Now we define the aerodynamic surfaces. They are really straight forward.
nosecone = Rocket.add_nose(pyargs( ...
'self', calisto, ...
'length', 0.55829, ...
'kind', "von karman", ...
'position', 1.278 ...
));
fin_set = Rocket.add_trapezoidal_fins(pyargs( ...
'self', calisto, ...
'n', int32(4), ...
'span', 0.110, ...
'root_chord', 0.120, ...
'tip_chord', 0.060, ...
'position', -1.04956 ...
));
tail = Rocket.add_tail(pyargs( ...
'self', calisto, ...
'top_radius', 0.0635, ...
'bottom_radius', 0.0435, ...
'length', 0.060, ...
'position', -1.194656 ...
));
% Adding Parachutes
% Finally, we have parachutes! calisto will have two parachutes, Drogue and
% Main.
%
% Both parachutes are activated by some special algorithm, which is usually
% really complex and a trade secret. Most algorithms are based on pressure sampling
% only, while some also use acceleration info.
%
% RocketPy allows you to define a trigger function which will decide when to
% activate the ejection event for each parachute. This trigger function is supplied
% with pressure measurement at a predefined sampling rate. This pressure signal
% is usually noisy, so artificial noise parameters can be given. Call
% py.help(Rocket.add_parachute)
%%
% for more details. Furthermore, the trigger function also receives the complete
% state vector of the rocket, allowing us to use velocity, acceleration or even
% attitude to decide when the parachute event should be triggered.
%
% Here, we define our trigger functions rather simply using Python. Unfortunately,
% defining these with MATLAB® code is not yet possible.
% Drogue parachute is triggered when vertical velocity is negative, i.e. rocket is falling past apogee
drogue_trigger = py.eval("lambda p, y: y[5] < 0", py.dict);
% Main parachute is triggered when vertical velocity is negative and altitude is below 800 AGL
main_trigger = py.eval("lambda p, y: (y[5] < 0) and (y[2] < 800 + 1400)", py.dict);
%%
% Now we add both the drogue and the main parachute to our rocket.
Main = Rocket.add_parachute(pyargs( ...
'self', calisto, ...
'name', "Main", ...
'cd_s', 10.0, ...
'trigger', main_trigger, ...
'sampling_rate', 105, ...
'lag', 1.5, ...
'noise', py.tuple({0, 8.3, 0.5}) ...
));
Drogue = Rocket.add_parachute(pyargs( ...
'self', calisto, ...
'name', "Drogue", ...
'cd_s', 1.0, ...
'trigger', drogue_trigger, ...
'sampling_rate', 105, ...
'lag', 1.5, ...
'noise', py.tuple({0, 8.3, 0.5}) ...
));
%%
% |Just be careful if you run this last cell multiple times! If you do so, your
% rocket will end up with lots of parachutes which activate together, which may
% cause problems during the flight simulation. We advise you to re-run all cells
% which define our rocket before running this, preventing unwanted old parachutes.
% Alternatively, you can run the following lines to remove parachutes.|
% calisto.parachutes.remove(Drogue)
% calisto.parachutes.remove(Main)
%% |Simulating a Flight|
% |Simulating a flight trajectory is as simple as initializing a Flight class
% object givin the rocket and environnement set up above as inputs. The launch
% rail inclination and heading are also given here.|
test_flight = Flight(pyargs(...
'rocket', calisto, ...
'environment',env, ...
'rail_length', 5.2, ...
'inclination', 85, ...
'heading', 0 ...
));
%% |Analyzing the Results|
% |RocketPy gives you many plots, thats for sure! They are divided into sections
% to keep them organized. Alternatively, see the Flight class documentation to
% see how to get plots for specific variables only, instead of all of them at
% once.|
test_flight.all_info()
%%
% Plots will open in a separate window, so be sure to run this last cell to
% see them!
%% Working with Data Generated by RocketPy in MATLAB®
% You can access the entire trajectory solution matrix with the following line
% of code. The returned matrix contain the following columns: time $t$ (s), $x$
% (m), $y$ (m), $z$ (m), $v_x$ (m/s), $v_y$ (m/s), $v_z$ (m/s), $q_0$, $q_1$,
% $q_2$, $q_3$, $\omega_1$ (rad/s), $\omega_2$ (rad/s), $\omega_3$ (rad/s).
solution_matrix = double(py.numpy.array(test_flight.solution))
%%
% Support for accessing secondary values calculated during post processing,
% such as energy, mach number, and angle of attack, is also available for all
% versions of RocketPy greater than or equal to version 0.11.0.
%
% To showcase this, let's get the angle of attack of the rocket and plot it
% using MATLAB®:
angle_of_attack = double(test_flight.angle_of_attack.source)
plot(angle_of_attack(:,1), angle_of_attack(:,2)) % First column is time (s), second is the angle of attack
ylabel('Angle of Attack (Deg)')
xlabel('Time(s)')
xlim([test_flight.out_of_rail_time, 10])
%%
% You can also convert data from other objects besides the Flight class, such
% as from the Environment. For example, let's say you want to get the wind velocity,
% both the x and y component:
wind_velocity_x = double(env.wind_velocity_x.source) % First column is altitude (ASL m), while the second one is the speed (m/s)
wind_velocity_y = double(env.wind_velocity_y.source) % First column is altitude (ASL m), while the second one is the speed (m/s)
%% Time to Fly!
% This is all you need to get started using RocketPy in MATLAB®! Now it is time
% to play around and create amazing rockets. Have a great launch!
##### SOURCE END #####
-->
</div></body></html>