Skip to content

Commit e0c18ba

Browse files
authored
Merge pull request #13 from ssc-ai/r0.19.0
v0.19.0
2 parents 9de0455 + 238517c commit e0c18ba

26 files changed

+486
-107
lines changed

HISTORY.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
History
22
=======
33

4+
0.19.0
5+
---------------------
6+
7+
* Add lambertian sphere brightness model for objects. Set object key `model` `mode` to `lambertian_sphere` and set `albedo` and `size` (meters) parameters. For 2D simulations, `distance` (km) and `phase_angle` (degrees) parameters must also be specified.
8+
9+
410
0.18.0
511
---------------------
612

Makefile

+3-3
Original file line numberDiff line numberDiff line change
@@ -111,12 +111,12 @@ install: clean ## install the package to the active python3's site-packages
111111
@echo IMPORTANT: You may need to close and restart your shell after running "make install".
112112

113113
docker: docs dist
114-
docker build -t satsim:0.18.0 -t satsim:latest -f docker/ubuntu20.04_cuda11.2_py3.8.dockerfile .
114+
docker build -t satsim:0.19.0 -t satsim:latest -f docker/ubuntu20.04_cuda11.2_py3.8.dockerfile .
115115

116116
dind:
117117
docker run --rm -it -v .:/workspace/ -w /workspace python:3.8-bullseye ./build.sh
118-
docker build -t satsim:0.18.0-cuda11.2 -f docker/ubuntu20.04_cuda11.2_py3.8.dockerfile .
119-
docker build -t satsim:0.18.0-cuda11.8 -t satsim:0.18.0 -t satsim:latest -f docker/ubuntu22.04_cuda11.8_py3.10.dockerfile .
118+
docker build -t satsim:0.19.0-cuda11.2 -f docker/ubuntu20.04_cuda11.2_py3.8.dockerfile .
119+
docker build -t satsim:0.19.0-cuda11.8 -t satsim:0.19.0 -t satsim:latest -f docker/ubuntu22.04_cuda11.8_py3.10.dockerfile .
120120

121121
uninstall: clean
122122
cat .install.log | xargs rm -rf

docker/ubuntu20.04_cuda11.2_py3.8.dockerfile

+3-3
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ RUN pip3 --no-cache-dir install --upgrade pip setuptools
2727
RUN pip3 --no-cache-dir install tensorflow~=2.11.0
2828

2929
# copy wheel file
30-
ENV SATSIM_VERSION='0.18.0'
31-
COPY dist/satsim-0.18.0-py2.py3-none-any.whl /tmp
30+
ENV SATSIM_VERSION='0.19.0'
31+
COPY dist/satsim-0.19.0-py2.py3-none-any.whl /tmp
3232

3333
# install satsim wheel file together with jupyterlab so dependency compatibility are resolved
3434
RUN pip3 --no-cache-dir install \
35-
tmp/satsim-0.18.0-py2.py3-none-any.whl \
35+
tmp/satsim-0.19.0-py2.py3-none-any.whl \
3636
jupyterlab \
3737
scikit-learn \
3838
virtualenv

docker/ubuntu22.04_cuda11.8_py3.10.dockerfile

+3-3
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@ RUN pip3 --no-cache-dir install --upgrade pip setuptools
2828
RUN pip3 --no-cache-dir install tensorflow~=2.13.0
2929

3030
# copy wheel file
31-
ENV SATSIM_VERSION='0.18.0'
32-
COPY dist/satsim-0.18.0-py2.py3-none-any.whl /tmp
31+
ENV SATSIM_VERSION='0.19.0'
32+
COPY dist/satsim-0.19.0-py2.py3-none-any.whl /tmp
3333

3434
# install satsim wheel file together with jupyterlab so dependency compatibility are resolved
3535
RUN pip3 --no-cache-dir install \
36-
tmp/satsim-0.18.0-py2.py3-none-any.whl \
36+
tmp/satsim-0.19.0-py2.py3-none-any.whl \
3737
jupyterlab \
3838
scikit-learn \
3939
virtualenv

docs/api/satsim.geometry.rst

+8
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ satsim.geometry.observation module
4949
:undoc-members:
5050
:show-inheritance:
5151

52+
satsim.geometry.photometric module
53+
----------------------------------
54+
55+
.. automodule:: satsim.geometry.photometric
56+
:members:
57+
:undoc-members:
58+
:show-inheritance:
59+
5260
satsim.geometry.random module
5361
-----------------------------
5462

docs/api/satsim.util.rst

+8
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ satsim.util package
99
Submodules
1010
----------
1111

12+
satsim.util.python module
13+
-------------------------
14+
15+
.. automodule:: satsim.util.python
16+
:members:
17+
:undoc-members:
18+
:show-inheritance:
19+
1220
satsim.util.system module
1321
-------------------------
1422

docs/conf.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,16 @@
5858
# the built documents.
5959
#
6060
# The short X.Y version.
61-
version = '0.18.0'
61+
version = '0.19.0'
6262
# The full version, including alpha/beta/rc tags.
63-
release = '0.18.0'
63+
release = '0.19.0'
6464

6565
# The language for content autogenerated by Sphinx. Refer to documentation
6666
# for a list of supported languages.
6767
#
6868
# This is also used if you do content translation via gettext catalogs.
6969
# Usually you set "language" from the command line for these cases.
70-
language = None
70+
language = "en"
7171

