Download as pdf or txt
Download as pdf or txt
You are on page 1of 65

Study and simulation of communication

links in a LEO satellite constellation


based on Link Budget calculations
Document:
Appendices

Author:

Sergi Gallardo Marquina

Director – Co-director:
Juan Jose Alins Delgado - Javier Gago Barrio

Degree:
Bachelor ’s degree in Aerospace Vehicles Engineering

Examination sesion:
Spring, 2022
Contents

Appendices 1

A Run the simulation in a new computer 1

B Python scripts 2
B.1 GUI.py . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
B.2 Constellation.py . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
B.3 Linkb.py . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
B.4 Simulation.py . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
B.5 City_data.txt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63

i
Appendix A

Run the simulation in a new


computer

To run the simulation on a new computer you need to have Python 3 installed first. If Python
3 is installed, the following Python libraries are required:
• Numpy
• Networkx
• Scipy
• PyAstronomy
• PyQt5
• vtk
With these libraries installed you only need to have the 4 Python files (gui.py, constellation.py,
simulation.py, linkb.py) saved in the same folder together with the city_data.txt document where
the ground stations are saved. And run the file gui.py from the python console.

1
Appendix B

Python scripts

This appendix shows all the necessary scripts to run the simulation.
• gui.py: The user interface code
• Constellation.py: The code in charge of generating the constellation and performing all
calculations related to satellites, ground stations and links.
• Linkb.py: Code in which the link budget equations have been implemented
• Simulation.py: Code that runs the simulation at each time instant
• City_data.txt: Ground station latitude and longitude

B.1 GUI.py
1

2 # imports
3
4 # normal python l i b s
5 import s y s
6 import math
7

8 import m u l t i p r o c e s s i n g a s mp
9 import t h r e a d i n g a s td
10
11 # engineering
12

13 # qt5 s t u f f
14 from PyQt5 . QtWidgets import QApplication , QLabel , QWidget , QPushButton
15 from PyQt5 . QtWidgets import QLineEdit , QGridLayout , QStyle , QCheckBox
16 from PyQt5 . QtWidgets import QComboBox , Q F i l e D i a l o g
17
18 from s i m u l a t i o n import S i m u l a t i o n
19
20
21 ##################################################################
22 # globals
23
24 # t h e mean r a d i u s o f t h e e a r t h i n m e t e r s a c c o r d i n g t o w i k i p e d i a
25 EARTH_RADIUS = 6371000

2
APPENDIX B. PYTHON SCRIPTS

26
27 # i f t r u e , w i l l e n a b l e c a l c u l a t i n g network l i n k −s t a t e
28 MAKE_LINKS = True
29
30 # i f you add a new network d e s i g n ( l i n k i n g method )
31 # t h i s l i s t w i l l need t o be updated f o r i t t o appear
32 # i n t h e GUI
33 NETWORK_DESIGNS = [ "SPARSE" , "+GRID" , "IDEAL" ]
34
35 # button s t y l e s :
36
37 # red , b l a c k t e x t
38 STYLE_1 = ’ QPushButton { background−c o l o r : rgba ( 2 5 5 , 5 0 , 5 0 , 1 0 ) ; c o l o r :
rgba ( 0 , 0 , 0 , 2 5 5 ) ; } ’
39
40 # green , b l a c k t e x t
41 STYLE_2 = ’ QPushButton { background−c o l o r : rgba ( 5 0 , 2 5 5 , 5 0 , 1 0 ) ; c o l o r :
rgba ( 0 , 0 , 0 , 2 5 5 ) ; } ’
42
43 # gray , b l a c k t e x t
44 STYLE_3 = ’ QPushButton { background−c o l o r : rgba ( 0 , 0 , 0 , 5 0 ) ; c o l o r : rgba
(0 ,0 ,0 ,5) ;} ’
45

46 # gray , b l a c k t e x t
47 STYLE_4 = ’ QLabel { background−c o l o r : rgba ( 2 5 5 , 2 5 5 , 0 , 1 5 0 ) ; c o l o r : rgba
(0 ,0 ,0 ,255) ;} ’
48
49 #################################################################
50

51
52 c l a s s ApplicationWindow ( QWidget ) :
53 d e f __init__ ( s e l f ) :
54 s u p e r ( ) . __init__ ( )
55 s e l f . _main = QWidget ( )
56

57 s e l f . c t x = mp. g e t _ c o n t e x t ( ’ spawn ’ )
58
59 s e l f . topGrid = QGridLayout ( s e l f )
60
61 # create input
62 s e l f . i n p u t = QGridLayout ( s e l f )
63 s e l f . makeInput ( )
64 s e l f . topGrid . addLayout ( s e l f . input , 0 , 0 )
65
66 # c r e a t e c o n t r o l s box
67 s e l f . c o n t r o l s = QGridLayout ( s e l f )
68 s e l f . makeControls ( )
69 s e l f . topGrid . addLayout ( s e l f . c o n t r o l s , 1 , 0 )
70
71 s e l f . makeConstellation ()
72
73 def closeEvent ( s e l f , event ) :
74 print ( " c a l l e d c l o s e func " )
75 try :
76 s e l f . vtkProcess . terminate ()
77 except AttributeError :

Polytechnic University of Catalonia - Barcelona Tech - UPC 3


APPENDIX B. PYTHON SCRIPTS

78 print ( " Exiting . . . " )


79 e x c e p t EOFError :
80 print ( " Exiting . . . " )
81 event . accept ( )
82
83 d e f makeInput ( s e l f ) :
84 s e l f . input . setSpacing (5) # s p a c e between f i e l d s
85
86 self . p l a n e s L a b e l = QLabel ( " Number o f P l a n e s : " )
87 self . p l a n e s E d i t = QLineEdit ( " 12 " )
88 self . planesEdit . setToolTip ( ’ i n t ’ )
89 self . i n p u t . addWidget ( s e l f . p l a n e s L a b e l , 1 , 0 )
90 self . i n p u t . addWidget ( s e l f . p l a n e s E d i t , 1 , 1 )
91
92 self . n o d e s L a b e l = QLabel ( " Number o f Nodes / Plane : " )
93 self . n o d e s E d i t = QLineEdit ( " 30 " )
94 self . nodesEdit . setToolTip ( " i n t " )
95 self . i n p u t . addWidget ( s e l f . nodesLabel , 2 , 0 )
96 self . i n p u t . addWidget ( s e l f . nodesEdit , 2 , 1 )
97
98 self . i n c L a b e l = QLabel ( " Plane i n c l i n a t i o n ( deg ) : " )
99 self . i n c E d i t = QLineEdit ( " 9 8 . 0 " )
100 self . incEdit . setToolTip ( ’ f l o a t ’ )
101 self . i n p u t . addWidget ( s e l f . i n c L a b e l , 3 , 0 )
102 self . i n p u t . addWidget ( s e l f . i n c E d i t , 3 , 1 )
103
104 self . smaLabel = QLabel ( " O r b i t A l t i t u d e (Km) : " )
105 self . smaEdit = QLineEdit ( s t r ( i n t ( 6 5 0 ) ) )
106 self . smaEdit . s e t T o o l T i p ( ’ i n t ’ )
107 self . i n p u t . addWidget ( s e l f . smaLabel , 4 , 0 )
108 self . i n p u t . addWidget ( s e l f . smaEdit , 4 , 1 )
109
110 ########### ISL p a r a m e t e r s ###############
111
112 s e l f . f r e c L a b e l = QLabel ( " Communication Frequency (GHz) : " )
113 s e l f . f r e c E d i t = QLineEdit ( " 2 . 2 " )
114 s e l f . f r e c E d i t . setToolTip ( ’ f l o a t ’ )
115 s e l f . i n p u t . addWidget ( s e l f . f r e c L a b e l , 5 , 0 )
116 s e l f . i n p u t . addWidget ( s e l f . f r e c E d i t , 5 , 1 )
117
118 self . powLabel = QLabel ( " T r a n s m i s s i o n Power (W) : " )
119 self . powEdit = QLineEdit ( " 2 0 . 0 " )
120 self . powEdit . s e t T o o l T i p ( ’ f l o a t ’ )
121 self . i n p u t . addWidget ( s e l f . powLabel , 6 , 0 )
122 self . i n p u t . addWidget ( s e l f . powEdit , 6 , 1 )
123

124 self . bLabel = QLabel ( " Bandwidth ( kHz ) : " )


125 self . bEdit = QLineEdit ( " 5 1 2 . 0 " )
126 self . bEdit . s e t T o o l T i p ( ’ f l o a t ’ )
127 self . i n p u t . addWidget ( s e l f . bLabel , 7 , 0 )
128 self . i n p u t . addWidget ( s e l f . bEdit , 7 , 1 )
129

130 self . n f L a b e l = QLabel ( " R e c e i v e r N o i s e F i g u r e (dB) : " )


131 self . n f E d i t = QLineEdit ( " 2 . 0 " )
132 self . nfEdit . setToolTip ( ’ f l o a t ’ )
133 self . i n p u t . addWidget ( s e l f . n f L a b e l , 8 , 0 )

Polytechnic University of Catalonia - Barcelona Tech - UPC 4


APPENDIX B. PYTHON SCRIPTS

134 s e l f . i n p u t . addWidget ( s e l f . n f E d i t , 8 , 1)
135
136 self . r s L a b e l = QLabel ( " R e c e i v e r s e n s i t i v i t y (dBm) : " )
137 self . r s E d i t = QLineEdit ( " −104.0 " )
138 self . rsEdit . setToolTip ( ’ f l o a t ’ )
139 self . i n p u t . addWidget ( s e l f . r s L a b e l , 9 , 0 )
140 self . i n p u t . addWidget ( s e l f . r s E d i t , 9 , 1 )
141
142 self . s n r L a b e l = QLabel ( "Minumum SNR (dB) : " )
143 self . s n r E d i t = QLineEdit ( " 0 . 0 " )
144 self . snrEdit . setToolTip ( ’ f l o a t ’ )
145 self . i n p u t . addWidget ( s e l f . s n r L a b e l , 1 0 , 0 )
146 self . i n p u t . addWidget ( s e l f . s n r E d i t , 1 0 , 1 )
147
148
149
150
151

152 d e f makeControls ( s e l f ) :
153 s e l f . controls . setSpacing (5) # s p a c e between b u t t o n s
154
155 # make spawn s i m u l a t i o n button
156 s e l f . g e n e r a t e B u t t o n = QPushButton ( " g e n e r a t e " )
157 s e l f . g e n e r a t e B u t t o n . s e t T o o l T i p ( " spawn a new s i m u l a t i o n p r o c e s s " )
158 s e l f . g e n e r a t e B u t t o n . s e t S t y l e S h e e t (STYLE_2)
159 s e l f . c o n t r o l s . addWidget ( s e l f . g e n e r a t e B u t t o n , 0 , 0 )
160 s e l f . g e n e r a t e B u t t o n . c l i c k e d . c o n n e c t ( s e l f . makeVTKModel )
161
162 # make k i l l s i m u l a t i o n p r o c e s s button
163 s e l f . k i l l B u t t o n = QPushButton ( " k i l l " )
164 s e l f . k i l l B u t t o n . setToolTip ( " k i l l the l a s t created simulation p r o c e s s " )
165 s e l f . k i l l B u t t o n . s e t S t y l e S h e e t (STYLE_1)
166 s e l f . c o n t r o l s . addWidget ( s e l f . k i l l B u t t o n , 0 , 1 )
167 s e l f . k i l l B u t t o n . c l i c k e d . c o n n e c t ( s e l f . killVTKModel )
168

169 # make p l a y / pause button


170 s e l f . pause = True
171 s e l f . t o g g l e P l a y B u t t o n = QPushButton ( )
172 s e l f . t o g g l e P l a y B u t t o n . s e t T o o l T i p ( " pause / run t h e s i m u l a t i o n p r o c e s s " )
173 s e l f . t o g g l e P l a y B u t t o n . s e t I c o n ( s e l f . s t y l e ( ) . s t a n d a r d I c o n ( QStyle .
SP_MediaPlay ) )
174 s e l f . t o g g l e P l a y B u t t o n . s e t S t y l e S h e e t (STYLE_3)
175 s e l f . t o g g l e P l a y B u t t o n . s e t E n a b l e d ( True )
176 s e l f . c o n t r o l s . addWidget ( s e l f . t o g g l e P l a y B u t t o n , 0 , 2 )
177 s e l f . togglePlayButton . c l i c k e d . connect ( s e l f . pauseStart )
178

179 # make import model from gml button


