@@ -20,21 +20,25 @@ def _rotation_from_vectors(v, local=np.array([[1,0,0], [0,1,0], [0,0,1]])):
20
20
return M
21
21
22
22
23
- def _generate_random_mv (mv , scale , n , sigma = 1.0 ):
24
- ZP = 1.0
23
+ def _generate_random_mv_or_size (mv_or_size , scale , n , sigma = 1.0 , brightness_model = 'mv' ):
25
24
# samples = np.abs(np.random.normal(0, sigma, n))
26
25
samples = np .abs (np .random .lognormal (0 , sigma , n ))
27
- samples = samples / np .sum (samples )
28
- pe_target = mv_to_pe (ZP , mv )
29
- pe_part = samples * pe_target
30
- return pe_to_mv (ZP , pe_target * scale [0 ]), pe_to_mv (ZP , pe_part * scale [1 ])
26
+ samples = samples / np .sum (samples ) # normalize
27
+
28
+ if brightness_model == 'mv' :
29
+ ZP = 1.0
30
+ pe_target = mv_to_pe (ZP , mv_or_size )
31
+ pe_part = samples * pe_target
32
+ return pe_to_mv (ZP , pe_target * scale [0 ]), pe_to_mv (ZP , pe_part * scale [1 ])
33
+ else :
34
+ return mv_or_size * scale [0 ], samples * mv_or_size * scale [1 ]
31
35
32
36
33
37
def collision_from_tle (tle , collision_time , radius = 37.5 , K = 0.5 ,
34
38
attack_angle = 'random' , attack_velocity = None , attack_velocity_scale = 1.0 ,
35
39
n = [100 ,100 ], target_mv_scale = [0.5 , 2.0 ], rpo_mv_scale = [0.5 , 2.0 ],
36
40
target_mv = 12.0 , rpo_mv = 12.0 , offset = [0.0 , 0.0 ], collision_time_offset = 0.0 , variable_brightness = True ,
37
- fragment_angle = 'random' , scale_fragment_velocity = False ):
41
+ fragment_angle = 'random' , scale_fragment_velocity = False , brightness_model = 'mv' ):
38
42
"""Generates a two object collision configuration from the input `tle`.
39
43
40
44
Args:
@@ -55,6 +59,7 @@ def collision_from_tle(tle, collision_time, radius=37.5, K=0.5,
55
59
variable_brightness: `boolean`, if True randomly assign sine variable brightness between 0 to 1 hz. default=True
56
60
fragment_angle: `string`, specified the fragment angle sampling. `random` or `linspace`. default=`random`
57
61
scale_fragment_velocity: `boolean`, if True scale the fragment velocity by cosine of the exit velocity. default=`false`
62
+ brightness_model: `string`, the model to use for brightness calculations. valid options `mv`, `lambertian_sphere` default=`mv`
58
63
59
64
Example usage in SatSim configuration::
60
65
@@ -109,10 +114,10 @@ def collision_from_tle(tle, collision_time, radius=37.5, K=0.5,
109
114
collision_time = time .to_utc_list (t )
110
115
111
116
# brightness calculations
112
- target_mv_after , target_particles_mv = _generate_random_mv (target_mv , target_mv_scale , n [0 ], np .random .uniform (0.0 ,1.0 ))
117
+ target_mv_after , target_particles_mv = _generate_random_mv_or_size (target_mv , target_mv_scale , n [0 ], np .random .uniform (0.0 ,1.0 ), brightness_model = brightness_model )
113
118
114
119
if rpo_mv is not None :
115
- rpo_mv_after , rpo_particles_mv = _generate_random_mv (rpo_mv , rpo_mv_scale , n [1 ], np .random .uniform (0.0 ,1.0 ))
120
+ rpo_mv_after , rpo_particles_mv = _generate_random_mv_or_size (rpo_mv , rpo_mv_scale , n [1 ], np .random .uniform (0.0 ,1.0 ), brightness_model = brightness_model )
116
121
else :
117
122
rpo_mv_after , rpo_particles_mv = (None , [])
118
123
@@ -184,93 +189,133 @@ def collision_from_tle(tle, collision_time, radius=37.5, K=0.5,
184
189
vv [ndiv2 :,2 ] = np .abs (vv [ndiv2 :,2 ])
185
190
vv [ndiv2 :,:] = M1 .dot (vv [ndiv2 :,:].T ).T + velocity1
186
191
187
- if variable_brightness is True :
188
- def mv_func (mv_in ):
189
- return {
190
- "$pipeline" : [
191
- {
192
- "module" : "satsim.pipeline" ,
193
- "function" : "constant" ,
194
- "kwargs" : {
195
- "value" : mv_in
196
- }
197
- },
198
- {
199
- "module" : "satsim.pipeline" ,
200
- "function" : "sin_add" ,
201
- "kwargs" : {
202
- "freq" : np .random .normal (0 , 1.0 ),
203
- "mag_scale" : np .random .uniform (0 , 7.0 )
204
- }
205
- }
206
- ]
207
- }
208
- else :
209
- def mv_func (mv_in ):
210
- return mv_in
211
-
212
192
obs = {
213
193
"mode" : "list" ,
214
194
"list" : [{
215
195
"mode" : "twobody" ,
216
196
"position" : list (position ),
217
197
"velocity" : list (v ),
218
198
"epoch" : collision_time ,
219
- "mv" : mv_func (m ),
220
199
"offset" : offset ,
221
200
"events" : {
222
201
"create" : collision_time
223
202
}
224
203
} for v , m in zip (vv , np .concatenate ([target_particles_mv , rpo_particles_mv ]))]
225
204
}
226
205
206
+ target_obs = None
227
207
if target_mv is not None :
228
- obs [ 'list' ]. append ( {
208
+ target_obs = {
229
209
"mode" : "twobody" ,
230
210
"position" : list (position ),
231
211
"velocity" : list (velocity0 ),
232
212
"epoch" : collision_time ,
233
- "mv" : target_mv ,
234
213
"offset" : offset ,
235
214
"events" : {
236
215
"update" : [
237
216
{
238
217
"time" : collision_time ,
239
218
"values" : {
240
- "mv" : mv_func (target_mv_after )
241
219
}
242
220
}
243
221
]
244
222
}
245
- })
223
+ }
224
+ obs ['list' ].append (target_obs )
246
225
226
+ rpo_obs = None
247
227
if rpo_mv is not None :
248
- obs [ 'list' ]. append ( {
228
+ rpo_obs = {
249
229
"mode" : "twobody" ,
250
230
"position" : list (position ),
251
231
"velocity" : list (velocity1 ),
252
232
"epoch" : collision_time ,
253
- "mv" : rpo_mv ,
254
233
"offset" : offset ,
255
234
"events" : {
256
235
"update" : [
257
236
{
258
237
"time" : collision_time ,
259
238
"values" : {
260
- "mv" : mv_func (rpo_mv_after )
261
239
}
262
240
}
263
241
]
264
242
}
265
- })
243
+ }
244
+ obs ['list' ].append (rpo_obs )
245
+
246
+ if variable_brightness is True :
247
+ def mv_func (mv_in ):
248
+ return {
249
+ "$pipeline" : [
250
+ {
251
+ "module" : "satsim.pipeline" ,
252
+ "function" : "constant" ,
253
+ "kwargs" : {
254
+ "value" : mv_in
255
+ }
256
+ },
257
+ {
258
+ "module" : "satsim.pipeline" ,
259
+ "function" : "sin_add" ,
260
+ "kwargs" : {
261
+ "freq" : np .random .normal (0 , 1.0 ),
262
+ "mag_scale" : np .random .uniform (0 , 7.0 )
263
+ }
264
+ }
265
+ ]
266
+ }
267
+ else :
268
+ def mv_func (mv_in ):
269
+ return mv_in
270
+
271
+ if brightness_model == 'mv' :
272
+
273
+ for i , m in enumerate (np .concatenate ([target_particles_mv , rpo_particles_mv ])):
274
+ obs ['list' ][i ]['mv' ] = mv_func (m )
275
+
276
+ if target_obs is not None :
277
+ target_obs ['mv' ] = mv_func (target_mv_after )
278
+ target_obs ['events' ]['update' ][- 1 ]['values' ]['mv' ] = mv_func (target_mv_after )
279
+ if rpo_obs is not None :
280
+ rpo_obs ['mv' ] = mv_func (rpo_mv_after )
281
+ rpo_obs ['events' ]['update' ][- 1 ]['values' ]['mv' ] = mv_func (rpo_mv_after )
282
+
283
+ else :
284
+ albedo = 0.3 # TODO: make this a parameter
285
+ for i , m in enumerate (np .concatenate ([target_particles_mv , rpo_particles_mv ])):
286
+ obs ['list' ][i ]['model' ] = {
287
+ 'mode' : brightness_model ,
288
+ 'albedo' : albedo ,
289
+ 'size' : m
290
+ }
291
+
292
+ if target_obs is not None :
293
+ target_obs ['model' ] = {
294
+ 'mode' : brightness_model ,
295
+ 'albedo' : albedo ,
296
+ 'size' : target_mv
297
+ }
298
+ target_obs ['events' ]['update' ][- 1 ]['values' ]['model' ] = {
299
+ 'size' : target_mv_after
300
+ }
301
+
302
+ if rpo_obs is not None :
303
+ rpo_obs ['model' ] = {
304
+ 'mode' : brightness_model ,
305
+ 'albedo' : albedo ,
306
+ 'size' : rpo_mv
307
+ }
308
+ rpo_obs ['events' ]['update' ][- 1 ]['values' ]['model' ] = {
309
+ 'size' : rpo_mv_after
310
+ }
266
311
267
312
return obs
268
313
269
314
270
315
def breakup_from_tle (tle , breakup_time , radius = 37.5 , breakup_velocity = 108 ,
271
316
n = 100 , target_mv_scale = [0.5 , 2.0 ], target_mv = 12.0 ,
272
317
offset = [0.0 , 0.0 ], breakup_time_offset = 0.0 ,
273
- variable_brightness = True ):
318
+ variable_brightness = True , brightness_model = 'mv' ):
274
319
"""Generates a breakup configuration from the input `tle`.
275
320
276
321
Args:
@@ -283,6 +328,7 @@ def breakup_from_tle(tle, breakup_time, radius=37.5, breakup_velocity=108,
283
328
offset: `array`, row column offset of target position on fpa in normalized coordinates. default=12
284
329
breakup_time_offset: `float`, number of seconds to offset breakup time from `breakup`. default=[0,0]
285
330
variable_brightness: `boolean`, if True randomly assign sine variable brightness between 0 to 1 hz. default=True
331
+ brightness_model: `string`, the model to use for brightness calculations. valid options `mv`, `lambertian_sphere` default=`mv`
286
332
287
333
Example usage in SatSim configuration::
288
334
@@ -319,6 +365,6 @@ def breakup_from_tle(tle, breakup_time, radius=37.5, breakup_velocity=108,
319
365
attack_angle = 'random' , attack_velocity = breakup_velocity , attack_velocity_scale = 1.0 ,
320
366
n = n , target_mv_scale = target_mv_scale , rpo_mv_scale = None , target_mv = target_mv , rpo_mv = None ,
321
367
offset = offset , collision_time_offset = breakup_time_offset , variable_brightness = variable_brightness ,
322
- scale_fragment_velocity = False )
368
+ scale_fragment_velocity = False , brightness_model = brightness_model )
323
369
324
370
return obs
0 commit comments