Skip to content

Commit 98aa3d4

Browse files
author
Lukasz Krawczyk
committed
Improve plotting and ground path generation, code refactorization
1 parent fa848ec commit 98aa3d4

11 files changed

+1300
-549
lines changed

README.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@ High precision satellite orbit simulation based on [skyfield](http://rhodesmill.
99
- Output ground path in CSV
1010
- Generate animations
1111

12-
**Example:**
12+
## Examples
1313

14-
[orbit_simulator.ipynb](./orbit_simulator.ipynb)
14+
- [ground_path_simulation.ipynb](./ground_path_simulation.ipynb)
15+
- [visualization.ipynb](./visualization.ipynb)
16+
- [animation.ipynb](./animation.ipynb)
17+
- [custom_satellites.ipynb](./custom_satellites.ipynb)
18+
19+
## Sources
20+
21+
- https://en.wikipedia.org/wiki/Simplified_perturbations_models
22+
- http://rhodesmill.org/skyfield/
23+
- https://en.wikipedia.org/wiki/Terminator_%28solar%29
24+
- https://github.com/SciTools/cartopy

animation.ipynb

Lines changed: 361 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,361 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# Animation"
8+
]
9+
},
10+
{
11+
"cell_type": "code",
12+
"execution_count": 1,
13+
"metadata": {},
14+
"outputs": [],
15+
"source": [
16+
"import os\n",
17+
"from skyfield.api import load\n",
18+
"from ground_path import ground_path\n",
19+
"from tqdm import tqdm\n",
20+
"from subprocess import Popen, PIPE\n",
21+
"import pandas as pd\n",
22+
"from plotting import plot_ground_path\n",
23+
"from ground_path import ground_path\n",
24+
"import matplotlib.pyplot as plt\n",
25+
"import cartopy\n",
26+
"import matplotlib.gridspec as gridspec"
27+
]
28+
},
29+
{
30+
"cell_type": "markdown",
31+
"metadata": {},
32+
"source": [
33+
"### Load data"
34+
]
35+
},
36+
{
37+
"cell_type": "code",
38+
"execution_count": 2,
39+
"metadata": {},
40+
"outputs": [
41+
{
42+
"name": "stderr",
43+
"output_type": "stream",
44+
"text": [
45+
"[#################################] 100% tle.txt\n"
46+
]
47+
},
48+
{
49+
"name": "stdout",
50+
"output_type": "stream",
51+
"text": [
52+
"EarthSatellite 'HODOYOSHI-1' number=40299 epoch=2018-08-06T18:53:38Z\n"
53+
]
54+
}
55+
],
56+
"source": [
57+
"resource_url = 'http://celestrak.com/NORAD/elements/resource.txt'\n",
58+
"\n",
59+
"fname = 'tle.txt'\n",
60+
"if os.path.isfile(fname):\n",
61+
" os.remove(fname)\n",
62+
"\n",
63+
"satellites = load.tle(resource_url, filename=fname, reload=True)\n",
64+
"satellite = satellites['HODOYOSHI-1']\n",
65+
"print(satellite)"
66+
]
67+
},
68+
{
69+
"cell_type": "code",
70+
"execution_count": 3,
71+
"metadata": {},
72+
"outputs": [
73+
{
74+
"name": "stderr",
75+
"output_type": "stream",
76+
"text": [
77+
"100%|██████████| 1441/1441 [00:02<00:00, 611.47it/s]\n"
78+
]
79+
},
80+
{
81+
"data": {
82+
"text/html": [
83+
"<div>\n",
84+
"<style scoped>\n",
85+
" .dataframe tbody tr th:only-of-type {\n",
86+
" vertical-align: middle;\n",
87+
" }\n",
88+
"\n",
89+
" .dataframe tbody tr th {\n",
90+
" vertical-align: top;\n",
91+
" }\n",
92+
"\n",
93+
" .dataframe thead th {\n",
94+
" text-align: right;\n",
95+
" }\n",
96+
"</style>\n",
97+
"<table border=\"1\" class=\"dataframe\">\n",
98+
" <thead>\n",
99+
" <tr style=\"text-align: right;\">\n",
100+
" <th></th>\n",
101+
" <th>elevation</th>\n",
102+
" <th>lon</th>\n",
103+
" <th>lat</th>\n",
104+
" <th>orbit</th>\n",
105+
" <th>X</th>\n",
106+
" <th>Y</th>\n",
107+
" <th>Z</th>\n",
108+
" </tr>\n",
109+
" <tr>\n",
110+
" <th>datetime</th>\n",
111+
" <th></th>\n",
112+
" <th></th>\n",
113+
" <th></th>\n",
114+
" <th></th>\n",
115+
" <th></th>\n",
116+
" <th></th>\n",
117+
" <th></th>\n",
118+
" </tr>\n",
119+
" </thead>\n",
120+
" <tbody>\n",
121+
" <tr>\n",
122+
" <th>2018-08-01 00:00:00</th>\n",
123+
" <td>499.230718</td>\n",
124+
" <td>-31.446707</td>\n",
125+
" <td>64.790392</td>\n",
126+
" <td>0</td>\n",
127+
" <td>413.215323</td>\n",
128+
" <td>-2909.273962</td>\n",
129+
" <td>6198.663736</td>\n",
130+
" </tr>\n",
131+
" <tr>\n",
132+
" <th>2018-08-01 00:01:00</th>\n",
133+
" <td>499.578778</td>\n",
134+
" <td>-34.793866</td>\n",
135+
" <td>68.392579</td>\n",
136+
" <td>0</td>\n",
137+
" <td>222.727486</td>\n",
138+
" <td>-2530.886132</td>\n",
139+
" <td>6371.367487</td>\n",
140+
" </tr>\n",
141+
" <tr>\n",
142+
" <th>2018-08-01 00:02:00</th>\n",
143+
" <td>499.878571</td>\n",
144+
" <td>-39.293342</td>\n",
145+
" <td>71.914512</td>\n",
146+
" <td>0</td>\n",
147+
" <td>31.254193</td>\n",
148+
" <td>-2141.301213</td>\n",
149+
" <td>6515.803948</td>\n",
150+
" </tr>\n",
151+
" <tr>\n",
152+
" <th>2018-08-01 00:03:00</th>\n",
153+
" <td>500.119329</td>\n",
154+
" <td>-45.714047</td>\n",
155+
" <td>75.299764</td>\n",
156+
" <td>0</td>\n",
157+
" <td>-160.357438</td>\n",
158+
" <td>-1742.243180</td>\n",
159+
" <td>6631.333473</td>\n",
160+
" </tr>\n",
161+
" <tr>\n",
162+
" <th>2018-08-01 00:04:00</th>\n",
163+
" <td>500.292291</td>\n",
164+
" <td>-55.537856</td>\n",
165+
" <td>78.429194</td>\n",
166+
" <td>0</td>\n",
167+
" <td>-351.259742</td>\n",
168+
" <td>-1335.477706</td>\n",
169+
" <td>6717.444445</td>\n",
170+
" </tr>\n",
171+
" </tbody>\n",
172+
"</table>\n",
173+
"</div>"
174+
],
175+
"text/plain": [
176+
" elevation lon lat orbit X \\\n",
177+
"datetime \n",
178+
"2018-08-01 00:00:00 499.230718 -31.446707 64.790392 0 413.215323 \n",
179+
"2018-08-01 00:01:00 499.578778 -34.793866 68.392579 0 222.727486 \n",
180+
"2018-08-01 00:02:00 499.878571 -39.293342 71.914512 0 31.254193 \n",
181+
"2018-08-01 00:03:00 500.119329 -45.714047 75.299764 0 -160.357438 \n",
182+
"2018-08-01 00:04:00 500.292291 -55.537856 78.429194 0 -351.259742 \n",
183+
"\n",
184+
" Y Z \n",
185+
"datetime \n",
186+
"2018-08-01 00:00:00 -2909.273962 6198.663736 \n",
187+
"2018-08-01 00:01:00 -2530.886132 6371.367487 \n",
188+
"2018-08-01 00:02:00 -2141.301213 6515.803948 \n",
189+
"2018-08-01 00:03:00 -1742.243180 6631.333473 \n",
190+
"2018-08-01 00:04:00 -1335.477706 6717.444445 "
191+
]
192+
},
193+
"execution_count": 3,
194+
"metadata": {},
195+
"output_type": "execute_result"
196+
}
197+
],
198+
"source": [
199+
"# generate ground path\n",
200+
"df = ground_path(satellite, '2018-08-01T00:00:00', '2018-08-02T00:00:00', '1min')\n",
201+
"df.head()"
202+
]
203+
},
204+
{
205+
"cell_type": "markdown",
206+
"metadata": {},
207+
"source": [
208+
"### Create frames"
209+
]
210+
},
211+
{
212+
"cell_type": "code",
213+
"execution_count": 4,
214+
"metadata": {},
215+
"outputs": [],
216+
"source": [
217+
"frames_directory = './frames'\n",
218+
"if not os.path.exists(frames_directory):\n",
219+
" os.makedirs(frames_directory)"
220+
]
221+
},
222+
{
223+
"cell_type": "code",
224+
"execution_count": 5,
225+
"metadata": {},
226+
"outputs": [
227+
{
228+
"name": "stderr",
229+
"output_type": "stream",
230+
"text": [
231+
"100%|██████████| 288/288 [01:33<00:00, 3.09it/s]\n"
232+
]
233+
}
234+
],
235+
"source": [
236+
"for i in tqdm(range(1, len(df), 5)):\n",
237+
" df_sub = df.iloc[:i]\n",
238+
" dt = df_sub.index[-1]\n",
239+
" \n",
240+
" title = \"Hodoyoshi-1\\n{:} ~ {:}\".format(df_sub.index.min(), df_sub.index.max())\n",
241+
"\n",
242+
" fig = plt.figure(figsize=(20,10))\n",
243+
" # map projection\n",
244+
" projection0 = cartopy.crs.PlateCarree()\n",
245+
" # object transformation\n",
246+
" transform = cartopy.crs.PlateCarree()\n",
247+
" ax0 = fig.add_subplot(1,1,1, projection=projection0)\n",
248+
" plot_ground_path(ax0, df_sub, title, transform=transform, daynight=True, legend=True)\n",
249+
" plt.savefig(frames_directory + '/hodoyoshi1_{:%Y%m%d%H%M%S}.jpg'.format(dt))\n",
250+
" plt.cla() # Clear axis\n",
251+
" plt.clf() # Clear figure\n",
252+
" plt.close() # Close a figure window"
253+
]
254+
},
255+
{
256+
"cell_type": "markdown",
257+
"metadata": {},
258+
"source": [
259+
"### Create video"
260+
]
261+
},
262+
{
263+
"cell_type": "code",
264+
"execution_count": 6,
265+
"metadata": {},
266+
"outputs": [],
267+
"source": [
268+
"def make_video(in_dir, out_dir):\n",
269+
" p = Popen(['./make_video.sh \"{:}\" \"{:}\"'.format(in_dir, out_dir)], stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=True)\n",
270+
" output, err = p.communicate()\n",
271+
" print(p.returncode)\n",
272+
" #print(output.decode('utf-8'), err.decode('utf-8'))\n",
273+
" del p\n",
274+
" return None"
275+
]
276+
},
277+
{
278+
"cell_type": "code",
279+
"execution_count": 7,
280+
"metadata": {},
281+
"outputs": [],
282+
"source": [
283+
"videos_directory = './videos'\n",
284+
"if not os.path.exists(videos_directory):\n",
285+
" os.makedirs(videos_directory)"
286+
]
287+
},
288+
{
289+
"cell_type": "code",
290+
"execution_count": 8,
291+
"metadata": {},
292+
"outputs": [
293+
{
294+
"name": "stdout",
295+
"output_type": "stream",
296+
"text": [
297+
"0\n"
298+
]
299+
}
300+
],
301+
"source": [
302+
"make_video(frames_directory + '/hodoyoshi1_*.jpg', videos_directory + '/hodoyoshi1.mp4')"
303+
]
304+
},
305+
{
306+
"cell_type": "code",
307+
"execution_count": 9,
308+
"metadata": {},
309+
"outputs": [
310+
{
311+
"data": {
312+
"text/html": [
313+
"<video controls>\n",
314+
" <source src=\"./videos/hodoyoshi1.mp4\" type=\"video/mp4\">\n",
315+
"</video>"
316+
],
317+
"text/plain": [
318+
"<IPython.core.display.HTML object>"
319+
]
320+
},
321+
"metadata": {},
322+
"output_type": "display_data"
323+
}
324+
],
325+
"source": [
326+
"%%HTML\n",
327+
"<video controls>\n",
328+
" <source src=\"./videos/hodoyoshi1.mp4\" type=\"video/mp4\">\n",
329+
"</video>"
330+
]
331+
},
332+
{
333+
"cell_type": "code",
334+
"execution_count": null,
335+
"metadata": {},
336+
"outputs": [],
337+
"source": []
338+
}
339+
],
340+
"metadata": {
341+
"kernelspec": {
342+
"display_name": "Python 3",
343+
"language": "python",
344+
"name": "python3"
345+
},
346+
"language_info": {
347+
"codemirror_mode": {
348+
"name": "ipython",
349+
"version": 3
350+
},
351+
"file_extension": ".py",
352+
"mimetype": "text/x-python",
353+
"name": "python",
354+
"nbconvert_exporter": "python",
355+
"pygments_lexer": "ipython3",
356+
"version": "3.6.4"
357+
}
358+
},
359+
"nbformat": 4,
360+
"nbformat_minor": 2
361+
}

0 commit comments

Comments
 (0)