7272
# List of patterns, relative to source directory, that match files and
7373
# directories to ignore when looking for source files.
@@ -98,7 +98,7 @@
9898
# Add any paths that contain custom static files (such as style sheets) here,
9999
# relative to this directory. They are copied after the builtin static files,
100100
# so a file named "default.css" will overwrite the builtin "default.css".
101-
html_static_path = ['static']
101+
# html_static_path = ['static']
102102

103103

104104
# -- Options for HTMLHelp output ---------------------------------------

satsim/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
__author__ = """Alex Cabello"""
66
__email__ = 'alexander.cabello@algoritics.com'
7-
__version__ = '0.18.0'
7+
__version__ = '0.19.0'
88

99
from .satsim import gen_images, gen_multi, image_generator
1010
from .config import load_json, load_yaml

satsim/generator/obs/breakup.py

+91-45
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,25 @@ def _rotation_from_vectors(v, local=np.array([[1,0,0], [0,1,0], [0,0,1]])):
2020
return M
2121

2222

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'):
2524
# samples = np.abs(np.random.normal(0, sigma, n))
2625
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]
3135

3236

3337
def collision_from_tle(tle, collision_time, radius=37.5, K=0.5,
3438
attack_angle='random', attack_velocity=None, attack_velocity_scale=1.0,
3539
n=[100,100], target_mv_scale=[0.5, 2.0], rpo_mv_scale=[0.5, 2.0],
3640
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'):
3842
"""Generates a two object collision configuration from the input `tle`.
3943
4044
Args:
@@ -55,6 +59,7 @@ def collision_from_tle(tle, collision_time, radius=37.5, K=0.5,
5559
variable_brightness: `boolean`, if True randomly assign sine variable brightness between 0 to 1 hz. default=True
5660
fragment_angle: `string`, specified the fragment angle sampling. `random` or `linspace`. default=`random`
5761
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`
5863
5964
Example usage in SatSim configuration::
6065
@@ -109,10 +114,10 @@ def collision_from_tle(tle, collision_time, radius=37.5, K=0.5,
109114
collision_time = time.to_utc_list(t)
110115

111116
# 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)
113118

114119
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)
116121
else:
117122
rpo_mv_after, rpo_particles_mv = (None, [])
118123

@@ -184,93 +189,133 @@ def collision_from_tle(tle, collision_time, radius=37.5, K=0.5,
184189
vv[ndiv2:,2] = np.abs(vv[ndiv2:,2])
185190
vv[ndiv2:,:] = M1.dot(vv[ndiv2:,:].T).T + velocity1
186191

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-
212192
obs = {
213193
"mode": "list",
214194
"list": [{
215195
"mode": "twobody",
216196
"position": list(position),
217197
"velocity": list(v),
218198
"epoch": collision_time,
219-
"mv": mv_func(m),
220199
"offset": offset,
221200
"events": {
222201
"create": collision_time
223202
}
224203
} for v, m in zip(vv, np.concatenate([target_particles_mv, rpo_particles_mv]))]
225204
}
226205

206+
target_obs = None
227207
if target_mv is not None:
228-
obs['list'].append({
208+
target_obs = {
229209
"mode": "twobody",
230210
"position": list(position),
231211
"velocity": list(velocity0),
232212
"epoch": collision_time,
233-
"mv": target_mv,
234213
"offset": offset,
235214
"events": {
236215
"update": [
237216
{
238217
"time": collision_time,
239218
"values": {
240-
"mv": mv_func(target_mv_after)
241219
}
242220
}
243221
]
244222
}
245-
})
223+
}
224+
obs['list'].append(target_obs)
246225

226+
rpo_obs = None
247227
if rpo_mv is not None:
248-
obs['list'].append({
228+
rpo_obs = {
249229
"mode": "twobody",
250230
"position": list(position),
251231
"velocity": list(velocity1),
252232
"epoch": collision_time,
253-
"mv": rpo_mv,
254233
"offset": offset,
255234
"events": {
256235
"update": [
257236
{
258237
"time": collision_time,
259238
"values": {
260-
"mv": mv_func(rpo_mv_after)
261239
}
262240
}
263241
]
264242
}
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+
}
266311

267312
return obs
268313

269314

270315
def breakup_from_tle(tle, breakup_time, radius=37.5, breakup_velocity=108,
271316
n=100, target_mv_scale=[0.5, 2.0], target_mv=12.0,
272317
offset=[0.0, 0.0], breakup_time_offset=0.0,
273-
variable_brightness=True):
318+
variable_brightness=True, brightness_model='mv'):
274319
"""Generates a breakup configuration from the input `tle`.
275320
276321
Args:
@@ -283,6 +328,7 @@ def breakup_from_tle(tle, breakup_time, radius=37.5, breakup_velocity=108,
283328
offset: `array`, row column offset of target position on fpa in normalized coordinates. default=12
284329
breakup_time_offset: `float`, number of seconds to offset breakup time from `breakup`. default=[0,0]
285330
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`
286332
287333
Example usage in SatSim configuration::
288334
@@ -319,6 +365,6 @@ def breakup_from_tle(tle, breakup_time, radius=37.5, breakup_velocity=108,
319365
attack_angle='random', attack_velocity=breakup_velocity, attack_velocity_scale=1.0,
320366
n=n, target_mv_scale=target_mv_scale, rpo_mv_scale=None, target_mv=target_mv, rpo_mv=None,
321367
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)
323369

324370
return obs

0 commit comments

Comments
 (0)