├── docs ├── earth_rocket_launch.png └── europa_clipper_arriving_jupiter.png ├── scenes ├── ct004_set_camera_view │ ├── mro_orbits │ │ ├── mro-sep-21.bsp │ │ ├── mar097-sep-21.bsp │ │ ├── load.json │ │ ├── spice.json │ │ ├── spacecraft.json │ │ └── script.py │ └── run_mro_orbits.sh ├── ct006_iau_earth │ ├── iau_earth_orbits │ │ ├── ct006-orbits.bsp │ │ ├── load.json │ │ ├── spice.json │ │ ├── script.py │ │ └── spacecraft.json │ └── run_iau_earth_orbits.sh ├── ct003_py_json_spice │ ├── sun_synchronous_orbit │ │ ├── sso_j2.bsp │ │ ├── spice.json │ │ ├── load.json │ │ ├── spacecraft.json │ │ └── script.py │ └── run_sun_synchronous_orbit.sh └── ct005_inertial_scene_from_scratch │ ├── geo_inertial │ ├── GEO.bsp │ ├── spice.json │ ├── load.json │ ├── spacecraft.json │ └── script.py │ └── run_geo_inertial.sh ├── src ├── parse_cosmo_url.py └── parse_cosmo_url_test.py └── README.md /docs/earth_rocket_launch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NablaZeroLabs/cosmo-demos/HEAD/docs/earth_rocket_launch.png -------------------------------------------------------------------------------- /docs/europa_clipper_arriving_jupiter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NablaZeroLabs/cosmo-demos/HEAD/docs/europa_clipper_arriving_jupiter.png -------------------------------------------------------------------------------- /scenes/ct004_set_camera_view/mro_orbits/mro-sep-21.bsp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NablaZeroLabs/cosmo-demos/HEAD/scenes/ct004_set_camera_view/mro_orbits/mro-sep-21.bsp -------------------------------------------------------------------------------- /scenes/ct006_iau_earth/iau_earth_orbits/ct006-orbits.bsp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NablaZeroLabs/cosmo-demos/HEAD/scenes/ct006_iau_earth/iau_earth_orbits/ct006-orbits.bsp -------------------------------------------------------------------------------- /scenes/ct004_set_camera_view/mro_orbits/mar097-sep-21.bsp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NablaZeroLabs/cosmo-demos/HEAD/scenes/ct004_set_camera_view/mro_orbits/mar097-sep-21.bsp -------------------------------------------------------------------------------- /scenes/ct003_py_json_spice/sun_synchronous_orbit/sso_j2.bsp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NablaZeroLabs/cosmo-demos/HEAD/scenes/ct003_py_json_spice/sun_synchronous_orbit/sso_j2.bsp -------------------------------------------------------------------------------- /scenes/ct005_inertial_scene_from_scratch/geo_inertial/GEO.bsp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NablaZeroLabs/cosmo-demos/HEAD/scenes/ct005_inertial_scene_from_scratch/geo_inertial/GEO.bsp -------------------------------------------------------------------------------- /scenes/ct004_set_camera_view/mro_orbits/load.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0", 3 | "name" : "MRO Orbits Load Catalog", 4 | "require": [ 5 | "spice.json", 6 | "spacecraft.json" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /scenes/ct006_iau_earth/iau_earth_orbits/load.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0", 3 | "name" : "IAU_EARTH Orbits Load Catalog", 4 | "require": [ 5 | "spice.json", 6 | "spacecraft.json" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /scenes/ct006_iau_earth/iau_earth_orbits/spice.json: -------------------------------------------------------------------------------- 1 | { 2 | "version" : "1.0", 3 | "name" : "IAU_EARTH Orbits SPICE Catalog", 4 | "spiceKernels": [ 5 | "ct006-orbits.bsp" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /scenes/ct003_py_json_spice/sun_synchronous_orbit/spice.json: -------------------------------------------------------------------------------- 1 | { 2 | "version" : "1.0", 3 | "name" : "Sun Synchronous Orbit SPICE Catalog", 4 | "spiceKernels": [ 5 | "sso_j2.bsp" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /scenes/ct005_inertial_scene_from_scratch/geo_inertial/spice.json: -------------------------------------------------------------------------------- 1 | { 2 | "version" : "1.0", 3 | "name" : "Geostationary Orbit SPICE Catalog", 4 | "spiceKernels": [ 5 | "GEO.bsp" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /scenes/ct003_py_json_spice/sun_synchronous_orbit/load.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0", 3 | "name" : "Sun Synchronous Orbit Load Catalog", 4 | "require": [ 5 | "spice.json", 6 | "spacecraft.json" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /scenes/ct005_inertial_scene_from_scratch/geo_inertial/load.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0", 3 | "name" : "Geostationary Orbit Load Catalog", 4 | "require": [ 5 | "spice.json", 6 | "spacecraft.json" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /scenes/ct004_set_camera_view/mro_orbits/spice.json: -------------------------------------------------------------------------------- 1 | { 2 | "version" : "1.0", 3 | "name" : "MRO Orbits SPICE Catalog", 4 | "spiceKernels": [ 5 | "mar097-sep-21.bsp", 6 | "mro-sep-21.bsp" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /scenes/ct004_set_camera_view/run_mro_orbits.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ${COSMOGRAPHIA} \ 4 | ${COSMO_DEMOS}/ct004_set_camera_view/mro_orbits/load.json \ 5 | -p ${COSMO_DEMOS}/ct004_set_camera_view/mro_orbits/script.py 6 | 7 | exit 8 | -------------------------------------------------------------------------------- /scenes/ct006_iau_earth/run_iau_earth_orbits.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ${COSMOGRAPHIA} \ 4 | ${COSMO_DEMOS}/ct006_iau_earth/iau_earth_orbits/load.json \ 5 | -p ${COSMO_DEMOS}/ct006_iau_earth/iau_earth_orbits/script.py 6 | 7 | exit 8 | -------------------------------------------------------------------------------- /scenes/ct003_py_json_spice/run_sun_synchronous_orbit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ${COSMOGRAPHIA} \ 4 | ${COSMO_DEMOS}/ct003_py_json_spice/sun_synchronous_orbit/load.json \ 5 | -p ${COSMO_DEMOS}/ct003_py_json_spice/sun_synchronous_orbit/script.py 6 | 7 | exit 8 | -------------------------------------------------------------------------------- /scenes/ct005_inertial_scene_from_scratch/run_geo_inertial.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ${COSMOGRAPHIA} \ 4 | ${COSMO_DEMOS}/ct005_inertial_scene_from_scratch/geo_inertial/load.json \ 5 | -p ${COSMO_DEMOS}/ct005_inertial_scene_from_scratch/geo_inertial/script.py 6 | 7 | exit 8 | -------------------------------------------------------------------------------- /scenes/ct004_set_camera_view/mro_orbits/spacecraft.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0", 3 | "name" : "MRO Orbits Spacecraft Catalog", 4 | "items" : [ 5 | { 6 | "class" : "spacecraft", 7 | "name" : "MRO", 8 | "startTime" : "2021-09-21 00:01:00 UTC", 9 | "center" : "Mars", 10 | "trajectory": { 11 | "type" : "Spice", 12 | "target": "-74", 13 | "center": "Mars", 14 | "frame" : "J2000" 15 | }, 16 | "label": { 17 | "color": [ 1.0, 0.3, 0.3 ] 18 | }, 19 | "trajectoryPlot": { 20 | "color" : [ 1.0, 0.3, 0.3 ], 21 | "lineWidth" : 4, 22 | "sampleCount": 200, 23 | "duration" : "5 d", 24 | "lead" : "1 s", 25 | "fade" : 1.0 26 | } 27 | } 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /scenes/ct003_py_json_spice/sun_synchronous_orbit/spacecraft.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0", 3 | "name" : "Sun Synchronous Orbit Spacecraft Catalog", 4 | "items" : [ 5 | { 6 | "class" : "spacecraft", 7 | "name" : "SSO Spacecraft", 8 | "startTime" : "2021-09-17 00:02:00 TDB", 9 | "center" : "Earth", 10 | "trajectory": { 11 | "type" : "Spice", 12 | "target": "-999", 13 | "center": "Earth", 14 | "frame" : "J2000" 15 | }, 16 | "label": { 17 | "color": [ 1.0, 0.1, 1.0 ] 18 | }, 19 | "trajectoryPlot": { 20 | "color" : [ 1.0, 0.1, 1.0 ], 21 | "lineWidth" : 4, 22 | "sampleCount": 200, 23 | "duration" : "5 d", 24 | "lead" : "1 s", 25 | "fade" : 1.0 26 | } 27 | } 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /scenes/ct005_inertial_scene_from_scratch/geo_inertial/spacecraft.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0", 3 | "name" : "Geostationary Orbit Spacecraft Catalog", 4 | "items" : [ 5 | { 6 | "class" : "spacecraft", 7 | "name" : "GEO Spacecraft", 8 | "startTime" : "2021-08-05 00:02:00 TDB", 9 | "center" : "Earth", 10 | "trajectory": { 11 | "type" : "Spice", 12 | "target": "-997", 13 | "center": "Earth", 14 | "frame" : "J2000" 15 | }, 16 | "label": { 17 | "color": [ 1.0, 0.1, 1.0 ] 18 | }, 19 | "trajectoryPlot": { 20 | "color" : [ 1.0, 0.1, 1.0 ], 21 | "lineWidth" : 4, 22 | "sampleCount": 200, 23 | "duration" : "1 d", 24 | "lead" : "1 s", 25 | "fade" : 1.0 26 | } 27 | } 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /scenes/ct004_set_camera_view/mro_orbits/script.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8; mode:python; mode:auto-fill; fill-column:79; -*- 2 | 3 | ## @file script.py 4 | ## @brief Cosmographia script for MRO Orbits scene. 5 | ## @author A. Gonzalez 6 | ## @copyright (C) 2021 Nabla Zero Labs 7 | 8 | import cosmoscripting 9 | 10 | cosmo = cosmoscripting.Cosmo() 11 | bodies = [ 'Sun', 'Earth', 'Mars', 'Phobos', 'Deimos', 'MRO' ] 12 | 13 | ######################################## 14 | # Initial setup 15 | 16 | #cosmo.showFullScreen() 17 | cosmo.pause() 18 | cosmo.setTime( '2021-09-21 01:00:00 UTC' ) 19 | cosmo.hideAllObjects() 20 | cosmo.hideToolBar() 21 | cosmo.hideSpiceMessages() 22 | cosmo.hideEcliptic() 23 | cosmo.hideCenterIndicator() 24 | cosmo.hideLabels() 25 | cosmo.hidePlanetOrbits() 26 | 27 | for body in bodies: 28 | cosmo.showObject( body ) 29 | cosmo.showTrajectory( 'MRO' ) 30 | cosmo.showTrajectory( 'Phobos' ) 31 | cosmo.showTrajectory( 'Deimos' ) 32 | cosmo.showTrajectory( 'Earth' ) 33 | 34 | cosmo.setCentralObject( 'Mars' ) 35 | cosmo.selectObject( 'Mars' ) 36 | cosmo.setCameraToInertialFrame() 37 | 38 | 39 | cosmo.showLabels() 40 | 41 | ######################################## 42 | # Begin scene 43 | 44 | cosmo.fadeIn( 1 ) 45 | cosmo.wait( 2 ) 46 | -------------------------------------------------------------------------------- /src/parse_cosmo_url.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8; mode:python; mode:auto-fill; fill-column:79; -*- 2 | 3 | ## @file script.py 4 | ## @brief Parse Cosmograhia URL to Python commands. 5 | ## @author A. Gonzalez 6 | ## @copyright (C) 2021 Nabla Zero Labs 7 | 8 | from sys import argv 9 | 10 | def parse_url( args ): 11 | nargs = len( args ) 12 | 13 | if nargs != 2 or not args[ 1 ]: 14 | raise RuntimeError( 15 | f'Expected 1 commmand line argument, got {nargs}.' ) 16 | 17 | s = args[ 1 ].split( '&' ) 18 | nvars = len( s ) 19 | 20 | if nvars == 11: 21 | x = s[ 2 ].replace( 'x=', '' ) 22 | y = s[ 3 ].replace( 'y=', '' ) 23 | z = s[ 4 ].replace( 'z=', '' ) 24 | qw = s[ 5 ].replace( 'qw=', '' ) 25 | qx = s[ 6 ].replace( 'qx=', '' ) 26 | qy = s[ 7 ].replace( 'qy=', '' ) 27 | qz = s[ 8 ].replace( 'qz=', '' ) 28 | elif nvars == 12: 29 | x = s[ 3 ].replace( 'x=', '' ) 30 | y = s[ 4 ].replace( 'y=', '' ) 31 | z = s[ 5 ].replace( 'z=', '' ) 32 | qw = s[ 6 ].replace( 'qw=', '' ) 33 | qx = s[ 7 ].replace( 'qx=', '' ) 34 | qy = s[ 8 ].replace( 'qy=', '' ) 35 | qz = s[ 9 ].replace( 'qz=', '' ) 36 | else: 37 | raise RuntimeError( 38 | f'Expected 11 or 12 variables in URL, got {nvars}.' ) 39 | 40 | line0 = f'cosmo.setCameraPosition( [ {x}, {y}, {z} ] )' 41 | line1 = f'cosmo.setCameraOrientation( [ {qw}, {qx}, {qy}, {qz} ] )' 42 | 43 | print( s ) 44 | print( nvars ) 45 | print() 46 | print( line0 ) 47 | print( line1 ) 48 | print() 49 | 50 | if __name__ == '__main__': 51 | parse_url( argv ) 52 | -------------------------------------------------------------------------------- /scenes/ct005_inertial_scene_from_scratch/geo_inertial/script.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8; mode:python; mode:auto-fill; fill-column:79; -*- 2 | 3 | ## @file script.py 4 | ## @brief Cosmographia script for Geostationary Orbit scene. 5 | ## @author A. Gonzalez 6 | ## @copyright (C) 2021 Nabla Zero Labs 7 | 8 | import cosmoscripting 9 | 10 | cosmo = cosmoscripting.Cosmo() 11 | bodies = [ 'Sun', 'Earth', 'Moon', 'GEO Spacecraft' ] 12 | 13 | ######################################## 14 | # Initial setup 15 | 16 | cosmo.showFullScreen() 17 | cosmo.pause() 18 | cosmo.setTime( '2021-08-06 00:10:00 UTC' ) 19 | cosmo.hideAllObjects() 20 | cosmo.hideToolBar() 21 | cosmo.hideSpiceMessages() 22 | cosmo.hideEcliptic() 23 | cosmo.hideCenterIndicator() 24 | cosmo.hideLabels() 25 | cosmo.hidePlanetOrbits() 26 | 27 | for body in bodies: 28 | cosmo.showObject( body ) 29 | cosmo.showTrajectory( 'GEO Spacecraft' ) 30 | cosmo.showTrajectory( 'Moon' ) 31 | 32 | cosmo.setCentralObject( 'Earth' ) 33 | cosmo.selectObject( 'Earth' ) 34 | cosmo.setCameraToInertialFrame() 35 | cosmo.setCameraPosition( [ -20588.815307, 128356.247694, 27401.753157 ] ) 36 | cosmo.setCameraOrientation( [ -0.076761, -0.043044, 0.607017, 0.789801 ] ) 37 | cosmo.showLabels() 38 | 39 | ######################################## 40 | # Begin scene 41 | 42 | cosmo.fadeIn( 1 ) 43 | cosmo.wait( 2 ) 44 | cosmo.showDirectionVector( 'Earth', 'GEO Spacecraft' ) 45 | cosmo.wait( 1 ) 46 | cosmo.setTimeRate( 6000 ) 47 | cosmo.unpause() 48 | cosmo.wait( 5 ) 49 | cosmo.circleCenterUp( 75, 5 ) 50 | cosmo.wait( 5 ) 51 | 52 | cosmo.pause() 53 | -------------------------------------------------------------------------------- /scenes/ct003_py_json_spice/sun_synchronous_orbit/script.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8; mode:python; mode:auto-fill; fill-column:79; -*- 2 | 3 | ## @file script.py 4 | ## @brief Cosmographia script for Sun Synchronous Orbit scene. 5 | ## @author A. Gonzalez 6 | ## @copyright (C) 2021 Nabla Zero Labs 7 | 8 | import cosmoscripting 9 | 10 | cosmo = cosmoscripting.Cosmo() 11 | bodies = [ 'Sun', 'Earth', 'Moon', 'SSO Spacecraft' ] 12 | 13 | ######################################## 14 | # Initial setup 15 | 16 | cosmo.showFullScreen() 17 | cosmo.pause() 18 | cosmo.setTime( '2021-09-17 00:10:00 UTC' ) 19 | cosmo.hideAllObjects() 20 | cosmo.hideToolBar() 21 | cosmo.hideSpiceMessages() 22 | cosmo.hideEcliptic() 23 | cosmo.hideCenterIndicator() 24 | cosmo.hideLabels() 25 | cosmo.hidePlanetOrbits() 26 | 27 | for body in bodies: 28 | cosmo.showObject( body ) 29 | cosmo.showTrajectory( 'SSO Spacecraft' ) 30 | cosmo.showTrajectory( 'Moon' ) 31 | 32 | cosmo.setCentralObject( 'Earth' ) 33 | cosmo.selectObject( 'Earth' ) 34 | cosmo.setCameraToInertialFrame() 35 | cosmo.setCameraPosition( [ -18763.520461, -3770.166644, 8500.870754 ] ) 36 | cosmo.setCameraOrientation( [ 0.692937, 0.376302, -0.383892, -0.480481 ] ) 37 | cosmo.showLabels() 38 | 39 | ######################################## 40 | # Begin scene 41 | 42 | cosmo.fadeIn( 1 ) 43 | cosmo.wait( 2 ) 44 | cosmo.showDirectionVector( 'Earth', 'Sun' ) 45 | cosmo.wait( 1 ) 46 | cosmo.setTimeRate( 1000 ) 47 | cosmo.unpause() 48 | cosmo.wait( 5 ) 49 | cosmo.setTimeRate( 5000 ) 50 | cosmo.wait( 5 ) 51 | cosmo.setTimeRate( 50000 ) 52 | cosmo.wait( 5 ) 53 | cosmo.pause() 54 | -------------------------------------------------------------------------------- /scenes/ct006_iau_earth/iau_earth_orbits/script.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8; mode:python; mode:auto-fill; fill-column:79; -*- 2 | 3 | ## @file script.py 4 | ## @brief Cosmographia script for IAU_EARTH Orbits scene. 5 | ## @author A. Gonzalez 6 | ## @copyright (C) 2021 Nabla Zero Labs 7 | 8 | import cosmoscripting 9 | 10 | cosmo = cosmoscripting.Cosmo() 11 | bodies = [ 'Sun', 'Earth', 'Moon' ] 12 | bodies += [ 'Geosynchronous', 'Sun-Synchronous' ] 13 | bodies += [ 'Geostationary', 'Molniya' ] 14 | 15 | groundtracks = [ 'Geosynchronous GT' ] 16 | groundtracks += [ 'Geostationary GT', 'Molniya GT' ] 17 | 18 | ######################################## 19 | # Initial setup 20 | 21 | cosmo.showFullScreen() 22 | cosmo.pause() 23 | cosmo.setTime( '2021-09-27 08:00:00 UTC' ) 24 | cosmo.hideAllObjects() 25 | cosmo.hideToolBar() 26 | cosmo.hideSpiceMessages() 27 | cosmo.hideEcliptic() 28 | cosmo.hideCenterIndicator() 29 | cosmo.hideLabels() 30 | cosmo.hidePlanetOrbits() 31 | 32 | for body in bodies: 33 | cosmo.showObject( body ) 34 | 35 | for body in bodies[ 3: ]: 36 | cosmo.showTrajectory( body ) 37 | 38 | for gt in groundtracks: 39 | cosmo.showTrajectory( gt ) 40 | 41 | cosmo.setCentralObject( 'Earth' ) 42 | cosmo.selectObject( 'Earth' ) 43 | cosmo.setCameraToBodyFixedFrame() 44 | cosmo.setCameraPosition( [ -73415.388504, 65302.397619, 4464.887641 ] ) 45 | cosmo.setCameraOrientation( [ -0.313724, -0.270648, 0.666240, 0.620041 ] ) 46 | 47 | cosmo.showLabels() 48 | 49 | ######################################## 50 | # Begin scene 51 | 52 | cosmo.fadeIn( 1 ) 53 | cosmo.wait( 2 ) 54 | cosmo.dollyForward( 400, 1 ) 55 | cosmo.setTimeRate( 4000 ) 56 | cosmo.unpause() 57 | cosmo.wait( 7 ) 58 | cosmo.circleCenterLeft( 360, 30 ) 59 | cosmo.pause() 60 | -------------------------------------------------------------------------------- /src/parse_cosmo_url_test.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8; mode:python; mode:auto-fill; fill-column:79; -*- 2 | 3 | ## @file parse_cosmo_url_test.py 4 | ## @brief Cosmograhia URL parser unit tests. 5 | ## @author A. Gonzalez 6 | ## @copyright (C) 2021 Nabla Zero Labs 7 | 8 | import pytest 9 | from parse_cosmo_url import parse_url 10 | 11 | def test_no_arguments_passed_in_expect_throw(): 12 | with pytest.raises( RuntimeError ): 13 | parse_url( [ 'parse_cosmo_url.py' ] ) 14 | 15 | def test_empty_first_argument_expect_throw(): 16 | with pytest.raises( RuntimeError ): 17 | parse_url( [ 'parse_cosmo_url.py', '' ] ) 18 | 19 | def test_too_many_variables_in_url_expect_throw(): 20 | url = ( 'cosmo:Sun?select=Sun&frame=icrf&jd=2459479.166353' 21 | '&x=621948642.994960&y=-1345464080.888191&z=234503252.731015' 22 | '&qw=0.723297&qx=0.644880&qy=0.077452&qz=0.234462&ts=1&fov=50' 23 | '&test' 24 | ) 25 | with pytest.raises( RuntimeError ): 26 | parse_url( [ 'parse_cosmo_url.py', url ] ) 27 | 28 | def test_too_few_variables_in_url_expect_throw(): 29 | url = ( 'frame=icrf&jd=2459479.166353' 30 | '&x=621948642.994960&y=-1345464080.888191&z=234503252.731015' 31 | '&qw=0.723297&qx=0.644880&qy=0.077452&qz=0.234462&ts=1' 32 | ) 33 | with pytest.raises( RuntimeError ): 34 | parse_url( [ 'parse_cosmo_url.py', url ] ) 35 | 36 | def test_basic_usage_11_vars(): 37 | url = ( 'frame=icrf&jd=2459479.166353' 38 | '&x=621948642.994960&y=-1345464080.888191&z=234503252.731015' 39 | '&qw=0.723297&qx=0.644880&qy=0.077452&qz=0.234462&ts=1&fov=50' 40 | ) 41 | parse_url( [ 'parse_cosmo_url.py', url ] ) 42 | 43 | def test_basic_usage_12_vars(): 44 | url = ( 'cosmo:Sun?select=Sun&frame=icrf&jd=2459479.166353' 45 | '&x=621948642.994960&y=-1345464080.888191&z=234503252.731015' 46 | '&qw=0.723297&qx=0.644880&qy=0.077452&qz=0.234462&ts=1&fov=50' 47 | ) 48 | parse_url( [ 'parse_cosmo_url.py', url ] ) 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cosmo-demos | SPICE-Enhanced Cosmographia Tutorials 2 | ## Nabla Zero Labs, 2021 3 | 4 | This is `cosmo-demos`, a software utility for creating advanced astrodynamics visualizations using NASA's SPICE-Enhanced Cosmographia. 5 | 6 | ![Europa Clipper arriving at Jupiter](docs/europa_clipper_arriving_jupiter.png) 7 | ![Earth rocket launch](docs/earth_rocket_launch.png) 8 | 9 | ## Dependencies 10 | * [SPICE-Enhanced Cosmographia 4.0](https://naif.jpl.nasa.gov/naif/cosmographia.html) 11 | 12 | # Cosmographia 13 | SPICE-enhanced Cosmographia is an open source visualization tool used to 14 | produce 3D animations of planets (3D models and orbits), stars, and spacecraft 15 | (trajectories, 3D models, sensor FOVs, etc.). This repository interacts with 16 | Cosmographia via Python scripts, SPICE kernels, JSON catalogs, and CAD models. 17 | 18 | # Getting Started 19 | This repository is accompanied by YouTube videos that explain how to run the existing scenes and create scenes from scratch. 20 | * [Cosmographia Tutorials Video Series](https://www.youtube.com/playlist?list=PLinlYN8Y2w8dF_FI2baI5YXM476_7kekz) 21 | 22 | ## Setting Environment Variables 23 | `cosmo-demos` calls Cosmographia via bash scripts that point to the Cosmographia executable, JSON catalogs, SPICE kernels, and Python scripts. In order to use this repository, one must set 2 environment variables: `COSMOGRAPHIA` and `COSMO_DEMOS`. 24 | 25 | This is done via the `export` command, which for convenience can be placed in a .bash_profile or .bashrc file. For example: 26 | 27 | ```sh 28 | $ export COSMOGRAPHIA=${HOME}/cosmographia-4.0/Cosmographia.app/Contents/MacOS/Cosmographia 29 | $ export COSMO_DEMOS=${HOME}/cosmo-demos/scenes 30 | ``` 31 | 32 | * [Video explaining how to set these environment variables](https://youtu.be/OU6bOjYOVus) 33 | 34 | Once the environment variables are set, one can call any bash script that corresponds to a scene in this repository. For example (from the base of the repository): 35 | 36 | ```sh 37 | $ ./scenes/ct003_py_json_spice/run_sun_synchronous_orbit.sh 38 | ``` 39 | 40 | # Manually Setting Camera Views 41 | The following is a "cheat sheet" of how to use the keyboard and mouse to maneuver the camera position and orientation manually. 42 | 43 | * **Circle around central body** - Hold left click and move mouse 44 | * **Rotate camera orientation only (no translation)** - Hold right click and move mouse 45 | * **Move camera forward** - Scroll up 46 | * **Move camera backward** - Scroll down 47 | * **Rotate camera clockwise** - Right arrow 48 | * **Rotate camera counterclockwise** - Left arrow 49 | * **Go to object** - Left double click 50 | 51 | ## Plugging in Desired View to Scene Python Scripts 52 | Once the desired view is achieved by manually moving the camera, the 53 | position and orientation values can be extracted and passed into a Python 54 | script to set the initial view of a scene. Here are the steps: 55 | 56 | 1. Click on File --> Copy State URL to Clipboard (Command+u on MacOS) 57 | 2. Pass in URL to the parse_cosmo_url.py script 58 | ```sh 59 | $ python3 src/parse_cosmo_url.py "[paste URL here inside of double quotes]" 60 | ``` 61 | 3. Copy and paste the printed setCameraPosition and setCameraOrientation commands to the scene Python script. The following is an example output: 62 | ```py 63 | cosmo.setCameraPosition( [ -52536.063013, -29446.819564, -8254.010454 ] ) 64 | cosmo.setCameraOrientation( [ 0.452261, 0.731298, -0.286255, -0.422755 ] ) 65 | ``` 66 | 67 | For convenience, the following bash function can be placed in a .bash_profile or .bashrc after the `COSMO_DEMOS` environment variable definition to more easily call the parse_cosmo_url script: 68 | 69 | ```sh 70 | parse_cosmo_url() { 71 | python3 ${COSMO_DEMOS}/../src/parse_cosmo_url.py "$1"; 72 | } 73 | ``` 74 | 75 | This way, one can parse the Cosmographia URL without considering relative paths to the Python script. The following is how to call the bash function (parse_cosmo_url can be tab autocompleted in the terminal): 76 | 77 | ```sh 78 | $ parse_cosmo_url "[paste URL here inside of double quotes]" 79 | ``` 80 | 81 | [Video with example of setting camera view and using URL parser](https://youtu.be/3UP0Uo0WFf0) 82 | -------------------------------------------------------------------------------- /scenes/ct006_iau_earth/iau_earth_orbits/spacecraft.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0", 3 | "name" : "IAU_EARTH Orbits Spacecraft Catalog", 4 | "items" : [ 5 | { 6 | "class" : "spacecraft", 7 | "name" : "Geosynchronous", 8 | "startTime" : "2021-09-27 00:02:00 UTC", 9 | "center" : "Earth", 10 | "trajectoryFrame": { 11 | "type": "Spice", 12 | "name": "IAU_EARTH" 13 | }, 14 | "trajectory": { 15 | "type" : "Spice", 16 | "target": "-999", 17 | "center": "Earth", 18 | "frame" : "IAU_EARTH" 19 | }, 20 | "label": { 21 | "color": [ 0.3, 1.0, 0.4 ] 22 | }, 23 | "trajectoryPlot": { 24 | "color" : [ 0.3, 1.0, 0.4 ], 25 | "lineWidth" : 4, 26 | "sampleCount": 200, 27 | "duration" : "1 d", 28 | "lead" : "1 s", 29 | "fade" : 1.0 30 | } 31 | }, 32 | { 33 | "class" : "spacecraft", 34 | "name" : "Geosynchronous GT", 35 | "startTime" : "2021-09-27 00:02:00 UTC", 36 | "center" : "Earth", 37 | "trajectoryFrame": { 38 | "type": "Spice", 39 | "name": "IAU_EARTH" 40 | }, 41 | "trajectory": { 42 | "type" : "Spice", 43 | "target": "-9990", 44 | "center": "Earth", 45 | "frame" : "IAU_EARTH" 46 | }, 47 | "label": { 48 | "color": [ 0.3, 1.0, 0.4 ] 49 | }, 50 | "trajectoryPlot": { 51 | "color" : [ 0.3, 1.0, 0.4 ], 52 | "lineWidth" : 4, 53 | "sampleCount": 200, 54 | "duration" : "1 d", 55 | "lead" : "1 s", 56 | "fade" : 1.0 57 | } 58 | }, 59 | { 60 | "class" : "spacecraft", 61 | "name" : "Sun-Synchronous", 62 | "startTime" : "2021-09-27 00:02:00 UTC", 63 | "center" : "Earth", 64 | "trajectoryFrame": { 65 | "type": "Spice", 66 | "name": "IAU_EARTH" 67 | }, 68 | "trajectory": { 69 | "type" : "Spice", 70 | "target": "-998", 71 | "center": "Earth", 72 | "frame" : "IAU_EARTH" 73 | }, 74 | "label": { 75 | "color": [ 1.0, 0.3, 1.0 ] 76 | }, 77 | "trajectoryPlot": { 78 | "color" : [ 1.0, 0.3, 1.0 ], 79 | "lineWidth" : 4, 80 | "sampleCount": 200, 81 | "duration" : "0.5 d", 82 | "lead" : "1 s", 83 | "fade" : 1.0 84 | } 85 | }, 86 | { 87 | "class" : "spacecraft", 88 | "name" : "Sun-Synchronous GT", 89 | "startTime" : "2021-09-27 00:02:00 UTC", 90 | "center" : "Earth", 91 | "trajectoryFrame": { 92 | "type": "Spice", 93 | "name": "IAU_EARTH" 94 | }, 95 | "trajectory": { 96 | "type" : "Spice", 97 | "target": "-9980", 98 | "center": "Earth", 99 | "frame" : "IAU_EARTH" 100 | }, 101 | "label": { 102 | "color": [ 1.0, 0.3, 1.0 ] 103 | }, 104 | "trajectoryPlot": { 105 | "color" : [ 1.0, 0.3, 1.0 ], 106 | "lineWidth" : 4, 107 | "sampleCount": 200, 108 | "duration" : "0.5 d", 109 | "lead" : "1 s", 110 | "fade" : 1.0 111 | } 112 | }, { 113 | "class" : "spacecraft", 114 | "name" : "Geostationary", 115 | "startTime" : "2021-09-27 00:02:00 UTC", 116 | "center" : "Earth", 117 | "trajectoryFrame": { 118 | "type": "Spice", 119 | "name": "IAU_EARTH" 120 | }, 121 | "trajectory": { 122 | "type" : "Spice", 123 | "target": "-997", 124 | "center": "Earth", 125 | "frame" : "IAU_EARTH" 126 | }, 127 | "label": { 128 | "color": [ 1.0, 0.4, 0.4 ] 129 | }, 130 | "trajectoryPlot": { 131 | "color" : [ 1.0, 0.4, 0.4 ], 132 | "lineWidth" : 4, 133 | "sampleCount": 200, 134 | "duration" : "1 d", 135 | "lead" : "1 s", 136 | "fade" : 1.0 137 | } 138 | }, 139 | { 140 | "class" : "spacecraft", 141 | "name" : "Geostationary GT", 142 | "startTime" : "2021-09-27 00:02:00 UTC", 143 | "center" : "Earth", 144 | "trajectoryFrame": { 145 | "type": "Spice", 146 | "name": "IAU_EARTH" 147 | }, 148 | "trajectory": { 149 | "type" : "Spice", 150 | "target": "-9970", 151 | "center": "Earth", 152 | "frame" : "IAU_EARTH" 153 | }, 154 | "label": { 155 | "color": [ 1.0, 0.4, 0.4 ] 156 | }, 157 | "trajectoryPlot": { 158 | "color" : [ 1.0, 0.4, 0.4 ], 159 | "lineWidth" : 4, 160 | "sampleCount": 200, 161 | "duration" : "1 d", 162 | "lead" : "1 s", 163 | "fade" : 1.0 164 | } 165 | }, 166 | { 167 | "class" : "spacecraft", 168 | "name" : "Molniya", 169 | "startTime" : "2021-09-27 00:02:00 UTC", 170 | "center" : "Earth", 171 | "trajectoryFrame": { 172 | "type": "Spice", 173 | "name": "IAU_EARTH" 174 | }, 175 | "trajectory": { 176 | "type" : "Spice", 177 | "target": "-996", 178 | "center": "Earth", 179 | "frame" : "IAU_EARTH" 180 | }, 181 | "label": { 182 | "color": [ 0.2, 1.0, 1.0 ] 183 | }, 184 | "trajectoryPlot": { 185 | "color" : [ 0.2, 1.0, 1.0 ], 186 | "lineWidth" : 4, 187 | "sampleCount": 200, 188 | "duration" : "2 d", 189 | "lead" : "1 s", 190 | "fade" : 1.0 191 | } 192 | }, 193 | { 194 | "class" : "spacecraft", 195 | "name" : "Molniya GT", 196 | "startTime" : "2021-09-27 00:02:00 UTC", 197 | "center" : "Earth", 198 | "trajectoryFrame": { 199 | "type": "Spice", 200 | "name": "IAU_EARTH" 201 | }, 202 | "trajectory": { 203 | "type" : "Spice", 204 | "target": "-9960", 205 | "center": "Earth", 206 | "frame" : "IAU_EARTH" 207 | }, 208 | "label": { 209 | "color": [ 0.2, 1.0, 1.0 ] 210 | }, 211 | "trajectoryPlot": { 212 | "color" : [ 0.2, 1.0, 1.0 ], 213 | "lineWidth" : 4, 214 | "sampleCount": 600, 215 | "duration" : "2 d", 216 | "lead" : "1 s", 217 | "fade" : 1.0 218 | } 219 | } 220 | ] 221 | } 222 | --------------------------------------------------------------------------------