180 s e l f . importGMLButton = QPushButton ( " Import GML" )
181 s e l f . importGMLButton . s e t T o o l T i p ( " spawn a new s i m u l a t i o n p r o c e s s from a
GML f i l e " )
182 s e l f . importGMLButton . s e t S t y l e S h e e t (STYLE_2)
183 s e l f . c o n t r o l s . addWidget ( s e l f . importGMLButton , 0 , 3 )
184 s e l f . importGMLButton . c l i c k e d . c o n n e c t ( s e l f . genModelFromGML )
185
186 # make t i m e s t e p s e t t e r
187 s e l f . t i m e s t e p L a b e l = QLabel ( ’ Timestep ( s e c o n d s ) : ’ )

Polytechnic University of Catalonia - Barcelona Tech - UPC 5


APPENDIX B. PYTHON SCRIPTS

188 s e l f . t i m e s t e p E d i t = QLineEdit ( s t r ( i n t ( 1 0 ) ) ) # 30 s e c o n d d e f a u l t
timestep
189 s e l f . timestepEdit . setToolTip ( " i n t : simulation process timestep " )
190 s e l f . t i m e s t e p B u t t o n = QPushButton ( " s e t " )
191 s e l f . t i m e s t e p B u t t o n . s e t T o o l T i p ( " must p r e s s t o update s i m u l a t i o n " )
192 s e l f . timestepButton . c l i c k e d . connect ( s e l f . setTimestep )
193 s e l f . c o n t r o l s . addWidget ( s e l f . t i m e s t e p L a b e l , 1 , 0 )
194 s e l f . c o n t r o l s . addWidget ( s e l f . t i m e s t e p E d i t , 1 , 1 )
195 s e l f . c o n t r o l s . addWidget ( s e l f . timestepButton , 1 , 2 )
196
197 # make l a b e l t o show c u r r e n t time
198 s e l f . t i m e L a b e l = QLabel ( " Time : 0 : 0 0 : 0 0 " )
199 s e l f . t i m e L a b e l . s e t T o o l T i p ( " c u r r e n t time o f s i m u l a t i o n , updated l i v e " )
200 s e l f . t i m e L a b e l . s e t S t y l e S h e e t (STYLE_4)
201 s e l f . c o n t r o l s . addWidget ( s e l f . timeLabel , 2 , 0 )
202
203 # make checkbox f o r t o g g l e image c a p t u r e
204 s e l f . s a v e I m a g e s L a b e l = QLabel ( " Save Images : " )
205 s e l f . saveImagesCheckbox = QCheckBox ( )
206 s e l f . saveImagesCheckbox . s e t T o o l T i p ( ’ check t h i s box t o b e g i n s a v i n g
images \ npath : . / p i c s ’ )
207 s e l f . saveImagesCheckbox . stateChanged . c o n n e c t ( s e l f . t o g g l e S a v e I m a g e s )
208 s e l f . c o n t r o l s . addWidget ( s e l f . sa v e I m ag e s L a be l , 3 , 0 )
209 s e l f . c o n t r o l s . addWidget ( s e l f . saveImagesCheckbox , 3 , 1 )
210
211 # make checkbox f o r t o g g l e image c a p t u r e
212 s e l f . saveGMLSLabel = QLabel ( " Save GMLs: " )
213 s e l f . saveGMLSCheckbox = QCheckBox ( )
214 s e l f . saveGMLSCheckbox . s e t T o o l T i p ( ’ check t h i s box t o b e g i n s a v i n g GML
f i l e s \ npath : . / gmls ’ )
215 s e l f . saveGMLSCheckbox . stateChanged . c o n n e c t ( s e l f . toggleSaveGMLS )
216 s e l f . c o n t r o l s . addWidget ( s e l f . saveGMLSLabel , 4 , 0 )
217 s e l f . c o n t r o l s . addWidget ( s e l f . saveGMLSCheckbox , 4 , 1 )
218
219 # add a drop down t o s e l e c t network d e s i g n method
220 s e l f . l i n k s L a b e l = QLabel ( " Network Design : " )
221 s e l f . l i n k s S e l e c t = QComboBox ( )
222 s e l f . l i n k s S e l e c t . addItems (NETWORK_DESIGNS)
223 s e l f . l i n k s S e l e c t . a c t i v a t e d [ s t r ] . c o n n e c t ( s e l f . se tL in ki ng Me th od )
224 s e l f . c o n t r o l s . addWidget ( s e l f . l i n k s L a b e l , 5 , 0 )
225 s e l f . c o n t r o l s . addWidget ( s e l f . l i n k s S e l e c t , 5 , 1 )
226
227 # c o n t r o l s f o r r u n n i n g f o r a s e t time
228 s e l f . r u n f o r L a b e l = QLabel ( " Run For ( s e c o n d s ) : " )
229 s e l f . r u n f o r E d i t = QLineEdit ( s t r ( i n t ( 6 0 ) ) )
230 s e l f . runforEdit . setToolTip ( ’ i n t ’ )
231 s e l f . r u n f o r B u t t o n = QPushButton ( " Run ! " )
232 s e l f . r u n f o r B u t t o n . s e t T o o l T i p ( ’ c l i c k t o run t h e s i m u l a t i o n f o r a s e t
time ’ )
233 s e l f . runforButton . c l i c k e d . connect ( s e l f . setRunfor )
234 s e l f . c o n t r o l s . addWidget ( s e l f . r u n f o r L a b e l , 6 , 0 )
235 s e l f . c o n t r o l s . addWidget ( s e l f . r u n f o r E d i t , 6 , 1 )
236 s e l f . c o n t r o l s . addWidget ( s e l f . r u n f o r B u t t o n , 6 , 2 )
237
238 # s e c t i o n f o r s e t t i n g up a c o n n e c t i o n
239 s e l f . node1Label = QLabel ( " Node 1 : " )

Polytechnic University of Catalonia - Barcelona Tech - UPC 6


APPENDIX B. PYTHON SCRIPTS

240 self . n o d e 1 S e l e c t = QComboBox ( )


241 self . n o d e 1 S e l e c t . a c t i v a t e d [ s t r ] . c o n n e c t ( s e l f . setPathNode1 )
242 self . node2Label = QLabel ( " Node 2 : " )
243 self . n o d e 2 S e l e c t = QComboBox ( )
244 self . n o d e 2 S e l e c t . a c t i v a t e d [ s t r ] . c o n n e c t ( s e l f . setPathNode2 )
245 self . c a l c P a t h B u t t o n = QPushButton ( " Enable Path C a l c u l a t i o n " )
246 self . c a l c P a t h B u t t o n . s e t C h e c k a b l e ( True )
247 self . calcPathButton . c l i c k e d . connect ( s e l f . t o g g l e P a t h C a l c u l a t i o n )
248 self . c o n t r o l s . addWidget ( s e l f . node1Label , 7 , 0 )
249 self . c o n t r o l s . addWidget ( s e l f . n o d e 1 S e l e c t , 7 , 1 )
250 self . c o n t r o l s . addWidget ( s e l f . node2Label , 7 , 2 )
251 self . c o n t r o l s . addWidget ( s e l f . n o d e 2 S e l e c t , 7 , 3 )
252 self . c o n t r o l s . addWidget ( s e l f . calcPathButton , 8 , 0 )
253
254 # s e c t i o n f o r showing p e r f o r m a n c e data
255 s e l f . frameTimeLabel = QLabel ( "−−−" )
256 s e l f . modelTimeLabel = QLabel ( "−−−" )
257 s e l f . gmlTimeLabel = QLabel ( "−−−" )
258 s e l f . renderTimeLabel = QLabel ( "−−−" )
259 s e l f . imgTimeLabel = QLabel ( ’−−− ’ )
260 s e l f . maxNodeDegreeLabel = QLabel ( ’−−− ’ )
261 s e l f . totalNumLinksLabel = QLabel ( ’−−− ’ )
262 s e l f . c o n t r o l s . addWidget ( s e l f . frameTimeLabel , 1 0 , 0 )
263 s e l f . c o n t r o l s . addWidget ( s e l f . modelTimeLabel , 1 1 , 0 )
264 s e l f . c o n t r o l s . addWidget ( s e l f . renderTimeLabel , 1 2 , 0 )
265 s e l f . c o n t r o l s . addWidget ( s e l f . gmlTimeLabel , 1 3 , 0 )
266 s e l f . c o n t r o l s . addWidget ( s e l f . imgTimeLabel , 1 4 , 0 )
267 s e l f . c o n t r o l s . addWidget ( s e l f . maxNodeDegreeLabel , 1 5 , 0 )
268 s e l f . c o n t r o l s . addWidget ( s e l f . totalNumLinksLabel , 1 6 , 0 )
269
270 # a debugging t e s t button
271 s e l f . t e s t B u t t o n = QPushButton ( " t e s t " )
272 s e l f . t e s t B u t t o n . s e t T o o l T i p ( ’ a debugging t e s t button ’ )
273 s e l f . c o n t r o l s . addWidget ( s e l f . t e s t B u t t o n , 2 0 , 0 )
274 s e l f . testButton . c l i c k e d . connect ( s e l f . testFunc )
275
276 d e f genModelFromGML ( s e l f ) :
277 f i l e n a m e = Q F i l e D i a l o g . getOpenFileName ( s e l f )
278 p r i n t ( " importing the f i l e : " , filename [ 0 ] )
279
280 # make s u r e any e x i s t i n g models a r e k i l l e d
281 try :
282 s e l f . vtkProcess . terminate ()
283 except AttributeError :
284 print ( " . . . " )
285 e x c e p t EOFError :
286 print ( " . . . " )
287
288 # a p i p e t o a l l o w communication between p r o c e s s e s
289 s e l f . myPipeConn , otherPipeConn = s e l f . c t x . Pipe ( )
290 kwargsToSend = {
291 ’ pipeConn ’ : otherPipeConn ,
292 ’ animate ’ : True ,
293 ’ gmlImportFileName ’ : f i l e n a m e [ 0 ]
294 }
295 p r i n t ( kwargsToSend )

Polytechnic University of Catalonia - Barcelona Tech - UPC 7


APPENDIX B. PYTHON SCRIPTS

296
297 s e l f . v t k P r o c e s s = s e l f . c t x . P r o c e s s ( t a r g e t=S i m u l a t i o n , kwargs=
kwargsToSend )
298 s e l f . vtkProcess . s t a r t ()
299
300 # s t a r t a t h r e a d t o l i s t e n f o r s t u f f from t h e model
301 s e l f . comsThread = td . Thread ( t a r g e t= s e l f . comsThreadHandler )
302 s e l f . comsThread . s t a r t ( )
303
304 def makeConstellation ( s e l f ) :
305
306 # gen a c o n s t e l l a t i o n o b j e c t
307 p = int ( s e l f . planesEdit . text () )
308 n = i n t ( s e l f . nodesEdit . text ( ) )
309 i = f l o a t ( s e l f . incEdit . text () )
310 f =f l o a t ( s e l f . f r e c E d i t . t e x t ( ) )
311 pw= f l o a t ( s e l f . powEdit . t e x t ( ) )
312 b= f l o a t ( s e l f . bEdit . t e x t ( ) )
313 n f= f l o a t ( s e l f . n f E d i t . t e x t ( ) )
314 rs = f l o a t ( s e l f . rsEdit . text () )
315 s n r= f l o a t ( s e l f . s n r E d i t . t e x t ( ) )
316 a = f l o a t ( s e l f . smaEdit . t e x t ( ) ) ∗1000 + EARTH_RADIUS
317 ts = int ( s e l f . timestepEdit . text () )
318 s e l f . con = {
319 ’ planes ’ : p ,
320 ’ nodesPerPlane ’ : n ,
321 ’ inclination ’ : i ,
322 ’ frequency ’ : f ,
323 ’ t r a n s m i s s i o n P o w e r ’ : pw ,
324 ’ bandwidth ’ : b ,
325 ’ n o i s e F i g u r e ’ : nf ,
326 ’ r e c e i v e r S e n s i t i v i t y ’ : rs ,
327 ’ s n r ’ : snr ,
328 ’ semiMajorAxis ’ : a ,
329 ’ timeStep ’ : t s
330 }
331
332 d e f killVTKModel ( s e l f ) :
333 try :
334 s e l f . vtkProcess . terminate ()
335 e x c e p t EOFError :
336 p r i n t ( "ERROR: t r i e d t o k i l l vtk p r o c e s s , but something went wrong " )
337
338 d e f makeVTKModel ( s e l f ) :
339 # make s u r e any e x i s t i n g models a r e k i l l e d
340 try :
341 s e l f . vtkProcess . terminate ()
342 except AttributeError :
343 print ( " . . . " )
344 e x c e p t EOFError :
345 print ( " . . . " )
346

347 # be s u r e t o grab l a t e s t i n p u t params


348 s e l f . makeConstellation ()
349
350 # a p i p e t o a l l o w communication between p r o c e s s e s

Polytechnic University of Catalonia - Barcelona Tech - UPC 8


APPENDIX B. PYTHON SCRIPTS

351 s e l f . myPipeConn , otherPipeConn = s e l f . c t x . Pipe ( )


352 kwargsToSend = { ’ pipeConn ’ : otherPipeConn , ’ makeLinks ’ : MAKE_LINKS}
353 kwargsToSend . update ( s e l f . con ) # add t h e s e l f . con d i c t t o kwargs d i c t
354 s e l f . v t k P r o c e s s = s e l f . c t x . P r o c e s s ( t a r g e t=S i m u l a t i o n , kwargs=
kwargsToSend )
355 s e l f . vtkProcess . s t a r t ()
356
357 # s t a r t a t h r e a d t o l i s t e n f o r s t u f f from t h e model
358 s e l f . comsThread = td . Thread ( t a r g e t= s e l f . comsThreadHandler )
359 s e l f . comsThread . s t a r t ( )
360
361 d e f comsThreadHandler ( s e l f ) :
362 # now I j u s t l i s t e n f o r data coming
363 # back from t h e s i m u l a t i o n
364 w h i l e True :
365 try :
366 r e c v = s e l f . myPipeConn . r e c v ( )
367 i f type ( r e c v ) == s t r :
368 print ( recv )
369
370 e l i f type ( r e c v ) == l i s t :
371 command = r e c v [ 0 ]
372 i f command == " simTime " :
373 time = r e c v [ 1 ]
374 h o u r s = i n t ( time / 3 6 0 0 )
375 time = time % 3600
376 mins = i n t ( time / 6 0 )
377 s e c s = i n t ( time % 6 0 )
378 time = s t r ( h o u r s )+" : "+s t r ( mins )+" : "+s t r ( s e c s )
379 s e l f . t i m e L a b e l . s e t T e x t ( " Time : "+time )
380 e l i f command == ’ timeForFrame ’ :
381 s e l f . frameTime = r e c v [ 1 ]
382 temp = 1 . 0 / r e c v [ 1 ]
383 s e l f . frameTimeLabel . s e t T e x t ( s t r ( " %3.3 f Hz " % temp ) )
384 e l i f command == ’ timeToUpdateModel ’ :
385 temp = ( r e c v [ 1 ] / ( s e l f . frameTime ) ) ∗100
386 s e l f . modelTimeLabel . s e t T e x t ( ’ sim : %3.2 f%%’ % temp )
387 e l i f command == ’ timeToExportGML ’ :
388 temp = r e c v [ 1 ] / ( s e l f . frameTime ) ∗100
389 s e l f . gmlTimeLabel . s e t T e x t ( " gml : %3.2 f%%" % temp )
390 e l i f command == ’ timeToUpdateRender ’ :
391 temp = r e c v [ 1 ] / ( s e l f . frameTime ) ∗100
392 s e l f . renderTimeLabel . s e t T e x t ( " r e n : %3.2 f%%" % temp )
393 e l i f command == ’ timeToExportImg ’ :
394 temp = r e c v [ 1 ] / ( s e l f . frameTime ) ∗100
395 s e l f . imgTimeLabel . s e t T e x t ( " img : %3.2 f%%" % temp )
396 e l i f command == ’ maxNodeDegree ’ :
397 temp = s t r ( r e c v [ 1 ] )
398 s e l f . maxNodeDegreeLabel . s e t T e x t ( ’Max node d e g r e e : ’ + temp )
399 e l i f command == ’ totalNumberOfLinks ’ :
400 temp = s t r ( r e c v [ 1 ] )
401 s e l f . totalNumLinksLabel . s e t T e x t ( ’ T o t a l L i n k s ( e d g e s ) : ’ + temp )
402 e l i f command == ’ placeNames ’ :
403 s e l f . placenames = r e c v [ 1 ]
404 s e l f . node1Select . clear ()
405 s e l f . node2Select . clear ()

Polytechnic University of Catalonia - Barcelona Tech - UPC 9


APPENDIX B. PYTHON SCRIPTS

406 s e l f . n o d e 1 S e l e c t . addItems ( r e c v [ 1 ] )
407 s e l f . n o d e 2 S e l e c t . addItems ( r e c v [ 1 ] )
408
409 e x c e p t EOFError :
410 break
411

412 def pauseStart ( s e l f ) :


413 s e l f . pause = not s e l f . pause
414 i f not s e l f . pause :
415 s e l f . t o g g l e P l a y B u t t o n . s e t I c o n ( s e l f . s t y l e ( ) . s t a n d a r d I c o n ( QStyle .
SP_MediaPause ) )
416 else :
417 s e l f . t o g g l e P l a y B u t t o n . s e t I c o n ( s e l f . s t y l e ( ) . s t a n d a r d I c o n ( QStyle .
SP_MediaPlay ) )
418 try :
419 s e l f . myPipeConn . send ( " t o g g l e P a u s e " )
420 e x c e p t EOFError :
421 p r i n t ( ’ pause button d i d not work ’ )
422 except AttributeError :
423 p r i n t ( ’ no model t o pause . . . ’ )
424
425 def setTimestep ( s e l f ) :
426 timestep = int ( s e l f . timestepEdit . text () )
427 temp = [ " s e t T i m e s t e p " , t i m e s t e p ]
428 s e l f . myPipeConn . send ( temp )
429
430 d e f s et Li nk in gM et ho d ( s e l f , t e x t ) :
431 s e l f . myPipeConn . send ( [ " s et Li nk in gM et ho d " , t e x t ] )
432

433 def setRunfor ( s e l f ) :


434 """
435 r u n s t h e s i m u l a t i o n f o r a s e t time then s t o p s
436 """
437
438 runtime = i n t ( s e l f . r u n f o r E d i t . t e x t ( ) )
439 s e l f . pause = F a l s e
440 s e l f . t o g g l e P l a y B u t t o n . s e t I c o n ( s e l f . s t y l e ( ) . s t a n d a r d I c o n ( QStyle .
SP_MediaPause ) )
441 try :
442 s e l f . myPipeConn . send ( [ ’ s e t R u n f o r ’ , runtime ] )
443 e x c e p t EOFError :
444 p r i n t ( ’ no model ’ )
445
446 def togglePathCalculation ( s e l f ) :
447 i f s e l f . calcPathButton . isChecked ( ) :
448 try :
449 s e l f . myPipeConn . send ( " e n a b l e P a t h C a l c " )
450 e x c e p t EOFError :
451 p r i n t ( ’ no model ’ )
452 else :
453 try :
454 s e l f . myPipeConn . send ( " d i s a b l e P a t h C a l c " )
455 e x c e p t EOFError :
456 p r i n t ( ’ no model ’ )
457
458 d e f setPathNode1 ( s e l f , t e x t ) :

Polytechnic University of Catalonia - Barcelona Tech - UPC 10


APPENDIX B. PYTHON SCRIPTS

459 s e l f . myPipeConn . send ( [ " setPathNode1 " , t e x t ] )


460
461 d e f setPathNode2 ( s e l f , t e x t ) :
462 s e l f . myPipeConn . send ( [ " setPathNode2 " , t e x t ] )
463
464 d e f toggleSaveGMLS ( s e l f ) :
465 i f s e l f . saveGMLSCheckbox . i s C h e c k e d ( ) :
466 s e l f . enableGMLCapture ( )
467 else :
468 s e l f . disableGMLCapture ( )
469
470 d e f enableGMLCapture ( s e l f ) :
471 try :
472 s e l f . myPipeConn . send ( " enableGMLCapture " )
473 e x c e p t EOFError :
474 p r i n t ( ’ e n a b l e c a p t u r e d i d not work ’ )
475
476 d e f disableGMLCapture ( s e l f ) :
477 try :
478 s e l f . myPipeConn . send ( " disableGMLCapture " )
479 e x c e p t EOFError :
480 p r i n t ( " d i s a b l e c a p t u r e d i d not work " )
481

482 def toggleSaveImages ( s e l f ) :


483 i f s e l f . saveImagesCheckbox . i s C h e c k e d ( ) :
484 s e l f . enableImageCapture ( )
485 else :
486 s e l f . disableImageCapture ()
487

488 d e f enableImageCapture ( s e l f ) :
489 try :
490 s e l f . myPipeConn . send ( " enableImageCapture " )
491 e x c e p t EOFError :
492 p r i n t ( ’ e n a b l e c a p t u r e d i d not work ’ )
493

494 def disableImageCapture ( s e l f ) :


495 try :
496 s e l f . myPipeConn . send ( " d i s a b l e I m a g e C a p t u r e " )
497 e x c e p t EOFError :
498 p r i n t ( " d i s a b l e c a p t u r e d i d not work " )
499

500 def testFunc ( s e l f ) :


501 try :
502 gndNodeInfo = [ ’ newGndNode ’ , [ 1 . 0 , 0 , 0 ] ]
503 s e l f . myPipeConn . send ( gndNodeInfo )
504 e x c e p t EOFError :
505 p r i n t ( ’ t e s t button d i d not work ’ )
506
507 d e f makeGroundPoint ( s e l f ) :
508 # try :
509 lat = f l o a t ( s e l f . latEdit . text () )
510 lon = f l o a t ( s e l f . lonEdit . text () )
511 xyz = s e l f . latLonToXYZ ( l a t , l o n )
512 s e l f . myPipeConn . send ( [ ’ newGndNode ’ , xyz ] )
513
514 d e f latLonToXYZ ( s e l f , l a t , l o n ) :

Polytechnic University of Catalonia - Barcelona Tech - UPC 11


APPENDIX B. PYTHON SCRIPTS

515 x = EARTH_RADIUS ∗ math . c o s ( l a t ) ∗ math . c o s ( l o n )


516 y = EARTH_RADIUS ∗ math . c o s ( l a t ) ∗ math . s i n ( l o n )
517 z = EARTH_RADIUS ∗ math . s i n ( l a t )
518 return [ x , y , z ]
519
520

521 i f __name__ == "__main__" :


522 qt_app = Q A p p l i c a t i o n ( s y s . argv )
523 app = ApplicationWindow ( )
524 app . show ( )
525 qt_app . exec_ ( )

B.2 Constellation.py
1 import l i n k b # import l i n k budget f u n c t i o n s
2 # g o t t a have numpy
3 import numpy a s np
4
5 # used t o c a l c u l a t e k e p l e r 2 body o r b i t s
6 from PyAstronomy import p y a s l
7

8 import math
9
10 import networkx a s nx
11
12
13 # XXX: Plathon −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
14
15 LATITUDE_NORTH_THRESHOLD = 6 5 . 0
16 LATITUDE_SOUTH_THRESHOLD = −65.0
17 RAAN = 1 8 0 . 0
18 K= −228.6 # Boltzmman c o n s t a n t
19

20 SPEED_OF_LIGHT_M_PER_S = 2 9 9 7 9 2 4 5 8 . 0
21 PLATHON_DEBUG = 0
22 PRINT_RTT = 1
23 LATITUDE_DEBUG = 0
24 ANTENNA={
25 0:10.093 ,1:10.0881 ,2:10.0756 ,3:10.0554 ,4:10.0275 ,5:9.992 ,6:9.9488 ,
26 7:9.8979 , 8:9.8393 ,9:9.7731 ,10:9.6992 ,11:9.6176 ,12:9.5284 ,13:9.4315 ,
27 14:9.327 ,15:9.2149 ,16:9.0951 ,17:8.9677 ,18:8.8326 ,19:8.69 , 20:8.5397 ,
28 21:8.3819 ,22:8.2164 ,23:8.0434 ,24:7.8628 ,25:7.6746 ,26:7.4789 ,27:7.2755 ,
29 28:7.0647 ,29:6.8462 ,30:6.6202 ,31:6.3866 ,32:6.1455 ,33:5.8968 ,34:5.6404 ,
30 35:5.3765 ,36:5.105 ,37:4.8258 ,38:4.5389 ,39:4.2444 ,40:3.9421 ,41:3.632 ,
31 42:3.3141 ,43:2.9883 ,44:2.6546 ,45:2.3128 ,46:1.9629 ,47:1.6047 ,48:1.2382 ,
32 49:0.8633 ,50:0.4798 ,51:0.0874 ,52: −0.3139 ,53: −0.7243 ,54: −1.1442 ,
33 55: −1.5738 ,56: −2.0134 ,57: −2.4633 ,58: −2.9239 ,59: −3.3957 ,60: −3.8792 ,
34 61: −4.375 ,62: −4.8836 ,63: −5.4059 ,64: −5.9426 ,65: −6.4948 ,66: −7.0636 ,
35 67: −7.6503 ,68: −8.2564 ,69: −8.8836 ,70: −9.5339 ,71: −10.2098 ,72: −10.9142 ,
36 73: −11.6503 ,74: −12.4223 ,75: −13.235 ,76: −14.0944 ,77: −15.0078 ,78: −15.9842 ,
37 79: −17.035 ,80: −18.1741 ,81: −19.4193 ,82: −20.7917 ,83: −22.3154 ,84: −24.0094 ,

Polytechnic University of Catalonia - Barcelona Tech - UPC 12


APPENDIX B. PYTHON SCRIPTS

38 85: −25.8627 ,86: −27.7523 ,87: −29.27 ,88: −29.7186 ,89: −28.8856 ,90: −27.3843
39 }
40
41 ANTENNA_GS= {
42 0:12.3862 ,1:12.3654 ,2:12.3159 ,3:12.2375 ,4:12.13 ,5:11.9932 ,6:11.827 ,
43 7:11.6311 ,8: 11.405 ,9:11.1485 ,10:10.861 ,11:10.542 ,12:10.1909 ,
44 13:9.8071 ,14:9.3899 ,15:8.9385 ,16:8.452 ,17:7.9296 ,18:7.3704 ,
45 19:6.7736 ,20:6.1387 ,21:5.4651 ,22:4.7532 ,23:4.0039 ,24:3.2196 ,25:2.405 ,
46 26:1.5678 ,27:0.7203 ,28: −0.1187 ,29: −0.9231 ,30: −1.6594 ,31: −2.2894 ,
47 32: −2.7774 ,33: −3.0997 ,34: −3.253 ,35: −3.2551 ,36: −3.1387 ,37: −2.9413 ,
48 38: −2.6977 ,39: −2.4356 ,40: −2.1747 ,41: −1.9284 ,42: −1.7049 ,43: −1.509 ,
49 44: −1.3428 ,45: −1.207 ,46: −1.1013 ,47: −1.0249 ,48: −0.9765 ,49: −0.9547 ,
50 50: −0.958 ,51: −0.9848 ,52: −1.0338 ,53: −1.1034 ,54: −1.1924 ,55: −1.2995 ,
51 56: −1.4234 ,57: −1.563 ,58: −1.7172 ,59: −1.8851 ,60: −2.0658 ,61: −2.2583 ,
52 62: −2.4618 ,63: −2.6757 ,64: −2.8991 ,65: −3.1315 ,66: −3.3723 ,67: −3.6209 ,
53 68: −3.8767 ,69: −4.1395 ,70: −4.4086 ,71: −4.6838 ,72: −4.9647 ,73: −5.251 ,
54 74: −5.5424 ,75: −5.8387 ,76: −6.1397 ,77: −6.4452 ,78: −6.7552 ,79: −7.0694 ,
55 80: −7.3879 ,81: −7.7106 ,82: −8.0375 ,83: −8.3686 ,84: −8.704 ,85: −9.0437 ,
56 86: −9.3879 ,87: −9.7366 ,88: −10.09 ,89: −10.4483 ,90: −10.8117
57 }
58
59 # XXX: End Plathon −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
60

61
62 # t r y t o import numba f u n c s
63 try :
64 import numba
65 USING_NUMBA = F a l s e
66 e x c e p t ModuleNotFoundError :
67 USING_NUMBA = F a l s e
68 p r i n t ( " you p r o b a b l y do not have numba i n s t a l l e d . . . " )
69 p r i n t ( " r e v e r t i n g t o non−numba mode " )
70
71 PRINT_LEVEL = 0 # t h e h i g h e r t h e number , t h e more s t u f f p r i n t e d
72

73 def print_plathon () :
74 p r i n t ( " Plathon p a r a m e t e r s −−−−−−−−−−−−−−−−−−−−−−−" )
75 p r i n t ( " L a t i t u d e t h r e s h o l d s d e g r e e s ( North / South ) : %.2 f /%.2 f " % (
LATITUDE_NORTH_THRESHOLD, LATITUDE_SOUTH_THRESHOLD) )
76
77

78 d e f s d o u t ( l e v e l =0, ∗ a r g s ) :
79 " " " a p r i n t f u n c t i o n ; c h o o s e s t o p r i n t based on PRINT_LEVEL
80
81 Parameters
82 −−−−−−−−−−
83 level : int
84 p r i n t _ l e v e l , h i g h e r = more p r i n t i n g
85 args :
86 the s t u f f to p r i n t
87
88 Returns
89 −−−−−−−
90 None
91 """
92

Polytechnic University of Catalonia - Barcelona Tech - UPC 13


APPENDIX B. PYTHON SCRIPTS

93 i f l e v e l <= PRINT_LEVEL:
94 toPrint = ’ ’
95 f o r arg in args :
96 t o P r i n t += s t r ( a r g )
97 print ( toPrint )
98 r e t u r n None
99
100
101 # t h e mean r a d i u s o f t h e e a r t h i n m e t e r s a c c o r d i n g t o w i k i p e d i a
102 EARTH_RADIUS = 6371000
103
104 # e a r t h ’ s z a x i s ( eg a v e c t o r i n t h e p o s i t i v e z d i r e c t i o n )
105 EARTH_ROTATION_AXIS = [ 0 , 0 , 1 ]
106
107 # number o f s e c o n d s p e r e a r t h r o t a t i o n ( day )
108 SECONDS_PER_DAY = 86400
109
110 # according to wikipedia
111 STD_GRAVITATIONAL_PARAMATER_EARTH = 3 . 9 8 6 0 0 4 4 1 8 e14
112
113 # how b i g t o i n i t i a l i z e t h e ground p o i n t a r r a y . . .
114 NUM_GROUND_POINTS = 0
115

116 # The numpy data type used t o s t o r e s a t e l l i t e data


117 # n o t e u s e o f i n t 1 6 f o r names : max number o f s a t e l l i t e s = ( 2 ^ 1 5 )−1
118 # n o t e u s e o f i n t 3 2 f o r p o s i t i o n : max pos v a l u e = ( 2 ^ 3 1 )−1 m e t e r s
119 # ( t h i s i s 5 . 5 t i m e s t h e d i s t a n c e t o t h e moon
120 # and s h o u l d be f i n e f o r e a r t h o r b i t s i m u l a t i o n )
121 # Note t h a t f i e l d s can be a c c e s s e d by t h e i r name : a r r a y [ i d x ] [ ’ ID ’ ]
122 SATELLITE_DTYPE = np . dtype ( [
123 ( ’ ID ’ , np . i n t 1 6 ) , # ID number , unique , = a r r a y i n d e x
124 ( ’ plane_number ’ , np . i n t 1 6 ) , # which o r b i t a l p l a n e i s t h e s a t e l l i t e i n ?
125 ( ’ offset_number ’ , np . i n t 1 6 ) , # What s a t e l l i t e withen t h e p l a n e ?
126 ( ’ t i m e _ o f f s e t ’ , np . f l o a t 3 2 ) , # time o f f s e t f o r k e p l e r e l l i p s e s o l v e r
127 ( ’ x ’ , np . i n t 3 2 ) , # x p o s i t i o n in meters
128 ( ’ y ’ , np . i n t 3 2 ) , # y p o s i t i o n in meters
129 ( ’ z ’ , np . i n t 3 2 ) , # z p o s i t i o n in meters
130 ( ’ vx ’ , np . i n t 3 2 ) , # vx v e l o c i t y i n m/ s
131 ( ’ vy ’ , np . i n t 3 2 ) , # vy v e l o c i t y i n m/ s
132 ( ’ vz ’ , np . i n t 3 2 ) ] ) # vz v e l o c i t y i n m/ s
133

134
135 # The numpy data type used t o s t o r e ground p o i n t data
136 # ground p o i n t s have n e g a t i v e unique IDs
137 # p o s i t i o n s a r e always c a l c u l a t e d from t h e i n i t i a l p o s i t i o n
138 # t o keep r o u n d i n g e r r o r from compounding
139 GROUNDPOINT_DTYPE = np . dtype ( [
140 ( ’ ID ’ , np . i n t 1 6 ) , # ID number , unique , = a r r a y i n d e x
141 ( ’ i n i t _ x ’ , np . i n t 3 2 ) , # i n i t i a l x p o s i t i o n i n m e t e r s
142 ( ’ i n i t _ y ’ , np . i n t 3 2 ) , # i n i t i a l y p o s i t i o n i n m e t e r s
143 ( ’ i n i t _ z ’ , np . i n t 3 2 ) , # i n i t i a l z p o s i t i o n i n m e t e r s
144 ( ’ x ’ , np . i n t 3 2 ) , # x p o s i t i o n in meters
145 ( ’ y ’ , np . i n t 3 2 ) , # y p o s i t i o n in meters
146 ( ’ z ’ , np . i n t 3 2 ) ] ) # z p o s i t i o n in meters
147
148

Polytechnic University of Catalonia - Barcelona Tech - UPC 14


APPENDIX B. PYTHON SCRIPTS

149 # The numpy data type used t o s t o r e l i n k data


150 # l i n k a r r a y s i z e may have t o be a d j u s t e d
151 # each i n d e x i s 8 b y t e s
152 LINK_DTYPE = np . dtype ( [
153 ( ’ node_1 ’ , np . i n t 1 6 ) , # an e n d p o i n t o f t h e l i n k
154 ( ’ node_2 ’ , np . i n t 1 6 ) , # the other endpoint of the l i n k
155 ( ’ d i s t a n c e ’ , np . i n t 3 2 ) , # d i s t a n c e o f the l i n k in meters
156 ( ’SNR ’ , np . f l o a t 3 2 ) , # SNR o f t h e l i n k
157 ( ’ s t a t u s ’ , np . i n t 1 6 ) ] ) # s t a t u s o f t h e l i n k 0−1( i n a c t i v e / a c t i v e )
158
159
160 LINK_ARRAY_SIZE = 10000000 # 10 m i l l i o n i n d i c e s = 80 megabyte a r r a y ( huge )
161
162 #
##############################################################################

163 # const c l a s s
164

165
166 class Constellation () :
167 """
168 A c l a s s used t o c o n t a i n and manage a s a t e l l i t e c o n s t i l l a t i o n
169

170 ...
171
172 Attributes
173 −−−−−−−−−−
174 number_of_planes : i n t
175 t h e number o f p l a n e s i n t h e c o n s t i l l a t i o n
176 nodes_per_plane : i n t
177 t h e number o f s a t e l l i t e s p e r p l a n e
178 total_sats : int
179 t h e t o t a l number o f nodes ( s a t e l l i t e s ) i n c o n s t i l l a t i o n
180 ground_node_counter : i n t
181 always n e g a t i v e , countdown , used t o keep t r a c k o f ground node IDs
182 inclination : float
183 the i n c l i n a t i o n of a l l planes in c o n s t i l l a t i o n
184 semi_major_axis : f l o a t
185 semi major a x i s o f t h e o r b i t s ( r a d i u s , i f o r b i t s c i r c u l a r )
186 period : int
187 the period of the o r b i t s in seconds
188 eccentricity : float
189 the e c c e n t r i c i t y of the o r b i t s ; range = 0.0 − 1.0
190 s a t e l l i t e s _ a r r a y : SATELLITE_DTYPE
191 numpy a r r a y o f s a t e l l i t e _ d t y p e , c o n t a i n s s a t e l l i t e data
192 raan_offsets : List [ float ]
193 l i s t o f f l o a t s , k e e p s t r a c k o f a l l t h e a s c e n d i n g node o f f s e t s i n
degrees
194 plane_solvers : List [ ke_solver ]
195 c o n t a i n s t h e PyAstronomy K e p l e r E l l i p s e s o l v e r f o r each o r b i t a l p l a n e
196 time_offsets : List [ float ]
197 c o n t a i n s t h e time o f f s e t s f o r s a t e l l t i e s withen a p l a n e
198 current_time : i n t
199 k e e p s t r a c k o f t h e c u r r e n t s i m u l a t i o n time
200
201 Methods

Polytechnic University of Catalonia - Barcelona Tech - UPC 15


APPENDIX B. PYTHON SCRIPTS

202 −−−−−−−
203 i n i t S a t e l l i t e A r r a y ( s a t _ a r r a y=None )
204 f i l l s t h e s a t a r r a y with i n i t i a l v a l u e s f o r time=0
205 getArrayOfNodePositions ()
206 r e t u r n s a a s l i c e o f t h e c o n s t i l l a t i o n array , c o n t a i n i n g o n l y p o s i t i o n
values
207 s e t C o n s t i l l a t i o n T i m e ( time =0.0)
208 u p d a t e s a l l s a t e l l i t e s and ground s t a t i o n s p o s i t i o n s t o r e f l e c t t h e new
time
209 """
210
211 d e f __init__ (
212 self ,
213 p l a n e s =1,
214 nodes_per_plane =4,
215 i n c l i n a t i o n =0,
216 f r e q u e n c y =1,
217 t r a n s m i s s i o n _ p o w e r =1.0 ,
218 bandwidth =1.0 ,
219 n o i s e _ f i g u r e =1.0 ,
220 r e c e i v e r _ s e n s i t i v i t y =1.0 ,
221 s n r =0.0 ,
222 semi_major_axis =6372000 ,
223 e c c =0.0 ,
224 minCommunicationsAltitude =100000 ,
225 m i n S a t E l e v a t i o n =40 ,
226 l i n k i n g M e t h o d= ’SPARSE ’ ,
227 arcOfAscendingNodes =360.0) :
228 """
229 Parameters
230 −−−−−−−−−−
231 planes : int
232 t h e number o f p l a n e s i n t h e c o n s t i l l a t i o n
233 nodes_per_plane : i n t
234 t h e number o f s a t e l l i t e s p e r p l a n e
235 inclination : float
236 the i n c l i n a t i o n of a l l planes in c o n s t i l l a t i o n
237 semi_major_axis : f l o a t
238 semi major a x i s o f t h e o r b i t s ( r a d i u s , i f o r b i t s c i r c u l a r )
239 ecc : f l o a t
240 the e c c e n t r i c i t y of the o r b i t s ; range = 0.0 − 1.0
241 minCommunicationsAltitude : i n t 3 2
242 The minimum a l t i t u d e t h a t i n t e r s a t e l l i t e l i n k s must p a s s
243 above t h e Earth ’ s s u r f a c e .
244 minSatElevation : i n t
245 The minimum a n g l e o f e l e v a t i o n i n d e g r e e s above t h e h o r i z o n a
satellite
246 n e e d s t o have f o r a ground s t a t i o n t o communicate with i t .
247 linkingMethod : s t r i n g
248 The c u r r e n t l i n k i n g method used by t h e c o n s t i l l a t i o n
249 c u r r e n t l y o n l y used f o r g e n e r a t i n g GML f i l e s .
250 arcOfAscendingNodes : f l o a t
251 The a n g l e o f a r c ( i n d e g r e e s ) t h a t t h e a s c e n d i n g nodes o f a l l t h e
252 o r b i t a l p l a n e s i s e v e n l y s p a c e d a l o n g . Ex , s e t i n g t h i s t o 180 r e s u l t s
253 i n a Pi c o n s t e l l a t i o n l i k e I r i d i u m
254

Polytechnic University of Catalonia - Barcelona Tech - UPC 16


APPENDIX B. PYTHON SCRIPTS

255 """
256 #s e l f . f d = open ( " f i l e . c s v " , "w" )
257 #s e l f . f d . w r i t e ( " \ " L a t i t u d \ " ; \ " Angulo1 \ " ; \ " Angulo2 \ " ; \ " Pt \ " \ n " )
258 p r i n t ( " ArcOfAscendingNodes=%d " % arcOfAscendingNodes )
259 s e l f . number_of_planes = p l a n e s
260 s e l f . nodes_per_plane = nodes_per_plane
261 s e l f . t o t a l _ s a t s = p l a n e s ∗ nodes_per_plane
262 s e l f . ground_node_counter = 0
263 self . inclination = inclination
264 s e l f . communication_frequency = f r e q u e n c y
265 s e l f . t r a n s m i s s i o n _ p o w e r= t r a n s m i s s i o n _ p o w e r
266 s e l f . bandwidth=bandwidth
267 s e l f . n o i s e _ f i g u r e= n o i s e _ f i g u r e
268 s e l f . r e c e i v e r _ s e n s i t i v i t y= r e c e i v e r _ s e n s i t i v i t y
269 s e l f . snr_minimum=s n r
270 s e l f . semi_major_axis = semi_major_axis
271 s e l f . p e r i o d = s e l f . c a l c u l a t e O r b i t P e r i o d ( semi_major_axis= s e l f .
semi_major_axis )
272 s e l f . e c c e n t r i c i t y = ecc
273 s e l f . current_time = 0
274 s e l f . number_of_isl_links = 0
275 s e l f . number_of_gnd_links = 0
276 s e l f . total_links = 0
277 s e l f . l i n k _ a r r a y _ s i z e = LINK_ARRAY_SIZE
278 s e l f . min_communications_altitude = 100000
279 s e l f . m i n _ s a t _ e l e v a t i o n = 40
280 s e l f . linking_method = ’SPARSE ’
281 s e l f .G = None
282 s e l f . arcOfAscendingNodes = arcOfAscendingNodes
283
284
285
286 if s e l f . snr_minimum==0.0:
287 s e l f . s n r _ t h r e s h o l d =( s e l f . r e c e i v e r _ s e n s i t i v i t y −30)−K−10∗np . l o g 1 0 ( s e l f .
bandwidth ∗ 1 0 ∗ ∗ 3 ) −10∗np . l o g 1 0 ( 2 9 0 )− s e l f . n o i s e _ f i g u r e
288
289 else :
290 s e l f . s n r _ t h r e s h o l d= s e l f . snr_minimum
291
292
293 # t h i s i s not w r i t t e n t o z e r o , b e c a u s e i t has i t ’ s own i n i t
294 # f u n c t i o n a a few l i n e s down : i n i t S a t e l l i t e A r r a y ( )
295 s e l f . s a t e l l i t e s _ a r r a y = np . empty ( s e l f . t o t a l _ s a t s , dtype=SATELLITE_DTYPE
)
296
297 # d e c l a r e an empty ground
298 s e l f . g r o u n d p o i n t s _ a r r a y = np . z e r o s (NUM_GROUND_POINTS,
299 dtype=GROUNDPOINT_DTYPE)
300
301 # d e c l a r e an empty l i n k a r r a y
302 s e l f . l i n k _ a r r a y = np . z e r o s ( s e l f . l i n k _ a r r a y _ s i z e , dtype=LINK_DTYPE)
303

304 # f i g u r e out how many d e g r e e s t o s p a c e r i g h t a s c e n d i n g nodes o f t h e


planes
305 s e l f . r a a n _ o f f s e t s = [ ( arcOfAscendingNodes / s e l f . number_of_planes ) ∗ i
for i in

Polytechnic University of Catalonia - Barcelona Tech - UPC 17


APPENDIX B. PYTHON SCRIPTS

306 r a n g e ( 0 , s e l f . number_of_planes ) ]
307
308 # g e n e r a t e a l i s t with a k e p l e r e l l i p s e s o l v e r o b j e c t f o r each p l a n e
309 s e l f . plane_solvers = [ ]
310 f o r raan i n s e l f . r a a n _ o f f s e t s :
311 s e l f . p l a n e _ s o l v e r s . append ( p y a s l . K e p l e r E l l i p s e (
312 p e r= s e l f . p e r i o d , # how l o n g t h e o r b i t t a k e s i n s e c o n d s
313 a= s e l f . semi_major_axis , # i f c i r c u l a r o r b i t , t h i s i s same a s
radius
314 e= s e l f . e c c e n t r i c i t y , # g e n e r a l l y c l o s e to 0 f o r l e o
constillations
315 Omega=raan , # r i g h t a s c e n t i o n o f t h e a s c e n d i n g node
316 w=0.0 , # i n i t i a l time o f f s e t / mean anamoly
317 i= s e l f . i n c l i n a t i o n ) ) # orbit inclination
318
319 # f i g u r e out t h e time o f f s e t s f o r nodes withen a p l a n e
320 s e l f . t i m e _ o f f s e t s = [ ( s e l f . p e r i o d / nodes_per_plane ) ∗ i f o r i i n
321 r a n g e ( 0 , nodes_per_plane ) ]
322
323
324 # i n i t i a l i z e the s a t e l l i t e array
325 s e l f . initSatelliteArray ()
326

327 def i n i t S a t e l l i t e A r r a y ( s e l f ) :
328 " " " i n i t i a l i z e s t h e s a t e l l i t e a r r a y with p o s i t i o n s a t time z e r o
329
330 Parameters
331 −−−−−−−−−−
332 sat_array :
333 the s a t e l l i t e array object , modified in place
334
335 """
336
337 # we o f f s e t each p l a n e by a s m a l l amount , s o they do not ’ c o l l i d e ’
338 # t h i s l i t t l e a l g o r i t h m comes up with a l i s t o f o f f s e t v a l u e s
339 phase_offset = 0
340 p h a s e _ o f f s e t _ i n c r e m e n t = ( ( s e l f . p e r i o d / s e l f . nodes_per_plane ) /
341 s e l f . number_of_planes )
342 temp = [ ]
343 toggle = False
344

345 # XXX: Plathon


346 f o r i i n r a n g e ( s e l f . number_of_planes ) :
347 i f toggle :
348 p h a s e _ o f f s e t = ( s e l f . p e r i o d / ( 2 . 0 ∗ s e l f . nodes_per_plane ) )
349

350
351 else :
352 phase_offset = 0
353
354 t o g g l e = not t o g g l e
355 temp . append ( p h a s e _ o f f s e t )
356
357 p h a s e _ o f f s e t s = temp
358
359 # l o o p through a l l s a t e l l i t e s

Polytechnic University of Catalonia - Barcelona Tech - UPC 18


APPENDIX B. PYTHON SCRIPTS

360 f o r p l a n e i n r a n g e ( 0 , s e l f . number_of_planes ) :
361 f o r node i n r a n g e ( 0 , s e l f . nodes_per_plane ) :
362
363 # c a l c u l a t e t h e KE s o l v e r time o f f s e t
364
365 o f f s e t = ( s e l f . t i m e _ o f f s e t s [ node ] + p h a s e _ o f f s e t s [ p l a n e ] )
366 # c a l c u l a t e t h e unique ID o f t h e node ( same a s a r r a y i n d e x )
367 unique_id = ( p l a n e ∗ s e l f . nodes_per_plane ) + node
368
369 # calculate i n i t i a l position
370 i n i t _ p o s = s e l f . p l a n e _ s o l v e r s [ p l a n e ] . xyzPos ( o f f s e t )
371 # XXX: C a l a c u l a t e i n i t i a l v e l o c i t y
372 i n i t _ v e l = s e l f . p l a n e _ s o l v e r s [ p l a n e ] . xyzVel ( o f f s e t )
373
374 # update s a t e l l t i e s a r r a y
375 s e l f . s a t e l l i t e s _ a r r a y [ unique_id ][ ’ ID ’ ] = np . i n t 1 6 ( unique_id )
376 s e l f . s a t e l l i t e s _ a r r a y [ unique_id ][ ’ plane_number ’ ] = np . i n t 1 6 ( p l a n e )
377 s e l f . s a t e l l i t e s _ a r r a y [ unique_id ][ ’ offset_number ’ ] = np . i n t 1 6 ( node )
378 s e l f . s a t e l l i t e s _ a r r a y [ unique_id ][ ’ t i m e _ o f f s e t ’ ] = np . f l o a t 3 2 ( o f f s e t
)
379 s e l f . s a t e l l i t e s _ a r r a y [ unique_id ][ ’ x ’ ] = np . i n t 3 2 ( i n i t _ p o s [ 0 ] )
380 s e l f . s a t e l l i t e s _ a r r a y [ unique_id ][ ’ y ’ ] = np . i n t 3 2 ( i n i t _ p o s [ 1 ] )
381 s e l f . s a t e l l i t e s _ a r r a y [ unique_id ][ ’ z ’ ] = np . i n t 3 2 ( i n i t _ p o s [ 2 ] )
382 s e l f . s a t e l l i t e s _ a r r a y [ unique_id ][ ’ vx ’ ] = np . i n t 3 2 ( i n i t _ v e l [ 0 ] )
383 s e l f . s a t e l l i t e s _ a r r a y [ unique_id ][ ’ vy ’ ] = np . i n t 3 2 ( i n i t _ v e l [ 1 ] )
384 s e l f . s a t e l l i t e s _ a r r a y [ unique_id ][ ’ vz ’ ] = np . i n t 3 2 ( i n i t _ v e l [ 2 ] )
385
386 def getArrayOfNodePositions ( s e l f ) :
387 " " " c o p i e s a sub a r r a y o f o n l y p o s i t i o n data from
388 s a t e l l i t e AND g r o u n d p o i n t a r r a y s
389
390 Returns
391 −−−−−−−
392 p o s i t i o n s : np a r r a y
393 a c o p i e d sub a r r a y o f t h e s a t e l l i t e array , t h a t o n l y c o n t a i n s
p o s i t i o n s data
394 """
395
396 s a t _ p o s i t i o n s = np . copy ( s e l f . s a t e l l i t e s _ a r r a y [ [ ’ x ’ , ’ y ’ , ’ z ’ ] ] )
397 g r o u n d _ p o s i t i o n s = np . copy ( s e l f . g r o u n d p o i n t s _ a r r a y [ [ ’ x ’ , ’ y ’ , ’ z ’ ] ] )
398

399 # combine s a t and ground p o s i t i o n s i n t o a ’ p o s i t i o n s ’ a r r a y


400 p o s i t i o n s = np . append ( s a t _ p o s i t i o n s , g r o u n d _ p o s i t i o n s )
401 return positions
402
403 def getArrayOfSatPositions ( s e l f ) :
404 " " " c o p i e s a sub a r r a y o f o n l y p o s i t i o n data from
405 s a t e l l i t e array
406
407 Returns
408 −−−−−−−
409 s a t _ p o s i t i o n s : np a r r a y
410 a c o p i e d sub a r r a y o f t h e s a t e l l i t e array , t h a t o n l y c o n t a i n s
p o s i t i o n s data
411 """
412

Polytechnic University of Catalonia - Barcelona Tech - UPC 19


APPENDIX B. PYTHON SCRIPTS

413 s a t _ p o s i t i o n s = np . copy ( s e l f . s a t e l l i t e s _ a r r a y [ [ ’ x ’ , ’ y ’ , ’ z ’ ] ] )
414
415 return sat_positions
416
417 def getArrayOfGndPositions ( s e l f ) :
418 " " " c o p i e s a sub a r r a y o f o n l y p o s i t i o n data from
419 groundpoint array
420
421 Returns
422 −−−−−−−
423 g r o u n d _ p o s i t i o n s : np a r r a y
424 a c o p i e d sub a r r a y o f t h e ground p o i n t array , t h a t o n l y c o n t a i n s
positions
425 """
426
427 g r o u n d _ p o s i t i o n s = np . copy ( s e l f . g r o u n d p o i n t s _ a r r a y [ [ ’ x ’ , ’ y ’ , ’ z ’ ] ] )
428
429 return ground_positions
430
431 def getArrayOfLinks ( s e l f ) :
432 " " " c o p i e s a sub a r r a y o f l i n k data
433
434 Returns
435 −−−−−−−
436 l i n k s : np a r r a y
437 contains a l l links
438 """
439 total_links = s e l f . total_links
440 l i n k s = np . copy ( s e l f . l i n k _ a r r a y [ : t o t a l _ l i n k s −1])
441
442 return links
443
444 d e f s e t C o n s t i l l a t i o n T i m e ( s e l f , time =0.0) :
445 " " " u p d a t e s a l l p o s i t i o n and l i n k data t o s p e c i f i e d time
446

447 Parameters
448 −−−−−−−−−−
449 time : f l o a t
450 s i m u l a t i o n time t o s e t t o i n s e c o n d s
451
452 Returns
453 −−−−−−−
454 None
455 """
456
457 # c a s t time t o an i n t
458 s e l f . c u r r e n t _ t i m e = i n t ( time )
459
460 # update a l l t h e s a t e l l i t e p o s i t i o n s
461 f o r sat_id in range ( s e l f . s a t e l l i t e s _ a r r a y . s i z e ) :
462 p l a n e = s e l f . s a t e l l i t e s _ a r r a y [ s a t _ i d ] [ ’ plane_number ’ ]
463 o f f s e t = s e l f . s a t e l l i t e s _ a r r a y [ sat_id ] [ ’ time_offset ’ ]
464 pos = s e l f . p l a n e _ s o l v e r s [ p l a n e ] . xyzPos ( s e l f . c u r r e n t _ t i m e + o f f s e t )
465 v e l = s e l f . p l a n e _ s o l v e r s [ p l a n e ] . xyzVel ( s e l f . c u r r e n t _ t i m e + o f f s e t )
466 s e l f . s a t e l l i t e s _ a r r a y [ s a t _ i d ] [ ’ x ’ ] = np . i n t 3 2 ( pos [ 0 ] )
467 s e l f . s a t e l l i t e s _ a r r a y [ s a t _ i d ] [ ’ y ’ ] = np . i n t 3 2 ( pos [ 1 ] )

Polytechnic University of Catalonia - Barcelona Tech - UPC 20


APPENDIX B. PYTHON SCRIPTS

468 self . satellites_array [ sat_id ][ ’ z ’ ] = np . i n t 3 2 ( pos [ 2 ] )


469 self . satellites_array [ sat_id ][ ’ vx ’ ] = np . i n t 3 2 ( v e l [ 0 ] )
470 self . satellites_array [ sat_id ][ ’ vy ’ ] = np . i n t 3 2 ( v e l [ 1 ] )
471 self . satellites_array [ sat_id ][ ’ vz ’ ] = np . i n t 3 2 ( v e l [ 2 ] )
472
473 # update a l l t h e ground p o i n t p o s i t i o n s
474 i f s e l f . c u r r e n t _ t i m e == 0 o r s e l f . c u r r e n t _ t i m e % SECONDS_PER_DAY == 0 :
475 degrees_to_rotate = 0
476 else :
477 d e g r e e s _ t o _ r o t a t e = 3 6 0 . 0 / (SECONDS_PER_DAY /
478 ( s e l f . c u r r e n t _ t i m e % SECONDS_PER_DAY) )
479

480 r o t a t i o n _ m a t r i x = s e l f . g e t R o t a t i o n M a t r i x (EARTH_ROTATION_AXIS,
481 degrees_to_rotate )
482
483 f o r gnd_pt i n r a n g e ( s e l f . g r o u n d p o i n t s _ a r r a y . s i z e ) :
484 i n i t i a l _ p o s = s e l f . g r o u n d p o i n t s _ a r r a y [ gnd_pt ] [
485 [ ’ init_x ’ , ’ init_y ’ , ’ init_z ’ ] ]
486 initial_pos = [ initial_pos [0] , initial_pos [1] , initial_pos [ 2 ] ]
487 new_pos = np . dot ( r o t a t i o n _ m a t r i x , i n i t i a l _ p o s )
488 s e l f . g r o u n d p o i n t s _ a r r a y [ gnd_pt ] [ ’ x ’ ] = new_pos [ 0 ]
489 s e l f . g r o u n d p o i n t s _ a r r a y [ gnd_pt ] [ ’ y ’ ] = new_pos [ 1 ]
490 s e l f . g r o u n d p o i n t s _ a r r a y [ gnd_pt ] [ ’ z ’ ] = new_pos [ 2 ]
491
492 r e t u r n None
493
494 d e f generateNetworkGraph ( s e l f , city_names ) :
495 " " " Makes a NetworkX graph o f t h e network a t t h e c u r r e n t time .
496

497 """
498 s e l f .G = nx . Graph (
499 numPlanes=s t r ( s e l f . number_of_planes ) ,
500 numNodesPerPlane=s t r ( s e l f . nodes_per_plane ) ,
501 p l a n e I n c l i n a t i o n=s t r ( s e l f . i n c l i n a t i o n ) ,
502 semiMajorAxisMeters=s t r ( s e l f . semi_major_axis ) ,
503 minCommunicationsAltitudeMeters=s t r ( s e l f . min_communications_altitude )
,
504 m i n S a t E l e v a t i o n D e g r e e s=s t r ( s e l f . m i n _ s a t _ e l e v a t i o n ) ,
505 s i m u l a t i o n T i m e=s t r ( s e l f . c u r r e n t _ t i m e ) ,
506 c o n n e c t i o n S t r a t e g y= s e l f . linking_method )
507

508 # now add i n s a t s


509 # remember , f o r s a t s , t h e a r r a y i n d e x = s a t ID
510 f o r sat_idx in range ( s e l f . t o t a l _ s a t s ) :
511 s e l f .G. add_node (
512 s t r ( s e l f . s a t e l l i t e s _ a r r a y [ s a t _ i d x ] [ ’ ID ’ ] ) ,
513 planeNumber=s t r ( s e l f . s a t e l l i t e s _ a r r a y [ s a t _ i d x ] [ ’ plane_number ’ ] ) ,
514 o f f s e t N u m b e r=s t r ( s e l f . s a t e l l i t e s _ a r r a y [ s a t _ i d x ] [ ’ offset_number ’ ] ) )
515
516 # now add a l l t h e ground nodes
517 # gnd p t s have n e g a t i v e ID numbers
518 f o r gnd_idx i n r a n g e ((− s e l f . ground_node_counter ) ) :
519 p r i n t ( " Ground Nodes I d e n t i f i e r %d , gnd_idx i s %d " % ( s e l f .
g r o u n d p o i n t s _ a r r a y [ gnd_idx ] [ ’ ID ’ ] , gnd_idx ) )
520 s e l f .G. add_node ( s t r ( s e l f . g r o u n d p o i n t s _ a r r a y [ gnd_idx ] [ ’ ID ’ ] ) ,
521 placeName=city_names [ gnd_idx ] )

Polytechnic University of Catalonia - Barcelona Tech - UPC 21


APPENDIX B. PYTHON SCRIPTS

522
523 # and f i n a l l y t h e l i n k s ( e d g e s i n nx terms )
524 f o r lnk_idx i n r a n g e ( s e l f . t o t a l _ l i n k s ) :
525 p r i n t ( " s e l f . l i n k _ a r r a y [%d ] [ ’ node_1 ’]=% s " % ( lnk_idx , s e l f . l i n k _ a r r a y [
lnk_idx ] [ ’ node_1 ’ ] ) )
526 s e l f .G. add_edge (
527 s t r ( s e l f . l i n k _ a r r a y [ lnk_idx ] [ ’ node_1 ’ ] ) ,
528 s t r ( s e l f . l i n k _ a r r a y [ lnk_idx ] [ ’ node_2 ’ ] ) ,
529 d i s t a n c e=i n t ( s e l f . l i n k _ a r r a y [ lnk_idx ] [ ’ d i s t a n c e ’ ] ) )
530
531 d e f generateNetworkGraph2 ( s e l f , city_names , id_gnd_1 , id_gnd_2 ) :
532 " " " Makes a NetworkX graph o f t h e network a t t h e c u r r e n t time .
533
534 """
535 #XXX: Plathon −−− Routing o n l y with s a t s :
536 # gnd −− s a t −− s a t −− s a t −− gnd
537 s e l f .G = nx . Graph (
538 numPlanes=s t r ( s e l f . number_of_planes ) ,
539 numNodesPerPlane=s t r ( s e l f . nodes_per_plane ) ,
540 p l a n e I n c l i n a t i o n=s t r ( s e l f . i n c l i n a t i o n ) ,
541 semiMajorAxisMeters=s t r ( s e l f . semi_major_axis ) ,
542 minCommunicationsAltitudeMeters=s t r ( s e l f . min_communications_altitude )
,
543 m i n S a t E l e v a t i o n D e g r e e s=s t r ( s e l f . m i n _ s a t _ e l e v a t i o n ) ,
544 s i m u l a t i o n T i m e=s t r ( s e l f . c u r r e n t _ t i m e ) ,
545 c o n n e c t i o n S t r a t e g y= s e l f . linking_method )
546
547 # now add i n s a t s
548 # remember , f o r s a t s , t h e a r r a y i n d e x = s a t ID
549 f o r sat_idx in range ( s e l f . t o t a l _ s a t s ) :
550 s e l f .G. add_node (
551 s t r ( s e l f . s a t e l l i t e s _ a r r a y [ s a t _ i d x ] [ ’ ID ’ ] ) ,
552 planeNumber=s t r ( s e l f . s a t e l l i t e s _ a r r a y [ s a t _ i d x ] [ ’ plane_number ’ ] ) ,
553 o f f s e t N u m b e r=s t r ( s e l f . s a t e l l i t e s _ a r r a y [ s a t _ i d x ] [ ’ offset_number ’ ] ) )
554

555 # now add a l l t h e ground nodes


556 # gnd p t s have n e g a t i v e ID numbers
557 f o r gnd_idx i n r a n g e ((− s e l f . ground_node_counter ) ) :
558 s e l f .G. add_node ( s t r ( s e l f . g r o u n d p o i n t s _ a r r a y [ gnd_idx ] [ ’ ID ’ ] ) ,
559 placeName=city_names [ gnd_idx ] )
560

561 # and f i n a l l y t h e l i n k s ( e d g e s i n nx terms )


562 f o r lnk_idx i n r a n g e ( s e l f . t o t a l _ l i n k s ) :
563 i f s e l f . l i n k _ a r r a y [ lnk_idx ] [ ’ node_1 ’ ] >= 0 and s e l f . l i n k _ a r r a y [
lnk_idx ] [ ’ node_2 ’ ] >= 0 :
564 ID1 = s e l f . s a t e l l i t e s _ a r r a y [ s e l f . l i n k _ a r r a y [ lnk_idx ] [ ’ node_1 ’ ] ] [ ’ ID
’]
565 ID2 = s e l f . s a t e l l i t e s _ a r r a y [ s e l f . l i n k _ a r r a y [ lnk_idx ] [ ’ node_2 ’ ] ] [ ’ ID
’]
566 i f s e l f . s a t e l l i t e s _ a r r a y [ ID1 ] [ ’ plane_number ’ ] != s e l f .
s a t e l l i t e s _ a r r a y [ ID2 ] [ ’ plane_number ’ ] :
567 lat_skip = 0
568 l a t 1 _ d e g r e e , x1 , y1 , z1 , R1 = s e l f . s a t e l l i t e _ l a t i t u d e ( ID1 )
569
570 l a t 2 _ d e g r e e , x2 , y2 , z2 , R2 = s e l f . s a t e l l i t e _ l a t i t u d e ( ID2 )
571

Polytechnic University of Catalonia - Barcelona Tech - UPC 22


APPENDIX B. PYTHON SCRIPTS

572 if s e l f . l i n k _ a r r a y [ lnk_idx ] [ ’ s t a t u s ’ ] == 0 :
573 continue
574 i f l a t 1 _ d e g r e e > LATITUDE_NORTH_THRESHOLD o r l a t 1 _ d e g r e e <
LATITUDE_SOUTH_THRESHOLD:
575 i f LATITUDE_DEBUG > 1 :
576 p r i n t ( " Avoid l i n k due t o s a t 1 : %d : x1 , y1 , z1 = %f ,% f ,% f , l a t :
%f " % ( ID1 , x1 , y1 , z1 , l a t 1 _ d e g r e e ) )
577 lat_skip = 1
578 i f l a t 2 _ d e g r e e > LATITUDE_NORTH_THRESHOLD o r l a t 2 _ d e g r e e <
LATITUDE_SOUTH_THRESHOLD:
579 i f LATITUDE_DEBUG > 1 :
580 p r i n t ( " Avoid l i n k due t o s a t 2 : %d : x2 , y2 , z2 = %f ,% f ,% f , l a t :
%f " % ( ID2 , x2 , y2 , z2 , l a t 2 _ d e g r e e ) )
581 lat_skip = 1
582
583 i f l a t _ s k i p == 1 :
584 i f LATITUDE_DEBUG > 1 :
585 print ( " " )
586 lat_skip = 0
587 continue
588
589
590 s e l f .G. add_edge (
591 s t r ( s e l f . l i n k _ a r r a y [ lnk_idx ] [ ’ node_1 ’ ] ) ,
592 s t r ( s e l f . l i n k _ a r r a y [ lnk_idx ] [ ’ node_2 ’ ] ) ,
593 d i s t a n c e=i n t ( s e l f . l i n k _ a r r a y [ lnk_idx ] [ ’ d i s t a n c e ’ ] ) )
594 else :
595 i f s e l f . l i n k _ a r r a y [ lnk_idx ] [ ’ node_1 ’ ] == id_gnd_1 o r s e l f .
l i n k _ a r r a y [ lnk_idx ] [ ’ node_1 ’ ] == id_gnd_2 o r \
596 s e l f . l i n k _ a r r a y [ lnk_idx ] [ ’ node_2 ’ ] == id_gnd_1 o r s e l f .
l i n k _ a r r a y [ lnk_idx ] [ ’ node_2 ’ ] == id_gnd_2 :
597 s e l f .G. add_edge (
598 s t r ( s e l f . l i n k _ a r r a y [ lnk_idx ] [ ’ node_1 ’ ] ) ,
599 s t r ( s e l f . l i n k _ a r r a y [ lnk_idx ] [ ’ node_2 ’ ] ) ,
600 d i s t a n c e=i n t ( s e l f . l i n k _ a r r a y [ lnk_idx ] [ ’ d i s t a n c e ’ ] ) )
601
602
603 def s a t e l l i t e _ l a t i t u d e ( s e l f , id_sat ) :
604 x = s e l f . s a t e l l i t e s _ a r r a y [ id_sat ] [ ’ x ’ ]
605 y = s e l f . s a t e l l i t e s _ a r r a y [ id_sat ] [ ’ y ’ ]
606 z = s e l f . s a t e l l i t e s _ a r r a y [ id_sat ] [ ’ z ’ ]
607 R = math . s q r t ( math . pow ( x , 2 ) + math . pow ( y , 2 ) + math . pow ( z , 2 ) )
608 l a t _ r a d = math . a s i n ( z /R)
609 l a t _ d e g r e e = l a t _ r a d ∗ 1 8 0 . 0 / math . p i
610 r e t u r n l a t _ d e g r e e , x , y , z ,R
611

612
613 d e f exportGMLFile ( s e l f , f i l e n a m e ) :
614 " " " Exports a GML f i l e o f t h e c u r r e n t graph ( s e l f .G)
615
616 """
617 nx . write_gml ( s e l f .G, f i l e n a m e )
618
619 d e f c a l c u l a t e O r b i t P e r i o d ( s e l f , semi_major_axis =0.0) :
620 " " " c a l c u l a t e s t h e p e r i o d o f a o r b i t f o r Earth
621

Polytechnic University of Catalonia - Barcelona Tech - UPC 23


APPENDIX B. PYTHON SCRIPTS

622 Parameters
623 −−−−−−−−−−
624 semi_major_axis : f l o a t
625 semi major a x i s o f t h e o r b i t i n m e t e r s
626
627 Returns
628 −−−−−−−
629 Period : i n t
630 t h e p e r i o d o f t h e o r b i t i n s e c o n d s ( rounded t o whole s e c o n d s )
631 """
632
633 tmp = math . pow ( semi_major_axis , 3 ) / STD_GRAVITATIONAL_PARAMATER_EARTH
634 r e t u r n i n t ( 2 . 0 ∗ math . p i ∗ math . s q r t ( tmp ) )
635
636 d e f addGroundPoint ( s e l f , l a t i t u d e , l o n g i t u d e , a l t i t u d e =100.0) :
637 " " " adds a ground p o i n t a t g i v e n c o o r d i n a t e s , assumes e a r t h i s p e r f e c t
sphere
638

639 Parameters
640 −−−−−−−−−−
641 latitude : float
642 l a t i t u d e o f ground p o i n t ( i n d e g r e e s )
643 longitude : float
644 l o n g i t u d e o f ground p o i n t ( i n d e g r e e s )
645 altitude : float
646 a l t i t u d e o f point in meters (0 = earth s u r f a c e )
647
648 Returns
649 −−−−−−−
650 unique_id : i n t
651 t h e ID v a l u e a s s i g n e d t o ground p o i n t ( w i l l be < 0 )
652 """
653
654 # must c o n v e r t t h e l a t / l o n g / a l t t o c a r t e s i a n c o o r d i n a t e s
655 r a d i u s = EARTH_RADIUS + a l t i t u d e
656 init_pos = [0 , 0 , 0]
657 l a t i t u d e = math . r a d i a n s ( l a t i t u d e )
658 l o n g i t u d e = math . r a d i a n s ( l o n g i t u d e )
659 i n i t _ p o s [ 0 ] = r a d i u s ∗ math . c o s ( l a t i t u d e ) ∗ math . c o s ( l o n g i t u d e )
660 i n i t _ p o s [ 1 ] = r a d i u s ∗ math . c o s ( l a t i t u d e ) ∗ math . s i n ( l o n g i t u d e )
661 i n i t _ p o s [ 2 ] = r a d i u s ∗ math . s i n ( l a t i t u d e )
662
663
664
665 # be s u r e t o decrement t h i s f o r t h e next ground p o i n t
666 s e l f . ground_node_counter = s e l f . ground_node_counter − 1
667 unique_id = s e l f . ground_node_counter
668
669 # i f s i m u l a t i o n time i s not 0 , f i g u r e out c u r r e n t p o s i t i o n
670 i f s e l f . c u r r e n t _ t i m e == 0 o r s e l f . c u r r e n t _ t i m e % SECONDS_PER_DAY == 0 :
671 degrees_to_rotate = 0
672 pos = i n i t _ p o s
673
674 else :
675 d e g r e e s _ t o _ r o t a t e = 3 6 0 . 0 / (SECONDS_PER_DAY /
676 ( s e l f . c u r r e n t _ t i m e % SECONDS_PER_DAY) )

Polytechnic University of Catalonia - Barcelona Tech - UPC 24


APPENDIX B. PYTHON SCRIPTS

677
678 r o t a t i o n _ m a t r i x = s e l f . g e t R o t a t i o n M a t r i x (EARTH_ROTATION_AXIS,
679 degrees_to_rotate )
680
681 pos = np . dot ( r o t a t i o n _ m a t r i x , i n i t _ p o s )
682

683
684 # add t h e new ground p o i n t t o a r r a y
685 # yes , append means a f u l l a r r a y copy e v e r y time ,
686 # but t h i s s h o u l d be a v e r y s m a l l array ,
687 # and ground p o i n t s a r e p r o b a b l y o n l y added once
688 # at the begining of the simulation
689 temp = np . z e r o s ( 1 , dtype=GROUNDPOINT_DTYPE)
690 temp [ 0 ] [ ’ ID ’ ] = np . i n t 1 6 ( unique_id )
691 temp [ 0 ] [ ’ i n i t _ x ’ ] = np . i n t 3 2 ( i n i t _ p o s [ 0 ] )
692 temp [ 0 ] [ ’ i n i t _ y ’ ] = np . i n t 3 2 ( i n i t _ p o s [ 1 ] )
693 temp [ 0 ] [ ’ i n i t _ z ’ ] = np . i n t 3 2 ( i n i t _ p o s [ 2 ] )
694 temp [ 0 ] [ ’ x ’ ] = np . i n t 3 2 ( pos [ 0 ] )
695 temp [ 0 ] [ ’ y ’ ] = np . i n t 3 2 ( pos [ 1 ] )
696 temp [ 0 ] [ ’ z ’ ] = np . i n t 3 2 ( pos [ 2 ] )
697
698 s e l f . g r o u n d p o i n t s _ a r r a y = np . append ( s e l f . g r o u n d p o i n t s _ a r r a y , temp )
699

700 r e t u r n unique_id
701
702 def getRotationMatrix ( s e l f , axis , degrees ) :
703 """
704 Return t h e r o t a t i o n matrix a s s o c i a t e d with c o u n t e r c l o c k w i s e r o t a t i o n
about
705 t h e g i v e n a x i s by t h e t a r a d i a n s .
706
707 Parameters
708 −−−−−−−−−−
709 axis : l i s t [ x , y , z ]
710 a vector d e f i n i n g the r o t a i o n a x i s
711 degrees : f l o a t
712 The number o f d e g r e e s t o r o t a t e
713
714 """
715
716 t h e t a = math . r a d i a n s ( d e g r e e s )
717 a x i s = np . a s a r r a y ( a x i s )
718 a x i s = a x i s / math . s q r t ( np . dot ( a x i s , a x i s ) )
719 a = math . c o s ( t h e t a / 2 . 0 )
720 b , c , d = −a x i s ∗ math . s i n ( t h e t a / 2 . 0 )
721 aa , bb , cc , dd = a ∗ a , b ∗ b , c ∗ c , d ∗ d
722 bc , ad , ac , ab , bd , cd = b ∗ c , a ∗ d , a ∗ c , a ∗ b , b ∗ d , c ∗ d
723 r e t u r n np . a r r a y ( [
724 [ aa + bb − c c − dd , 2 ∗ ( bc + ad ) , 2 ∗ ( bd − ac ) ] ,
725 [ 2 ∗ ( bc − ad ) , aa + c c − bb − dd , 2 ∗ ( cd + ab ) ] ,
726 [ 2 ∗ ( bd + ac ) , 2 ∗ ( cd − ab ) , aa + dd − bb − c c ] ] )
727

728 d e f c a l c u l a t e M a x I S L D i s t a n c e ( s e l f , min_communication_altitude ) :
729 """
730 u e s some t r i g t o c a l c u l a t e t h e max coms r a n g e between s a t e l l i t e s
731 based on some minium communications a l t i t u d e

Polytechnic University of Catalonia - Barcelona Tech - UPC 25


APPENDIX B. PYTHON SCRIPTS

732
733 Parameters
734 −−−−−−−−−−
735 min_communication_altitude : i n t
736 min coms a l t i t u d e i n meters , r e f e r e n c e d from Earth ’ s s u r f a c e
737

738 Returns
739 −−−−−−−
740 max d i s t a n c e : i n t
741 max d i s t a n c e i n m e t e r s
742
743 """
744
745 c = EARTH_RADIUS + min_communication_altitude
746 b = s e l f . semi_major_axis
747 B = math . r a d i a n s ( 9 0 )
748 C = math . a s i n ( ( c ∗ math . s i n (B) ) / b )
749 A = math . r a d i a n s ( 1 8 0 ) − B − C
750 a = ( b ∗ math . s i n (A) ) / math . s i n (B)
751 return i n t ( a ∗ 2)
752
753 d e f calculateMaxSpaceToGndDistance ( s e l f , m i n _ e l e v a t i o n ) :
754 """
755 Return max s a t e l l i t e t o ground coms d i s t a n c e
756
757 Uses some t r i g t o c a l c u l a t e t h e max s p a c e t o ground communications
758 d i s t a n c e g i v e n a f i e l d o f view f o r g r o u n d s t a t i o n s d e f i n e d by an
759 minimum e l e v a t i o n a n g l e above t h e h o r i z o n .
760 Uses a c i r c l e & l i n e segment i n t e r c e p t c a l c u l a t i o n .
761
762 Parameters
763 −−−−−−−−−−
764 min_elevation : i n t
765 min e l e v a t i o n i n d e g r e e s , r a n g e : 0<val <90
766

767 Returns
768 −−−−−−−
769 max d i s t a n c e : i n t
770 max coms d i s t a n c e i n m e t e r s
771
772 """
773
774 # TODO
775 # make a drawing e x p l a i n i n g t h i s
776
777 f u l l _ l i n e = False
778 t a n g e n t _ t o l = 1 e−9
779
780 # p o i n t 1 o f l i n e segment , r e p r e s e n t i n g g r o u n d s t a t i o n
781 p1x , p1y = ( 0 , EARTH_RADIUS)
782
783 # p o i n t 2 o f l i n e segment , r e p r e s e n t i n g r e a l l y f a r p o i n t
784 # a t m i n _ e l e v a t i o n s l o p e from p o i n t 1
785 s l o p e = math . tan ( math . r a d i a n s ( m i n _ e l e v a t i o n ) )
786 run = 384748000 # meters , sma o f moon
787 r i s e = s l o p e ∗ run + EARTH_RADIUS

Polytechnic University of Catalonia - Barcelona Tech - UPC 26


APPENDIX B. PYTHON SCRIPTS

788 p2x , p2y = ( run , r i s e )


789
790 # center of orbit c i r c l e = earth center
791 # radius = orbit radius
792 cx , cy = ( 0 , 0 )
793 c i r c l e _ r a d i u s = s e l f . semi_major_axis
794
795 ( x1 , y1 ) , ( x2 , y2 ) = ( p1x − cx , p1y − cy ) , ( p2x − cx , p2y − cy )
796 dx , dy = ( x2 − x1 ) , ( y2 − y1 )
797 dr = ( dx ∗∗ 2 + dy ∗∗ 2 ) ∗ ∗ . 5
798 big_d = x1 ∗ y2 − x2 ∗ y1
799 d i s c r i m i n a n t = c i r c l e _ r a d i u s ∗∗ 2 ∗ dr ∗∗ 2 − big_d ∗∗ 2
800
801 i f d i s c r i m i n a n t < 0 : # No i n t e r s e c t i o n between c i r c l e and l i n e
802 p r i n t ( "ERROR! problem with calculateMaxSpaceToGndDistance , no
intersection " )
803 return 0
804 e l s e : # There may be 0 , 1 , o r 2 i n t e r s e c t i o n s with t h e segment
805 intersections = [
806 ( cx+(big_d ∗dy+s i g n ∗(−1 i f dy < 0 e l s e 1 ) ∗dx∗ d i s c r i m i n a n t ∗ ∗ . 5 ) / dr
∗∗2 ,
807 cy + (−big_d ∗ dx + s i g n ∗ abs ( dy ) ∗ d i s c r i m i n a n t ∗ ∗ . 5 ) / dr ∗∗ 2 )
808 f o r s i g n i n ( ( 1 , −1) i f dy < 0 e l s e ( −1 , 1 ) ) ]
809
810 # This makes s u r e t h e o r d e r a l o n g t h e segment i s c o r r e c t
811 i f not f u l l _ l i n e :
812 # F i l t e r out i n t e r s e c t i o n s t h a t do not f a l l w i t h i n t h e segment
813 f r a c t i o n _ a l o n g _ s e g m e n t = [ ( x i − p1x ) / dx i f abs ( dx ) > abs ( dy )
814 e l s e ( y i − p1y ) / dy f o r xi , y i i n
intersections ]
815
816 i n t e r s e c t i o n s = [ pt f o r pt , f r a c i n
817 zip ( i n t e r s e c t i o n s , fraction_along_segment )
818 i f 0 <= f r a c <= 1 ]
819

820 i f l e n ( i n t e r s e c t i o n s ) == 2 and abs ( d i s c r i m i n a n t ) <= t a n g e n t _ t o l :


821 # I f l i n e i s t a n g e n t t o c i r c l e , r e t u r n j u s t one p o i n t
822 p r i n t ( "ERROR! , g o t 2 i n t e r s e c t i o n s , e x p e c t i n g 1 " )
823 return 0
824 else :
825 ints_lst = intersections
826
827 # assuming 2 i n t e r s e c t i o n s were found . . .
828 for i in ints_lst :
829 i f i [ 1 ] < 0:
830 continue
831 else :
832 # c a l c u l a t e d i s t to t h i s i n t e r s e c t i o n
833 d = math . s q r t (
834 math . pow ( i [0] − p1x , 2 ) +
835 math . pow ( i [1] − p1y , 2 )
836 )
837 return int (d)
838
839 d e f c a l c u l a t e I d e a l L i n k s ( s e l f , max_isl_range , max_stg_range ) :
840 """

Polytechnic University of Catalonia - Barcelona Tech - UPC 27


APPENDIX B. PYTHON SCRIPTS

841 f i g u r e out a l l p o s s i b l e i n t e r − s a t e l l i t e l i n k s
842 f o r each s a t e l l i t e , with a d i s t a n c e l e s s than max_coms_range
843
844 Parameters
845 −−−−−−−−−−
846 max_coms_range : i n t
847 t h e max coms r a n g e i n m e t e r s
848
849 """
850
851 i f USING_NUMBA i s True :
852 temp = s e l f . n u m b a _ c a l c u l a t e I d e a l L i n k s (
853 max_isl_range ,
854 max_stg_range ,
855 s e l f . total_sats ,
856 self . satellites_array ,
857 s e l f . link_array ,
858 s e l f . groundpoints_array ,
859 s e l f . ground_node_counter ,
860 s e l f . link_array_size )
861 i f temp i s not None :
862 s e l f . n u m b e r _ o f _ i s l _ l i n k s = temp [ 0 ]
863 s e l f . number_of_gnd_links = temp [ 1 ]
864 s e l f . t o t a l _ l i n k s = temp [ 2 ]
865
866 else :
867
868 link_idx = 0
869

870 # add t h e ISL l i n k s


871 f o r sat_idx_a i n r a n g e ( s e l f . t o t a l _ s a t s − 1 ) :
872 # copy t h e p o s i t i o n o f s a t a
873 sat_a_pos = [
874 s e l f . s a t e l l i t e s _ a r r a y [ sat_idx_a ] [ ’ x ’ ] ,
875 s e l f . s a t e l l i t e s _ a r r a y [ sat_idx_a ] [ ’ y ’ ] ,
876 s e l f . s a t e l l i t e s _ a r r a y [ sat_idx_a ] [ ’ z ’ ]
877 ]
878 f o r sat_idx_b i n r a n g e ( sat_idx_a + 1 , s e l f . t o t a l _ s a t s ) :
879 # c a l c u l a t e d i s t a n c e from a t o b
880 d = i n t ( math . s q r t (
881 math . pow ( s e l f . s a t e l l i t e s _ a r r a y [ sat_idx_b ] [ ’ x ’ ] − sat_a_pos [ 0 ] ,
2) +
882 math . pow ( s e l f . s a t e l l i t e s _ a r r a y [ sat_idx_b ] [ ’ y ’ ] − sat_a_pos [ 1 ] ,
2) +
883 math . pow ( s e l f . s a t e l l i t e s _ a r r a y [ sat_idx_b ] [ ’ z ’ ] − sat_a_pos [ 2 ] ,
2) ) )
884 # d e i c i d e i f l i n k i s v a l i d o r not
885 i f d < max_isl_range :
886 i f link_idx < s e l f . link_array_size − 1:
887 s e l f . l i n k _ a r r a y [ l i n k _ i d x ] [ ’ node_1 ’ ] = np . i n t 1 6 ( sat_idx_a )
888 s e l f . l i n k _ a r r a y [ l i n k _ i d x ] [ ’ node_2 ’ ] = np . i n t 1 6 ( sat_idx_b )
889 s e l f . l i n k _ a r r a y [ l i n k _ i d x ] [ ’ d i s t a n c e ’ ] = np . i n t 3 2 ( d )
890 link_idx = link_idx + 1
891 else :
892 p r i n t ( ’ERROR! ran out o f room i n t h e l i n k a r r a y ’ )
893 return

Polytechnic University of Catalonia - Barcelona Tech - UPC 28


APPENDIX B. PYTHON SCRIPTS

894
895 s e l f . number_of_isl_links = link_idx
896
897 # add t h e StG l i n k s
898 f o r gnd_idx i n r a n g e (− s e l f . ground_node_counter ) :
899 gnd_pos = [
900 s e l f . g r o u n d p o i n t s _ a r r a y [ gnd_idx ] [ ’ x ’ ] ,
901 s e l f . g r o u n d p o i n t s _ a r r a y [ gnd_idx ] [ ’ y ’ ] ,
902 s e l f . g r o u n d p o i n t s _ a r r a y [ gnd_idx ] [ ’ z ’ ]
903 ]
904 f o r sat_idx in range ( s e l f . t o t a l _ s a t s ) :
905 # calculate distance
906 d = i n t ( math . s q r t (
907 math . pow ( s e l f . s a t e l l i t e s _ a r r a y [ s a t _ i d x ] [ ’ x ’ ] − gnd_pos [ 0 ] , 2 ) +
908 math . pow ( s e l f . s a t e l l i t e s _ a r r a y [ s a t _ i d x ] [ ’ y ’ ] − gnd_pos [ 1 ] , 2 ) +
909 math . pow ( s e l f . s a t e l l i t e s _ a r r a y [ s a t _ i d x ] [ ’ z ’ ] − gnd_pos [ 2 ] , 2 ) ) )
910 # d e i c i d e i f l i n k i s v a l i d o r not
911 i f d < max_stg_range :
912 i f link_idx < s e l f . link_array_size − 1:
913 gnd_id = s e l f . g r o u n d p o i n t s _ a r r a y [ gnd_idx ] [ ’ ID ’ ]
914 s a t _ i d = s e l f . s a t e l l i t e s _ a r r a y [ s a t _ i d x ] [ ’ ID ’ ]
915 s e l f . l i n k _ a r r a y [ l i n k _ i d x ] [ ’ node_1 ’ ] = gnd_id
916 s e l f . l i n k _ a r r a y [ l i n k _ i d x ] [ ’ node_2 ’ ] = s a t _ i d
917 s e l f . l i n k _ a r r a y [ l i n k _ i d x ] [ ’ d i s t a n c e ’ ] = np . i n t 3 2 ( d )
918 link_idx = link_idx + 1
919 else :
920 p r i n t ( ’ERROR! ran out o f room i n t h e l i n k a r r a y ’ )
921 return
922

923 s e l f . number_of_gnd_links = l i n k _ i d x − s e l f . n u m b e r _ o f _ i s l _ l i n k s
924 s e l f . total_links = link_idx
925
926 @staticmethod
927 @numba . j i t ( nopython=True )
928 def numba_calculateIdealLinks (
929 max_isl_range ,
930 max_stg_range ,
931 total_sats ,
932 satellites_array ,
933 link_array ,
934 groundpoints_array ,
935 ground_node_counter ,
936 link_array_size ) :
937 """
938 f i g u r e out a l l p o s s i b l e i n t e r − s a t e l l i t e l i n k s
939 f o r each s a t e l l i t e , with a d i s t a n c e l e s s than max_coms_range
940
941 Parameters
942 −−−−−−−−−−
943 max_coms_range : i n t
944 t h e max coms r a n g e i n m e t e r s
945

946 """
947
948 link_idx = 0
949

Polytechnic University of Catalonia - Barcelona Tech - UPC 29


APPENDIX B. PYTHON SCRIPTS

950 # add t h e ISL l i n k s


951 f o r sat_idx_a i n r a n g e ( t o t a l _ s a t s − 1 ) :
952 # copy t h e p o s i t i o n o f s a t a
953 sat_a_pos = [
954 s a t e l l i t e s _ a r r a y [ sat_idx_a ] [ ’ x ’ ] ,
955 s a t e l l i t e s _ a r r a y [ sat_idx_a ] [ ’ y ’ ] ,
956 s a t e l l i t e s _ a r r a y [ sat_idx_a ] [ ’ z ’ ]
957 ]
958 f o r sat_idx_b i n r a n g e ( sat_idx_a + 1 , t o t a l _ s a t s ) :
959 # c a l c u l a t e d i s t a n c e from a t o b
960 d = i n t ( math . s q r t (
961 math . pow ( s a t e l l i t e s _ a r r a y [ sat_idx_b ] [ ’ x ’ ] − sat_a_pos [ 0 ] , 2 ) +
962 math . pow ( s a t e l l i t e s _ a r r a y [ sat_idx_b ] [ ’ y ’ ] − sat_a_pos [ 1 ] , 2 ) +
963 math . pow ( s a t e l l i t e s _ a r r a y [ sat_idx_b ] [ ’ z ’ ] − sat_a_pos [ 2 ] , 2 ) ) )
964 # d e i c i d e i f l i n k i s v a l i d o r not
965 i f d < max_isl_range :
966 i f link_idx < link_array_size − 1:
967 l i n k _ a r r a y [ l i n k _ i d x ] [ ’ node_1 ’ ] = np . i n t 1 6 ( sat_idx_a )
968 l i n k _ a r r a y [ l i n k _ i d x ] [ ’ node_2 ’ ] = np . i n t 1 6 ( sat_idx_b )
969 l i n k _ a r r a y [ l i n k _ i d x ] [ ’ d i s t a n c e ’ ] = np . i n t 3 2 ( d )
970 link_idx = link_idx + 1
971 else :
972 # p r i n t ( ’ERROR! ran out o f room i n t h e l i n k a r r a y ’ )
973 return
974
975 number_of_isl_links = link_idx
976
977 # add t h e StG l i n k s
978 f o r gnd_idx i n r a n g e ( 0 , −(ground_node_counter ) ) :
979 gnd_pos = [
980 g r o u n d p o i n t s _ a r r a y [ gnd_idx ] [ ’ x ’ ] ,
981 g r o u n d p o i n t s _ a r r a y [ gnd_idx ] [ ’ y ’ ] ,
982 g r o u n d p o i n t s _ a r r a y [ gnd_idx ] [ ’ z ’ ]
983 ]
984 f o r sat_idx in range ( t o t a l _ s a t s ) :
985 # calculate distance
986 d = i n t ( math . s q r t (
987 math . pow ( s a t e l l i t e s _ a r r a y [ s a t _ i d x ] [ ’ x ’ ] − gnd_pos [ 0 ] , 2 ) +
988 math . pow ( s a t e l l i t e s _ a r r a y [ s a t _ i d x ] [ ’ y ’ ] − gnd_pos [ 1 ] , 2 ) +
989 math . pow ( s a t e l l i t e s _ a r r a y [ s a t _ i d x ] [ ’ z ’ ] − gnd_pos [ 2 ] , 2 ) ) )
990 # d e i c i d e i f l i n k i s v a l i d o r not
991 i f d < max_stg_range :
992 d = np . i n t 3 2 ( d )
993 i f link_idx < link_array_size − 1:
994 gnd_id = g r o u n d p o i n t s _ a r r a y [ gnd_idx ] [ ’ ID ’ ]
995 s a t _ i d = s a t e l l i t e s _ a r r a y [ s a t _ i d x ] [ ’ ID ’ ]
996 l i n k _ a r r a y [ l i n k _ i d x ] [ ’ node_1 ’ ] = gnd_id
997 l i n k _ a r r a y [ l i n k _ i d x ] [ ’ node_2 ’ ] = s a t _ i d
998 link_array [ link_idx ] [ ’ distance ’ ] = d
999 link_idx = link_idx + 1
1000 else :
1001 p r i n t ( ’ERROR! ran out o f room i n t h e l i n k a r r a y ’ )
1002 return
1003
1004 number_of_gnd_links = l i n k _ i d x − n u m b e r _ o f _ i s l _ l i n k s
1005 total_links = link_idx

Polytechnic University of Catalonia - Barcelona Tech - UPC 30


APPENDIX B. PYTHON SCRIPTS

1006
1007 r e t u r n [ number_of_isl_links , number_of_gnd_links , t o t a l _ l i n k s ]
1008
1009 def calculatePlusGridLinks (
1010 self ,
1011 max_stg_range ,
1012 max_isl_range =(2∗∗31) −1,
1013 i n i t i a l i z e =F a l s e ,
1014 c r o s s l i n k _ i n t e r p o l a t i o n =1) :
1015 """
1016 c o n n e c t s a t e l l i t e s i n a +g r i d network
1017

1018 Parameters
1019 −−−−−−−−−−
1020 max_stg_range : i n t
1021 t h e max space −ground coms r a n g e
1022 i n i t i a l i z e : bool
1023 Because PlusGrid ISL a r e s t a t i c , they o n l y need t o be g e n e r a t e d once ,
1024 I f i n i t i a l i z e =F a l s e , o n l y update l i n k d i s t a n c e s , do not r e g e r e r a t e
1025 crosslink_interpolation : int
1026 This v a l u e i s used t o make o n l y 1 out o f e v e r y
crosslink_interpolation
1027 s a t e l l i t e s a b l e t o have c r o s s l i n k s . For example , with a i n t e r p o l a t i o n
1028 v a l u e o f ’ 2 ’ , o n l y e v e r y o t h e r s a t e l l i t e w i l l have c r o s s l i n k s , t h e
rest
1029 w i l l have o n l y i n t r a −p l a n e l i n k s
1030
1031 """
1032

1033 # TODO: s p l i t t h i s i n t o two f u n c t i o n s :


1034 # initialize_plus_grid_links ()
1035 # j u s t i n i t s p l u s g r i d l i n k s , d o e s not c a l c u l a t e d i s t a n c e s
1036 # update_link_distances ()
1037 # j u s t g o e s through e x i s t i n g l i n k s and r e c a l c u l a t e s d i s t a n c e s
1038 # same a s c a l l i n g t h i s with i n i t i a l i z e =f a l s e
1039
1040 if initialize :
1041 s e l f . number_of_isl_links = 0
1042
1043 i f USING_NUMBA i s True :
1044 temp = s e l f . n u m b a _ c a l c u l a t e P l u s G r i d L i n k s (
1045 max_stg_range ,
1046 s e l f . total_sats ,
1047 self . satellites_array ,
1048 s e l f . link_array ,
1049 s e l f . groundpoints_array ,
1050 s e l f . ground_node_counter ,
1051 s e l f . link_array_size ,
1052 s e l f . number_of_planes ,
1053 s e l f . nodes_per_plane ,
1054 arcOfAscendingNodes = s e l f . arcOfAscendingNodes ,
1055 n u m b e r _ o f _ i s l _ l i n k s= s e l f . number_of_isl_links ,
1056 i n i t i a l i z e=i n i t i a l i z e ,
1057 c r o s s l i n k _ i n t e r p o l a t i o n=c r o s s l i n k _ i n t e r p o l a t i o n ,
1058 max_isl_range=max_isl_range )
1059 i f temp i s not None :

Polytechnic University of Catalonia - Barcelona Tech - UPC 31


APPENDIX B. PYTHON SCRIPTS

1060 s e l f . n u m b e r _ o f _ i s l _ l i n k s = temp [ 0 ]
1061 s e l f . number_of_gnd_links = temp [ 1 ]
1062 s e l f . t o t a l _ l i n k s = temp [ 2 ]
1063
1064 else :
1065

1066 if initialize :
1067
1068 link_idx = 0
1069
1070 # add t h e i n t r a −p l a n e l i n k s
1071 f o r p l a n e i n r a n g e ( s e l f . number_of_planes ) :
1072 f o r node i n r a n g e ( s e l f . nodes_per_plane ) :
1073 node_1 = node + ( p l a n e ∗ s e l f . nodes_per_plane )
1074 i f node == s e l f . nodes_per_plane − 1 :
1075 node_2 = p l a n e ∗ s e l f . nodes_per_plane
1076 else :
1077 node_2 = node + ( p l a n e ∗ s e l f . nodes_per_plane ) + 1
1078
1079 i f link_idx < s e l f . link_array_size − 1:
1080 s e l f . l i n k _ a r r a y [ l i n k _ i d x ] [ ’ node_1 ’ ] = np . i n t 1 6 ( node_1 )
1081 s e l f . l i n k _ a r r a y [ l i n k _ i d x ] [ ’ node_2 ’ ] = np . i n t 1 6 ( node_2 )
1082 link_idx = link_idx + 1
1083 else :
1084 p r i n t ( ’ERROR! ran out o f room i n t h e l i n k a r r a y f o r i n t r a −
plane l i n k s ’ )
1085 return
1086 # add t h e c r o s s −p l a n e l i n k s
1087 p r i n t ( "Go t o i n i t i a l i z e c r o s s −p l a n e l i n k s " )
1088 f o r p l a n e i n r a n g e ( s e l f . number_of_planes ) :
1089 i f p l a n e == s e l f . number_of_planes − 1 :
1090 plane2 = 0
1091 # XXX: Plathon −−− Exclude c r o s s −seam l i n k s
1092
1093 if s e l f . arcOfAscendingNodes == 1 8 0 . 0 :
1094 break
1095 #break
1096 else :
1097 plane2 = plane + 1
1098 f o r node i n r a n g e ( s e l f . nodes_per_plane ) :
1099 node_1 = node + ( p l a n e ∗ s e l f . nodes_per_plane )
1100 node_2 = node + ( p l a n e 2 ∗ s e l f . nodes_per_plane )
1101 i f link_idx < s e l f . link_array_size − 1:
1102 i f ( node_1 + 1 ) % c r o s s l i n k _ i n t e r p o l a t i o n == 0 :
1103 s e l f . l i n k _ a r r a y [ l i n k _ i d x ] [ ’ node_1 ’ ] = np . i n t 1 6 ( node_1 )
1104 s e l f . l i n k _ a r r a y [ l i n k _ i d x ] [ ’ node_2 ’ ] = np . i n t 1 6 ( node_2 )
1105 link_idx = link_idx + 1
1106 else :
1107 p r i n t ( ’ERROR! ran out o f room i n t h e l i n k a r r a y f o r c r o s s −
plane l i n k s ’ )
1108 return
1109

1110 s e l f . number_of_isl_links = link_idx


1111
1112 link_idx = s e l f . number_of_isl_links
1113

Polytechnic University of Catalonia - Barcelona Tech - UPC 32


APPENDIX B. PYTHON SCRIPTS

1114 # update ISL l i n k d i s t a n c e s


1115 f o r i s l _ i d x in range ( s e l f . number_of_isl_links ) :
1116 sat_1 = s e l f . l i n k _ a r r a y [ i s l _ i d x ] [ ’ node_1 ’ ]
1117 sat_2 = s e l f . l i n k _ a r r a y [ i s l _ i d x ] [ ’ node_2 ’ ]
1118
1119

1120 d = i n t ( math . s q r t (
1121 math . pow ( s e l f . s a t e l l i t e s _ a r r a y [ sat_1 ] [ ’ x ’ ] −
1122 s e l f . s a t e l l i t e s _ a r r a y [ sat_2 ] [ ’ x ’ ] , 2 ) +
1123 math . pow ( s e l f . s a t e l l i t e s _ a r r a y [ sat_1 ] [ ’ y ’ ] −
1124 s e l f . s a t e l l i t e s _ a r r a y [ sat_2 ] [ ’ y ’ ] , 2 ) +
1125 math . pow ( s e l f . s a t e l l i t e s _ a r r a y [ sat_1 ] [ ’ z ’ ] −
1126 s e l f . s a t e l l i t e s _ a r r a y [ sat_2 ] [ ’ z ’ ] , 2 ) ) )
1127 i f d > max_isl_range :
1128 s e l f . l i n k _ a r r a y [ i s l _ i d x ] [ ’ node_1 ’ ] = np . i n t 1 6 ( 0 )
1129 s e l f . l i n k _ a r r a y [ i s l _ i d x ] [ ’ node_2 ’ ] = np . i n t 1 6 ( 0 )
1130 s e l f . l i n k _ a r r a y [ i s l _ i d x ] [ ’ d i s t a n c e ’ ] = np . i n t 3 2 ( 0 )
1131 s e l f . l i n k _ a r r a y [ i s l _ i d x ] [ ’SNR ’ ] = np . f l o a t 3 2 ( 0 )
1132 else :
1133
1134 s e l f . l i n k _ a r r a y [ i s l _ i d x ] [ ’ d i s t a n c e ’ ] = np . i n t 3 2 ( d )
1135 s e l f . l i n k _ a r r a y [ i s l _ i d x ] [ ’ s t a t u s ’ ]= np . i n t 1 6 ( 0 )
1136

1137 if s e l f . s a t e l l i t e s _ a r r a y [ sat_1 ] [ ’ plane_number ’]== s e l f .


s a t e l l i t e s _ a r r a y [ sat_2 ] [ ’ plane_number ’ ] : # s a t e l l i t e a r e i n
t h e same p l a n e
1138 a n g l e s= l i n k b . s p a r s e _ a n g l e ( s e l f . s a t e l l i t e s _ a r r a y [ sat_1 ] [ ’ x ’ ] ,
s e l f . s a t e l l i t e s _ a r r a y [ sat_1 ] [ ’ y ’ ] ,
1139 s e l f . s a t e l l i t e s _ a r r a y [ sat_1 ] [ ’ z ’ ] , s e l f . s a t e l l i t e s _ a r r a y [ sat_2
] [ ’ x ’ ] , s e l f . s a t e l l i t e s _ a r r a y [ sat_2 ] [ ’ y ’ ] ,
1140 s e l f . s a t e l l i t e s _ a r r a y [ sat_2 ] [ ’ z ’ ] , s e l f . s a t e l l i t e s _ a r r a y [
sat_1 ] [ ’ vx ’ ] , s e l f . s a t e l l i t e s _ a r r a y [ sat_1 ] [ ’ vy ’ ] ,
1141 s e l f . s a t e l l i t e s _ a r r a y [ sat_1 ] [ ’ vz ’ ] , s e l f . s a t e l l i t e s _ a r r a y [
sat_2 ] [ ’ vx ’ ] , s e l f . s a t e l l i t e s _ a r r a y [ sat_2 ] [ ’ vy ’ ] ,
1142 s e l f . s a t e l l i t e s _ a r r a y [ sat_2 ] [ ’ vz ’ ] ) # I n t r a −p l a n e Angle
calculation
1143
1144 s n r=l i n k b . ISL_linkBudget ( d , a n g l e s [ 0 ] , a n g l e s [ 1 ] ,ANTENNA, s e l f .
communication_frequency , s e l f . transmission_power ,
1145 s e l f . bandwidth , s e l f . n o i s e _ f i g u r e ) # SNR c a l c u l a t i o n
1146

1147 i f snr > s e l f . snr_threshold :


1148 s e l f . l i n k _ a r r a y [ i s l _ i d x ] [ ’ s t a t u s ’ ]= np . i n t 1 6 ( 1 )
1149
1150 else :
1151 a n g l e s= l i n k b . c r o s s _ a n g l e ( s e l f . s a t e l l i t e s _ a r r a y [ sat_1 ] [ ’ x ’ ] ,
s e l f . s a t e l l i t e s _ a r r a y [ sat_1 ] [ ’ y ’ ] ,
1152 s e l f . s a t e l l i t e s _ a r r a y [ sat_1 ] [ ’ z ’ ] , s e l f . s a t e l l i t e s _ a r r a y [ sat_2
] [ ’ x ’ ] , s e l f . s a t e l l i t e s _ a r r a y [ sat_2 ] [ ’ y ’ ] ,
1153 s e l f . s a t e l l i t e s _ a r r a y [ sat_2 ] [ ’ z ’ ] , s e l f . s a t e l l i t e s _ a r r a y [ sat_1
] [ ’ vx ’ ] , s e l f . s a t e l l i t e s _ a r r a y [ sat_1 ] [ ’ vy ’ ] ,
1154 s e l f . s a t e l l i t e s _ a r r a y [ sat_1 ] [ ’ vz ’ ] , s e l f . s a t e l l i t e s _ a r r a y [
sat_2 ] [ ’ vx ’ ] , s e l f . s a t e l l i t e s _ a r r a y [ sat_2 ] [ ’ vy ’ ] ,
1155 s e l f . s a t e l l i t e s _ a r r a y [ sat_2 ] [ ’ vz ’ ] ) #i n t e r −p l a n e a n g l e
calculation
1156

Polytechnic University of Catalonia - Barcelona Tech - UPC 33


APPENDIX B. PYTHON SCRIPTS

1157 s n r=l i n k b . ISL_linkBudget ( d , a n g l e s [ 0 ] , a n g l e s [ 1 ] ,ANTENNA, s e l f .


communication_frequency , s e l f . transmission_power ,
1158 s e l f . bandwidth , s e l f . n o i s e _ f i g u r e ) #s n r c a l c u l a t i o n
1159
1160 s e l f . l i n k _ a r r a y [ i s l _ i d x ] [ ’SNR ’ ] = np . f l o a t 3 2 ( s n r )
1161 i f snr > s e l f . snr_threshold :
1162 s e l f . l i n k _ a r r a y [ i s l _ i d x ] [ ’ s t a t u s ’ ]= np . i n t 1 6 ( 1 )
1163
1164
1165 # add t h e StG l i n k s
1166 f o r gnd_idx i n r a n g e (− s e l f . ground_node_counter ) :
1167 gnd_pos = [
1168 s e l f . g r o u n d p o i n t s _ a r r a y [ gnd_idx ] [ ’ x ’ ] ,
1169 s e l f . g r o u n d p o i n t s _ a r r a y [ gnd_idx ] [ ’ y ’ ] ,
1170 s e l f . g r o u n d p o i n t s _ a r r a y [ gnd_idx ] [ ’ z ’ ]
1171 ]
1172
1173 f o r sat_idx in range ( s e l f . t o t a l _ s a t s ) :
1174 # calculate distance
1175 d = i n t ( math . s q r t (
1176 math . pow ( s e l f . s a t e l l i t e s _ a r r a y [ s a t _ i d x ] [ ’ x ’ ] − gnd_pos [ 0 ] , 2 ) +
1177 math . pow ( s e l f . s a t e l l i t e s _ a r r a y [ s a t _ i d x ] [ ’ y ’ ] − gnd_pos [ 1 ] , 2 ) +
1178 math . pow ( s e l f . s a t e l l i t e s _ a r r a y [ s a t _ i d x ] [ ’ z ’ ] − gnd_pos [ 2 ] , 2 ) ) )
1179
1180 # d e i c i d e i f l i n k i s v a l i d o r not
1181 i f d < max_stg_range :
1182 i f link_idx < s e l f . link_array_size − 1:
1183 gnd_id = s e l f . g r o u n d p o i n t s _ a r r a y [ gnd_idx ] [ ’ ID ’ ]
1184 s a t _ i d = s e l f . s a t e l l i t e s _ a r r a y [ s a t _ i d x ] [ ’ ID ’ ]
1185 s e l f . l i n k _ a r r a y [ l i n k _ i d x ] [ ’ node_1 ’ ] = gnd_id
1186 s e l f . l i n k _ a r r a y [ l i n k _ i d x ] [ ’ node_2 ’ ] = s a t _ i d
1187 s e l f . l i n k _ a r r a y [ l i n k _ i d x ] [ ’ d i s t a n c e ’ ] = np . i n t 3 2 ( d )
1188 s e l f . l i n k _ a r r a y [ l i n k _ i d x ] [ ’ s t a t u s ’ ]= np . i n t 1 6 ( 0 )
1189 snrd , s n r u= l i n k b . GSL_linkBudget ( d , s e l f . s a t e l l i t e s _ a r r a y [
sat_idx ] [ ’ x ’ ] , s e l f . s a t e l l i t e s _ a r r a y [ sat_idx ] [ ’ y ’ ] , s e l f .
s a t e l l i t e s _ a r r a y [ sat_idx ] [ ’ z ’ ] ,
1190 gnd_pos [ 0 ] , gnd_pos [ 1 ] , gnd_pos [ 2 ] ,ANTENNA, ANTENNA_GS ) #
downlink and u p l i n k SNR c a l c u l a t i o n
1191
1192 i f s n r u >= 9 . 5 and s n r d >= 9 . 5 :
1193 s e l f . l i n k _ a r r a y [ l i n k _ i d x ] [ ’ s t a t u s ’ ]= np . i n t 1 6 ( 1 )
1194
1195 link_idx = link_idx + 1
1196 else :
1197 p r i n t ( ’ERROR! ran out o f room i n t h e l i n k a r r a y ’ )
1198 return
1199
1200 s e l f . number_of_gnd_links = l i n k _ i d x − s e l f . n u m b e r _ o f _ i s l _ l i n k s
1201 s e l f . total_links = link_idx
1202
1203 @staticmethod
1204 @numba . j i t ( nopython=True )
1205 def numba_calculatePlusGridLinks (
1206 max_stg_range ,
1207 total_sats ,
1208 satellites_array ,

Polytechnic University of Catalonia - Barcelona Tech - UPC 34


APPENDIX B. PYTHON SCRIPTS

1209 link_array ,
1210 groundpoints_array ,
1211 ground_node_counter ,
1212 link_array_size ,
1213 number_of_planes ,
1214 nodes_per_plane ,
1215 number_of_isl_links ,
1216 arcOfAscendingNodes = 3 6 0 . 0 ,
1217 i n i t i a l i z e =F a l s e ,
1218 c r o s s l i n k _ i n t e r p o l a t i o n =1,
1219 max_isl_range =(2∗∗31) −1) :
1220 """
1221 f i g u r e out a l l p o s s i b l e i n t e r − s a t e l l i t e l i n k s
1222 f o r each s a t e l l i t e , with a d i s t a n c e l e s s than max_coms_range
1223
1224 Parameters
1225 −−−−−−−−−−
1226 max_stg_range : i n t
1227 t h e max space −ground coms r a n g e
1228 i n i t i a l i z e : bool
1229 Because PlusGrid ISL a r e s t a t i c , they o n l y need t o be g e n e r a t e d once ,
1230 I f i n i t i a l i z e =F a l s e , o n l y update l i n k d i s t a n c e s , do not r e g e r e r a t e
1231 crosslink_interpolation : int
1232 This v a l u e i s used t o make o n l y 1 out o f e v e r y
crosslink_interpolation
1233 s a t e l l i t e s a b l e t o have c r o s s l i n k s . For example , with a i n t e r p o l a t i o n
1234 v a l u e o f ’ 2 ’ , o n l y e v e r y o t h e r s a t e l l i t e w i l l have c r o s s l i n k s , t h e
rest
1235 w i l l have o n l y i n t r a −p l a n e l i n k s
1236
1237 """
1238
1239 if initialize :
1240
1241 link_idx = 0
1242
1243 # add t h e i n t r a −p l a n e l i n k s
1244 f o r p l a n e i n r a n g e ( number_of_planes ) :
1245 f o r node i n r a n g e ( nodes_per_plane ) :
1246 node_1 = node + ( p l a n e ∗ nodes_per_plane )
1247 i f node == nodes_per_plane − 1 :
1248 node_2 = p l a n e ∗ nodes_per_plane
1249 else :
1250 node_2 = node + ( p l a n e ∗ nodes_per_plane ) + 1
1251
1252 i f link_idx < link_array_size − 1:
1253 l i n k _ a r r a y [ l i n k _ i d x ] [ ’ node_1 ’ ] = np . i n t 1 6 ( node_1 )
1254 l i n k _ a r r a y [ l i n k _ i d x ] [ ’ node_2 ’ ] = np . i n t 1 6 ( node_2 )
1255 link_idx = link_idx + 1
1256 else :
1257 p r i n t ( ’ERROR! ran out o f room i n t h e l i n k a r r a y f o r i n t r a −p l a n e
links ’ )
1258 return
1259 # add t h e c r o s s −p l a n e l i n k s
1260 f o r p l a n e i n r a n g e ( number_of_planes ) :
1261 i f p l a n e == number_of_planes − 1 :

Polytechnic University of Catalonia - Barcelona Tech - UPC 35


APPENDIX B. PYTHON SCRIPTS

1262 plane2 = 0
1263 #XXX: AlMa −−− Exclude seam l i n k s
1264 i f arcOfAscendingNodes == 1 8 0 . 0 :
1265 break
1266 #break
1267 else :
1268 plane2 = plane + 1
1269 f o r node i n r a n g e ( nodes_per_plane ) :
1270 node_1 = node + ( p l a n e ∗ nodes_per_plane )
1271 node_2 = node + ( p l a n e 2 ∗ nodes_per_plane )
1272 i f link_idx < link_array_size − 1:
1273 i f ( node_1 + 1 ) % c r o s s l i n k _ i n t e r p o l a t i o n == 0 :
1274 l i n k _ a r r a y [ l i n k _ i d x ] [ ’ node_1 ’ ] = np . i n t 1 6 ( node_1 )
1275 l i n k _ a r r a y [ l i n k _ i d x ] [ ’ node_2 ’ ] = np . i n t 1 6 ( node_2 )
1276 link_idx = link_idx + 1
1277 else :
1278 p r i n t ( ’ERROR! ran out o f room i n t h e l i n k a r r a y f o r c r o s s −p l a n e
links ’ )
1279 return
1280
1281 number_of_isl_links = link_idx
1282
1283 link_idx = number_of_isl_links
1284
1285 # update ISL l i n k d i s t a n c e s
1286 f o r i s l _ i d x in range ( number_of_isl_links ) :
1287 sat_1 = l i n k _ a r r a y [ i s l _ i d x ] [ ’ node_1 ’ ]
1288 sat_2 = l i n k _ a r r a y [ i s l _ i d x ] [ ’ node_2 ’ ]
1289 d = i n t ( math . s q r t (
1290 math . pow ( s a t e l l i t e s _ a r r a y [ sat_1 ] [ ’ x ’ ] − s a t e l l i t e s _ a r r a y [ sat_2 ] [ ’ x ’
] , 2) +
1291 math . pow ( s a t e l l i t e s _ a r r a y [ sat_1 ] [ ’ y ’ ] − s a t e l l i t e s _ a r r a y [ sat_2 ] [ ’ y ’
] , 2) +
1292 math . pow ( s a t e l l i t e s _ a r r a y [ sat_1 ] [ ’ z ’ ] − s a t e l l i t e s _ a r r a y [ sat_2 ] [ ’ z ’
] , 2) ) )
1293 i f d > max_isl_range :
1294 l i n k _ a r r a y [ i s l _ i d x ] [ ’ node_1 ’ ] = np . i n t 1 6 ( 0 )
1295 l i n k _ a r r a y [ i s l _ i d x ] [ ’ node_2 ’ ] = np . i n t 1 6 ( 0 )
1296 l i n k _ a r r a y [ i s l _ i d x ] [ ’ d i s t a n c e ’ ] = np . i n t 3 2 ( 0 )
1297 else :
1298 l i n k _ a r r a y [ i s l _ i d x ] [ ’ d i s t a n c e ’ ] = np . i n t 3 2 ( d )
1299
1300 # add t h e StG l i n k s
1301 f o r gnd_idx i n r a n g e (−ground_node_counter ) :
1302 gnd_pos = [
1303 g r o u n d p o i n t s _ a r r a y [ gnd_idx ] [ ’ x ’ ] ,
1304 g r o u n d p o i n t s _ a r r a y [ gnd_idx ] [ ’ y ’ ] ,
1305 g r o u n d p o i n t s _ a r r a y [ gnd_idx ] [ ’ z ’ ]
1306 ]
1307
1308 f o r sat_idx in range ( t o t a l _ s a t s ) :
1309 # calculate distance
1310 d = i n t ( math . s q r t (
1311 math . pow ( s a t e l l i t e s _ a r r a y [ s a t _ i d x ] [ ’ x ’ ] − gnd_pos [ 0 ] , 2 ) +
1312 math . pow ( s a t e l l i t e s _ a r r a y [ s a t _ i d x ] [ ’ y ’ ] − gnd_pos [ 1 ] , 2 ) +
1313 math . pow ( s a t e l l i t e s _ a r r a y [ s a t _ i d x ] [ ’ z ’ ] − gnd_pos [ 2 ] , 2 ) ) )

Polytechnic University of Catalonia - Barcelona Tech - UPC 36


APPENDIX B. PYTHON SCRIPTS

1314
1315 # d e i c i d e i f l i n k i s v a l i d o r not
1316 i f d < max_stg_range :
1317 i f link_idx < link_array_size − 1:
1318 gnd_id = g r o u n d p o i n t s _ a r r a y [ gnd_idx ] [ ’ ID ’ ]
1319 s a t _ i d = s a t e l l i t e s _ a r r a y [ s a t _ i d x ] [ ’ ID ’ ]
1320 l i n k _ a r r a y [ l i n k _ i d x ] [ ’ node_1 ’ ] = gnd_id
1321 l i n k _ a r r a y [ l i n k _ i d x ] [ ’ node_2 ’ ] = s a t _ i d
1322 l i n k _ a r r a y [ l i n k _ i d x ] [ ’ d i s t a n c e ’ ] = np . i n t 3 2 ( d )
1323 link_idx = link_idx + 1
1324 else :
1325 p r i n t ( ’ERROR! ran out o f room i n t h e l i n k a r r a y ’ )
1326 return
1327
1328 number_of_gnd_links = l i n k _ i d x − n u m b e r _ o f _ i s l _ l i n k s
1329 total_links = link_idx
1330 r e t u r n [ number_of_isl_links , number_of_gnd_links , t o t a l _ l i n k s ]
1331

1332 d e f import_links_from_gml_data ( s e l f , l i n k s ) :
1333 " " " Takes a l i n k s array , and f i l l s i n t e r n a l l i n k s _ a r r a y with them .
1334
1335 Paramaters
1336 −−−−−−−−−−
1337 l i n k s : a r r a y [ [ ( i n t : node_1_ID ) , ( i n t : node_2_ID ) ] , . . . ]
1338 An a r r a y where each i n d e x i s a p a i r o f e n d p o i n t IDs d e s c r i b i n g a l i n k
.
1339
1340 """
1341

1342 link_idx = 0
1343
1344 # add t h e i n t e r s a t e l l i t e l i n k s
1345 f o r idx in range ( len ( l i n k s ) ) :
1346 node_1 = l i n k s [ i d x ] [ 0 ]
1347 node_2 = l i n k s [ i d x ] [ 1 ]
1348 # i f both node IDs a r e p o s i t i v e ( both s a t e l l i t e s )
1349 # we add them h e r e
1350 i f ( node_1 >= 0 ) and ( node_2 >= 0 ) :
1351 i f link_idx < s e l f . link_array_size − 1:
1352 s e l f . l i n k _ a r r a y [ l i n k _ i d x ] [ ’ node_1 ’ ] = np . i n t 1 6 ( node_1 )
1353 s e l f . l i n k _ a r r a y [ l i n k _ i d x ] [ ’ node_2 ’ ] = np . i n t 1 6 ( node_2 )
1354 link_idx = link_idx + 1
1355 else :
1356 p r i n t ( ’ERROR! ran out o f room i n t h e l i n k a r r a y f o r i n t r a −p l a n e
links ’ )
1357 r e t u r n None
1358
1359 s e l f . number_of_isl_links = link_idx
1360
1361 # no we go back o v e r t h e l i n k s array , and add
1362 # a l l t h e l i n k s i n v o l v i n g g r o u n d p o i n t s ( n e g a t i v e IDs )
1363 f o r idx in range ( len ( l i n k s ) ) :
1364 node_1 = l i n k s [ i d x ] [ 0 ]
1365 node_2 = l i n k s [ i d x ] [ 1 ]
1366 # i f one o f t h e IDs i s n e g a t i v e , i t i s a ground p o i n t
1367 i f ( node_1 < 0 ) o r ( node_2 < 0 ) :

Polytechnic University of Catalonia - Barcelona Tech - UPC 37


APPENDIX B. PYTHON SCRIPTS

1368 i f link_idx < s e l f . link_array_size − 1:


1369 s e l f . l i n k _ a r r a y [ l i n k _ i d x ] [ ’ node_1 ’ ] = np . i n t 1 6 ( node_1 )
1370 s e l f . l i n k _ a r r a y [ l i n k _ i d x ] [ ’ node_2 ’ ] = np . i n t 1 6 ( node_2 )
1371 link_idx = link_idx + 1
1372 else :
1373 p r i n t ( ’ERROR! ran out o f room i n t h e l i n k a r r a y f o r i n t r a −p l a n e
links ’ )
1374 r e t u r n None
1375
1376 s e l f . number_of_gnd_links = l i n k _ i d x − s e l f . n u m b e r _ o f _ i s l _ l i n k s
1377 s e l f . total_links = link_idx

B.3 Linkb.py
1 #Link budget f u n c t i o n s
2 import math
3 import numpy a s np
4

5 d e f c r o s s _ a n g l e ( xsat1 , ysat1 , z s a t 1 , xsat2 , ysat2 , z s a t 2 , vxsat1 , vysat1 , v z s a t 1 ,


vxsat2 , vysat2 , v z s a t 2 ) : # c a l c u l a t i o n o f communication a n g l e s o f a n t e n n a s
i n i n t e r −p l a n e communications
6
7 sat1_p=np . a r r a y ( [ xsat1 , ysat1 , z s a t 1 ] , dtype= ’ i n t 6 4 ’ ) # p o s i t i o n v e c t o r o f
the sat1
8 sat1_v=np . a r r a y ( [ vxsat1 , vysat1 , v z s a t 1 ] , dtype= ’ i n t 6 4 ’ ) # v e l o c i t y v e c t o r
sat1
9 sat2_p=np . a r r a y ( [ xsat2 , ysat2 , z s a t 2 ] , dtype= ’ i n t 6 4 ’ ) # p o s i t i o n v e c t o r o f
the sat2
10 sat2_v= np . a r r a y ( [ vxsat2 , vysat2 , v z s a t 2 ] , dtype= ’ i n t 6 4 ’ ) ;# v e l o c i t y
vector sat2
11 s a t 1 _ s a t 2= np . a r r a y ( [ xsat1 −xsat2 , ysat1 −ysat2 , z s a t 1 −z s a t 2 ] , dtype= ’ i n t 6 4 ’
) ; #Link d i r e c t i o n
12 s a t 1 _ c r o s s=np . c r o s s ( sat1_p , sat1_v ) # o b t a i n i n g t h e d i r e c t i o n v e c t o r o f
t h e s i d e antenna with t h e c r o s s p r o d u c t
13 s a t 2 _ c r o s s=np . c r o s s ( sat2_p , sat2_v ) # o b t a i n i n g t h e d i r e c t i o n v e c t o r o f
t h e s i d e antenna with t h e c r o s s p r o d u c t
14
15 v1=s a t 1 _ c r o s s /np . l i n a l g . norm ( s a t 1 _ c r o s s ) # Vector n o r m a l i z a t i o n
16 v2=s a t 2 _ c r o s s /np . l i n a l g . norm ( s a t 2 _ c r o s s )
17 v3=s a t 1 _ s a t 2 /np . l i n a l g . norm ( s a t 1 _ s a t 2 )
18 t h e t a _ s a t 1=np . d e g r e e s ( np . a r c c o s ( np . c l i p ( np . dot ( v1 , v3 ) , −1.0 , 1 . 0 ) ) ) #
a n g l e between s a t 1 _ c r o s s and t h e l i n k d i r e c t i o n
19 t h e t a _ s a t 2=np . d e g r e e s ( np . a r c c o s ( np . c l i p ( np . dot ( v2 , v3 ) , −1.0 , 1 . 0 ) ) ) #
a n g l e between s a t 2 _ c r o s s and t h e l i n k d i r e c t i o n
20
21 i f theta_s at1 >90: # The a n g l e must be 90 d e g r e e s maximum
22 t h e t a _ s a t 1 =180− t h e t a _ s a t 1 ;
23 i f t h e t a _ s a t 2 >90:
24 t h e t a _ s a t 2 =180− t h e t a _ s a t 2
25
26
27 r e t u r n theta_sat1 , t h e t a _ s a t 2
28

Polytechnic University of Catalonia - Barcelona Tech - UPC 38


APPENDIX B. PYTHON SCRIPTS

29 d e f s p a r s e _ a n g l e ( xsat1 , ysat1 , z s a t 1 , xsat2 , ysat2 , z s a t 2 , vxsat1 , vysat1 , v z s a t 1 ,


vxsat2 , vysat2 , v z s a t 2 ) :
30 sat1_v=np . a r r a y ( [ vxsat1 , vysat1 , v z s a t 1 ] ) # v e l o c i t y v e c t o r s a t 1
31 sat2_v= np . a r r a y ( [ vxsat2 , vysat2 , v z s a t 2 ] )# v e l o c i t y v e c t o r s a t 2
32 s a t 1 _ s a t 2= np . a r r a y ( [ xsat1 −xsat2 , ysat1 −ysat2 , z s a t 1 −z s a t 2 ] ) # Link
direction
33
34 v1=sat1_v /np . l i n a l g . norm ( sat1_v ) # v e c t o r n o r m a l i z a t i o n
35 v2=sat2_v /np . l i n a l g . norm ( sat2_v )
36 v3=s a t 1 _ s a t 2 /np . l i n a l g . norm ( s a t 1 _ s a t 2 )
37
38

39 t h e t a _ s a t 1 =180−np . d e g r e e s ( np . a r c c o s ( np . c l i p ( np . dot ( v1 , v3 ) , −1.0 , 1 . 0 ) )


) # a n g l e between sat1_v and t h e l i n k d i r e c t i o n
40 t h e t a _ s a t 2 =180−np . d e g r e e s ( np . a r c c o s ( np . c l i p ( np . dot ( v2 , v3 ) , −1.0 , 1 . 0 ) )
) # a n g l e between sat2_v and t h e l i n k d i r e c t i o n
41
42 r e t u r n theta_sat1 , t h e t a _ s a t 2
43
44
45
46
47 d e f ISL_linkBudget ( d , theta_sat 1 , theta_sat 2 , antena , f , Pt , B, NF) :
48 i f d==0:
49 return (0)
50 else :
51 c =299792458 # l i g h t s p e e d
52 k= −228.6 # Boltzmann c o n s t a n t dBW/K/Hz
53 B=10∗np . l o g 1 0 (B∗ 1 0 ∗ ∗ 3 ) ; #Bandwidth dBHz
54 f=f ∗10∗∗9 #l i n k f r e c u e n c y
55 lamda=c / f
56 Pt=10∗np . l o g 1 0 ( Pt ) #t r a n s m i t e d power i n dBW
57 # o b t a i n i n g t h e g a i n s with t h e r a d i a t i o n p a t t e r n o f t h e a n t e n n a s
58 t h e t a=antena . k e y s ( )
59 t h e t a= l i s t ( t h e t a )
60 g a i n=antena . v a l u e s ( )
61 g a i n= l i s t ( g a i n )
62 Gsat1=np . i n t e r p ( thet a_sat1 , t h e t a , g a i n )
63 Gsat2=np . i n t e r p ( thet a_sat2 , t h e t a , g a i n )
64
65 Lf =20∗np . l o g 1 0 ( 4 ∗ math . p i ∗d/ lamda ) ; # f r e e s p a c e l o s s e s dB
66 Pr=Pt+Gsat1+Gsat2−Lf # R e c e i v e d Power i n dB
67 Tant=22 # antenna t e m p e r a t u r e i n K
68 T0=290 # r e f e r e n c e t e m p e r a t u r i n K
69 n f =10∗∗(NF/ 1 0 ) # N o i s e f i g u r e
70 Tsyst =10∗np . l o g 1 0 ( Tant+T0∗ ( nf −1) ) # System t e m p e r a t u r e i n dB
71 Nout=k+B+Tsyst # N o i s e power dBW
72 SNR=Pr−Nout # S i g n a l −to−n o i s e r a t i o
73
74 r e t u r n SNR
75
76 d e f minpower ( d , theta_sat1 , theta_sat2 , antena , f , pr ) : # f u n c t i o n f o r
c a l c u l a t i n g t h e r e q u i r e d t r a n s m i t t e d power o f ISLs
77
78 c =299792458 # l i g h t s p e e d
79 k= −228.6 # Boltzmann c o n s t a n t dBW/K/Hz

Polytechnic University of Catalonia - Barcelona Tech - UPC 39


APPENDIX B. PYTHON SCRIPTS

80 f=f ∗10∗∗9 #l i n k f r e c u e n c y
81 lamda=c / f
82 Lf =20∗np . l o g 1 0 ( 4 ∗ math . p i ∗d/ lamda ) # f r e e s p a c e l o s s e s
83
84 Pr=pr −30 # R e c e i v e r s e n s i t i v i t y i n dB
85

86 #Antennas g a i n s
87 t h e t a=antena . k e y s ( )
88 t h e t a= l i s t ( t h e t a )
89 g a i n=antena . v a l u e s ( )
90 g a i n= l i s t ( g a i n )
91 Gsat1=np . i n t e r p ( thet a_sat1 , t h e t a , g a i n )
92 Gsat2=np . i n t e r p ( thet a_sat2 , t h e t a , g a i n )
93
94 Pt=Pr−Gsat1−Gsat2+Lf # Transmitted power r e q u i r e d
95
96 r e t u r n 1 0 ∗ ∗ ( Pt / 1 0 )
97

98
99
100
101
102 d e f GSL_linkBudget ( d , xsat , ysat , z s a t , xgs , ygs , zgs , antenna_sat , antenna_gs ) :
103 i f d==0:
104 return (0)
105 else :
106 Dgs =1.5 # g s antenna d i a m e t e r i n m
107 e f f =0.8 # Antenna e f f i e n c y
108 c =299792458 # l i g h t s p e e d
109 k= −228.6 # Boltzmann c o n s t a n t dBW/K/Hz
110 B=10∗np . l o g 1 0 ( 5 1 2 ∗ 1 0 ∗ ∗ 3 ) ; #Bandwidth dBHz
111 T0=290
112 r_earth =6371000
113 gs_v=np . a r r a y ( [ xgs , ygs , z g s ] ) ; # g s t o Earth c e n t e r v e c t o r
114 sat_v= np . a r r a y ( [ xsat , ysat , z s a t ] ) ;# s a t t o Eath c e n t e r v e c t o r
115 sat_gs= np . a r r a y ( [ xsat −xgs , ysat −ygs , z s a t −z g s ] ) ; # Link d i r e c t i o n
116
117 v1=gs_v/np . l i n a l g . norm ( gs_v )
118 v2=sat_v /np . l i n a l g . norm ( sat_v )
119 v3=sat_gs /np . l i n a l g . norm ( sat_gs )
120

121 t h e t a _ s a t=np . d e g r e e s ( np . a r c c o s ( np . c l i p ( np . dot ( v1 , v3 ) , −1.0 , 1 . 0 ) ) ) #


a n g l e between sat_v and sat_gs
122 theta_gs=np . d e g r e e s ( np . a r c c o s ( np . c l i p ( np . dot ( v2 , v3 ) , −1.0 , 1 . 0 ) ) ) #
a n g l e between gs_v and sat_gs i f t h e antenna i s f i x e d
123

124
125 #S a t e l l i t e antenna r a d i a t i o n p a t t e r n
126 theta_s=antenna_sat . k e y s ( ) ;
127 theta_s= l i s t ( theta_s ) ;
128 gain_s=antenna_sat . v a l u e s ( ) ;
129 gain_s= l i s t ( gain_s ) ;
130 Gsat=np . i n t e r p ( theta_sat , theta_s , gain_s ) # s a t antenna g a i n with
radiation pattern
131
132

Polytechnic University of Catalonia - Barcelona Tech - UPC 40


APPENDIX B. PYTHON SCRIPTS

133 # GS antenna r a d i a t i o n p a t t e r n
134 #theta_g=antenna_gs . k e y s ( ) ;
135 #theta_g= l i s t ( theta_g ) ;
136 #gain_g=antenna_gs . v a l u e s ( ) ;
137 #gain_g= l i s t ( gain_g ) ;
138

139
140
141 ######### E l e v a t i o n Angle ##########
142 #H=math . s q r t ( math . pow ( xsat , 2 ) + math . pow ( ysat , 2 ) + math . pow ( z s a t , 2 ) )−
r_earth
143 #s i n E I =(H∗ (H+2∗ r_earth )−d ∗ ∗ 2 ) / ( 2 ∗ d∗ r_earth )
144 #i f s i n E I <=1:
145 # EI=math . d e g r e e s ( math . a s i n ( s i n E I ) )
146 #e l s e :
147 # EI=90
148
149 ###### Atmospheric L o s s e s #######
150 #fGhz=f ∗10∗∗( −9)
151 #gamma_0=( 7 . 1 / ( f ∗∗2+0.36) + 4 . 5 / ( ( fGhz −57) ∗∗2+0.98) ) ∗ fGhz ∗∗2
∗10∗∗( −3)
152 #gamma_w=( 0 . 0 6 7 + 3 / ( ( fGhz −22.3) ∗∗2+7.3) ) ∗12∗ fGhz ∗∗2 ∗10∗∗( −4)
153 #h_w=2.2+ 3/ ( ( fGhz −22.3) ∗∗2 + 3 )
154 #hs =0.3
155 #L_gd = (gamma_0∗6∗ np . e ∗∗(− hs / 6 ) + gamma_w∗h_w) / s i n E I
156
157
158 #Downlink
159 f =437∗10∗∗6; #downlink f r e c u e n c y
160 lamda=c / f #
161 Ggs=10∗np . l o g 1 0 ( e f f ∗ ( np . p i ∗Dgs∗ f / c ) ∗ ∗ 2 ) # GS antenna g a i n with f o r m u l a
162 #Ggs=np . i n t e r p ( theta_gs , theta_g , gain_g ) # GS antenna g a i n with
radiation pattern
163 Pt=10∗np . l o g 1 0 ( 1 ) ; # Downlink t r a n s m i t t e d power
164 Lfd =20∗np . l o g 1 0 ( 4 ∗ np . p i ∗d/ lamda ) ; # Free s p a c e l o s s e
165 Pr=Pt+Ggs+Gsat−Lfd ; # R e c e i v e d power dB
166 NF=3 # R e c e i v e r n o i s e f i g u r e (GS)
167 Tant=290 # Antenna t e m p e r a t u r e
168 Tsyst =10∗np . l o g 1 0 ( Tant+T0 ∗ ( 1 0 ∗ ∗ (NF/ 1 0 ) −1) ) ; # System t e m p e r a t u r e dB
169 Nout=k+Tsyst+B # N o i s e power dBW
170 SNRd=Pr−Nout # Downlink SNR
171
172 #Uplink
173 f =146∗10∗∗6; #u p l i n k f r e c u e n c y
174 lamda=c / f ;
175 Ggs=10∗np . l o g 1 0 ( e f f ∗ ( np . p i ∗Dgs∗ f / c ) ∗ ∗ 2 ) # GS antenna g a i n with f o r m u l a
176 #Ggs=np . i n t e r p ( theta_gs , theta_g , gain_g ) # GS antenna g a i n with
radiation pattern
177 Pt=10∗np . l o g 1 0 ( 7 0 ) # Uplink t r a n s m i t e d power i n dBW
178 Lfu =20∗np . l o g 1 0 ( 4 ∗ np . p i ∗d/ lamda ) # Free s p a c e l o s s e s
179 Pr=Pt+Ggs+Gsat−Lfu # R e c e i v e d power dB
180 NF=2.05 # R e c e i v e r n o i s e f i g u r e ( s a t e l l i t e )
181 Tant=290 # Antenna t e m p e r a t u r e
182 Tsyst =10∗np . l o g 1 0 ( Tant+T0 ∗ ( 1 0 ∗ ∗ (NF/ 1 0 ) −1) ) # System t e m p e r a t u r e
183 Nout=k+Tsyst+B # N o i s e Power dB
184 SNRu=Pru−Nout # Uplink SNR

Polytechnic University of Catalonia - Barcelona Tech - UPC 41


APPENDIX B. PYTHON SCRIPTS

185
186 r e t u r n SNRd, SNRu

B.4 Simulation.py
1 # used t o make program f a s t e r & r e s p o n s i v e
2 import t h r e a d i n g a s td
3
4 # memory a l i g n e d a r r a y s t h e i r m a n i p u l a t i o n f o r Python
5 import numpy a s np
6
7 # custom c l a s s e s
8 from c o n s t e l l a t i o n import C o n s t e l l a t i o n , RAAN
9
10 # OpenGL API f o r Python
11 import vtk
12
13 # P r i m a r i l y u s i n g t h e write_gml ( ) f u n c t i o n . . .
14 import networkx a s nx
15
16 # u s e t o measure program p e r f o r m a n c e ( sim f r a m e r a t e )
17 import time
18

19
20 # t r y t o import numba f u n c s
21 try :
22 import numba_funcs a s n f
23 USING_NUMBA = F a l s e
24 e x c e p t ModuleNotFoundError :
25 USING_NUMBA = F a l s e
26 p r i n t ( " you p r o b a b l y do not have numba i n s t a l l e d . . . " )
27 p r i n t ( " r e v e r t i n g t o non−numba mode " )
28
29
30 #################### GLOBAL VARS ##############################
31
32 EARTH_RADIUS = 6371000 # r a d i u s o f Earth i n m e t e r s
33
34 PNG_OUTPUT_PATH = " p i c s /p " # where t o s a v e images o f t h e a n i m a t i o n
35 GML_OUTPUT_PATH = ’ gmls / g ’ # where t o s a v e gml f i l e s
36

37 MIN_SAT_ELEVATION = 30 # degrees
38
39 LANDMASS_OUTLINE_COLOR = ( 0 . 0 , 0 . 0 , 0 . 0 ) # bla ck , b e s t c o n t r a s t
40 EARTH_LAND_OPACITY = 1 . 0
41

42 EARTH_BASE_COLOR = ( 0 . 6 , 0 . 6 , 0 . 8 ) # l i g h t blue , l i k e water !


43 EARTH_OPACITY = 1 . 0
44
45 BACKGROUND_COLOR = ( 1 . 0 , 1 . 0 , 1 . 0 ) # white
46
47 SAT_COLOR = ( 1 . 0 , 0 . 0 , 0 . 0 ) # red , c o l o r o f s a t e l l i t e s
48 SAT_OPACITY = 1 . 0
49

Polytechnic University of Catalonia - Barcelona Tech - UPC 42


APPENDIX B. PYTHON SCRIPTS

50 GND_COLOR = ( 0 . 0 , 1 . 0 , 0 . 0 ) # green , c o l o r o f g r o u n d s t a t i o n s
51 GND_OPACITY = 1 . 0
52
53 ISL_LINK_COLOR = ( 0 . 9 , 0 . 5 , 0 . 1 ) # y e l l o w −brown , s a t e l l i t e − s a t e l l i t e l i n k s
54 ISL_LINK_OPACITY = 1 . 0
55 ISL_LINE_WIDTH = 3 # how wide t o draw l i n e i n p i x e l s
56
57 SGL_LINK_COLOR = ( 0 . 5 , 0 . 9 , 0 . 5 ) # g r e e n i s h ? s a t e l l i t e −g r o u n d s t a t i o n l i n k s
58 SGL_LINK_OPACITY = 0 . 7 5
59 SGL_LINE_WIDTH = 2 # how wide t o draw l i n e i n p i x e l s
60
61 PATH_LINK_COLOR = ( 0 . 8 , 0 . 2 , 0 . 8 ) # p u r p l e i s h ? path l i n k s
62 PATH_LINK_OPACITY = 0 . 7
63 PATH_LINE_WIDTH = 13 # how wide t o draw l i n e i n p i x e l s
64
65 EARTH_SPHERE_POINTS = 5000 # h i g h e r = smoother e a r t h model , s l o w e r t o
generate
66

67 SAT_POINT_SIZE = 9 # how b i g s a t e l l i t e s a r e i n ( p r o b a b l y ) s c r e e n p i x e l s
68 GND_POINT_SIZE = 8 # how b i g ground p o i n t s a r e i n ( p r o b a b l y ) s c r e e n p i x e l s
69
70 SECONDS_PER_DAY = 86400 # number o f s e c o n d s p e r e a r t h r o t a t i o n ( day )
71 SPEED_OF_LIGHT_M_PER_S = 2 9 9 7 9 2 4 5 8 . 0
72
73
74 d e f getFileNumber ( var ) :
75 """
76 Makes a n i c e i n t with l e a d i n g z e r o s f o r f i l e naming
77

78 Attributes
79 −−−−−−−−−−
80 var : i n t
81 an i n t t h a t w i l l be used t o l a b e l e x p o r t f i l e s
82
83 Returns
84 −−−−−−−
85 string : string
86 a 7 char int , using l e a d i n g z e r o s
87 """
88
89 mask = [ ’ 0 ’ , ’ 0 ’ , ’ 0 ’ , ’ 0 ’ , ’ 0 ’ , ’ 0 ’ , ’ 0 ’ ]
90 var = l i s t ( s t r ( var ) )
91 t = l e n ( mask ) − l e n ( var )
92 f o r i i n r a n g e ( l e n ( var ) ) :
93 mask [ i+t ] = var [ i ]
94 r e t u r n ’ ’ . j o i n ( mask )
95
96
97 #
##############################################################################

98 # SIMULATION CONTROL
#
99 #
##############################################################################

Polytechnic University of Catalonia - Barcelona Tech - UPC 43


APPENDIX B. PYTHON SCRIPTS

100
101
102 c l a s s Simulation () :
103
104 d e f __init__ (
105 self ,
106 pipeConn=None ,
107 p l a n e s =1,
108 nodesPerPlane =1,
109 i n c l i n a t i o n =70 ,
110 f r e q u e n c y =1,
111 t r a n s m i s s i o n P o w e r =1.0 ,
112 bandwidth =1.0 ,
113 n o i s e F i g u r e =1.0 ,
114 r e c e i v e r S e n s i t i v i t y =1.0 ,
115 s n r =0.0 ,
116 semiMajorAxis =6472000 ,
117 t i m e S t e p =10 ,
118 makeLinks=True ,
119 animate=True ,
120 c a p t u r e I m a g e s=F a l s e ,
121 c a p t u r e I n t e r p o l a t i o n =1,
122 captureGML=F a l s e ,
123 g r o u n d P t s F i l e= ’ c i t y _ d a t a . t x t ’ ,
124 gmlImportFileName=None ) :
125
126 i f gmlImportFileName i s not None :
127 # t r y t o import t h e g i v e n f i l e a s a networkX graph
128 try :
129 G = nx . read_gml ( gmlImportFileName )
130 e x c e p t FileNotFoundError a s e r r o r :
131 p r i n t ( "ERROR! t r i e d t o import gml f i l e , f i l e not found \n " , e r r o r )
132 r e t u r n None
133
134 # assuming gml import worked , we e x t r a c t t h e s i m u l a t i o n
135 # s t r u c t u r e data l i k e time , num−p l a n e s , i n c l i n a t i o n . . . e t c
136 # c o n s t i l l a t i o n structure information
137 s e l f . num_planes = i n t (G. graph [ ’ numPlanes ’ ] )
138 s e l f . num_nodes_per_plane = i n t (G. graph [ ’ numNodesPerPlane ’ ] )
139 s e l f . p l a n e _ i n c l i n a t i o n = f l o a t (G. graph [ ’ p l a n e I n c l i n a t i o n ’ ] )
140 s e l f . communication_frequency = f l o a t (G. graph [ ’ f r e q u e n c y ’ ] )
141 s e l f . t r a n s m i s s i o n _ p o w e r = f l o a t (G. graph [ ’ t r a n s m i s s i o n P o w e r ’ ] )
142 s e l f . bandwidth= f l o a t (G. graph [ ’ bandwidth ’ ] )
143 s e l f . n o i s e _ f i g u r e=f l o a t (G. graph [ ’ n o i s e F i g u r e ’ ] )
144 s e l f . r e c e i v e r _ s e n s i t i v i t y=f l o a t (G. graph [ ’ r e c e i v e r S e n s i t i v i t y ’ ] )
145 s e l f . snr_minimum= f l o a t (G. graph [ ’ s n r ’ ] )
146 s e l f . semi_major_axis = i n t ( f l o a t (G. graph [ ’ semiMajorAxisMeters ’ ] ) )
147 s e l f . min_communications_altitude = i n t (G. graph [ ’
minCommunicationsAltitudeMeters ’ ] )
148 s e l f . m i n _ s a t _ e l e v a t i o n = i n t (G. graph [ ’ m i n S a t E l e v a t i o n D e g r e e s ’ ] )
149
150

151 # path c a l c u l a t i o n
152 s e l f . path_node_1 = None
153 s e l f . path_node_2 = None
154 s e l f . path_length = 0 . 0

Polytechnic University of Catalonia - Barcelona Tech - UPC 44


APPENDIX B. PYTHON SCRIPTS

155 s e l f . p a t h _ l i n k s = None
156 s e l f . max_node_degree = −1
157
158 # control flags
159 s e l f . animate = True
160 s e l f . capture_gml = F a l s e
161 s e l f . capture_images = F a l s e
162 s e l f . capt_interpolation = 1
163 s e l f . make_links = True
164 s e l f . linking_method = ’+GRID ’ # used b e c a u s e i t d o e s not r e g e n e r a t e
links
165 s e l f . enable_path_calculation = False
166
167 # timing c o n t r o l
168 s e l f . time_step = 1
169 s e l f . c u r r e n t _ s i m u l a t i o n _ t i m e = i n t ( f l o a t (G. graph [ ’ s i m u l a t i o n T i m e ’ ] ) )
170 s e l f . pause = True
171 s e l f . num_steps_to_run = −1
172
173 # p e r f o r m a n c e data
174 s e l f . time_1 = 1
175 s e l f . time_for_frame = 1
176 s e l f . time_to_update_model = 1
177 s e l f . time_to_export_gml = 1
178 s e l f . time_to_update_render = 1
179 s e l f . time_to_export_img = 1
180
181 # g e t a l l o f t h e edge data
182 edge_data = l i s t (G. e d g e s ( ) )
183 # r e t u r n s i n data i n s t r i n g format , s o I c o n v e r t data t o i n t s
184 f o r i i n r a n g e ( l e n ( edge_data ) ) :
185 edge_data [ i ] = [ i n t ( edge_data [ i ] [ 0 ] ) , i n t ( edge_data [ i ] [ 1 ] ) ]
186
187 # i n i t t h e ’ p i p e ’ o b j e c t used f o r i n t e r −p r o c e s s communication
188 # t h i s comes from t h e m u l t i p r o c e s s i n g l i b r a r y
189 s e l f . pipeConn = pipeConn
190 s e l f . c o n t r o l T h r e a d = td . Thread ( t a r g e t= s e l f . c o n t r o l T h r e a d H a n d l e r )
191 s e l f . controlThread . s t a r t ()
192
193 # i n i t t h e C o n s t e l l a t i o n model
194 s e l f . model = C o n s t e l l a t i o n (
195 p l a n e s= s e l f . num_planes ,
196 nodes_per_plane= s e l f . num_nodes_per_plane ,
197 i n c l i n a t i o n= s e l f . p l a n e _ i n c l i n a t i o n ,
198 f r e q u e n c y= s e l f . communication_frequency ,
199 t r a n s m i s s i o n _ p o w e r= s e l f . transmission_power ,
200 bandwidth= s e l f . bandwidth ,
201 n o i s e _ f i g u r e= s e l f . n o i s e _ f i g u r e ,
202 r e c e i v e r _ s e n s i t i v i t y= s e l f . r e c e i v e r _ s e n s i t i v i t y ,
203 s n r= s e l f . snr_minimum ,
204 semi_major_axis= s e l f . semi_major_axis ,
205 minCommunicationsAltitude= s e l f . min_communications_altitude ,
206 m i n S a t E l e v a t i o n= s e l f . min_sat_elevation ,
207 l i n k i n g M e t h o d= s e l f . linking_method ,
208 arcOfAscendingNodes =180.0)
209

Polytechnic University of Catalonia - Barcelona Tech - UPC 45


APPENDIX B. PYTHON SCRIPTS

210 # add ground p o i n t s t o t h e c o n s t i l l a t i o n model


211 # from t h e g i v e n f i l e path
212 # TODO: add e r r o r p r o t e c t i o n . . .
213 data = [ ]
214 s e l f . city_names = [ ]
215 with open ( g r o u n d P t s F i l e , ’ r ’ ) a s f :
216 for l i n e in f :
217 my_line = [ ]
218 f o r word i n l i n e . s p l i t ( ) :
219 my_line . append ( word )
220 data . append ( my_line )
221 f o r i i n r a n g e ( 1 , l e n ( data ) ) :
222 s e l f . city_names . append ( data [ i ] [ 0 ] )
223 s e l f . model . addGroundPoint ( f l o a t ( data [ i ] [ 1 ] ) , f l o a t ( data [ i ] [ 2 ] ) )
224
225 # send t h e names t o t h e GUI s o t h e u s e r
226 # can s e e them i n drop down menu
227 s e l f . pipeConn . send ( [ " placeNames " , s e l f . city_names ] )
228
229 # i n i t t h e network d e s i g n
230 i f s e l f . make_links :
231 print ( " test " )
232 s e l f . m a x _ i s l _ d i s t a n c e = s e l f . model . c a l c u l a t e M a x I S L D i s t a n c e (
233 s e l f . min_communications_altitude )
234 p r i n t ( s e l f . max_isl_distance )
235
236 s e l f . max_stg_distance = s e l f . model . calculateMaxSpaceToGndDistance (
237 s e l f . min_sat_elevation )
238

239 s e l f . model . import_links_from_gml_data ( edge_data )


240
241 s e l f . model . s e t C o n s t i l l a t i o n T i m e ( s e l f . c u r r e n t _ s i m u l a t i o n _ t i m e )
242
243 s e l f . model . c a l c u l a t e P l u s G r i d L i n k s ( s e l f . max_stg_distance ,
max_isl_range= s e l f . m a x _ i s l _ d i s t a n c e )
244
245 print ( ’ test2 ’ )
246 # so , a f t e r much e f f o r t i t a p p e a r s t h a t I cannot c o n t r o l an
247 # i n t e r a c t i v e vtk window e x t e r n a l l y . T h e r e f o r e when r u n n i n g
248 # with an animation , t h e a n i m a t i o n c l a s s w i l l have t o d r i v e
249 # t h e s i m u l a t i o n u s i n g an i n t e r n a l t i m e r . . .
250 i f s e l f . animate :
251 s e l f . setupAnimation (
252 s e l f . model . t o t a l _ s a t s ,
253 s e l f . model . g e t A r r a y O f S a t P o s i t i o n s ( ) ,
254 − s e l f . model . ground_node_counter ,
255 s e l f . model . g e t A r r a y O f G n d P o s i t i o n s ( ) ,
256 s e l f . time_step ,
257 s e l f . current_simulation_time ,
258 s e l f . capture_images
259 )
260

261 print ( ’ test3 ’ )


262
263 else :
264 # TODO: then we run d r i v e t h e s i m u l a t i o n from h e r e

Polytechnic University of Catalonia - Barcelona Tech - UPC 46


APPENDIX B. PYTHON SCRIPTS

265 return
266
267 else : # i f gmlImportFileName i s None
268
269 # c o n s t i l l a t i o n structure information
270 s e l f . num_planes = p l a n e s
271 s e l f . num_nodes_per_plane = nodesPerPlane
272 s e l f . plane_inclination = inclination
273 s e l f . communication_frequency = f r e q u e n c y
274 s e l f . transmission_power = transmissionPower
275 s e l f . bandwidth=bandwidth
276 s e l f . n o i s e _ f i g u r e=n o i s e F i g u r e
277 s e l f . r e c e i v e r _ s e n s i t i v i t y= r e c e i v e r S e n s i t i v i t y
278 s e l f . snr_minimum=s n r
279 s e l f . semi_major_axis = semiMajorAxis
280 s e l f . min_communications_altitude = 100000
281 s e l f . m i n _ s a t _ e l e v a t i o n = MIN_SAT_ELEVATION
282

283 # path c a l c u l a t i o n
284 s e l f . path_node_1 = None
285 s e l f . path_node_2 = None
286 s e l f . path_length = 0 . 0
287 s e l f . p a t h _ l i n k s = None
288 s e l f . max_node_degree = −1
289
290 # control flags
291 s e l f . animate = animate
292 s e l f . capture_gml = captureGML
293 s e l f . capture_images = c a p t u r e I m a g e s
294 s e l f . capt_interpolation = 1
295 s e l f . make_links = makeLinks
296 s e l f . linking_method = ’SPARSE ’ # o p t i o n s : ’IDEAL ’ , ’+GRID ’ , ’SPARSE ’
297 s e l f . enable_path_calculation = False
298
299 # timing c o n t r o l
300 s e l f . time_step = t i m e S t e p
301 s e l f . current_simulation_time = 0.0
302 s e l f . pause = True
303 s e l f . num_steps_to_run = −1
304
305 # p e r f o r m a n c e data
306 s e l f . time_1 = 1
307 s e l f . time_for_frame = 1
308 s e l f . time_to_update_model = 1
309 s e l f . time_to_export_gml = 1
310 s e l f . time_to_update_render = 1
311 s e l f . time_to_export_img = 1
312
313 # i n i t t h e ’ p i p e ’ o b j e c t used f o r i n t e r −p r o c e s s communication
314 # t h i s comes from t h e m u l t i p r o c e s s i n g l i b r a r y
315 s e l f . pipeConn = pipeConn
316 s e l f . c o n t r o l T h r e a d = td . Thread ( t a r g e t= s e l f . c o n t r o l T h r e a d H a n d l e r )
317 s e l f . controlThread . s t a r t ()
318
319 # i n i t t h e C o n s t e l l a t i o n model
320 s e l f . model = C o n s t e l l a t i o n (

Polytechnic University of Catalonia - Barcelona Tech - UPC 47


APPENDIX B. PYTHON SCRIPTS

321 p l a n e s= s e l f . num_planes ,
322 nodes_per_plane= s e l f . num_nodes_per_plane ,
323 i n c l i n a t i o n= s e l f . p l a n e _ i n c l i n a t i o n ,
324 f r e q u e n c y= s e l f . communication_frequency ,
325 t r a n s m i s s i o n _ p o w e r= s e l f . transmission_power ,
326 bandwidth= s e l f . bandwidth ,
327 n o i s e _ f i g u r e= s e l f . n o i s e _ f i g u r e ,
328 r e c e i v e r _ s e n s i t i v i t y= s e l f . r e c e i v e r _ s e n s i t i v i t y ,
329 s n r= s e l f . snr_minimum ,
330 semi_major_axis= s e l f . semi_major_axis ,
331 minCommunicationsAltitude= s e l f . min_communications_altitude ,
332 m i n S a t E l e v a t i o n= s e l f . min_sat_elevation ,
333 l i n k i n g M e t h o d= s e l f . linking_method ,
334 arcOfAscendingNodes=RAAN)
335
336 # add ground p o i n t s t o t h e c o n s t i l l a t i o n model
337 # from t h e g i v e n f i l e path
338 # TODO: add e r r o r p r o t e c t i o n . . .
339 data = [ ]
340 s e l f . city_names = [ ]
341 with open ( g r o u n d P t s F i l e , ’ r ’ ) a s f :
342 for l i n e in f :
343 my_line = [ ]
344 f o r word i n l i n e . s p l i t ( ) :
345 my_line . append ( word )
346 data . append ( my_line )
347 f o r i i n r a n g e ( 1 , l e n ( data ) ) :
348 s e l f . city_names . append ( data [ i ] [ 0 ] )
349 s e l f . model . addGroundPoint ( f l o a t ( data [ i ] [ 1 ] ) , f l o a t ( data [ i ] [ 2 ] ) )
350
351 # send t h e names t o t h e GUI s o t h e u s e r
352 # can s e e them i n drop down menu
353 s e l f . pipeConn . send ( [ " placeNames " , s e l f . city_names ] )
354
355 # i n i t t h e network d e s i g n
356 i f s e l f . make_links :
357 s e l f . initializeNetworkDesign ()
358
359 # so , a f t e r much e f f o r t i t a p p e a r s t h a t I cannot c o n t r o l an
360 # i n t e r a c t i v e vtk window e x t e r n a l l y . T h e r e f o r e when r u n n i n g
361 # with an animation , t h e a n i m a t i o n c l a s s w i l l have t o d r i v e
362 # t h e s i m u l a t i o n u s i n g an i n t e r n a l t i m e r . . .
363 i f s e l f . animate :
364 s e l f . setupAnimation (
365 s e l f . model . t o t a l _ s a t s ,
366 s e l f . model . g e t A r r a y O f S a t P o s i t i o n s ( ) ,
367 − s e l f . model . ground_node_counter ,
368 s e l f . model . g e t A r r a y O f G n d P o s i t i o n s ( ) ,
369 s e l f . time_step ,
370 s e l f . current_simulation_time ,
371 s e l f . capture_images
372 )
373
374 else :
375 # TODO: then we run d r i v e t h e s i m u l a t i o n from h e r e
376 return

Polytechnic University of Catalonia - Barcelona Tech - UPC 48


APPENDIX B. PYTHON SCRIPTS

377
378 def initializeNetworkDesign ( s e l f ) :
379 p r i n t ( " i n i t a l i z i n g network d e s i g n . . . " )
380 s e l f . m a x _ i s l _ d i s t a n c e = s e l f . model . c a l c u l a t e M a x I S L D i s t a n c e (
381 s e l f . min_communications_altitude )
382

383 s e l f . max_stg_distance = s e l f . model . calculateMaxSpaceToGndDistance (


384 s e l f . min_sat_elevation )
385
386 p r i n t ( ’ maxIsl : ’ , s e l f . max_isl_distance )
387 p r i n t ( ’ maxGtS : ’ , s e l f . max_stg_distance )
388

389 if s e l f . linking_method == ’IDEAL ’ :


390 s e l f . model . c a l c u l a t e I d e a l L i n k s (
391 s e l f . max_isl_distance ,
392 s e l f . max_stg_distance )
393
394 if s e l f . linking_method == ’+GRID ’ :
395 s e l f . model . c a l c u l a t e P l u s G r i d L i n k s (
396 s e l f . max_stg_distance ,
397 i n i t i a l i z e =True ,
398 c r o s s l i n k _ i n t e r p o l a t i o n =1)
399

400 if s e l f . linking_method == ’SPARSE ’ :


401 s e l f . model . c a l c u l a t e P l u s G r i d L i n k s (
402 s e l f . max_stg_distance ,
403 i n i t i a l i z e =True ,
404 c r o s s l i n k _ i n t e r p o l a t i o n= s e l f . model . t o t a l _ s a t s + 1 )
405

406 p r i n t ( " done i n i t a l i z i n g " )


407
408 def controlThreadHandler ( s e l f ) :
409 """
410 S t a r t a t h r e a d t o d e a l with i n t e r −p r o c e s s communications
411

412 """
413
414 w h i l e True :
415 r e c e i v e d _ d a t a = s e l f . pipeConn . r e c v ( )
416 i f type ( r e c e i v e d _ d a t a ) == s t r :
417 i f r e c e i v e d _ d a t a == " doTestFunc " :
418 s e l f . testFunc ( )
419
420 i f r e c e i v e d _ d a t a == " enableImageCapture " :
421 p r i n t ( " e n a b l e d image c a p t u r e " )
422 s e l f . capture_images = True
423
424 i f r e c e i v e d _ d a t a == " d i s a b l e I m a g e C a p t u r e " :
425 p r i n t ( " d i s a b l e d image c a p t u r e " )
426 s e l f . capture_images = F a l s e
427
428 i f r e c e i v e d _ d a t a == " enableGMLCapture " :
429 p r i n t ( " e n a b l e d GML c a p t u r e " )
430 s e l f . capture_gml = True
431
432 i f r e c e i v e d _ d a t a == " disableGMLCapture " :

Polytechnic University of Catalonia - Barcelona Tech - UPC 49


APPENDIX B. PYTHON SCRIPTS

433 p r i n t ( " d i s a b l e d GML c a p t u r e " )


434 s e l f . capture_gml = F a l s e
435
436 i f r e c e i v e d _ d a t a == " t o g g l e L i n k s " :
437 s e l f . make_links = not s e l f . make_links
438

439 i f r e c e i v e d _ d a t a == " t o g g l e P a u s e " :


440 s e l f . pause = not s e l f . pause
441 p r i n t ( ’ t o g g l e pause r e c i v e d by sim , pause i s : ’ , s e l f . pause )
442
443 i f r e c e i v e d _ d a t a == " e n a b l e P a t h C a l c " :
444 s e l f . e n a b l e _ p a t h _ c a l c u l a t i o n = True
445 p r i n t ( " e n a b l e d path c a l c u l a t i o n " )
446
447 i f r e c e i v e d _ d a t a == " d i s a b l e P a t h C a l c " :
448 s e l f . enable_path_calculation = False
449 p r i n t ( " d i s a b l e d path c a l c u l a t i o n " )
450

451 e l i f type ( r e c e i v e d _ d a t a ) == l i s t :
452 command = r e c e i v e d _ d a t a [ 0 ]
453 i f command == " s e t T i m e s t e p " :
454 p r i n t ( " s e t t i n g timestep to : " , received_data [ 1 ] )
455 s e l f . time_step = r e c e i v e d _ d a t a [ 1 ]
456
457 i f command == " se tL in ki ng Me th od " :
458 s e l f . linking_method = r e c e i v e d _ d a t a [ 1 ]
459 p r i n t ( " s e t l i n k i n g method t o : " , r e c e i v e d _ d a t a [ 1 ] )
460 # i f r e s e t l i n k i n g method , must r e i n i t network
461 s e l f . initializeNetworkDesign ()
462
463 i f command == " s e t R u n f o r " :
464 s e l f . num_steps_to_run = i n t ( r e c e i v e d _ d a t a [ 1 ] / s e l f . time_step )−1
465 p r i n t ( " r u n n i n g f o r : " , s e l f . num_steps_to_run , " t i m e s t e p s . . . " )
466 s e l f . pause = F a l s e
467

468 i f command == ’ setPathNode1 ’ :


469 s e l f . path_node_1 = r e c e i v e d _ d a t a [ 1 ]
470 p r i n t ( " s e t path node 1 : " , s e l f . path_node_1 )
471
472 i f command == ’ setPathNode2 ’ :
473 s e l f . path_node_2 = r e c e i v e d _ d a t a [ 1 ]
474 p r i n t ( " s e t path node 2 : " , s e l f . path_node_2 )
475
476 else :
477 print ( received_data )
478

479 def statusReport ( s e l f ) :


480 """
481 s e n d s some s t a t u s data l i k e c u r r e n t time back t o h o s t p r o c e s s
482
483 """
484

485 self . pipeConn . send ( [ " simTime " , s e l f . c u r r e n t _ s i m u l a t i o n _ t i m e ] )


486 self . pipeConn . send ( [ ’ timeForFrame ’ , s e l f . time_for_frame ] )
487 self . pipeConn . send ( [ ’ timeToUpdateModel ’ , s e l f . time_to_update_model ] )
488 self . pipeConn . send ( [ ’ timeToExportGML ’ , s e l f . time_to_export_gml ] )

Polytechnic University of Catalonia - Barcelona Tech - UPC 50


APPENDIX B. PYTHON SCRIPTS

489 self . pipeConn . send ( [ ’ timeToUpdateRender ’ , s e l f . time_to_update_render ] )


490 self . pipeConn . send ( [ ’ timeToExportImg ’ , s e l f . time_to_export_img ] )
491 self . pipeConn . send ( [ ’ maxNodeDegree ’ , s e l f . max_node_degree ] )
492 self . pipeConn . send ( [ ’ totalNumberOfLinks ’ , s e l f . model . t o t a l _ l i n k s ] )
493
494 def testFunc ( s e l f ) :
495 """
496 Test f u n c t i o n f o r debugging .
497 """
498
499 p r i n t ( " t h i s i s t h e vtk t e s t f u n c b e i n g run " )
500 # p r i n t ( s e l f . num_planes )
501 # s e l f . updateVtkSatPos ( )
502 # f o r name , node i n s e l f . conn . nodes . i t e m s ( ) :
503 # p r i n t ( name , node )
504
505 s e l f . pipeConn . send ( " back t o you " )
506 return
507
508 d e f updateModel ( s e l f , new_time ) :
509 """
510 Update t h e model with a new time , r e c a l c u l a t e l i n k s , & e x p o r t GML f i l e s
511

512 Function behaves d i f f e r e n t l y depending on wether animate i s t r u e o r not


.
513 I f t r u e , t h i s f u n c w i l l be c a l l e d from t h e updateAnimation ( ) f u n c
514 I f F a l s e , t h i s w i l l be c a l l e d i n a l o o p u n t i l some d e s i r e d runtime i s
reached
515

516 """
517
518 # grab i n i t i a l time
519 s e l f . time_1 = time . time ( )
520
521 s e l f . frameCount += 1
522
523 if s e l f . num_steps_to_run > 0 :
524 s e l f . num_steps_to_run −= 1
525 e l i f s e l f . num_steps_to_run == 0 :
526 s e l f . pause = True
527 s e l f . num_steps_to_run = −1
528
529 # update l i n k s / network d e s i g n / s a t p o s i t i o n s
530 s e l f . model . s e t C o n s t i l l a t i o n T i m e ( new_time )
531 i f s e l f . make_links :
532 i f s e l f . linking_method == ’IDEAL ’ :
533 s e l f . model . c a l c u l a t e I d e a l L i n k s (
534 s e l f . max_isl_distance ,
535 s e l f . max_stg_distance )
536 i f s e l f . linking_method == ’+GRID ’ :
537 s e l f . model . c a l c u l a t e P l u s G r i d L i n k s ( s e l f . max_stg_distance ,
max_isl_range= s e l f . m a x _ i s l _ d i s t a n c e )
538 i f s e l f . linking_method == ’SPARSE ’ :
539 s e l f . model . c a l c u l a t e P l u s G r i d L i n k s ( s e l f . max_stg_distance )
540
541 s e l f . time_to_update_model = time . time ( ) − s e l f . time_1

Polytechnic University of Catalonia - Barcelona Tech - UPC 51


APPENDIX B. PYTHON SCRIPTS

542
543 # g e n e r a t e GML graph i f a p p l i c a b l e
544 #i f s e l f . capture_gml and \
545 # s e l f . frameCount % s e l f . c a p t _ i n t e r p o l a t i o n == 0 o r \
546 # s e l f . enable_path_calculation :
547 i f s e l f . capture_gml and \
548 s e l f . frameCount % s e l f . c a p t _ i n t e r p o l a t i o n == 0 :
549 # s e t up graph , r e c o r d i n g i m p o r t a n t i n f o about t h e c u r r e n t model
550 s e l f . model . generateNetworkGraph ( s e l f . city_names )
551
552 # c a l c u l a t e max node d e g r e e ( number o f e d g e s c o n n e c t e d t o a node )
553 d e g r e e _ l i s t = l i s t ( s e l f . model .G. d e g r e e ( ) )
554 f o r i in range ( len ( d e g r e e _ l i s t ) ) :
555 degree_list [ i ] = int ( degree_list [ i ] [ 1 ] )
556 s e l f . max_node_degree = max( d e g r e e _ l i s t )
557
558 # i f enabled , we run d i j k s t r a ’ s between two p o i n t s
559 i f s e l f . enable_path_calculation :
560 node_1 = s e l f . path_node_1
561 node_2 = s e l f . path_node_2
562 i f ( node_1 i s not None ) and ( node_2 i s not None ) :
563 id_1 = −( s e l f . city_names . i n d e x ( node_1 ) + 1 )
564 id_2 = −( s e l f . city_names . i n d e x ( node_2 ) + 1 )
565 s e l f . model . generateNetworkGraph2 ( s e l f . city_names , id_1 , id_2 )
566 #p r i n t ( " node_1 %s , node_2 %s , id_1 %d , id_2 %s " % ( node_1 , node_2 ,
id_1 , id_2 ) )
567
568 # run s h o r t e s t path , h a n d l e e x c e p t i o n i f path not e x i s t
569 try :
570 path = nx . s h o r t e s t _ p a t h (
571 s e l f . model . G,
572 s o u r c e=s t r ( id_1 ) ,
573 t a r g e t=s t r ( id_2 ) ,
574 w e i g h t= ’ d i s t a n c e ’ )
575

576 # c o n v e r t l i s t o f nodes i n t o e d g e s
577 s e l f . path_links = [ ]
578
579
580
581 # XXX: Plathon −− P r i n t r o u t e nodes and compute and p r i n t end t o
end RTT
582 dist = 0.0
583 f o r i i n r a n g e ( l e n ( path ) −1) :
584 s e l f . p a t h _ l i n k s . append ( [ path [ i ] , path [ i + 1 ] ] )
585 d i s t = d i s t + f l o a t ( s e l f . model .G[ path [ i ] ] [ path [ i + 1 ] ] [ ’ d i s t a n c e ’
])
586
587 p r i n t ( " End t o End path : %s " % s t r ( path ) )
588 RTT = 2 . 0 ∗ d i s t /SPEED_OF_LIGHT_M_PER_S
589
590 p r i n t ( " d i t a n c i a : %d " % d i s t )
591 p r i n t ( "RTT: %f " % RTT)
592 p r i n t ( path )
593
594 e x c e p t nx . e x c e p t i o n . NetworkXNoPath :

Polytechnic University of Catalonia - Barcelona Tech - UPC 52


APPENDIX B. PYTHON SCRIPTS

595 p r i n t ( " path d o e s not e x i s t . . . " )


596 s e l f . p a t h _ l i n k s = None
597 #f i l e _ n a m e = GML_OUTPUT_PATH+"_"+ getFileNumber ( s e l f . frameCount )
+". gml "
598 #s e l f . model . exportGMLFile ( f i l e _ n a m e )
599

600 # TODO: f i g u r e out t h e max number o f l i n k s p e r s a t i n i d e a l c a s e


601
602 if s e l f . capture_gml and s e l f . frameCount % s e l f . c a p t _ i n t e r p o l a t i o n == 0 :
603 f i l e _ n a m e = GML_OUTPUT_PATH+"_"+getFileNumber ( s e l f . frameCount )+" . gml "
604 s e l f . model . exportGMLFile ( f i l e _ n a m e )
605

606 s e l f . time_to_export_gml = time . time ( ) −\


607 s e l f . time_1 − s e l f . time_to_update_model
608
609 ################# ANIMATION FUNCTIONS #########################
610
611 """
612 L i k e me , you might wonder what t h e numerous vkt c a l l s a r e f o r .
613 Answer : you need t o manually c o n f i g u r e a r e n d e r p i p e l i n e f o r
614 each o b j e c t ( vtk a c t o r ) i n t h e s c e n e .
615 A t y p i c a l VTK r e n d e r p i p e l i n e :
616

617 p o i n t data a r r a y <−− s e t / update p o s i t i o n data


618 |
619 p o l y data a r r a y
620 |
621 p o l y data mapper
622 |
623 object actor <−− e d i t c o l o r / s i z e / o p a c i t y , apply r o t a t i o n s / t r a n s l a t i o n s
624 |
625 vtk r e n d e r e r
626 |
627 vkt r e n d e r window
628 vkt r e n d e r i n t e r a c t o r <−− t r i g g e r e v e n t s , animate
629 |
630 Your computer s c r e e n
631 e x p o r t e d png f i l e s
632
633 """
634

635 d e f setupAnimation (
636 self ,
637 total_satellites ,
638 satellite_positions ,
639 total_groundpoints ,
640 groundpoint_positions ,
641 t i m e s t e p =60 ,
642 c u r r e n t _ s i m u l a t i o n _ t i m e =0,
643 capture_images=F a l s e ) :
644 """
645 Makes vtk r e n d e r window , and s e t s up p i p e l i n e s .
646
647 Parameters
648 −−−−−−−−−−
649 total_satellites : int

Polytechnic University of Catalonia - Barcelona Tech - UPC 53


APPENDIX B. PYTHON SCRIPTS

650 The t o t a l number o f s a t e l l t i e s i n t h e model


651 s a t e l l i t e _ p o s i t i o n s : np . a r r a y [ [ ( ’ x ’ , i n t 3 2 ) , ( ’ y ’ , i n t 3 2 ) , ( ’ z ’ , i n t 3 2
) ]]
652 Numpy a r r a y o f a l l t h e s a t e l l i t e p o s i t i o n s
653 total_groundpoints : int
654 T o t a l number o f g r o u n d p o i n t s i n t h e model
655 g r o u n d p o i n t _ p o s i t i o n s : np . a r r a y [ [ ( ’ x ’ , i n t 3 2 ) , ( ’ y ’ , i n t 3 2 ) , ( ’ z ’ ,
int32 ) ] ]
656 Numpy a r r a y o f a l l t h e g r o u n d p o i n t p o s i t i o n s
657 timestep : int
658 Timestep f o r t h e s i m u l a t i o n i n s e c o n d s
659 current_simulation_time : i n t
660 c u r r e n t time o f t h e s i m u l a t i o n i n s e c o n d s
661 capture_images : b o o l
662 I f t r u e , s a v e images o f t h e r e n d e r window t o f i l e
663
664 """
665

666 s e l f . current_simulation_time = current_simulation_time


667 s e l f . time_step = t i m e s t e p
668 s e l f . capture_images = capture_images
669
670 s e l f . frameCount = 0
671 s e l f . incFrameCount = 1
672
673 s e l f . makeEarthActors (EARTH_RADIUS)
674
675 i f total_satellites > 0:
676 s e l f . makeSatsActor ( t o t a l _ s a t e l l i t e s , s a t e l l i t e _ p o s i t i o n s )
677
678 i f total_groundpoints > 0:
679 s e l f . makeGndPtsActor ( t o t a l _ g r o u n d p o i n t s , g r o u n d p o i n t _ p o s i t i o n s )
680
681 if s e l f . make_links :
682 s e l f . makeLinkActors ( )
683
684 s e l f . makeRenderWindow ( )
685
686 d e f updateAnimation ( s e l f , obj , e v e n t ) :
687 """
688 This f u n c t i o n t a k e s i n new p o s i t i o n data and u p d a t e s t h e r e n d e r window
689
690 Parameters
691 −−−−−−−−−−
692 obj : ?
693 The o b j e c t t h a t g e n e r a t e d t h e event , p r o b a b l y vtk r e n d e r window
694 event : event
695 The e v e n t t h a t t r i g g e r e d t h i s f u n c t i o n
696 """
697
698 i f not s e l f . pause :
699 # update s i m u l a t i o n time
700 new_simulation_time = s e l f . c u r r e n t _ s i m u l a t i o n _ t i m e + s e l f . time_step
701
702 # c a l l f u n c t o update t h e model
703 s e l f . updateModel ( new_simulation_time )

Polytechnic University of Catalonia - Barcelona Tech - UPC 54


APPENDIX B. PYTHON SCRIPTS

704
705 # r o t a t e e a r t h and l a n d
706 r o t a t i o n _ p e r _ t i m e _ s t e p = 3 6 0 . 0 / (SECONDS_PER_DAY / s e l f . time_step )
707 s e l f . e a r t h A c t o r . RotateZ ( r o t a t i o n _ p e r _ t i m e _ s t e p )
708 s e l f . s p h e r e A c t o r . RotateZ ( r o t a t i o n _ p e r _ t i m e _ s t e p )
709

710 else :
711 new_simulation_time = s e l f . c u r r e n t _ s i m u l a t i o n _ t i m e
712
713 # grab new p o s i t i o n data
714 n e w _ s a t _ p o s i t i o n s = s e l f . model . g e t A r r a y O f S a t P o s i t i o n s ( )
715 n e w _ gr o u n d p o in t _ p o s i ti o n s = s e l f . model . g e t A r r a y O f G n d P o s i t i o n s ( )
716
717 # update s a t p o i n t s
718 f o r i in range ( s e l f . t o t a l S a t s ) :
719 x = new_sat_positions [ i ] [ ’ x ’ ]
720 y = new_sat_positions [ i ] [ ’ y ’ ]
721 z = new_sat_positions [ i ] [ ’ z ’ ]
722 s e l f . satVtkPts . S e t P o i n t ( s e l f . s a t P o i n t I D s [ i ] , x , y , z )
723 s e l f . satPolyData . GetPoints ( ) . M o d i f i e d ( )
724
725 # update gnd p t s
726 f o r i in range ( s e l f . totalGroundpoints ) :
727 x = n e w _ g ro u n d p o i nt _ p o s i t i on s [ i ] [ ’ x ’ ]
728 y = n e w _ g ro u n d p o i nt _ p o s i t i on s [ i ] [ ’ y ’ ]
729 z = n e w_ g r o u n d po i n t _ p o s it i o n s [ i ] [ ’ z ’ ]
730 s e l f . gndVtkPts . S e t P o i n t ( s e l f . gndPointIDs [ i ] , x , y , z )
731 s e l f . gndPolyData . GetPoints ( ) . M o d i f i e d ( )
732

733 # print ( ’ j u s t before func ’)


734 i f s e l f . make_links :
735
736 # grab t h e a r r a y s o f c o n n e c t i o n s
737 l i n k s = s e l f . model . g e t A r r a y O f L i n k s ( )
738 p o i n t s = s e l f . model . g e t A r r a y O f N o d e P o s i t i o n s ( )
739 maxSatIdx = s e l f . model . t o t a l _ s a t s −1
740
741 # b u i l d a v t k P o i n t s o b j e c t from a r r a y
742 s e l f . l i n k P o i n t s = vtk . v t k P o i n t s ( )
743 s e l f . l i n k P o i n t s . SetNumberOfPoints ( l e n ( p o i n t s ) )
744 f o r i in range ( len ( p o i n t s ) ) :
745 s e l f . linkPoints . SetPoint ( i , points [ i ] [ ’x ’ ] , points [ i ] [ ’y ’ ] , points [
i ][ ’z ’ ])
746
747 # make c l e a n l i n e a r r a y s
748 s e l f . i s l L i n k L i n e s = vtk . v t k C e l l A r r a y ( )
749 s e l f . s g l L i n k L i n e s = vtk . v t k C e l l A r r a y ( )
750 s e l f . p a t h L i n k L i n e s = vtk . v t k C e l l A r r a y ( )
751
752 # f i l l i s l and g s l a r r a y s
753 f o r i in range ( len ( l i n k s ) ) :
754 e1 = l i n k s [ i ] [ ’ node_1 ’ ]
755 e2 = l i n k s [ i ] [ ’ node_2 ’ ]
756 # must t r a n s l a t e l i n k e n d p o i n t s t o p o i n t names
757 # i f e n d p o i n t name i s p o s i t i v e , we u s e i t d i r e c t l y
758 # i f n e g a t i v e , i d x = maxSatIdx−endpointname

Polytechnic University of Catalonia - Barcelona Tech - UPC 55


APPENDIX B. PYTHON SCRIPTS

759 # ∗∗ ground e n d p o i n t s a r e always node_1 ∗∗


760 i f e1 < 0 :
761 s e l f . sglLinkLines . InsertNextCell (2)
762 s e l f . s g l L i n k L i n e s . I n s e r t C e l l P o i n t ( maxSatIdx−e1 )
763 s e l f . s g l L i n k L i n e s . I n s e r t C e l l P o i n t ( e2 )
764 else :
765 s e l f . islLinkLines . InsertNextCell (2)
766 s e l f . i s l L i n k L i n e s . I n s e r t C e l l P o i n t ( e1 )
767 s e l f . i s l L i n k L i n e s . I n s e r t C e l l P o i n t ( e2 )
768
769 self . sglPolyData . SetPoints ( s e l f . l i n k P o i n t s )
770 self . sglPolyData . SetLines ( s e l f . sglLinkLines )
771 self . islPolyData . SetPoints ( s e l f . linkPoints )
772 self . islPolyData . SetLines ( s e l f . islLinkLines )
773
774 if s e l f . e n a b l e _ p a t h _ c a l c u l a t i o n and ( s e l f . p a t h _ l i n k s i s not None ) :
775 f o r l i n k in s e l f . path_links :
776 e1 = i n t ( l i n k [ 0 ] )
777 e2 = i n t ( l i n k [ 1 ] )
778 s e l f . pathLinkLines . InsertNextCell (2)
779 i f e1 < 0 :
780 s e l f . p a t h L i n k L i n e s . I n s e r t C e l l P o i n t ( maxSatIdx−e1 )
781 else :
782 s e l f . p a t h L i n k L i n e s . I n s e r t C e l l P o i n t ( e1 )
783 i f e2 < 0 :
784 s e l f . p a t h L i n k L i n e s . I n s e r t C e l l P o i n t ( maxSatIdx−e2 )
785 else :
786 s e l f . p a t h L i n k L i n e s . I n s e r t C e l l P o i n t ( e2 )
787

788 s e l f . pathPolyData . S e t P o i n t s ( s e l f . l i n k P o i n t s )
789 s e l f . pathPolyData . S e t L i n e s ( s e l f . p a t h L i n k L i n e s )
790
791 o b j . GetRenderWindow ( ) . Render ( )
792 s e l f . c u r r e n t _ s i m u l a t i o n _ t i m e = new_simulation_time
793 i f not s e l f . pause :
794 s e l f . time_to_update_render = ( time . time ( ) − s e l f . time_1 ) −\
795 ( s e l f . time_to_update_model + s e l f . time_to_export_gml )
796
797 if s e l f . capture_images \
798 and s e l f . frameCount % s e l f . c a p t _ i n t e r p o l a t i o n == 0\
799 and not s e l f . pause :
800 s e l f . renderToPng ( )
801
802 i f not s e l f . pause :
803 s e l f . time_to_export_img = ( time . time ( ) − s e l f . time_1 ) −\
804 ( s e l f . time_to_update_model + s e l f . time_to_export_gml +
805 s e l f . time_to_update_render )
806
807 s e l f . time_for_frame = time . time ( ) − s e l f . time_1
808 s e l f . statusReport ()
809
810 d e f renderToPng ( s e l f , path=PNG_OUTPUT_PATH) :
811 """
812 Take a . png o f t h e r e n d e r window , and s a v e i t .
813
814 Parameters

Polytechnic University of Catalonia - Barcelona Tech - UPC 56


APPENDIX B. PYTHON SCRIPTS

815 −−−−−−−−−−
816 path : s t r
817 The r e l a t i v e path o f where t o s a v e t h e image
818
819 """
820

821 # make s u r e t h e path e x i s t s


822 i f not path :
823 return
824
825 # c o n n e c t t h e image w r i t e r t o t h e r e n d e r window
826 w2i = vtk . vtkWindowToImageFilter ( )
827 w2i . SetInputBufferTypeToRGBA ( )
828 w2i . S e t I n p u t ( s e l f . renderWindow )
829 w2i . Update ( )
830 p n g f i l e = vtk . vtkPNGWriter ( )
831 p n g f i l e . S e t I n p u t C o n n e c t i o n ( w2i . GetOutputPort ( ) )
832

833 # name t h e f i l e with 7 d i g i t i n t , l e a d i n g z e r o s


834 p n g f i l e . SetFileName ( path + "_" + getFileNumber ( s e l f . frameCount ) + " . png
")
835 p n g f i l e . Write ( )
836

837 d e f makeRenderWindow ( s e l f ) :
838 """
839 Makes a r e n d e r window o b j e c t u s i n g vtk .
840
841 This s h o u l d not be c a l l e d u n t i l a l l t h e a c t o r s a r e c r e a t e d .
842

843 """
844
845 # create a renderer object
846 s e l f . r e n d e r e r = vtk . vtk Ren dere r ( )
847 s e l f . renderWindow = vtk . vtkRenderWindow ( )
848 s e l f . renderWindow . AddRenderer ( s e l f . r e n d e r e r )
849
850 # c r e a t e an i n t e r a c t o r o b j e c t , t o i n t e r a c t with t h e window . . . duh
851 s e l f . i n t e r a c t o r = vtk . vtkRenderWindowInteractor ( )
852 s e l f . i n t e r a c t o r . S e t I n t e r a c t o r S t y l e ( vtk .
vtkInteractorStyleTrackballCamera () )
853 s e l f . i n t e r a c t o r . SetRenderWindow ( s e l f . renderWindow )
854
855 # add t h e a c t o r o b j e c t s
856 s e l f . r e n d e r e r . AddActor ( s e l f . s a t s A c t o r )
857 s e l f . r e n d e r e r . AddActor ( s e l f . e a r t h A c t o r )
858 s e l f . r e n d e r e r . AddActor ( s e l f . gndActor )
859 s e l f . r e n d e r e r . AddActor ( s e l f . s p h e r e A c t o r )
860 i f s e l f . make_links :
861 s e l f . r e n d e r e r . AddActor ( s e l f . i s l A c t o r )
862 s e l f . r e n d e r e r . AddActor ( s e l f . s g l A c t o r )
863 s e l f . r e n d e r e r . AddActor ( s e l f . pathActor )
864

865 # w h i t e background , makes i t e a s i e r t o


866 # put s c r e e n s h o t s o f a n i m a t i o n i n t o p a p e r s / p r e s e n t a t i o n s
867 s e l f . r e n d e r e r . SetBackground (BACKGROUND_COLOR)
868

Polytechnic University of Catalonia - Barcelona Tech - UPC 57


APPENDIX B. PYTHON SCRIPTS

869 s e l f . interactor . I n i t i a l i z e ()
870 print ( ’ i n i t i a l i z e d interactor ’ )
871
872 # s e t up a t i m e r t o c a l l t h e update f u n c t i o n a t a max r a t e
873 # o f e v e r y 7 ms (~144 hz )
874 s e l f . i n t e r a c t o r . AddObserver ( ’ TimerEvent ’ , s e l f . updateAnimation )
875 s e l f . i n t e r a c t o r . CreateRepeatingTimer ( 7 )
876 p r i n t ( ’ s e t up t i m e r ’ )
877
878 # s t a r t t h e model
879 s e l f . renderWindow . S e t S i z e ( 5 1 2 , 5 1 2 )
880 s e l f . renderWindow . Render ( )
881 print ( ’ started render ’ )
882 s e l f . interactor . Start ()
883 print ( ’ started interactor ’ )
884
885 d e f makeSatsActor ( s e l f , t o t a l _ s a t e l l i t e s , s a t e l l i t e _ p o s i t i o n s ) :
886 """
887 generate the point cloud to r e p r e s e n t s a t e l l i t e s
888
889 Parameters
890 −−−−−−−−−−
891 total_satellites : int
892 number o f s a t e l l t i e s i n t h e s i m u l a t i o n
893 s a t e l l i t e _ p o s i t i o n s : np . a r r a y [ [ ( ’ x ’ , i n t 3 2 ) , ( ’ y ’ , i n t 3 2 ) , ( ’ z ’ , i n t 3 2 )
]]
894 s a t e l l i t e p o s i t i o n data , s a t e l l i t e " unique_id " = i n d e x number
895 """
896

897 # d e c l a r e a p o i n t s & c e l l a r r a y t o h o l d p o s i t i o n data


898 s e l f . satVtkPts = vtk . v t k P o i n t s ( )
899 s e l f . s a t V t k V e r t s = vtk . v t k C e l l A r r a y ( )
900
901 # f i g u r e out t h e t o t a l number o f s a t s and g r o u n d p t s i n t h e
constillation
902 s el f . totalSats = total_satellites
903
904 # i n i t a a r r a y f o r IDs
905 s e l f . s a t P o i n t I D s = [ None ] ∗ s e l f . t o t a l S a t s
906
907 # i n i t i a l i z e a l l the p o s i t i o n s
908 f o r i in range ( s e l f . t o t a l S a t s ) :
909 s e l f . s a t P o i n t I D s [ i ] = s e l f . satVtkPts . I n s e r t N e x t P o i n t (
910 satellite_positions [ i ] [ ’x ’ ] ,
911 satellite_positions [ i ] [ ’y ’ ] ,
912 satellite_positions [ i ][ ’z ’ ])
913
914 s e l f . satVtkVerts . InsertNextCell (1)
915 s e l f . satVtkVerts . I n s e r t C e l l P o i n t ( s e l f . satPointIDs [ i ] )
916
917 # c o n v e r t p o i n t s i n t o p o l y data
918 # ( b e c a u s e t h a t ’ s what they do i n t h e vtk examples )
919 s e l f . satPolyData = vtk . vtkPolyData ( )
920 s e l f . satPolyData . S e t P o i n t s ( s e l f . satVtkPts )
921 s e l f . satPolyData . S e t V e r t s ( s e l f . s a t V t k V e r t s )
922

Polytechnic University of Catalonia - Barcelona Tech - UPC 58


APPENDIX B. PYTHON SCRIPTS

923 # c r e a t e mapper o b j e c t and c o n n e c t t o t h e p o l y data


924 s e l f . satsMapper = vtk . vtkPolyDataMapper ( )
925 s e l f . satsMapper . SetInputData ( s e l f . satPolyData )
926
927 # c r e a t e a c t o r , and c o n n e c t t o t h e mapper
928 # ( again , i t s j u s t what you do t o make a vtk r e n d e r p i p e l i n e )
929 s e l f . s a t s A c t o r = vtk . vtkActor ( )
930 s e l f . s a t s A c t o r . SetMapper ( s e l f . satsMapper )
931
932 # e d i t appearance o f s a t e l l i t e s
933 s e l f . s a t s A c t o r . GetProperty ( ) . S e t O p a c i t y (SAT_OPACITY)
934 s e l f . s a t s A c t o r . GetProperty ( ) . S e t C o l o r (SAT_COLOR)
935 s e l f . s a t s A c t o r . GetProperty ( ) . S e t P o i n t S i z e (SAT_POINT_SIZE)
936
937 d e f makeGndPtsActor ( s e l f , t o t a l _ g r o u n d p o i n t s , g r o u n d p o i n t _ p o s i t i o n s ) :
938 """
939 generate the point cloud to r e p r e s e n t groundpoints
940

941 Parameters
942 −−−−−−−−−−
943 total_groundpoints : int
944 number o f s a t e l l t i e s i n t h e s i m u l a t i o n
945 g r o u n d p o i n t _ p o s i t i o n s : np . a r r a y [ [ ( ’ x ’ , i n t 3 2 ) , ( ’ y ’ , i n t 3 2 ) , ( ’ z ’ , i n t 3 2
) ]]
946 ground p o i n t p o s i t i o n data , s a t e l l i t e " unique_id " = −(index_number −1)
947 """
948
949 # i n i t p o i n t and c e l l a r r a y s
950 s e l f . gndVtkPts = vtk . v t k P o i n t s ( )
951 s e l f . gndVtkVerts = vtk . v t k C e l l A r r a y ( )
952
953 # f i g u r e out t h e t o t a l number o f g r o u n d p t s i n t h e c o n s t i l l a t i o n
954 s e l f . totalGroundpoints = total_groundpoints
955
956 # i n i t a a r r a y f o r IDs ?
957 s e l f . gndPointIDs = [ None ] ∗ s e l f . t o t a l G r o u n d p o i n t s
958
959 # init positions
960 f o r i in range ( s e l f . totalGroundpoints ) :
961 s e l f . gndPointIDs [ i ] = s e l f . gndVtkPts . I n s e r t N e x t P o i n t (
962 groundpoint_positions [ i ] [ ’x ’ ] ,
963 groundpoint_positions [ i ] [ ’y ’ ] ,
964 groundpoint_positions [ i ] [ ’ z ’ ] )
965
966 s e l f . gndVtkVerts . I n s e r t N e x t C e l l ( 1 )
967 s e l f . gndVtkVerts . I n s e r t C e l l P o i n t ( s e l f . gndPointIDs [ i ] )
968
969 # more s t a n d a r d p i p e l i n e c r e a t i o n . . .
970 s e l f . gndPolyData = vtk . vtkPolyData ( )
971 s e l f . gndPolyData . S e t P o i n t s ( s e l f . gndVtkPts )
972 s e l f . gndPolyData . S e t V e r t s ( s e l f . gndVtkVerts )
973 s e l f . gndMapper = vtk . vtkPolyDataMapper ( )
974 s e l f . gndMapper . SetInputData ( s e l f . gndPolyData )
975 s e l f . gndActor = vtk . vtkActor ( )
976 s e l f . gndActor . SetMapper ( s e l f . gndMapper )
977

Polytechnic University of Catalonia - Barcelona Tech - UPC 59


APPENDIX B. PYTHON SCRIPTS

978 # set actor properties


979 s e l f . gndActor . GetProperty ( ) . S e t O p a c i t y (GND_OPACITY)
980 s e l f . gndActor . GetProperty ( ) . S e t C o l o r (GND_COLOR)
981 s e l f . gndActor . GetProperty ( ) . S e t P o i n t S i z e (GND_POINT_SIZE)
982
983 d e f makeLinkActors ( s e l f ) :
984 """
985 generate the l i n e s to r e p r e s e n t l i n k s
986
987 source :
988 h t t p s : / / vtk . o r g / Wiki /VTK/ Examples / Python / G e o m e t r i c O b j e c t s / D i s p l a y /
PolyLine
989
990 """
991
992 # grab t h e a r r a y s o f c o n n e c t i o n s
993 l i n k s = s e l f . model . g e t A r r a y O f L i n k s ( )
994 p o i n t s = s e l f . model . g e t A r r a y O f N o d e P o s i t i o n s ( )
995 maxSatIdx = s e l f . model . t o t a l _ s a t s −1
996
997 # b u i l d a v t k P o i n t s o b j e c t from a r r a y
998 s e l f . l i n k P o i n t s = vtk . v t k P o i n t s ( )
999 s e l f . l i n k P o i n t s . SetNumberOfPoints ( l e n ( p o i n t s ) )
1000 f o r i in range ( len ( p o i n t s ) ) :
1001 s e l f . linkPoints . SetPoint ( i , points [ i ] [ ’x ’ ] , points [ i ] [ ’y ’ ] , points [ i
][ ’z ’ ])
1002
1003 # build a c e l l array to r e p r e s e n t c o n n e c t i v i t y
1004 s e l f . i s l L i n k L i n e s = vtk . v t k C e l l A r r a y ( )
1005 s e l f . s g l L i n k L i n e s = vtk . v t k C e l l A r r a y ( )
1006 f o r i in range ( len ( l i n k s ) ) :
1007 e1 = l i n k s [ i ] [ ’ node_1 ’ ]
1008 e2 = l i n k s [ i ] [ ’ node_2 ’ ]
1009 # must t r a n s l a t e l i n k e n d p o i n t s t o p o i n t names
1010 # i f e n d p o i n t name i s p o s i t i v e , we u s e i t d i r e c t l y
1011 # i f n e g a t i v e , i d x = maxSatIdx−endpointname
1012 # ∗∗ ground e n d p o i n t s a r e always node_1 ∗∗
1013 i f e1 < 0 :
1014 s e l f . sglLinkLines . InsertNextCell (2)
1015 s e l f . s g l L i n k L i n e s . I n s e r t C e l l P o i n t ( maxSatIdx−e1 )
1016 s e l f . s g l L i n k L i n e s . I n s e r t C e l l P o i n t ( e2 )
1017 else :
1018 s e l f . islLinkLines . InsertNextCell (2)
1019 s e l f . i s l L i n k L i n e s . I n s e r t C e l l P o i n t ( e1 )
1020 s e l f . i s l L i n k L i n e s . I n s e r t C e l l P o i n t ( e2 )
1021

1022 s e l f . p a t h L i n k L i n e s = vtk . v t k C e l l A r r a y ( ) # i n i t , but do not f i l l this


one
1023
1024 ##
1025
1026 s e l f . i s l P o l y D a t a = vtk . vtkPolyData ( )
1027 s e l f . islPolyData . SetPoints ( s e l f . linkPoints )
1028 s e l f . islPolyData . SetLines ( s e l f . islLinkLines )
1029
1030 s e l f . s g l P o l y D a t a = vtk . vtkPolyData ( )

Polytechnic University of Catalonia - Barcelona Tech - UPC 60


APPENDIX B. PYTHON SCRIPTS

1031 s e l f . sglPolyData . SetPoints ( s e l f . l i n k P o i n t s )


1032 s e l f . sglPolyData . SetLines ( s e l f . sglLinkLines )
1033
1034 s e l f . pathPolyData = vtk . vtkPolyData ( )
1035 s e l f . pathPolyData . S e t P o i n t s ( s e l f . l i n k P o i n t s )
1036 s e l f . pathPolyData . S e t L i n e s ( s e l f . p a t h L i n k L i n e s )
1037
1038 ##
1039
1040 s e l f . i s l M a p p e r = vtk . vtkPolyDataMapper ( )
1041 s e l f . i s l M a p p e r . SetInputData ( s e l f . i s l P o l y D a t a )
1042

1043 s e l f . sglMapper = vtk . vtkPolyDataMapper ( )


1044 s e l f . sglMapper . SetInputData ( s e l f . s g l P o l y D a t a )
1045
1046 s e l f . pathMapper = vtk . vtkPolyDataMapper ( )
1047 s e l f . pathMapper . SetInputData ( s e l f . pathPolyData )
1048

1049 ##
1050
1051 s e l f . i s l A c t o r = vtk . vtkActor ( )
1052 s e l f . i s l A c t o r . SetMapper ( s e l f . i s l M a p p e r )
1053

1054 s e l f . s g l A c t o r = vtk . vtkActor ( )


1055 s e l f . s g l A c t o r . SetMapper ( s e l f . sglMapper )
1056
1057 s e l f . pathActor = vtk . vtkActor ( )
1058 s e l f . pathActor . SetMapper ( s e l f . pathMapper )
1059

1060 ##
1061
1062 s e l f . i s l A c t o r . GetProperty ( ) . S e t O p a c i t y (ISL_LINK_OPACITY)
1063 s e l f . i s l A c t o r . GetProperty ( ) . S e t C o l o r (ISL_LINK_COLOR)
1064 s e l f . i s l A c t o r . GetProperty ( ) . SetLineWidth (ISL_LINE_WIDTH)
1065

1066 s e l f . s g l A c t o r . GetProperty ( ) . S e t O p a c i t y (SGL_LINK_OPACITY)


1067 s e l f . s g l A c t o r . GetProperty ( ) . S e t C o l o r (SGL_LINK_COLOR)
1068 s e l f . s g l A c t o r . GetProperty ( ) . SetLineWidth (SGL_LINE_WIDTH)
1069
1070 s e l f . pathActor . GetProperty ( ) . S e t O p a c i t y (PATH_LINK_OPACITY)
1071 s e l f . pathActor . GetProperty ( ) . S e t C o l o r (PATH_LINK_COLOR)
1072 s e l f . pathActor . GetProperty ( ) . SetLineWidth (PATH_LINE_WIDTH)
1073
1074 ##
1075
1076 d e f makeEarthActors ( s e l f , e a r t h _ r a d i u s ) :
1077 """
1078 g e n e r a t e t h e e a r t h s p h e r e , and t h e landmass o u t l i n e
1079
1080 Parameters
1081 −−−−−−−−−−
1082 earth_radius : int
1083 r a d i u s o f t h e Earth i n m e t e r s
1084
1085 """
1086

Polytechnic University of Catalonia - Barcelona Tech - UPC 61


APPENDIX B. PYTHON SCRIPTS

1087 s e l f . earthRadius = earth_radius


1088
1089 # C r e a t e e a r t h map
1090 # a p o i n t c l o u d t h a t o u t l i n e s a l l t h e e a r t h s landmass
1091 s e l f . e a r t h S o u r c e = vtk . v t k E a r t h S o u r c e ( )
1092 # draws a s an o u t l i n e o f landmass , r a t h e r than f i l l i t i n
1093 s e l f . e a r t h S o u r c e . OutlineOn ( )
1094
1095 # want t h i s t o be s l i g h t l y l a r g e r than t h e s p h e r e i t s i t s on
1096 # s o t h a t i t i s not o c c l u d e d by t h e s p h e r e
1097 s e l f . e a r t h S o u r c e . Set Radius ( s e l f . e a r t h R a d i u s ∗ 1 . 0 0 1 )
1098

1099 # c o n t r o l e s t h e r e s o l u t i o n o f s u r f a c e data ( 1 = f u l l r e s o l u t i o n )
1100 s e l f . e a r t h S o u r c e . SetOnRatio ( 1 )
1101
1102 # C r e a t e a mapper
1103 s e l f . earthMapper = vtk . vtkPolyDataMapper ( )
1104 s e l f . earthMapper . S e t I n p u t C o n n e c t i o n ( s e l f . e a r t h S o u r c e . GetOutputPort ( ) )
1105
1106 # C r e a t e an a c t o r
1107 s e l f . e a r t h A c t o r = vtk . vtkActor ( )
1108 s e l f . e a r t h A c t o r . SetMapper ( s e l f . earthMapper )
1109

1110 # set color


1111 s e l f . e a r t h A c t o r . GetProperty ( ) . S e t C o l o r (LANDMASS_OUTLINE_COLOR)
1112 s e l f . e a r t h A c t o r . GetProperty ( ) . S e t O p a c i t y (EARTH_LAND_OPACITY)
1113
1114 # make s p h e r e data
1115 num_pts = EARTH_SPHERE_POINTS
1116 i n d i c e s = np . a r a n g e ( 0 , num_pts , dtype=f l o a t ) + 0 . 5
1117 p h i = np . a r c c o s ( 1 − 2 ∗ i n d i c e s / num_pts )
1118 t h e t a = np . p i ∗ ( 1 + 5 ∗∗ 0 . 5 ) ∗ i n d i c e s
1119 x = np . c o s ( t h e t a ) ∗ np . s i n ( p h i ) ∗ s e l f . e a r t h R a d i u s
1120 y = np . s i n ( t h e t a ) ∗ np . s i n ( p h i ) ∗ s e l f . e a r t h R a d i u s
1121 z = np . c o s ( p h i ) ∗ s e l f . e a r t h R a d i u s
1122
1123 # x , y , z i s coordination of evenly d i s t r i b u t e d sphere
1124 # I w i l l t r y t o make p o l y data u s e t h i s x , y , z
1125 p o i n t s = vtk . v t k P o i n t s ( )
1126 f o r i in range ( len ( x ) ) :
1127 points . InsertNextPoint (x [ i ] , y [ i ] , z [ i ] )
1128
1129 p o l y = vtk . vtkPolyData ( )
1130 poly . SetPoints ( points )
1131
1132 # To c r e a t e s u r f a c e o f a s p h e r e we need t o u s e Delaunay t r i a n g u l a t i o n
1133 d3D = vtk . vtkDelaunay3D ( )
1134 d3D . SetInputData ( p o l y ) # This g e n e r a t e s a 3D mesh
1135
1136 # We need t o e x t r a c t t h e s u r f a c e from t h e 3D mesh
1137 d s s = vtk . v t k D a t a S e t S u r f a c e F i l t e r ( )
1138 d s s . S e t I n p u t C o n n e c t i o n ( d3D . GetOutputPort ( ) )
1139 d s s . Update ( )
1140
1141 # Now we have our f i n a l p o l y d a t a
1142 s p h e r e P o l y = d s s . GetOutput ( )

Polytechnic University of Catalonia - Barcelona Tech - UPC 62


APPENDIX B. PYTHON SCRIPTS

1143
1144 # C r e a t e a mapper
1145 sphereMapper = vtk . vtkPolyDataMapper ( )
1146 sphereMapper . SetInputData ( s p h e r e P o l y )
1147
1148 # C r e a t e an a c t o r
1149 s e l f . s p h e r e A c t o r = vtk . vtkActor ( )
1150 s e l f . s p h e r e A c t o r . SetMapper ( sphereMapper )
1151
1152 # set color
1153 s e l f . s p h e r e A c t o r . GetProperty ( ) . S e t C o l o r (EARTH_BASE_COLOR)
1154 s e l f . s p h e r e A c t o r . GetProperty ( ) . S e t O p a c i t y (EARTH_OPACITY)

B.5 City_data.txt
1 name l a t l o n
2 CNU 3 7 . 0 6 3 9 −76.4947
3 Madrid 4 0 . 4 1 6 5 −3.70256
4 Buenos−A i r e s −34.605083 −58.400368
5 Lima −12.04318 −77.02824
6 R e y k i a v i k 6 4 . 2 2 0 7 0 −21.96139
7 Cape−Town −33.92584 1 8 . 4 2 3 2 2
8 B r i s b a n e −27.46794 1 5 3 . 0 2 8 0 9
9 Trondheim 6 3 . 4 3 3 0 0 1 0 . 3 9 5 1 6
10 Tokyo 3 5 . 6 8 9 5 1 3 9 . 6 9 1 7 1
11 Los−Angeles−Long−Beach−Santa−Ana 3 4 . 0 3 1 6 5 6 −118.241716
12 Halifax_CA 4 7 . 1 1 7 4 0 −63.54726

Polytechnic University of Catalonia - Barcelona Tech - UPC 63

You might also like