diff --git a/apps/OpenSpace/ext/sgct b/apps/OpenSpace/ext/sgct index ad940a5c95..4e00462a08 160000 --- a/apps/OpenSpace/ext/sgct +++ b/apps/OpenSpace/ext/sgct @@ -1 +1 @@ -Subproject commit ad940a5c955c1e5ef94bcb042cae15060a04e0e4 +Subproject commit 4e00462a08d5a38eb71a31a2e2f9ed4c7de72c45 diff --git a/data/assets/scene/solarsystem/missions/juice/CMR-illuminance2.txt b/data/assets/scene/solarsystem/missions/juice/CMR-illuminance2.txt new file mode 100644 index 0000000000..2ed4bff17e --- /dev/null +++ b/data/assets/scene/solarsystem/missions/juice/CMR-illuminance2.txt @@ -0,0 +1,14 @@ +width 10 +lower 0.0 +upper 1.0 + +mappingkey 0.0 60 38 164 255 +mappingkey 0.083 106 43 167 255 +mappingkey 0.166 173 54 110 255 +mappingkey 0.332 253 64 40 255 +mappingkey 0.415 234 117 6 255 +mappingkey 0.498 230 169 16 255 +mappingkey 0.664 236 236 159 255 +mappingkey 0.830 251 251 235 255 +mappingkey 0.915 255 255 255 255 +mappingkey 1.0 255 255 255 255 \ No newline at end of file diff --git a/data/assets/scene/solarsystem/missions/juice/fieldlines.asset b/data/assets/scene/solarsystem/missions/juice/fieldlines.asset new file mode 100644 index 0000000000..bc7b7c8c96 --- /dev/null +++ b/data/assets/scene/solarsystem/missions/juice/fieldlines.asset @@ -0,0 +1,52 @@ +local transforms = asset.require('./transforms') + +local data = asset.syncedResource({ + Type = "HttpSynchronization", + Name = "Ganymede Plane Simulations", + Identifier = "juice_ganymede_fieldlines", + Version = 1 +}) + + +local magnetosphere = { + Identifier = "GanymedeMagnetosphere", + Parent = transforms.GPHIO.Identifier, + Renderable = { + Type = "RenderableFieldlinesSequence", + SourceFolder = data, + LineWidth = 1.0, + InputFileType = "Json", + ColorMethod = "By Quantity", + ColorQuantity = 0, + ColorTableRanges = { { 62.556353386366766, 1665.5534182835445 } }, + ColorTablePaths = { asset.localResource("CMR-illuminance2.txt") }, + Color = { 1.0, 0.725, 0.75, 0.8 } + }, + GUI = { + Name = "Ganymede Magnetosphere", + Path = "/Solar System/Missions/Juice/Fieldlines", + Description = "Fieldlines showing a simulation of the magnetic fields around Ganymede" + } +} + + +asset.onInitialize(function() + openspace.addSceneGraphNode(magnetosphere) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(magnetosphere) +end) + + +asset.meta = { + Name = "Static fieldline representation of Ganymede's magnetic field", + Version = "1.0", + Description = [[ + Showing a single timestep of the magnetic fieldlines around Ganymede in the GPHIO + coordinate system + ]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license" +} diff --git a/data/assets/scene/solarsystem/missions/juice/fov.asset b/data/assets/scene/solarsystem/missions/juice/fov.asset new file mode 100644 index 0000000000..20768ffcb0 --- /dev/null +++ b/data/assets/scene/solarsystem/missions/juice/fov.asset @@ -0,0 +1,9 @@ +asset.require('./fov/gala') +asset.require('./fov/janus') +asset.require('./fov/jmc') +asset.require('./fov/majis') +asset.require('./fov/navcam') +asset.require('./fov/rime') +asset.require('./fov/startracker') +asset.require('./fov/swi') +asset.require('./fov/uvs') diff --git a/data/assets/scene/solarsystem/missions/juice/fov/gala.asset b/data/assets/scene/solarsystem/missions/juice/fov/gala.asset new file mode 100644 index 0000000000..564e5ed61a --- /dev/null +++ b/data/assets/scene/solarsystem/missions/juice/fov/gala.asset @@ -0,0 +1,59 @@ +local transforms = asset.require('../transforms') +local kernels = asset.require('../kernels') + + +local Gala = { + Identifier = "JuiceGala", + Parent = transforms.Juice.Identifier, + TimeFrame = { + Type = "TimeFrameInterval", + Start = "2031 JUL 02 00:00:00.000", + End = "2035 OCT 05 00:00:00.000" + }, + Renderable = { + Type = "RenderableFov", + Body = "JUICE", + Frame = "JUICE_GALA_RXT", + RGB = { 0.8, 0.7, 0.7 }, + Instrument = { + Name = "JUICE_GALA_RXT", + Method = "CIRCLE", + Aberration = "NONE" + }, + AlwaysDrawFov = true, + PotentialTargets = { "JUPITER", "CALLISTO", "EUROPA", "GANYMEDE", "IO" }, + FrameConversions = {} + }, + GUI = { + Name = "Gala FOV", + Path = "/Solar System/Missions/Juice/Instruments", + Description = "The field-of-view for the Ganymede Laster Altimeter (GALA) instrument." + } +} + + +asset.onInitialize(function() + -- Circle shapes are currently not supported + openspace.addSceneGraphNode(Gala) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(Gala) +end) + +asset.export(Gala) + + +asset.meta = { + Name = "GALA", + Version = "1.0", + Description = [[ + Shows the field-view for the Ganymede Laser Altimeter (GALA) instrument onboard Juice, + measuring a 2.5D heightfield of Ganymede and Europa. See + https://elib.dlr.de/94264/1/JUICE%20GALA%20-%20Design%20Overview%20v04.pdf for more + information. + ]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license" +} diff --git a/data/assets/scene/solarsystem/missions/juice/fov/janus.asset b/data/assets/scene/solarsystem/missions/juice/fov/janus.asset new file mode 100644 index 0000000000..6221361d74 --- /dev/null +++ b/data/assets/scene/solarsystem/missions/juice/fov/janus.asset @@ -0,0 +1,63 @@ +local transforms = asset.require('../transforms') +local kernels = asset.require('../kernels') + + +local Janus = { + Identifier = "JuiceJanus", + Parent = transforms.Juice.Identifier, + TimeFrame = { + Type = "TimeFrameInterval", + Start = "2031 JUL 02 00:00:00.000", + End = "2035 OCT 05 00:00:00.000" + }, + Transform = { + Translation = { + Type = "StaticTranslation", + Position = { 0.44, 0.33, 0.9 } + } + }, + Renderable = { + Type = "RenderableFov", + Body = "JUICE", + Frame = "JUICE_JANUS", + RGB = { 0.8, 0.7, 0.7 }, + Instrument = { + Name = "JUICE_JANUS", + Method = "RECTANGLE", + Aberration = "NONE" + }, + AlwaysDrawFov = true, + PotentialTargets = { "JUPITER", "CALLISTO", "EUROPA", "GANYMEDE", "IO" }, + FrameConversions = {} + }, + GUI = { + Name = "Janus FOV", + Path = "/Solar System/Missions/Juice/Instruments", + Description = "The field-of-view for the JANUS instrument onboard Juice" + + } +} + +asset.onInitialize(function() + openspace.addSceneGraphNode(Janus) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(Janus) +end) + +asset.export(Janus) + + +asset.meta = { + Name = "Janus", + Version = "1.0", + Description = [[ + Shows the field-view for the Jovis Amorum ac Natorum Undique Scrutator (JANUS) + instrument onboard Juice, which is the camera operating in visible wavelengths. See + https://elib.dlr.de/90175/1/2094.pdf for more information. + ]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license" +} diff --git a/data/assets/scene/solarsystem/missions/juice/fov/jmc.asset b/data/assets/scene/solarsystem/missions/juice/fov/jmc.asset new file mode 100644 index 0000000000..181006a43b --- /dev/null +++ b/data/assets/scene/solarsystem/missions/juice/fov/jmc.asset @@ -0,0 +1,90 @@ +local transforms = asset.require('../transforms') +local kernels = asset.require('../kernels') + + +local JMC1 = { + Identifier = "JuiceJMC1", + Parent = transforms.Juice.Identifier, + TimeFrame = { + Type = "TimeFrameInterval", + Start = "2031 JUL 02 00:00:00.000", + End = "2035 OCT 05 00:00:00.000" + }, + Renderable = { + Type = "RenderableFov", + Body = "JUICE", + Frame = "JUICE_JMC-1", + RGB = { 0.8, 0.7, 0.7 }, + Instrument = { + Name = "JUICE_JMC-1", + Method = "RECTANGLE", + Aberration = "NONE" + }, + AlwaysDrawFov = true, + PotentialTargets = { "JUPITER", "CALLISTO", "EUROPA", "GANYMEDE", "IO" }, + FrameConversions = {} + }, + GUI = { + Name = "JUICE_JMC-1 FOV", + Path = "/Solar System/Missions/Juice/Instruments", + Description = "The field-of-views for the Juice Monitoring cameras" + } +} + +local JMC2 = { + Identifier = "JuiceJMC2", + Parent = transforms.Juice.Identifier, + TimeFrame = { + Type = "TimeFrameInterval", + Start = "2031 JUL 02 00:00:00.000", + End = "2035 OCT 05 00:00:00.000" + }, + Renderable = { + Type = "RenderableFov", + Body = "JUICE", + Frame = "JUICE_JMC-2", + RGB = { 0.8, 0.7, 0.7 }, + Instrument = { + Name = "JUICE_JMC-2", + Method = "RECTANGLE", + Aberration = "NONE" + }, + AlwaysDrawFov = true, + PotentialTargets = { "JUPITER", "CALLISTO", "EUROPA", "GANYMEDE", "IO" }, + FrameConversions = {} + }, + GUI = { + Name = "JUICE_JMC-2 FOV", + Path = "/Solar System/Missions/Juice/Instruments", + Description = "The field-of-views for the Juice Monitoring cameras" + } +} + + +asset.onInitialize(function() + openspace.addSceneGraphNode(JMC1) + openspace.addSceneGraphNode(JMC2) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(JMC2) + openspace.removeSceneGraphNode(JMC1) +end) + +asset.export(JMC1) +asset.export(JMC2) + + +asset.meta = { + Name = "JMC", + Version = "1.0", + Description = [[ + Shows the field-view for the Juice Monitoring Cameras (JMC) onboard Juice, which + provide status information about the deployment of various Juice systems, like the + solar array, antenna, etc. See https://microcameras.space/project/juice/ for more + information. + ]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license" +} diff --git a/data/assets/scene/solarsystem/missions/juice/fov/majis.asset b/data/assets/scene/solarsystem/missions/juice/fov/majis.asset new file mode 100644 index 0000000000..26750603af --- /dev/null +++ b/data/assets/scene/solarsystem/missions/juice/fov/majis.asset @@ -0,0 +1,256 @@ +local transforms = asset.require('../transforms') +local kernels = asset.require('../kernels') + + +local MajisVisnir = { + Identifier = "JuiceMajisVisnir", + Parent = transforms.Juice.Identifier, + TimeFrame = { + Type = "TimeFrameInterval", + Start = "2031 JUL 02 00:00:00.000", + End = "2035 OCT 05 00:00:00.000" + }, + Renderable = { + Type = "RenderableFov", + Body = "JUICE", + Frame = "JUICE_MAJIS_VISNIR", + RGB = { 0.8, 0.7, 0.7 }, + Instrument = { + Name = "JUICE_MAJIS_VISNIR", + Method = "RECTANGLE", + Aberration = "NONE" + }, + AlwaysDrawFov = true, + PotentialTargets = { "JUPITER", "CALLISTO", "EUROPA", "GANYMEDE", "IO" }, + FrameConversions = {} + }, + GUI = { + Name = "Majis Visnir FOV", + Path = "/Solar System/Missions/Juice/Instruments", + Description = [[ + The field-of-view for the Moon and Jupiter Imaging Spectrometer measuring in the + visible and near-infrared spectra (0.4-1.9 um and 1.5-5.7 um). + ]] + } +} + +local MajisVisnirB2 = { + Identifier = "JuiceMajisVisnirB2", + Parent = transforms.Juice.Identifier, + TimeFrame = { + Type = "TimeFrameInterval", + Start = "2031 JUL 02 00:00:00.000", + End = "2035 OCT 05 00:00:00.000" + }, + Renderable = { + Type = "RenderableFov", + Body = "JUICE", + Frame = "JUICE_MAJIS_VISNIR_B2", + RGB = { 0.8, 0.7, 0.7 }, + Instrument = { + Name = "JUICE_MAJIS_VISNIR_B2", + Method = "RECTANGLE", + Aberration = "NONE" + }, + AlwaysDrawFov = true, + PotentialTargets = { "JUPITER", "CALLISTO", "EUROPA", "GANYMEDE", "IO" }, + FrameConversions = {} + }, + GUI = { + Name = "Majis Visnir B2 FOV", + Path = "/Solar System/Missions/Juice/Instruments" + } +} + +local MajisVisnirB4 = { + Identifier = "JuiceMajisVisnirB4", + Parent = transforms.Juice.Identifier, + TimeFrame = { + Type = "TimeFrameInterval", + Start = "2031 JUL 02 00:00:00.000", + End = "2035 OCT 05 00:00:00.000" + }, + Renderable = { + Type = "RenderableFov", + Body = "JUICE", + Frame = "JUICE_MAJIS_VISNIR_B4", + RGB = { 0.8, 0.7, 0.7 }, + Instrument = { + Name = "JUICE_MAJIS_VISNIR_B4", + Method = "RECTANGLE", + Aberration = "NONE" + }, + AlwaysDrawFov = true, + PotentialTargets = { "JUPITER", "CALLISTO", "EUROPA", "GANYMEDE", "IO" }, + FrameConversions = {} + }, + GUI = { + Name = "Majis Visnir B4 FOV", + Path = "/Solar System/Missions/Juice/Instruments" + } +} + +local MajisIr = { + Identifier = "JuiceMajisIr", + Parent = transforms.Juice.Identifier, + TimeFrame = { + Type = "TimeFrameInterval", + Start = "2031 JUL 02 00:00:00.000", + End = "2035 OCT 05 00:00:00.000" + }, + Renderable = { + Type = "RenderableFov", + Body = "JUICE", + Frame = "JUICE_MAJIS_IR", + RGB = { 0.8, 0.7, 0.7 }, + Instrument = { + Name = "JUICE_MAJIS_IR", + Method = "RECTANGLE", + Aberration = "NONE" + }, + AlwaysDrawFov = true, + PotentialTargets = { "JUPITER", "CALLISTO", "EUROPA", "GANYMEDE", "IO" }, + FrameConversions = {} + }, + GUI = { + Name = "Majis IR FOV", + Path = "/Solar System/Missions/Juice/Instruments" + } +} + +local MajisIrB2 = { + Identifier = "JuiceMajisIrB2", + Parent = transforms.Juice.Identifier, + TimeFrame = { + Type = "TimeFrameInterval", + Start = "2031 JUL 02 00:00:00.000", + End = "2035 OCT 05 00:00:00.000" + }, + Renderable = { + Type = "RenderableFov", + Body = "JUICE", + Frame = "JUICE_MAJIS_IR_B2", + RGB = { 0.8, 0.7, 0.7 }, + Instrument = { + Name = "JUICE_MAJIS_IR_B2", + Method = "RECTANGLE", + Aberration = "NONE" + }, + AlwaysDrawFov = true, + PotentialTargets = { "JUPITER", "CALLISTO", "EUROPA", "GANYMEDE", "IO" }, + FrameConversions = {} + }, + GUI = { + Name = "Majis IR B2 FOV", + Path = "/Solar System/Missions/Juice/Instruments" + } +} + +local MajisIrB4 = { + Identifier = "JuiceMajisIrB4", + Parent = transforms.Juice.Identifier, + TimeFrame = { + Type = "TimeFrameInterval", + Start = "2031 JUL 02 00:00:00.000", + End = "2035 OCT 05 00:00:00.000" + }, + Renderable = { + Type = "RenderableFov", + Body = "JUICE", + Frame = "JUICE_MAJIS_IR_B4", + RGB = { 0.8, 0.7, 0.7 }, + Instrument = { + Name = "JUICE_MAJIS_IR_B4", + Method = "RECTANGLE", + Aberration = "NONE" + }, + AlwaysDrawFov = true, + PotentialTargets = { "JUPITER", "CALLISTO", "EUROPA", "GANYMEDE", "IO" }, + FrameConversions = {} + }, + GUI = { + Name = "Majis IR B4 FOV", + Path = "/Solar System/Missions/Juice/Instruments" + } +} + +local Majis = { + Identifier = "JuiceMajis", + Parent = transforms.Juice.Identifier, + TimeFrame = { + Type = "TimeFrameInterval", + Start = "2031 JUL 02 00:00:00.000", + End = "2035 OCT 05 00:00:00.000" + }, + Renderable = { + Type = "RenderableFov", + Body = "JUICE", + Frame = "JUICE_MAJIS", + RGB = { 0.8, 0.7, 0.7 }, + Instrument = { + Name = "JUICE_MAJIS", + Method = "RECTANGLE", + Aberration = "NONE" + }, + AlwaysDrawFov = true, + PotentialTargets = { "JUPITER", "CALLISTO", "EUROPA", "GANYMEDE", "IO" }, + FrameConversions = {} + }, + GUI = { + Name = "Majis FOV", + Path = "/Solar System/Missions/Juice/Instruments", + Description = [[ + The field-of-view for the Moon and Jupiter Imaging Spectrometer measuring in the + visible and near-infrared spectra (0.4-1.9 um and 1.5-5.7 um). + ]] + } +} + + +asset.onInitialize(function() + -- We are only adding the main version of this instrument as a scene graph node. Other + -- versions are defined in the available SPICE kernels, but not a lot of information is + -- accessible about them. We don't want to remove them entirely as they might prove + -- useful to some users though + + -- openspace.addSceneGraphNode(MajisVisnir) + -- openspace.addSceneGraphNode(MajisVisnirB2) + -- openspace.addSceneGraphNode(MajisVisnirB4) + -- openspace.addSceneGraphNode(MajisIr) + -- openspace.addSceneGraphNode(MajisIrB2) + -- openspace.addSceneGraphNode(MajisIrB4) + openspace.addSceneGraphNode(Majis) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(Majis) + -- openspace.removeSceneGraphNode(MajisIrB4) + -- openspace.removeSceneGraphNode(MajisIrB2) + -- openspace.removeSceneGraphNode(MajisIr) + -- openspace.removeSceneGraphNode(MajisVisnirB4) + -- openspace.removeSceneGraphNode(MajisVisnirB2) + -- openspace.removeSceneGraphNode(MajisVisnir) +end) + +-- asset.export(MajisVisnir) +-- asset.export(MajisVisnirB2) +-- asset.export(MajisVisnirB4) +-- asset.export(MajisIr) +-- asset.export(MajisIrB2) +-- asset.export(MajisIrB4) +asset.export(Majis) + + +asset.meta = { + Name = "Majis", + Version = "1.0", + Description = [[ + Shows the field-view for the Moon and Jupiter Imaging Spectrometer (MAJIS) onboard + Juice, which is going to take spectroscopic measurements of the Jovian moons and + Jupiter. See https://www.hou.usra.edu/meetings/lpsc2014/pdf/2493.pdf for more + information. + ]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license" +} diff --git a/data/assets/scene/solarsystem/missions/juice/fov/navcam.asset b/data/assets/scene/solarsystem/missions/juice/fov/navcam.asset new file mode 100644 index 0000000000..88ded2eafe --- /dev/null +++ b/data/assets/scene/solarsystem/missions/juice/fov/navcam.asset @@ -0,0 +1,58 @@ +local transforms = asset.require('../transforms') +local kernels = asset.require('../kernels') + + +local NavCam = { + Identifier = "JuiceNavCam", + Parent = transforms.Juice.Identifier, + TimeFrame = { + Type = "TimeFrameInterval", + Start = "2031 JUL 02 00:00:00.000", + End = "2035 OCT 05 00:00:00.000" + }, + Renderable = { + Type = "RenderableFov", + Body = "JUICE", + Frame = "JUICE_NAVCAM-1", + RGB = { 0.8, 0.7, 0.7 }, + Instrument = { + Name = "JUICE_NAVCAM-1", + Method = "RECTANGLE", + Aberration = "NONE" + }, + AlwaysDrawFov = true, + PotentialTargets = { "JUPITER", "CALLISTO", "EUROPA", "GANYMEDE", "IO" }, + FrameConversions = {} + }, + GUI = { + Name = "NavCam FOV", + Path = "/Solar System/Missions/Juice/Instruments", + Description = "The camera onboard Juice used to navigate by the stars" + } +} + + +asset.onInitialize(function() + openspace.addSceneGraphNode(NavCam) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(NavCam) +end) + +asset.export(NavCam) + + +asset.meta = { + Name = "NavCam", + Version = "1.0", + Description = [[ + Shows the field-view for the navigational camera (NavCam) onboard Juice, which is used + to measure the location of Juice. See + https://www.spiedigitallibrary.org/proceedings/Download?urlId=10.1117%2F12.2536086 + for more information. + ]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license" +} diff --git a/data/assets/scene/solarsystem/missions/juice/fov/rime.asset b/data/assets/scene/solarsystem/missions/juice/fov/rime.asset new file mode 100644 index 0000000000..58fa281f24 --- /dev/null +++ b/data/assets/scene/solarsystem/missions/juice/fov/rime.asset @@ -0,0 +1,93 @@ +local transforms = asset.require('../transforms') +local kernels = asset.require('../kernels') + + +-- Circle shapes are not support +local RimeBase = { + Identifier = "JuiceRimeBase", + Parent = transforms.Juice.Identifier, + TimeFrame = { + Type = "TimeFrameInterval", + Start = "2031 JUL 02 00:00:00.000", + End = "2035 OCT 05 00:00:00.000" + }, + Renderable = { + Type = "RenderableFov", + Body = "JUICE", + Frame = "JUICE_RIME_BASE", + RGB = { 0.8, 0.7, 0.7 }, + Instrument = { + Name = "JUICE_RIME_BASE", + Method = "CIRCLE", + Aberration = "NONE" + }, + AlwaysDrawFov = true, + PotentialTargets = { "JUPITER", "CALLISTO", "EUROPA", "GANYMEDE", "IO" }, + FrameConversions = {} + }, + GUI = { + Name = "Rime Base FOV", + Path = "/Solar System/Missions/Juice/Instruments", + Description = "The location of the base for the RIME instrument onboard Juice." + } +} + +-- Circle shapes are not supported +local Rime = { + Identifier = "JuiceRime", + Parent = transforms.Juice.Identifier, + TimeFrame = { + Type = "TimeFrameInterval", + Start = "2031 JUL 02 00:00:00.000", + End = "2035 OCT 05 00:00:00.000" + }, + Renderable = { + Type = "RenderableFov", + Body = "JUICE", + Frame = "JUICE_RIME", + RGB = { 0.8, 0.7, 0.7 }, + Instrument = { + Name = "JUICE_RIME", + Method = "CIRCLE", + Aberration = "NONE" + }, + AlwaysDrawFov = true, + PotentialTargets = { "JUPITER", "CALLISTO", "EUROPA", "GANYMEDE", "IO" }, + FrameConversions = {} + }, + GUI = { + Name = "Rime FOV", + Path = "/Solar System/Missions/Juice/Instruments", + Description = "The location of the RIME instrument onboard Juice." + } +} + + +asset.onInitialize(function() + openspace.addSceneGraphNode(Rime) + openspace.addSceneGraphNode(RimeBase) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(RimeBase) + openspace.removeSceneGraphNode(Rime) +end) + +asset.export(Rime) +asset.export(RimeBase) + + +asset.meta = { + Name = "RIME", + Version = "1.0", + Description = [[ + Shows the field-view for the Radar for Icy Moons Exploration (RIME) onboard Juice, + which is a ground-penetrating radar meant to measure the subsurface structure of the + ice surrounding the icy Galilean moons of up to 9 km. See + https://www.spacetech-i.com/products/mechanisms/juice-rime-antenna for more + information. + ]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license" +} diff --git a/data/assets/scene/solarsystem/missions/juice/fov/startracker.asset b/data/assets/scene/solarsystem/missions/juice/fov/startracker.asset new file mode 100644 index 0000000000..356b23be0d --- /dev/null +++ b/data/assets/scene/solarsystem/missions/juice/fov/startracker.asset @@ -0,0 +1,121 @@ +local transforms = asset.require('../transforms') +local kernels = asset.require('../kernels') + + +local StarOh1 = { + Identifier = "JuiceStarOH1", + Parent = transforms.Juice.Identifier, + TimeFrame = { + Type = "TimeFrameInterval", + Start = "2031 JUL 02 00:00:00.000", + End = "2035 OCT 05 00:00:00.000" + }, + Renderable = { + Type = "RenderableFov", + Body = "JUICE", + Frame = "JUICE_STR-OH1", + RGB = { 0.0, 0.0, 0.0 }, + Instrument = { + Name = "JUICE_STR-OH1", + Method = "RECTANGLE", + Aberration = "NONE" + }, + AlwaysDrawFov = true, + PotentialTargets = { "JUPITER", "CALLISTO", "EUROPA", "GANYMEDE", "IO" }, + FrameConversions = {} + }, + GUI = { + Name = "Star Tracker OH1 FOV", + Path = "/Solar System/Missions/Juice/Instruments", + Description = "The first head of the Hydra star tracking system" + } +} + +local StarOh2 = { + Identifier = "JuiceStarOH2", + Parent = transforms.Juice.Identifier, + TimeFrame = { + Type = "TimeFrameInterval", + Start = "2031 JUL 02 00:00:00.000", + End = "2035 OCT 05 00:00:00.000" + }, + Renderable = { + Type = "RenderableFov", + Body = "JUICE", + Frame = "JUICE_STR-OH2", + RGB = { 0.0, 0.0, 0.0 }, + Instrument = { + Name = "JUICE_STR-OH2", + Method = "RECTANGLE", + Aberration = "NONE" + }, + AlwaysDrawFov = true, + PotentialTargets = { "JUPITER", "CALLISTO", "EUROPA", "GANYMEDE", "IO" }, + FrameConversions = {} + }, + GUI = { + Name = "Star Tracker OH2 FOV", + Path = "/Solar System/Missions/Juice/Instruments", + Description = "The second head of the Hydra star tracking system" + } +} + +local StarOh3 = { + Identifier = "JuiceStarOH3", + Parent = transforms.Juice.Identifier, + TimeFrame = { + Type = "TimeFrameInterval", + Start = "2031 JUL 02 00:00:00.000", + End = "2035 OCT 05 00:00:00.000" + }, + Renderable = { + Type = "RenderableFov", + Body = "JUICE", + Frame = "JUICE_STR-OH3", + RGB = { 0.0, 0.0, 0.0 }, + Instrument = { + Name = "JUICE_STR-OH3", + Method = "RECTANGLE", + Aberration = "NONE" + }, + AlwaysDrawFov = true, + PotentialTargets = { "JUPITER", "CALLISTO", "EUROPA", "GANYMEDE", "IO" }, + FrameConversions = {} + }, + GUI = { + Name = "Star Tracker OH3 FOV", + Path = "/Solar System/Missions/Juice/Instruments", + Description = "The third head of the Hydra star tracking system" + } +} + + +asset.onInitialize(function() + openspace.addSceneGraphNode(StarOh1) + openspace.addSceneGraphNode(StarOh2) + openspace.addSceneGraphNode(StarOh3) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(StarOh3) + openspace.removeSceneGraphNode(StarOh2) + openspace.removeSceneGraphNode(StarOh1) +end) + +asset.export(StarOh1) +asset.export(StarOh2) +asset.export(StarOh3) + + +asset.meta = { + Name = "Star Tracker", + Version = "1.0", + Description = [[ + Shows the field-view for the three headed "Hydra" star trackers onboard Juice, which + is measuring the location of stars and comparing them to their known locations in + order to determine the position of Juice relative to the celestial sphere. + ]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license" +} diff --git a/data/assets/scene/solarsystem/missions/juice/fov/swi.asset b/data/assets/scene/solarsystem/missions/juice/fov/swi.asset new file mode 100644 index 0000000000..c940a950cc --- /dev/null +++ b/data/assets/scene/solarsystem/missions/juice/fov/swi.asset @@ -0,0 +1,142 @@ +local transforms = asset.require('../transforms') +local kernels = asset.require('../kernels') + + +-- Circle shapes are not support +local SwiCh2 = { + Identifier = "JuiceSwiCH2", + Parent = transforms.Juice.Identifier, + TimeFrame = { + Type = "TimeFrameInterval", + Start = "2031 JUL 02 00:00:00.000", + End = "2035 OCT 05 00:00:00.000" + }, + Renderable = { + Type = "RenderableFov", + Body = "JUICE", + Frame = "JUICE_SWI_CH2", + RGB = { 0.0, 0.0, 0.0 }, + Instrument = { + Name = "JUICE_SWI_CH2", + Method = "CIRCLE", + Aberration = "NONE" + }, + AlwaysDrawFov = true, + PotentialTargets = { "JUPITER", "CALLISTO", "EUROPA", "GANYMEDE", "IO" }, + FrameConversions = {} + }, + GUI = { + Name = "SWI CH2 FOV", + Path = "/Solar System/Missions/Juice/Instruments" + } +} + +local SwiFull = { + Identifier = "JuiceSwiFull", + Parent = transforms.Juice.Identifier, + TimeFrame = { + Type = "TimeFrameInterval", + Start = "2031 JUL 02 00:00:00.000", + End = "2035 OCT 05 00:00:00.000" + }, + Transform = { + Translation = { + Type = "StaticTranslation", + -- These translations are eyeballed based on the existing model + Position = { 0.465, -0.1, 0.95 } + } + }, + Renderable = { + Type = "RenderableFov", + Body = "JUICE", + Frame = "JUICE_SWI_FULL", + RGB = { 0.0, 0.0, 0.0 }, + Instrument = { + Name = "JUICE_SWI_FULL", + Method = "RECTANGLE", + Aberration = "NONE" + }, + AlwaysDrawFov = true, + PotentialTargets = { "JUPITER", "CALLISTO", "EUROPA", "GANYMEDE", "IO" }, + FrameConversions = {} + }, + GUI = { + Name = "SWI Full FOV", + Path = "/Solar System/Missions/Juice/Instruments", + Description = "The field-of-view for the full SWI instrument onboard Juice." + } +} + +-- This frame throws an error as the JUICE_SWI_FULL_GCO500 is not a recognized frame in +-- the kernel set version 5 +local SwiFullGCO500 = { + Identifier = "JuiceSwiFullGCO500", + Parent = transforms.Juice.Identifier, + TimeFrame = { + Type = "TimeFrameInterval", + Start = "2031 JUL 02 00:00:00.000", + End = "2035 OCT 05 00:00:00.000" + }, + Transform = { + Translation = { + Type = "StaticTranslation", + -- These translations are eyeballed based on the existing model + Position = { 0.465, -0.1, 0.95 } + } + }, + Renderable = { + Type = "RenderableFov", + Body = "JUICE", + Frame = "JUICE_SWI_FULL_GCO500", + RGB = { 0.0, 0.0, 0.0 }, + Instrument = { + Name = "JUICE_SWI_FULL_GCO500", + Method = "RECTANGLE", + Aberration = "NONE" + }, + AlwaysDrawFov = true, + PotentialTargets = { "JUPITER", "CALLISTO", "EUROPA", "GANYMEDE", "IO" }, + FrameConversions = {} + }, + GUI = { + Name = "SWI Full GCO500 FOV", + Path = "/Solar System/Missions/Juice/Instruments" + } +} + + +asset.onInitialize(function() + -- We are only adding the main version of this instrument as a scene graph node. Other + -- versions are defined in the available SPICE kernels, but not a lot of information is + -- accessible about them. We don't want to remove them entirely as they might prove + -- useful to some users though + + -- openspace.addSceneGraphNode(SwiCh2) + -- openspace.addSceneGraphNode(SwiFullGCO500) + openspace.addSceneGraphNode(SwiFull) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(SwiFull) + -- openspace.removeSceneGraphNode(SwiFullGCO500) + -- openspace.removeSceneGraphNode(SwiCh2) +end) + +-- asset.export(SwiCh2) +asset.export(SwiFull) +-- asset.export(SwiFullGCO500) + + +asset.meta = { + Name = "SWI", + Version = "1.0", + Description = [[ + Shows the field-view for the Submillimetre Wave Instrument (SWI), which is measuring + the chemistry, meteorology, and structure of Jupiters middle atmosphere as well as the + habitability of the Galilean moons. See + https://www.mps.mpg.de/planetary-science/juice-swi for more information. + ]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license" +} diff --git a/data/assets/scene/solarsystem/missions/juice/fov/uvs.asset b/data/assets/scene/solarsystem/missions/juice/fov/uvs.asset new file mode 100644 index 0000000000..d630f6ddcc --- /dev/null +++ b/data/assets/scene/solarsystem/missions/juice/fov/uvs.asset @@ -0,0 +1,58 @@ +local transforms = asset.require('../transforms') +local kernels = asset.require('../kernels') + + +local UVS = { + Identifier = "JuiceUVS", + Parent = transforms.Juice.Identifier, + TimeFrame = { + Type = "TimeFrameInterval", + Start = "2031 JUL 02 00:00:00.000", + End = "2035 OCT 05 00:00:00.000" + }, + Renderable = { + Type = "RenderableFov", + Body = "JUICE", + Frame = "JUICE_UVS", + RGB = { 0.8, 0.7, 0.7 }, + Instrument = { + Name = "JUICE_UVS", + Method = "POLYGON", + Aberration = "NONE" + }, + AlwaysDrawFov = true, + PotentialTargets = { "JUPITER", "CALLISTO", "EUROPA", "GANYMEDE", "IO" }, + FrameConversions = {} + }, + GUI = { + Name = "UVS FOV", + Path = "/Solar System/Missions/Juice/Instruments", + Description = "The field-of-view for the UVS instrument onboard Juice" + } +} + + +asset.onInitialize(function() + openspace.addSceneGraphNode(UVS) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(UVS) +end) + +asset.export(UVS) + + +asset.meta = { + Name = "UVS", + Version = "1.0", + Description = [[ + Shows the field-view for the Ultraviolet Spectograph (UVS), which is measuring the + composition, chemistry, structure, and variability of Europa's atmopshere. See + https://www.lpi.usra.edu/opag/meetings/aug2015/presentations/day-1/8_b_retherford.pdf + for more information. + ]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license" +} diff --git a/data/assets/scene/solarsystem/missions/juice/kernels.asset b/data/assets/scene/solarsystem/missions/juice/kernels.asset new file mode 100644 index 0000000000..7a12b5f7fe --- /dev/null +++ b/data/assets/scene/solarsystem/missions/juice/kernels.asset @@ -0,0 +1,84 @@ +local kernels = asset.syncedResource({ + Name = "JUICE Kernels", + Type = "HttpSynchronization", + Identifier = "juice_kernels", + Version = 1 +}) + +-- From the crema 5.0b23_1 meta kernel +-- + GPHIO from Ronan +local Kernels = { + kernels .. "juice_sc_sat_crema_5_0b23_1_default_f20160326_v01.bc", + kernels .. "juice_sc_sat_crema_5_0b23_1_comms_f20160326_v01.bc", + kernels .. "juice_sc_sat_crema_5_0b23_1_conjctn_f20160326_v01.bc", + kernels .. "juice_sc_sat_crema_5_0b23_1_flybys_f20160326_v01.bc", + kernels .. "juice_lpbooms_f20160326_v01.bc", + kernels .. "juice_magboom_f20160326_v03.bc", + kernels .. "juice_mga_zero_f20160326_v02.bc", + kernels .. "juice_majis_scan_zero_f20160326_v02.bc", + kernels .. "juice_swi_scan_zero_f20160326_v02.bc", + kernels .. "juice_sa_crema_5_0b23_1_default_f20160326_v01.bc", + + kernels .. "juice_v26.tf", + kernels .. "juice_sci_v10.tf", + kernels .. "juice_ops_v07.tf", + kernels .. "juice_dsk_surfaces_v05.tf", + kernels .. "juice_roi_v02.tf", + kernels .. "gphio.tf", + kernels .. "rssd0002.tf", + kernels .. "earth_topo_050714.tf", + kernels .. "earthfixediau.tf", + kernels .. "estrack_v04.tf", + + kernels .. "juice_gala_v03.ti", + kernels .. "juice_janus_v06.ti", + kernels .. "juice_jmc_v02.ti", + kernels .. "juice_majis_v05.ti", + kernels .. "juice_navcam_v01.ti", + kernels .. "juice_pep_v10.ti", + kernels .. "juice_radem_v00.ti", + kernels .. "juice_rime_v04.ti", + kernels .. "juice_rpwi_v02.ti", + kernels .. "juice_str_v01.ti", + kernels .. "juice_swi_v07.ti", + kernels .. "juice_uvs_v03.ti", + kernels .. "juice_aux_v01.ti", + + kernels .. "de-403-masses.tpc", + kernels .. "gm_de431.tpc", + kernels .. "juice_jup006.tpc", + kernels .. "juice_roi_v01.tpc", + + kernels .. "juice_fict_20160326_v03.tsc", + kernels .. "juice_step_20160326_v03.tsc", + + kernels .. "juice_struct_v13.bsp", + kernels .. "juice_cog_v00.bsp", + kernels .. "juice_roi_v02.bsp", + kernels .. "mar085_20200101_20400101.bsp", + kernels .. "earthstns_fx_050714.bsp", + kernels .. "estrack_v04.bsp", + kernels .. "jup310_20200101_20500101.bsp", + kernels .. "jup343_20200101_20500101.bsp", + kernels .. "de432s.bsp", + kernels .. "noe-5-2017-gal-a-reduced_20200101_20380902.bsp", + + kernels .. "juice_mat_crema_5_0b23_1_20230405_20351005_v01.bsp", +} + +asset.export("Kernels", Kernels) + + + + +asset.meta = { + Name = "Spice Kernels for the Juice Mission", + Version = "1.0", + Description = [[ + Kernels were acquired from the official Juice mailing list and extended with the + GPHIO kernel provided by Ronan Modolo for the fieldline and plane data visualization + ]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license" +} diff --git a/data/assets/scene/solarsystem/missions/juice/model.asset b/data/assets/scene/solarsystem/missions/juice/model.asset new file mode 100644 index 0000000000..7e7bdd62bc --- /dev/null +++ b/data/assets/scene/solarsystem/missions/juice/model.asset @@ -0,0 +1,75 @@ +local sunTransforms = asset.require('scene/solarsystem/sun/transforms') +local transforms = asset.require('./transforms') + + +local model = asset.syncedResource({ + Name = "JUICE Model", + Type = "HttpSynchronization", + Identifier = "juice_models", + Version = 1 +}) + +local JuiceModel = { + Identifier = "JuiceModel", + Parent = transforms.Juice.Identifier, + Transform = { + Translation = { + Type = "StaticTranslation", + -- Offset numbers found by eyeballing + Position = { 4.5, 0.0, -1.0 } + }, + Rotation = { + Type = "StaticRotation", + Rotation = { math.pi / 2.0, 0.0, 0.0 } + } + }, + Renderable = { + Type = "RenderableModel", + Body = "JUICE", + GeometryFile = model .. "juice.fbx", + ModelScale = "Centimeter", + LightSources = { + { + Type = "SceneGraphLightSource", + Identifier = "Sun", + Node = sunTransforms.SolarSystemBarycenter.Identifier, + Intensity = 0.6 + }, + { + Identifier = "Camera", + Type = "CameraLightSource", + Intensity = 0.4, + Enabled = false + } + } + }, + GUI = { + Name = "Juice Model", + Path = "/Solar System/Missions/Juice", + Description = "The model of the JUICE spacecraft" + } +} + + +asset.onInitialize(function() + openspace.addSceneGraphNode(JuiceModel) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(JuiceModel) +end) + +asset.export(JuiceModel) + + +asset.meta = { + Name = "Juice Model", + Version = "1.0", + Description = [[ + The model of the JUICE spacecraft. The model file was taken from + https://www.cosmos.esa.int/web/esac-cmso/scifleet. + ]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license" +} diff --git a/data/assets/scene/solarsystem/missions/juice/plane.asset b/data/assets/scene/solarsystem/missions/juice/plane.asset new file mode 100644 index 0000000000..ddbeddd612 --- /dev/null +++ b/data/assets/scene/solarsystem/missions/juice/plane.asset @@ -0,0 +1,355 @@ +local transforms = asset.require('./transforms') + +-- Datasets created using the script found at: +-- https://github.com/OpenSpace/scripts/tree/master/juice-gphio-image-conversion +local data = asset.syncedResource({ + Type = "HttpSynchronization", + Name = "Ganymede Plane Simulations", + Identifier = "juice_ganymede_plane_cuts", + Version = 1 +}) + + +local GanymedeRadius = 2634 * 1000 +-- Size value from the original dataset provided by Ronan +local Size = 4.114 * GanymedeRadius + +local xy_n = { + Identifier = "Ganymede_Plane_XY_N", + Parent = transforms.GPHIO.Identifier, + Renderable = { + Type = "RenderablePlaneImageLocal", + Size = Size, + Texture = data .. "XY-n.png", + Enabled = false + }, + GUI = { + Name = "Ganymede XY Plane N", + Path = "/Solar System/Missions/Juice/Plane", + Description = "A cut plane in Ganymede's XY plane showing the number of particles" + } +} + +local xy_t = { + Identifier = "Ganymede_Plane_XY_T", + Parent = transforms.GPHIO.Identifier, + Renderable = { + Type = "RenderablePlaneImageLocal", + Size = Size, + Texture = data .. "XY-T.png", + Enabled = false + }, + GUI = { + Name = "Ganymede XY Plane T", + Path = "/Solar System/Missions/Juice/Plane", + Description = "A cut plane in Ganymede's XY plane showing the temperature" + } +} + +local xy_u = { + Identifier = "Ganymede_Plane_XY_U", + Parent = transforms.GPHIO.Identifier, + Renderable = { + Type = "RenderablePlaneImageLocal", + Size = Size, + Texture = data .. "XY-U.png", + Enabled = false + }, + GUI = { + Name = "Ganymede XY Plane U", + Path = "/Solar System/Missions/Juice/Plane", + Description = [[A cut plane in Ganymede's XY plane showing the strength of the + magnetic field]] + } +} + +local xy_utot = { + Identifier = "Ganymede_Plane_XY_Utot", + Parent = transforms.GPHIO.Identifier, + Renderable = { + Type = "RenderablePlaneImageLocal", + Size = Size, + Texture = data .. "XY-Utot.png", + Enabled = false + }, + GUI = { + Name = "Ganymede XY Plane U_tot", + Path = "/Solar System/Missions/Juice/Plane", + Description = [[A cut plane in Ganymede's XY plane showing the X, Y, and Z components + of the magnetic field mapped to the RGB components.]] + } +} + +local xy_ux = { + Identifier = "Ganymede_Plane_XY_Ux", + Parent = transforms.GPHIO.Identifier, + Renderable = { + Type = "RenderablePlaneImageLocal", + Size = Size, + Texture = data .. "XY-Ux.png", + Enabled = false + }, + GUI = { + Name = "Ganymede XY Plane Ux", + Path = "/Solar System/Missions/Juice/Plane", + Description = [[A cut plane in Ganymede's XY plane showing the X component of + Ganymede's magnetic field]] + } +} + +local xy_uy = { + Identifier = "Ganymede_Plane_XY_Uy", + Parent = transforms.GPHIO.Identifier, + Renderable = { + Type = "RenderablePlaneImageLocal", + Size = Size, + Texture = data .. "XY-Uy.png", + Enabled = false + }, + GUI = { + Name = "Ganymede XY Plane Uy", + Path = "/Solar System/Missions/Juice/Plane", + Description = [[A cut plane in Ganymede's XY plane showing the Y component of + Ganymede's magnetic field]] + } +} + +local xy_uz = { + Identifier = "Ganymede_Plane_XY_Uz", + Parent = transforms.GPHIO.Identifier, + Renderable = { + Type = "RenderablePlaneImageLocal", + Size = Size, + Texture = data .. "XY-Uz.png", + Enabled = false + }, + GUI = { + Name = "Ganymede XY Plane Uz", + Path = "/Solar System/Missions/Juice/Plane", + Description = [[A cut plane in Ganymede's XY plane showing the Z component of + Ganymede's magnetic field]] + } +} + +local xz_n = { + Identifier = "Ganymede_Plane_XZ_N", + Parent = transforms.GPHIO.Identifier, + Transform = { + Rotation = { + Type = "StaticRotation", + Rotation = { -math.pi/2, 0.0, 0.0 } + } + }, + Renderable = { + Type = "RenderablePlaneImageLocal", + Size = Size, + Texture = data .. "XZ-n.png", + Enabled = false + }, + GUI = { + Name = "Ganymede XZ Plane N", + Path = "/Solar System/Missions/Juice/Plane", + Description = "A cut plane in Ganymede's XZ plane showing the number of particles" + } +} + +local xz_t = { + Identifier = "Ganymede_Plane_XZ_T", + Parent = transforms.GPHIO.Identifier, + Transform = { + Rotation = { + Type = "StaticRotation", + Rotation = { -math.pi/2, 0.0, 0.0 } + } + }, + Renderable = { + Type = "RenderablePlaneImageLocal", + Size = Size, + Texture = data .. "XZ-T.png", + Enabled = false + }, + GUI = { + Name = "Ganymede XZ Plane T", + Path = "/Solar System/Missions/Juice/Plane", + Description = "A cut plane in Ganymede's XZ plane showing the temperature" + } +} + +local xz_u = { + Identifier = "Ganymede_Plane_XZ_U", + Parent = transforms.GPHIO.Identifier, + Transform = { + Rotation = { + Type = "StaticRotation", + Rotation = { -math.pi/2, 0.0, 0.0 } + } + }, + Renderable = { + Type = "RenderablePlaneImageLocal", + Size = Size, + Texture = data .. "XZ-U.png", + Enabled = false + }, + GUI = { + Name = "Ganymede XZ Plane U", + Path = "/Solar System/Missions/Juice/Plane", + Description = [[A cut plane in Ganymede's XZ plane showing the strength of the + magnetic field]] + } +} + +local xz_utot = { + Identifier = "Ganymede_Plane_XZ_Utot", + Parent = transforms.GPHIO.Identifier, + Transform = { + Rotation = { + Type = "StaticRotation", + Rotation = { -math.pi/2, 0.0, 0.0 } + } + }, + Renderable = { + Type = "RenderablePlaneImageLocal", + Size = Size, + Texture = data .. "XZ-Utot.png", + Enabled = false + }, + GUI = { + Name = "Ganymede XZ Plane U_tot", + Path = "/Solar System/Missions/Juice/Plane", + Description = [[A cut plane in Ganymede's XZ plane showing the X, Y, and Z components + of the magnetic field mapped to the RGB components.]] + } +} + +local xz_ux = { + Identifier = "Ganymede_Plane_XZ_Ux", + Parent = transforms.GPHIO.Identifier, + Transform = { + Rotation = { + Type = "StaticRotation", + Rotation = { -math.pi/2, 0.0, 0.0 } + } + }, + Renderable = { + Type = "RenderablePlaneImageLocal", + Size = Size, + Texture = data .. "XZ-Ux.png", + Enabled = false + }, + GUI = { + Name = "Ganymede XZ Plane Ux", + Path = "/Solar System/Missions/Juice/Plane", + Description = [[A cut plane in Ganymede's XZ plane showing the X component of + Ganymede's magnetic field]] + } +} + +local xz_uy = { + Identifier = "Ganymede_Plane_XZ_Uy", + Parent = transforms.GPHIO.Identifier, + Transform = { + Rotation = { + Type = "StaticRotation", + Rotation = { -math.pi/2, 0.0, 0.0 } + } + }, + Renderable = { + Type = "RenderablePlaneImageLocal", + Size = Size, + Texture = data .. "XZ-Uy.png", + Enabled = false + }, + GUI = { + Name = "Ganymede XZ Plane Uy", + Path = "/Solar System/Missions/Juice/Plane", + Description = [[A cut plane in Ganymede's XZ plane showing the Y component of + Ganymede's magnetic field]] + } +} + +local xz_uz = { + Identifier = "Ganymede_Plane_XZ_Uz", + Parent = transforms.GPHIO.Identifier, + Transform = { + Rotation = { + Type = "StaticRotation", + Rotation = { -math.pi/2, 0.0, 0.0 } + } + }, + Renderable = { + Type = "RenderablePlaneImageLocal", + Size = Size, + Texture = data .. "XZ-Uz.png", + Enabled = false + }, + GUI = { + Name = "Ganymede XZ Plane Uz", + Path = "/Solar System/Missions/Juice/Plane", + Description = [[A cut plane in Ganymede's XZ plane showing the Z component of + Ganymede's magnetic field]] + } +} + + +asset.onInitialize(function() + openspace.addSceneGraphNode(xy_n) + openspace.addSceneGraphNode(xy_t) + openspace.addSceneGraphNode(xy_u) + openspace.addSceneGraphNode(xy_utot) + openspace.addSceneGraphNode(xy_ux) + openspace.addSceneGraphNode(xy_uy) + openspace.addSceneGraphNode(xy_uz) + + openspace.addSceneGraphNode(xz_n) + openspace.addSceneGraphNode(xz_t) + openspace.addSceneGraphNode(xz_u) + openspace.addSceneGraphNode(xz_utot) + openspace.addSceneGraphNode(xz_ux) + openspace.addSceneGraphNode(xz_uy) + openspace.addSceneGraphNode(xz_uz) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(xz_uz) + openspace.removeSceneGraphNode(xz_uy) + openspace.removeSceneGraphNode(xz_ux) + openspace.removeSceneGraphNode(xz_utot) + openspace.removeSceneGraphNode(xz_u) + openspace.removeSceneGraphNode(xz_t) + openspace.removeSceneGraphNode(xz_n) + + openspace.removeSceneGraphNode(xy_uz) + openspace.removeSceneGraphNode(xy_uy) + openspace.removeSceneGraphNode(xy_ux) + openspace.removeSceneGraphNode(xy_utot) + openspace.removeSceneGraphNode(xy_u) + openspace.removeSceneGraphNode(xy_t) + openspace.removeSceneGraphNode(xy_n) +end) + +asset.export(xy_n) +asset.export(xy_t) +asset.export(xy_u) +asset.export(xy_utot) +asset.export(xy_ux) +asset.export(xy_uy) +asset.export(xy_uz) +asset.export(xz_n) +asset.export(xz_t) +asset.export(xz_u) +asset.export(xz_utot) +asset.export(xz_ux) +asset.export(xz_uy) +asset.export(xz_uz) + + +asset.meta = { + Name = "Ganymede Cut Planes", + Version = "1.0", + Description = [[ + Cutplane visualizations of Ganymede's magnetic field as prepared by Ronan Modolo. + ]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license" +} diff --git a/data/assets/scene/solarsystem/missions/juice/trail.asset b/data/assets/scene/solarsystem/missions/juice/trail.asset new file mode 100644 index 0000000000..9ce8b24660 --- /dev/null +++ b/data/assets/scene/solarsystem/missions/juice/trail.asset @@ -0,0 +1,4 @@ +asset.require('./trails/earth') +asset.require('./trails/ganymede') +asset.require('./trails/jupiter') +asset.require('./trails/ssb') diff --git a/data/assets/scene/solarsystem/missions/juice/trails/earth.asset b/data/assets/scene/solarsystem/missions/juice/trails/earth.asset new file mode 100644 index 0000000000..9022ee2c4a --- /dev/null +++ b/data/assets/scene/solarsystem/missions/juice/trails/earth.asset @@ -0,0 +1,49 @@ +local earthTransforms = asset.require('scene/solarsystem/planets/earth/transforms') +local kernels = asset.require('../kernels') + + +local JuiceTrailEarth = { + Identifier = "JuiceTrailEarth", + Parent = earthTransforms.EarthBarycenter.Identifier, + Renderable = { + Type = "RenderableTrailTrajectory", + Translation = { + Type = "SpiceTranslation", + Target = "JUICE", + Observer = "EARTH BARYCENTER", + Kernels = kernels.Kernels + }, + Color = { 0.30, 0.70, 0.20 }, + StartTime = "2023 APR 05 12:00:00.000", + EndTime = "2033 JUN 04 02:51:00.546", + SampleInterval = 3600 + }, + GUI = { + Name = "Juice Trail (Earth)", + Path = "/Solar System/Missions/Juice", + Description = "Juice's trajectory relative to the Earth barycenter" + } +} + + +asset.onInitialize(function() + openspace.addSceneGraphNode(JuiceTrailEarth) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(JuiceTrailEarth) +end) + +asset.export(JuiceTrailEarth) + + +asset.meta = { + Name = "Juice trajectory relative to the Earth barycenter", + Version = "1.0", + Description = [[ + The trajectory of the Juice spacecraft relative to the Earth barycenter + ]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license" +} diff --git a/data/assets/scene/solarsystem/missions/juice/trails/ganymede.asset b/data/assets/scene/solarsystem/missions/juice/trails/ganymede.asset new file mode 100644 index 0000000000..7bac990af9 --- /dev/null +++ b/data/assets/scene/solarsystem/missions/juice/trails/ganymede.asset @@ -0,0 +1,49 @@ +local transforms = asset.require('../transforms') +local kernels = asset.require('../kernels') + + +local JuiceTrailGanymede = { + Identifier = "JuiceTrailGanymede", + Parent = transforms.GanymedePosition.Identifier, + Renderable = { + Type = "RenderableTrailTrajectory", + Translation = { + Type = "SpiceTranslation", + Target = "JUICE", + Observer = "GANYMEDE", + Kernels = kernels.Kernels + }, + Color = { 0.70, 0.770, 0.35 }, + StartTime = "2034 DEC 01 00:00:00.000", + EndTime = "2035 OCT 05 00:00:00.000", + SampleInterval = 600 + }, + GUI = { + Name = "Juice Trail (Ganymede)", + Path = "/Solar System/Missions/Juice", + Description = "Juice's trajectory relative to Ganymede" + } +} + + +asset.onInitialize(function() + openspace.addSceneGraphNode(JuiceTrailGanymede) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(JuiceTrailGanymede) +end) + +asset.export(JuiceTrailGanymede) + + +asset.meta = { + Name = "Juice trajectory relative to Ganymede", + Version = "1.0", + Description = [[ + The trajectory of the Juice spacecraft relative to Ganymede + ]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license" +} diff --git a/data/assets/scene/solarsystem/missions/juice/trails/jupiter.asset b/data/assets/scene/solarsystem/missions/juice/trails/jupiter.asset new file mode 100644 index 0000000000..49b4d85720 --- /dev/null +++ b/data/assets/scene/solarsystem/missions/juice/trails/jupiter.asset @@ -0,0 +1,49 @@ +local jupiterTransforms = asset.require('scene/solarsystem/planets/jupiter/transforms') +local kernels = asset.require('../kernels') + + +local JuiceTrailJupiter = { + Identifier = "JuiceTrailJupiter", + Parent = jupiterTransforms.JupiterBarycenter.Identifier, + Renderable = { + Type = "RenderableTrailTrajectory", + Translation = { + Type = "SpiceTranslation", + Target = "JUICE", + Observer = "JUPITER BARYCENTER", + Kernels = kernels.Kernels + }, + Color = { 0.70, 0.370, 0.45 }, + StartTime = "2031 JUL 02 00:00:00.000", + EndTime = "2035 OCT 05 00:00:00.000", + SampleInterval = 3600 + }, + GUI = { + Name = "Juice Trail (Jupiter)", + Path = "/Solar System/Missions/Juice", + Description = "Juice's trajectory relative to Jupiter" + } +} + + +asset.onInitialize(function() + openspace.addSceneGraphNode(JuiceTrailJupiter) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(JuiceTrailJupiter) +end) + +asset.export(JuiceTrailJupiter) + + +asset.meta = { + Name = "Juice trajectory relative to Jupiter", + Version = "1.0", + Description = [[ + The trajectory of the Juice spacecraft relative to Jupiter + ]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license" +} diff --git a/data/assets/scene/solarsystem/missions/juice/trails/ssb.asset b/data/assets/scene/solarsystem/missions/juice/trails/ssb.asset new file mode 100644 index 0000000000..5aeec137e2 --- /dev/null +++ b/data/assets/scene/solarsystem/missions/juice/trails/ssb.asset @@ -0,0 +1,49 @@ +local sunTransforms = asset.require('scene/solarsystem/sun/transforms') +local kernels = asset.require('../kernels') + + +local JuiceTrail = { + Identifier = "JuiceTrail", + Parent = sunTransforms.SolarSystemBarycenter.Identifier, + Renderable = { + Type = "RenderableTrailTrajectory", + Translation = { + Type = "SpiceTranslation", + Target = "JUICE", + Observer = "SSB", + Kernels = kernels.Kernels + }, + Color = { 0.85, 0.85, 0.85 }, + StartTime = "2023 APR 05 12:00:00.000", + EndTime = "2035 OCT 05 00:00:00.000", + SampleInterval = 3600 + }, + GUI = { + Name = "Juice Trail", + Path = "/Solar System/Missions/Juice", + Description = "Juice's trajectory relative to the solar system's barycenter" + } +} + + +asset.onInitialize(function() + openspace.addSceneGraphNode(JuiceTrail) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(JuiceTrail) +end) + +asset.export(JuiceTrail) + + +asset.meta = { + Name = "Juice trajectory relative to the solar system's barycenter", + Version = "1.0", + Description = [[ + The trajectory of the Juice spacecraft relative to the solar system's barycenter + ]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license" +} diff --git a/data/assets/scene/solarsystem/missions/juice/transforms.asset b/data/assets/scene/solarsystem/missions/juice/transforms.asset new file mode 100644 index 0000000000..f0e2688c83 --- /dev/null +++ b/data/assets/scene/solarsystem/missions/juice/transforms.asset @@ -0,0 +1,96 @@ +local jupiterTransforms = asset.require('scene/solarsystem/planets/jupiter/transforms') +local kernels = asset.require('./kernels') + + +local Juice = { + Identifier = "Juice", + Parent = jupiterTransforms.JupiterBarycenter.Identifier, + Transform = { + Translation = { + Type = "SpiceTranslation", + Target = "JUICE", + Observer = "JUPITER BARYCENTER", + Kernels = kernels.Kernels + }, + Rotation = { + Type = "SpiceRotation", + SourceFrame = "JUICE_SPACECRAFT", + DestinationFrame = "GALACTIC", + Kernels = kernels.Kernels + }, + }, + GUI = { + Name = "Juice", + Path = "/Solar System/Missions/Juice", + Description = "The position of Juice in the reference frame of Jupiter" + } +} + +local GanymedePosition = { + Identifier = "GanymedePosition", + Parent = jupiterTransforms.JupiterBarycenter.Identifier, + Transform = { + Translation = { + Type = "SpiceTranslation", + Target = "GANYMEDE", + Observer = "JUPITER BARYCENTER", + Kernels = kernels.Kernels + } + }, + GUI = { + Path = "/Solar System/Planets/Jupiter/Moons", + Description = "Ganymede's position relative to Jupiter as an inertial reference frame" + } +} + +local GPHIO = { + Identifier = "GPHIO", + Parent = GanymedePosition.Identifier, + Transform = { + Rotation = { + Type = "SpiceRotation", + SourceFrame = "GPHIO", + DestinationFrame = "GALACTIC", + Kernels = kernels.Kernels + } + }, + GUI = { + Name = "GPHIO", + Path = "/Solar System/Missions/Juice", + Description = [[A rotating coordinate system called Ganymede Phi-Omega (G_PHI_O). The + X axis is pointing in the direction of corotational flow (System III flow), Z is + parallel to the Jovian spin axis (Omega), and Y completes the right handed set. The + basis vectors are fixed at the time of Ganymede closest approach (2000-12-28 + 08:25:28)]] + } +} + + +asset.onInitialize(function() + openspace.addSceneGraphNode(Juice) + openspace.addSceneGraphNode(GanymedePosition) + openspace.addSceneGraphNode(GPHIO) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(GPHIO) + openspace.removeSceneGraphNode(GanymedePosition) + openspace.removeSceneGraphNode(Juice) +end) + +asset.export(Juice) +asset.export(GanymedePosition) +asset.export(GPHIO) + + +asset.meta = { + Name = "Transformations for the JUICE mission profile", + Version = "1.0", + Description = [[ + Contains all of the base transformations necessary for the JUICE mission in the Jovian + system + ]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license" +} diff --git a/data/assets/scene/solarsystem/missions/osirisrex/kernels.asset b/data/assets/scene/solarsystem/missions/osirisrex/kernels.asset index 1b1b858e5c..ba1c27cfae 100644 --- a/data/assets/scene/solarsystem/missions/osirisrex/kernels.asset +++ b/data/assets/scene/solarsystem/missions/osirisrex/kernels.asset @@ -2,7 +2,7 @@ local kernels = asset.syncedResource({ Name = "Osiris Rex Kernels", Type = "HttpSynchronization", Identifier = "osirisrex_kernels", - Version = 3 + Version = 4 }) local OsirisRexKernels = { diff --git a/data/assets/scene/solarsystem/planets/saturn/minor/other_group.asset b/data/assets/scene/solarsystem/planets/saturn/minor/other_group.asset index e1806845d9..9ffa6187b5 100644 --- a/data/assets/scene/solarsystem/planets/saturn/minor/other_group.asset +++ b/data/assets/scene/solarsystem/planets/saturn/minor/other_group.asset @@ -18,91 +18,6 @@ local trailTags = { } local otherGroup = { - { - Identifier = "Atlas", - Parent = { - Identifier = parentIdentifier, - Spice = parentSpice - }, - Spice = "ATLAS", - Radii = { 41000, 35000, 19000 }, - Tags = tags, - TrailTags = trailTags, - GUI = { - Path = "/Solar System/Planets/Saturn/Moons/Other Group" - }, - TrailColor = trailColor, - OrbitPeriod = 0.60169, - Kernels = kernel393 - }, - { - Identifier = "Prometheus", - Parent = { - Identifier = parentIdentifier, - Spice = parentSpice - }, - Spice = "PROMETHEUS", - Radii = { 136000, 79000, 59000 }, - Tags = tags, - TrailTags = trailTags, - GUI = { - Path = "/Solar System/Planets/Saturn/Moons/Other Group" - }, - TrailColor = trailColor, - OrbitPeriod = 0.61299, - Kernels = kernel393 - }, - { - Identifier = "Pandora", - Parent = { - Identifier = parentIdentifier, - Spice = parentSpice - }, - Spice = "PANDORA", - Radii = { 104000, 81000, 64000 }, - Tags = tags, - TrailTags = trailTags, - GUI = { - Path = "/Solar System/Planets/Saturn/Moons/Other Group" - }, - TrailColor = trailColor, - OrbitPeriod = 0.62850, - Kernels = kernel393 - }, - { - Identifier = "Epimetheus", - Parent = { - Identifier = parentIdentifier, - Spice = parentSpice - }, - Spice = "EPIMETHEUS", - Radii = { 130000, 114000, 106000 }, - Tags = tags, - TrailTags = trailTags, - GUI = { - Path = "/Solar System/Planets/Saturn/Moons/Other Group" - }, - TrailColor = trailColor, - OrbitPeriod = 0.69433, - Kernels = kernel393 - }, - { - Identifier = "Janus", - Parent = { - Identifier = parentIdentifier, - Spice = parentSpice - }, - Spice = "JANUS", - Radii = { 203000, 185000, 153000 }, - Tags = tags, - TrailTags = trailTags, - GUI = { - Path = "/Solar System/Planets/Saturn/Moons/Other Group" - }, - TrailColor = trailColor, - OrbitPeriod = 0.69466, - Kernels = kernel393 - }, { Identifier = "Aegaeon", Parent = { @@ -264,10 +179,8 @@ asset.meta = { Name = "Saturn Other Group Moons", Version = "1.0", Description = [[ Procedural Globe asset containing Saturn's Other Group - moons: Phoebe, Skathi, S2007S2, Skoll, S2004S13, Greip, Hyrrokkin, Jarnsaxa, - Mundilfari, S2006S1, S2004S17, Bergelmir, Narvi, Suttungr, Hati, S2004S12, - Farbauti, Thrymr, Aegir, S2007S3, Bestla, S2004S7, S2006S3, Fenrir, Kari, Ymir, - Loge, Fornjot. Blank globes and SPICE trails are generated for each moon.]], + moons: Aegaeon, Methone, Anthe, Pallene, Telesto, Calypso, Helene, Polydeuces. + Blank globes and SPICE trails are generated for each moon.]], Author = "OpenSpace Team", URL = "http://openspaceproject.com", License = "MIT license" diff --git a/data/assets/scene/solarsystem/planets/saturn/minor/shepherd_group.asset b/data/assets/scene/solarsystem/planets/saturn/minor/shepherd_group.asset new file mode 100644 index 0000000000..cc2af9d9d7 --- /dev/null +++ b/data/assets/scene/solarsystem/planets/saturn/minor/shepherd_group.asset @@ -0,0 +1,178 @@ +local proceduralGlobes = asset.require("util/procedural_globe") +local transforms = asset.require("../transforms") + +local syncedKernels = asset.syncedResource({ + Name = "Saturn Shepherd Moons Spice Kernels", + Type = "HttpSynchronization", + Identifier = "saturn_shepherd_kernels", + Version = 1 +}) + +local kernels = { + syncedKernels .. "sat415.bsp", + syncedKernels .. "sat393_daphnis.bsp" +} + +local parentIdentifier = transforms.SaturnBarycenter.Identifier +local parentSpice = "SATURN BARYCENTER" +local guiPath = "/Solar System/Planets/Saturn/Moons/Shepherd Moons" +local tags = { "moon_solarSystem", "moon_giants", "moon_saturn", "moon_shepherd", "moon_minor" } +local trailColor = { 0.5, 0.3, 0.3 } +local trailTags = { + "moonTrail_solarSystem", + "moonTrail_giants", + "moonTrail_saturn", + "moonTrail_minor" +} + +local shepherdGroup = { + { + Identifier = "Prometheus", + Parent = { + Identifier = parentIdentifier, + Spice = parentSpice + }, + Spice = "PROMETHEUS", + Radii = { 135600, 79400, 59400 }, + Tags = tags, + TrailTags = trailTags, + GUI = { + Path = guiPath + }, + TrailColor = trailColor, + OrbitPeriod = 0.612990038, + Kernels = kernels + }, + { + Identifier = "Pandora", + Parent = { + Identifier = parentIdentifier, + Spice = parentSpice + }, + Spice = "PANDORA", + Radii = { 104000, 81000, 64000 }, + Tags = tags, + TrailTags = trailTags, + GUI = { + Path = guiPath + }, + TrailColor = trailColor, + OrbitPeriod = 0.628504213, + Kernels = kernels + }, + { + Identifier = "Atlas", + Parent = { + Identifier = parentIdentifier, + Spice = parentSpice + }, + Spice = "ATLAS", + Radii = { 40800, 35400, 18800 }, + Tags = tags, + TrailTags = trailTags, + GUI = { + Path = guiPath + }, + TrailColor = trailColor, + OrbitPeriod = 0.6016947883, + Kernels = kernels + }, + { + Identifier = "Janus", + Parent = { + Identifier = parentIdentifier, + Spice = parentSpice + }, + Spice = "JANUS", + Radii = { 203000, 185000, 152600 }, + Tags = tags, + TrailTags = trailTags, + GUI = { + Path = guiPath + }, + TrailColor = trailColor, + OrbitPeriod = 0.694660342, + Kernels = kernels + }, + { + Identifier = "Epimetheus", + Parent = { + Identifier = parentIdentifier, + Spice = parentSpice + }, + Spice = "EPIMETHEUS", + Radii = { 129800, 114000, 106200 }, + Tags = tags, + TrailTags = trailTags, + GUI = { + Path = guiPath + }, + TrailColor = trailColor, + OrbitPeriod = 0.694333517, + Kernels = kernels + }, + { + Identifier = "Daphnis", + Parent = { + Identifier = parentIdentifier, + Spice = parentSpice + }, + Spice = "DAPHNIS", + Radii = { 8600, 8200, 6400 }, + Tags = tags, + TrailTags = trailTags, + GUI = { + Path = guiPath + }, + TrailColor = trailColor, + OrbitPeriod = 0.5940798, + Kernels = kernels + }, + { + Identifier = "Pan", + Parent = { + Identifier = parentIdentifier, + Spice = parentSpice + }, + Spice = "PAN", + Radii = { 34400, 31400, 20800 }, + Tags = tags, + TrailTags = trailTags, + GUI = { + Path = guiPath + }, + TrailColor = trailColor, + OrbitPeriod = 0.575050718, + Kernels = kernels + } +} + +local nodes = proceduralGlobes.createGlobes(shepherdGroup) + +asset.onInitialize(function() + for _, node in ipairs(nodes) do + openspace.addSceneGraphNode(node) + end +end) + +asset.onDeinitialize(function() + for i = #nodes, 1, -1 do + openspace.removeSceneGraphNode(nodes[i]) + end +end) + +for _, node in ipairs(nodes) do + asset.export(node) +end + + +asset.meta = { + Name = "Saturn Shepherd Moons", + Version = "1.0", + Description = [[ Procedural Globe asset containing Saturn's Shepherd moons: + Prometheus, Pandora, Atlas, Janus, Epimetheus, Daphnis and Pan. Blank globes + and SPICE trails are generated for each moon.]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license" +} diff --git a/data/assets/scene/solarsystem/planets/saturn/minor_moons.asset b/data/assets/scene/solarsystem/planets/saturn/minor_moons.asset index 6fdc8071f4..0a22263985 100644 --- a/data/assets/scene/solarsystem/planets/saturn/minor_moons.asset +++ b/data/assets/scene/solarsystem/planets/saturn/minor_moons.asset @@ -2,13 +2,14 @@ asset.require("./minor/gallic_group") asset.require("./minor/inuit_group") asset.require("./minor/norse_group") asset.require("./minor/other_group") +asset.require("./minor/shepherd_group") asset.meta = { Name = "Saturn Minor Moons", Version = "1.0", - Description = [[ Meta asset containing four moon groups: Gallic, Inuit, Norse and - Other]], + Description = [[ Meta asset containing five moon groups: Gallic, Inuit, Norse, + Shepherd moons and Other]], Author = "OpenSpace Team", URL = "http://openspaceproject.com", License = "MIT license" diff --git a/data/assets/scene/solarsystem/sssb/itokawa.asset b/data/assets/scene/solarsystem/sssb/itokawa.asset new file mode 100644 index 0000000000..fc93ca5932 --- /dev/null +++ b/data/assets/scene/solarsystem/sssb/itokawa.asset @@ -0,0 +1,107 @@ +local sunTransforms = asset.require("scene/solarsystem/sun/transforms") +local sun = asset.require("scene/solarsystem/sun/sun") + +local orbit = asset.syncedResource({ + Name = "Itokawa Orbit", + Type = "HttpSynchronization", + Identifier = "itokawa_horizons", + Version = 1 +}) + +local model = asset.syncedResource({ + Name = "Itokawa Model", + Type = "HttpSynchronization", + Identifier = "itokawa_model", + Version = 1 +}) + +local ItokawaTrail = { + Identifier = "ItokawaTrail", + Parent = sunTransforms.SolarSystemBarycenter.Identifier, + Renderable = { + Type = "RenderableTrailOrbit", + Translation = { + Type = "HorizonsTranslation", + HorizonsTextFile = orbit .. "horizons_itokawa.hrz" + -- Target: 25143 Itokawa (1998 SF36) + -- Observer: SSB + -- Start time: 1950-Jan-01 00:00:00 (first data point) + -- End time: 2050-Jan-01 00:00:00 (last data point) + -- Step size: 1 day + }, + Color = { 0.0, 0.9, 0.9 }, + Period = 557, -- Orbit time 557 days + Resolution = 557 -- Step size 1 day + }, + GUI = { + Name = "Itokawa Trail", + Path = "/Solar System/SSSB/Itokawa", + Description = [[Trail of asteroid 25143 Itokawa from 1950 JAN 1 00:00:00 + to 2050 JAN 1 00:00:00. Data from JPL Horizons.]] + } +} + +local ItokawaPosition = { + Identifier = "ItokawaPosition", + Parent = sunTransforms.SolarSystemBarycenter.Identifier, + Transform = { + Translation = { + Type = "HorizonsTranslation", + HorizonsTextFile = orbit .. "horizons_itokawa.hrz" + } + }, + GUI = { + Name = "Itokawa Position", + Path = "/Solar System/SSSB/Itokawa", + Description = [[Position of asteroid 25143 Itokawa from 1950 JAN 1 00:00:00 + to 2050 JAN 1 00:00:00. Data from JPL Horizons.]] + } +} + +local ItokawaModel = { + Identifier = "ItokawaModel", + Parent = ItokawaPosition.Identifier, + Renderable = { + Type = "RenderableModel", + GeometryFile = model .. "itokawa.glb", + LightSources = { + sun.LightSource + }, + PerformShading = true, + DisableFaceCulling = true, + SpecularIntensity = 0.0 + }, + GUI = { + Name = "Itokawa Model", + Path = "/Solar System/SSSB/Itokawa", + Description = [[Model of asteroid 25143 Itokawa. 3D model from + https://solarsystem.nasa.gov/resources/2377/asteroid-itokawa-3d-model/]] + } +} + +asset.onInitialize(function() + openspace.addSceneGraphNode(ItokawaPosition) + openspace.addSceneGraphNode(ItokawaTrail) + openspace.addSceneGraphNode(ItokawaModel) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(ItokawaModel) + openspace.removeSceneGraphNode(ItokawaTrail) + openspace.removeSceneGraphNode(ItokawaPosition) +end) + +asset.export(ItokawaPosition) +asset.export(ItokawaTrail) +asset.export(ItokawaModel) + + +asset.meta = { + Name = "Itokawa Asteroid", + Version = "1.0", + Description = [[Position, trail and model of asteroid 25143 Itokawa from + 1950 JAN 1 00:00:00 to 2050 JAN 1 00:00:00. Data from JPL Horizons.]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license" +} diff --git a/data/assets/util/webgui.asset b/data/assets/util/webgui.asset index a1ea9836c2..070be0c3f0 100644 --- a/data/assets/util/webgui.asset +++ b/data/assets/util/webgui.asset @@ -3,7 +3,7 @@ asset.require("./static_server") local guiCustomization = asset.require("customization/gui") -- Select which commit hashes to use for the frontend and backend -local frontendHash = "fae0fddfcdbdd9bd78e7b1b3d2954823e2af26f5" +local frontendHash = "aeffda7eef46f4eaddfebcb41389672d2c473b35" local dataProvider = "data.openspaceproject.com/files/webgui" local frontend = asset.syncedResource({ diff --git a/data/profiles/juice.profile b/data/profiles/juice.profile new file mode 100644 index 0000000000..1f51606e81 --- /dev/null +++ b/data/profiles/juice.profile @@ -0,0 +1,123 @@ +{ + "additional_scripts": [ + "" + ], + "assets": [ + "base", + "scene/solarsystem/missions/juice/fieldlines", + "scene/solarsystem/missions/juice/fov/janus", + "scene/solarsystem/missions/juice/fov/navcam", + "scene/solarsystem/missions/juice/model", + "scene/solarsystem/missions/juice/plane", + "scene/solarsystem/missions/juice/trail", + "scene/solarsystem/planets/earth/earth" + ], + "camera": { + "altitude": 9220000000.0, + "anchor": "Jupiter", + "latitude": -7.1689, + "longitude": -173.3037, + "type": "goToGeo" + }, + "delta_times": [ + 1.0, + 5.0, + 30.0, + 60.0, + 300.0, + 1800.0, + 3600.0, + 43200.0, + 86400.0, + 604800.0, + 1209600.0, + 2592000.0, + 5184000.0, + 7776000.0, + 15552000.0, + 31536000.0, + 63072000.0, + 157680000.0, + 315360000.0, + 630720000.0 + ], + "mark_nodes": [ + "Earth", + "Juice", + "Jupiter", + "Ganymede" + ], + "meta": { + "author": "OpenSpace Team", + "description": "Juice profile that visualizes the currently best known trajectory for the JUICE mission the Jupiter and its moons. See https://sci.esa.int/documents/33960/35865/1567260128466-JUICE_Red_Book_i1.0.pdf for more information about the JUICE mission. Currently, only the Janus and NavCam instruments are included in this profile, but the other instruments are available for a custom profile. Some of these are not behaving correctly, which will be addressed later.", + "license": "MIT License", + "name": "Juice", + "url": "https://www.openspaceproject.com", + "version": "1.0" + }, + "properties": [ + { + "name": "NavigationHandler.OrbitalNavigator.MinimumAllowedDistance", + "type": "setPropertyValueSingle", + "value": "0.0" + }, + { + "name": "Scene.JuiceTrailEarth.Renderable.Enabled", + "type": "setPropertyValueSingle", + "value": "false" + }, + { + "name": "Scene.JuiceTrailJupiter.Renderable.Enabled", + "type": "setPropertyValueSingle", + "value": "true" + }, + { + "name": "Scene.JuiceTrailGanymede.Renderable.Enabled", + "type": "setPropertyValueSingle", + "value": "false" + }, + { + "name": "Scene.GanymedeMagnetosphere.Renderable.DomainEnabled", + "type": "setPropertyValueSingle", + "value": "false" + }, + { + "name": "Scene.JuiceTrail.Renderable.Enabled", + "type": "setPropertyValueSingle", + "value": "false" + }, + { + "name": "Scene.GanymedeMagnetosphere.Renderable.LineWidth", + "type": "setPropertyValueSingle", + "value": "2.0" + }, + { + "name": "Scene.GanymedeMagnetosphere.Renderable.Flow.ParticleSize", + "type": "setPropertyValueSingle", + "value": "25.000000" + }, + { + "name": "Scene.GanymedeMagnetosphere.Renderable.Flow.ParticleSpacing", + "type": "setPropertyValueSingle", + "value": "40" + }, + { + "name": "Scene.GanymedeMagnetosphere.Renderable.Flow.Speed", + "type": "setPropertyValueSingle", + "value": "150.000000" + }, + { + "name": "Scene.GanymedeMagnetosphere.Renderable.FlowEnabled", + "type": "setPropertyValueSingle", + "value": "true" + } + ], + "time": { + "type": "absolute", + "value": "2031-08-01T03:01:30" + }, + "version": { + "major": 1, + "minor": 1 + } +} diff --git a/ext/ghoul b/ext/ghoul index 7dc41a163e..2f0b8fb150 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 7dc41a163e2d4d90cc411a0e04cd8e8293f958b4 +Subproject commit 2f0b8fb15055fa3ff2a5ca67c12d7dda26f67e38 diff --git a/include/openspace/engine/openspaceengine.h b/include/openspace/engine/openspaceengine.h index 89bc1a28f7..83b6209b01 100644 --- a/include/openspace/engine/openspaceengine.h +++ b/include/openspace/engine/openspaceengine.h @@ -25,6 +25,9 @@ #ifndef __OPENSPACE_CORE___OPENSPACEENGINE___H__ #define __OPENSPACE_CORE___OPENSPACEENGINE___H__ +#include +#include +#include #include #include #include @@ -63,7 +66,7 @@ struct CommandlineArguments { std::string configurationOverride; }; -class OpenSpaceEngine { +class OpenSpaceEngine : public properties::PropertyOwner { public: // A mode that specifies which part of the system is currently in control. // The mode can be used to limit certain features, like setting time, navigation @@ -101,6 +104,8 @@ public: std::vector encode(); void decode(std::vector data); + properties::Property::Visibility visibility() const; + bool showHiddenSceneGraphNodes() const; void toggleShutdownMode(); Mode currentMode() const; @@ -136,6 +141,8 @@ private: void resetPropertyChangeFlagsOfSubowners(openspace::properties::PropertyOwner* po); properties::BoolProperty _printEvents; + properties::OptionProperty _visibility; + properties::BoolProperty _showHiddenSceneGraphNodes; std::unique_ptr _scene; std::unique_ptr _assetManager; diff --git a/include/openspace/properties/property.h b/include/openspace/properties/property.h index c5967a2aeb..6e9303a271 100644 --- a/include/openspace/properties/property.h +++ b/include/openspace/properties/property.h @@ -62,13 +62,15 @@ class Property { public: /** * The visibility classes for Property%s. The classes are strictly ordered as - * All > Developer > User > Hidden + * Hidden > Developer > AdvancedUser > User > NoviceUser > Always */ enum class Visibility { - Hidden = 3, ///< Never visible - Developer = 2, ///< Visible in Developer mode - User = 1, ///< Visible in User mode - All = 0, ///< Visible for all types, no matter what + Hidden = 5, ///< Never visible + Developer = 4, ///< Visible in Developer mode + AdvancedUser = 3, ///< Visible in Advanced User mode + User = 2, ///< Visible in User mode + NoviceUser = 1, ///< Visible in Novice User mode + Always = 0, ///< Visible for all types, no matter what }; /** @@ -99,7 +101,7 @@ public: /// The user facing description of this Property const char* description; /// Determines the visibility of this Property in the user interface - Visibility visibility = Visibility::All; + Visibility visibility = Visibility::Always; }; /// An OnChangeHandle is returned by the onChange method to uniquely identify an @@ -119,7 +121,7 @@ public: * necessary information for this Property. #PropertyInfo::identifier needs to be * unique for each PropertyOwner. The #PropertyInfo::guiName will be stored in the * metaData to be accessed by the GUI elements using the #PropertyInfo::guiName key. - * The default visibility settings is Visibility::All, whereas the default read-only + * The default visibility settings is Visibility::Always, whereas the default read-only * state is \c false. * * \param info The PropertyInfo structure that contains all the required static diff --git a/include/openspace/rendering/screenspacerenderable.h b/include/openspace/rendering/screenspacerenderable.h index f36382191c..b5b992788f 100644 --- a/include/openspace/rendering/screenspacerenderable.h +++ b/include/openspace/rendering/screenspacerenderable.h @@ -130,6 +130,7 @@ protected: properties::Vec3Property _localRotation; properties::FloatProperty _scale; + properties::FloatProperty _gamma; properties::Vec3Property _multiplyColor; properties::Vec4Property _backgroundColor; properties::FloatProperty _opacity; @@ -137,7 +138,7 @@ protected: properties::TriggerProperty _delete; glm::ivec2 _objectSize = glm::ivec2(0); - UniformCache(color, opacity, mvp, texture, backgroundColor) _uniformCache; + UniformCache(color, opacity, mvp, texture, backgroundColor, gamma) _uniformCache; std::unique_ptr _shader; }; diff --git a/modules/base/dashboard/dashboarditemangle.cpp b/modules/base/dashboard/dashboarditemangle.cpp index 914968f575..73c311e386 100644 --- a/modules/base/dashboard/dashboarditemangle.cpp +++ b/modules/base/dashboard/dashboarditemangle.cpp @@ -168,11 +168,6 @@ DashboardItemAngle::DashboardItemAngle(const ghoul::Dictionary& dictionary) { Type::Focus, "Focus" }, { Type::Camera, "Camera" } }); - _source.type.onChange([this]() { - _source.nodeName.setVisibility( - properties::Property::Visibility(_source.type == Type::Node) - ); - }); if (p.sourceType.has_value()) { _source.type = codegen::map(*p.sourceType); } @@ -201,11 +196,6 @@ DashboardItemAngle::DashboardItemAngle(const ghoul::Dictionary& dictionary) { Type::Focus, "Focus" }, { Type::Camera, "Camera" } }); - _reference.type.onChange([this]() { - _reference.nodeName.setVisibility( - properties::Property::Visibility(_reference.type == Type::Node) - ); - }); _reference.type = codegen::map(p.referenceType); addProperty(_reference.type); @@ -228,11 +218,6 @@ DashboardItemAngle::DashboardItemAngle(const ghoul::Dictionary& dictionary) { Type::Focus, "Focus" }, { Type::Camera, "Camera" } }); - _destination.type.onChange([this]() { - _destination.nodeName.setVisibility( - properties::Property::Visibility(_source.type == Type::Node) - ); - }); if (p.destinationType.has_value()) { _destination.type = codegen::map(*p.destinationType); } diff --git a/modules/base/rendering/renderableplane.cpp b/modules/base/rendering/renderableplane.cpp index 2749f74a08..a5a5fa198d 100644 --- a/modules/base/rendering/renderableplane.cpp +++ b/modules/base/rendering/renderableplane.cpp @@ -270,6 +270,7 @@ void RenderablePlane::render(const RenderData& data, RendererTasks&) { glDepthMask(false); glBlendFunc(GL_SRC_ALPHA, GL_ONE); } + glDisable(GL_CULL_FACE); glBindVertexArray(_quad); glDrawArrays(GL_TRIANGLES, 0, 6); diff --git a/modules/base/rotation/timelinerotation.cpp b/modules/base/rotation/timelinerotation.cpp index 9f34f58412..12302a6ea8 100644 --- a/modules/base/rotation/timelinerotation.cpp +++ b/modules/base/rotation/timelinerotation.cpp @@ -28,13 +28,24 @@ #include #include #include +#include namespace { + constexpr openspace::properties::Property::PropertyInfo ShouldInterpolateInfo = { + "ShouldInterpolate", + "Should Interpolate", + "If this value is set to 'true', an interpolation is applied between the given " + "keyframes. If this value is set to 'false', the interpolation is not applied." + }; + struct [[codegen::Dictionary(TimelineRotation)]] Parameters { // A table of keyframes, with keys formatted as YYYY-MM-DDTHH:MM:SS and values // that are valid Rotation objects std::map keyframes [[codegen::reference("core_transform_rotation")]]; + + // [[codegen::verbatim(ShouldInterpolateInfo.description)]] + std::optional shouldInterpolate; }; #include "timelinerotation_codegen.cpp" } // namespace @@ -45,7 +56,9 @@ documentation::Documentation TimelineRotation::Documentation() { return codegen::doc("base_transform_rotation_keyframe"); } -TimelineRotation::TimelineRotation(const ghoul::Dictionary& dictionary) { +TimelineRotation::TimelineRotation(const ghoul::Dictionary& dictionary) + : _shouldInterpolate(ShouldInterpolateInfo, true) +{ const Parameters p = codegen::bake(dictionary); for (const std::pair& kf : p.keyframes) { @@ -58,6 +71,9 @@ TimelineRotation::TimelineRotation(const ghoul::Dictionary& dictionary) { _timeline.addKeyframe(t, std::move(rotation)); } } + + _shouldInterpolate = p.shouldInterpolate.value_or(_shouldInterpolate); + addProperty(_shouldInterpolate); } glm::dmat3 TimelineRotation::matrix(const UpdateData& data) const { @@ -78,16 +94,26 @@ glm::dmat3 TimelineRotation::matrix(const UpdateData& data) const { } const double prevTime = prev->timestamp; const double nextTime = next->timestamp; + if (_shouldInterpolate) { + double t = 0.0; + if (nextTime - prevTime > 0.0) { + t = (now - prevTime) / (nextTime - prevTime); + } - double t = 0.0; - if (nextTime - prevTime > 0.0) { - t = (now - prevTime) / (nextTime - prevTime); + const glm::dquat nextRot = glm::quat_cast(next->data->matrix(data)); + const glm::dquat prevRot = glm::quat_cast(prev->data->matrix(data)); + + return glm::dmat3(glm::slerp(prevRot, nextRot, t)); } - - const glm::dquat nextRot = glm::quat_cast(next->data->matrix(data)); - const glm::dquat prevRot = glm::quat_cast(prev->data->matrix(data)); - - return glm::dmat3(glm::slerp(prevRot, nextRot, t)); + else { + if (prevTime <= now && now < nextTime) { + return prev->data->matrix(data); + } + else if (nextTime <= now) { + return next->data->matrix(data); + } + } + return glm::dmat3(0.0); } } // namespace openspace diff --git a/modules/base/rotation/timelinerotation.h b/modules/base/rotation/timelinerotation.h index d8a5450edd..1803f39e7a 100644 --- a/modules/base/rotation/timelinerotation.h +++ b/modules/base/rotation/timelinerotation.h @@ -26,6 +26,8 @@ #define __OPENSPACE_MODULE_BASE___TIMELINEROTATION___H__ #include + +#include #include namespace openspace { @@ -42,6 +44,7 @@ public: private: Timeline> _timeline; + properties::BoolProperty _shouldInterpolate; }; } // namespace openspace diff --git a/modules/base/shaders/screenspace_fs.glsl b/modules/base/shaders/screenspace_fs.glsl index b112559485..ea16f1167b 100644 --- a/modules/base/shaders/screenspace_fs.glsl +++ b/modules/base/shaders/screenspace_fs.glsl @@ -32,6 +32,7 @@ uniform sampler2D tex; uniform vec3 color = vec3(1.0); uniform float opacity = 1.0; uniform vec4 backgroundColor = vec4(0.0); +uniform float gamma = 1.0; Fragment getFragment() { Fragment frag; @@ -44,5 +45,6 @@ Fragment getFragment() { } frag.depth = vs_depth; + frag.color.rgb = pow(frag.color.rgb, vec3(1.0/(gamma))); return frag; } diff --git a/modules/base/translation/timelinetranslation.h b/modules/base/translation/timelinetranslation.h index 58df543e05..2041043db8 100644 --- a/modules/base/translation/timelinetranslation.h +++ b/modules/base/translation/timelinetranslation.h @@ -25,8 +25,9 @@ #ifndef __OPENSPACE_MODULE_BASE___TIMELINETRANSLATION___H__ #define __OPENSPACE_MODULE_BASE___TIMELINETRANSLATION___H__ -#include #include + +#include #include #include diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp index 87be9ca108..55888dd992 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp @@ -550,9 +550,6 @@ fls::Model stringToModel(std::string str) { bool RenderableFieldlinesSequence::loadJsonStatesIntoRAM() { fls::Model model = stringToModel(_modelStr); - if (model == fls::Model::Invalid) { - return false; - } for (const std::string& filePath : _sourceFiles) { FieldlinesState newState; const bool loadedSuccessfully = newState.loadStateFromJson( @@ -1079,6 +1076,12 @@ void RenderableFieldlinesSequence::update(const UpdateData& data) { if (!_hasBeenUpdated) { updateVertexPositionBuffer(); } + + if (_states[_activeStateIndex].nExtraQuantities() > 0) { + _shouldUpdateColorBuffer = true; + _shouldUpdateMaskingBuffer = true; + } + _hasBeenUpdated = true; } else { diff --git a/modules/imgui/imguimodule.cpp b/modules/imgui/imguimodule.cpp index f9132d9488..3019c97bb7 100644 --- a/modules/imgui/imguimodule.cpp +++ b/modules/imgui/imguimodule.cpp @@ -490,18 +490,6 @@ void ImGUIModule::renderFrame(float deltaTime, const glm::vec2& windowSize, comp->setEnabled(enabled); } - // Render and Update property visibility - // Fragile! Keep this in sync with properties::Property::Visibility - using V = properties::Property::Visibility; - int t = static_cast>(_currentVisibility); - - // Array is sorted by importance - std::array items = { "User", "Developer", "Hidden", "All" }; - ImGui::Combo("PropertyVisibility", &t, items.data(), static_cast(items.size())); - - _currentVisibility = static_cast(t); - _property.setVisibility(_currentVisibility); - #ifdef SHOW_IMGUI_HELPERS ImGui::Checkbox("ImGUI Internals", &_showInternals); if (_showInternals) { diff --git a/modules/imgui/imguimodule.h b/modules/imgui/imguimodule.h index 8c94675f2e..89dfb427f7 100644 --- a/modules/imgui/imguimodule.h +++ b/modules/imgui/imguimodule.h @@ -124,9 +124,6 @@ private: UniformCache(tex, ortho) _uniformCache; std::unique_ptr _fontTexture; - properties::Property::Visibility _currentVisibility = - properties::Property::Visibility::Developer; - std::vector _contexts; std::vector _validTouchStates; diff --git a/modules/imgui/include/guipropertycomponent.h b/modules/imgui/include/guipropertycomponent.h index fcdc5a013f..506110b00f 100644 --- a/modules/imgui/include/guipropertycomponent.h +++ b/modules/imgui/include/guipropertycomponent.h @@ -52,22 +52,17 @@ public: void setPropertyOwnerFunction( std::function()> func); - void setVisibility(properties::Property::Visibility visibility); - void render() override; protected: void renderPropertyOwner(properties::PropertyOwner* owner); void renderProperty(properties::Property* prop, properties::PropertyOwner* owner); - properties::Property::Visibility _visibility = properties::Property::Visibility::User; - std::vector _propertyOwners; std::function()> _propertyOwnerFunction; properties::BoolProperty _useTreeLayout; properties::StringListProperty _treeOrdering; - properties::BoolProperty _ignoreHiddenHint; }; } // namespace openspace::gui diff --git a/modules/imgui/src/guiparallelcomponent.cpp b/modules/imgui/src/guiparallelcomponent.cpp index 31c90bff88..07389f3e2d 100644 --- a/modules/imgui/src/guiparallelcomponent.cpp +++ b/modules/imgui/src/guiparallelcomponent.cpp @@ -42,7 +42,6 @@ namespace openspace::gui { GuiParallelComponent::GuiParallelComponent() : GuiPropertyComponent("Parallel", "Parallel Connection") { - setVisibility(properties::Property::Visibility::All); } void GuiParallelComponent::renderDisconnected() { diff --git a/modules/imgui/src/guipropertycomponent.cpp b/modules/imgui/src/guipropertycomponent.cpp index 7ccec97ed4..acc38646f0 100644 --- a/modules/imgui/src/guipropertycomponent.cpp +++ b/modules/imgui/src/guipropertycomponent.cpp @@ -26,6 +26,8 @@ #include #include +#include +#include #include #include #include @@ -59,15 +61,17 @@ namespace { "the hidden hints are followed." }; - int nVisibleProperties(const std::vector& props, - openspace::properties::Property::Visibility visibility) + int nVisibleProperties(const std::vector& props) { + using Visibility = openspace::properties::Property::Visibility; + Visibility visibilityFilter = openspace::global::openSpaceEngine->visibility(); + return static_cast(std::count_if( props.begin(), props.end(), - [visibility](openspace::properties::Property* p) { + [visibilityFilter](openspace::properties::Property* p) { using V = openspace::properties::Property::Visibility; - return static_cast>(visibility) >= + return static_cast>(visibilityFilter) >= static_cast>(p->visibility()); } )); @@ -187,11 +191,9 @@ GuiPropertyComponent::GuiPropertyComponent(std::string identifier, std::string g : GuiComponent(std::move(identifier), std::move(guiName)) , _useTreeLayout(UseTreeInfo, useTree) , _treeOrdering(OrderingInfo) - , _ignoreHiddenHint(IgnoreHiddenInfo) { addProperty(_useTreeLayout); addProperty(_treeOrdering); - addProperty(_ignoreHiddenHint); } void GuiPropertyComponent::setPropertyOwners( @@ -206,10 +208,6 @@ void GuiPropertyComponent::setPropertyOwnerFunction( _propertyOwnerFunction = std::move(func); } -void GuiPropertyComponent::setVisibility(properties::Property::Visibility visibility) { - _visibility = visibility; -} - void GuiPropertyComponent::renderPropertyOwner(properties::PropertyOwner* owner) { using namespace properties; @@ -217,12 +215,12 @@ void GuiPropertyComponent::renderPropertyOwner(properties::PropertyOwner* owner) return; } - const int nThisProperty = nVisibleProperties(owner->properties(), _visibility); + const int nThisProperty = nVisibleProperties(owner->properties()); ImGui::PushID(owner->identifier().c_str()); const std::vector& subOwners = owner->propertySubOwners(); for (PropertyOwner* subOwner : subOwners) { const std::vector& properties = subOwner->propertiesRecursive(); - int count = nVisibleProperties(properties, _visibility); + int count = nVisibleProperties(properties); if (count == 0) { continue; } @@ -286,6 +284,7 @@ void GuiPropertyComponent::render() { ImGui::SetNextWindowBgAlpha(0.75f); ImGui::Begin(guiName().c_str(), &v); _isEnabled = v; + bool showHiddenNode = openspace::global::openSpaceEngine->showHiddenSceneGraphNodes(); _isCollapsed = ImGui::IsWindowCollapsed(); using namespace properties; @@ -373,12 +372,14 @@ void GuiPropertyComponent::render() { dynamic_cast(*owners.begin())->guiPath().empty()); auto renderProp = [&](properties::PropertyOwner* pOwner) { - const int count = nVisibleProperties(pOwner->propertiesRecursive(), _visibility); + const int count = nVisibleProperties(pOwner->propertiesRecursive()); if (count == 0) { return; } + + auto header = [&]() -> bool { if (owners.size() > 1) { // Create a header in case we have multiple owners @@ -402,7 +403,7 @@ void GuiPropertyComponent::render() { }; if (!_useTreeLayout || noGuiGroups) { - if (!_ignoreHiddenHint) { + if (!showHiddenNode) { // Remove all of the nodes that we want hidden first owners.erase( std::remove_if( @@ -424,7 +425,7 @@ void GuiPropertyComponent::render() { for (properties::PropertyOwner* pOwner : owners) { // We checked above that pOwner is a SceneGraphNode SceneGraphNode* nOwner = static_cast(pOwner); - if (!_ignoreHiddenHint && nOwner->hasGuiHintHidden()) { + if (!showHiddenNode && nOwner->hasGuiHintHidden()) { continue; } const std::string gui = nOwner->guiPath(); @@ -491,7 +492,9 @@ void GuiPropertyComponent::renderProperty(properties::Property* prop, // Check if the visibility of the property is high enough to be displayed using V = properties::Property::Visibility; - const auto v = static_cast>(_visibility); + using Visibility = openspace::properties::Property::Visibility; + Visibility visibilityFilter = openspace::global::openSpaceEngine->visibility(); + const auto v = static_cast>(visibilityFilter); const auto propV = static_cast>(prop->visibility()); if (v >= propV) { auto it = FunctionMapping.find(prop->className()); diff --git a/modules/iswa/rendering/dataplane.cpp b/modules/iswa/rendering/dataplane.cpp index fdabcae90f..6f2120092c 100644 --- a/modules/iswa/rendering/dataplane.cpp +++ b/modules/iswa/rendering/dataplane.cpp @@ -63,7 +63,7 @@ void DataPlane::initializeGL() { // else if autofilter is turned off, register backgroundValues } else { - _backgroundValues.setVisibility(properties::Property::Visibility::All); + _backgroundValues.setVisibility(properties::Property::Visibility::Always); } }); } diff --git a/modules/iswa/rendering/datasphere.cpp b/modules/iswa/rendering/datasphere.cpp index 7fadb45dcb..82aa3a96cf 100644 --- a/modules/iswa/rendering/datasphere.cpp +++ b/modules/iswa/rendering/datasphere.cpp @@ -74,7 +74,7 @@ void DataSphere::initializeGL() { // else if autofilter is turned off, register backgroundValues } else { - _backgroundValues.setVisibility(properties::Property::Visibility::All); + _backgroundValues.setVisibility(properties::Property::Visibility::Always); //_backgroundValues.setVisible(true); } }); diff --git a/modules/iswa/rendering/iswadatagroup.cpp b/modules/iswa/rendering/iswadatagroup.cpp index 846b62531b..191f2491bc 100644 --- a/modules/iswa/rendering/iswadatagroup.cpp +++ b/modules/iswa/rendering/iswadatagroup.cpp @@ -134,7 +134,7 @@ void IswaDataGroup::registerProperties() { // else if autofilter is turned off, register backgroundValues } else { - _backgroundValues.setVisibility(properties::Property::Visibility::All); + _backgroundValues.setVisibility(properties::Property::Visibility::Always); //_backgroundValues.setVisible(true); } ghoul::Dictionary d; diff --git a/modules/iswa/rendering/kameleonplane.cpp b/modules/iswa/rendering/kameleonplane.cpp index 3763103b3c..2e60c7276e 100644 --- a/modules/iswa/rendering/kameleonplane.cpp +++ b/modules/iswa/rendering/kameleonplane.cpp @@ -151,7 +151,7 @@ void KameleonPlane::initializeGL() { // else if autofilter is turned off, register backgroundValues } else { - _backgroundValues.setVisibility(properties::Property::Visibility::All); + _backgroundValues.setVisibility(properties::Property::Visibility::Always); //_backgroundValues.setVisible(true); } }); diff --git a/modules/skybrowser/skybrowsermodule.cpp b/modules/skybrowser/skybrowsermodule.cpp index b180dbc125..e5028c0f72 100644 --- a/modules/skybrowser/skybrowsermodule.cpp +++ b/modules/skybrowser/skybrowsermodule.cpp @@ -300,6 +300,9 @@ void SkyBrowserModule::lookAtTarget(const std::string& id) { void SkyBrowserModule::setHoverCircle(SceneGraphNode* circle) { _hoverCircle = circle; + + // Always disable it per default. It should only be visible on interaction + disableHoverCircle(); } void SkyBrowserModule::moveHoverCircle(int i, bool useScript) { diff --git a/modules/skybrowser/skybrowsermodule_lua.inl b/modules/skybrowser/skybrowsermodule_lua.inl index b87b96712c..016d8fb905 100644 --- a/modules/skybrowser/skybrowsermodule_lua.inl +++ b/modules/skybrowser/skybrowsermodule_lua.inl @@ -87,6 +87,12 @@ namespace { using namespace openspace; SceneGraphNode* circle = global::renderEngine->scene()->sceneGraphNode(identifier); + if (!circle) { + throw ghoul::lua::LuaError(fmt::format( + "Could not find node to set as hover circle: '{}'", identifier + )); + } + global::moduleEngine->module()->setHoverCircle(circle); } @@ -435,6 +441,7 @@ namespace { "Name = '" + nameBrowser + "'," "Url = '" + url + "'," "FaceCamera = false," + "Gamma = 2.2," "CartesianPosition = " + ghoul::to_string(positionBrowser) + "}"; diff --git a/modules/space/horizonsfile.cpp b/modules/space/horizonsfile.cpp index 03e5841274..4f6edf0521 100644 --- a/modules/space/horizonsfile.cpp +++ b/modules/space/horizonsfile.cpp @@ -24,6 +24,7 @@ #include +#include #include #include #include @@ -167,11 +168,53 @@ std::string constructHorizonsUrl(HorizonsType type, const std::string& target, return url; } +json sendHorizonsRequest(const std::string& url, std::filesystem::path filePath) { + // Set up HTTP request and download result + std::unique_ptr download = std::make_unique( + url, + filePath, + HttpFileDownload::Overwrite::Yes + ); + + HttpFileDownload* dl = download.get(); + dl->start(); + + bool failed = false; + dl->wait(); + if (!dl->hasSucceeded()) { + LERROR(fmt::format("Error downloading horizons file with URL {}", dl->url())); + failed = true; + } + + if (failed) { + dl->cancel(); + } + + return convertHorizonsDownloadToJson(filePath); +} + +nlohmann::json convertHorizonsDownloadToJson(std::filesystem::path filePath) { + // Read the entire file into a string + constexpr size_t readSize = std::size_t(4096); + std::ifstream stream = std::ifstream(filePath); + stream.exceptions(std::ios_base::badbit); + + std::string answer; + std::string buf = std::string(readSize, '\0'); + while (stream.read(buf.data(), readSize)) { + answer.append(buf, 0, stream.gcount()); + } + answer.append(buf, 0, stream.gcount()); + + // convert to a json object + return json::parse(answer); +} + HorizonsResultCode isValidHorizonsAnswer(const json& answer) { // Signature, source and version - if (auto signature = answer.find("signature"); signature != answer.end()) { + if (auto signature = answer.find("signature"); signature != answer.end()) { - if (auto source = signature->find("source"); source != signature->end()) { + if (auto source = signature->find("source"); source != signature->end()) { if (*source != static_cast(ApiSource)) { LWARNING(fmt::format("Horizons answer from unkown source '{}'", *source)); } @@ -180,7 +223,7 @@ HorizonsResultCode isValidHorizonsAnswer(const json& answer) { LWARNING("Could not find source information, source might not be acceptable"); } - if (auto version = signature->find("version"); version != signature->end()) { + if (auto version = signature->find("version"); version != signature->end()) { if (*version != static_cast(CurrentVersion)) { LWARNING(fmt::format( "Unknown Horizons version '{}' found. The currently supported " diff --git a/modules/space/horizonsfile.h b/modules/space/horizonsfile.h index 8995eb779b..0129cd0862 100644 --- a/modules/space/horizonsfile.h +++ b/modules/space/horizonsfile.h @@ -127,6 +127,8 @@ std::string constructHorizonsUrl(HorizonsType type, const std::string& target, const std::string& observer, const std::string& startTime, const std::string& stopTime, const std::string& stepSize, const std::string& unit); +nlohmann::json sendHorizonsRequest(const std::string& url, std::filesystem::path filePath); +nlohmann::json convertHorizonsDownloadToJson(std::filesystem::path filePath); HorizonsResultCode isValidHorizonsAnswer(const nlohmann::json& answer); HorizonsResultCode isValidHorizonsFile(std::filesystem::path file); HorizonsResult readHorizonsFile(std::filesystem::path file); diff --git a/modules/touch/include/tuioear.h b/modules/touch/include/tuioear.h index dbf77292bc..aed2f9f663 100644 --- a/modules/touch/include/tuioear.h +++ b/modules/touch/include/tuioear.h @@ -25,26 +25,22 @@ #ifndef __OPENSPACE_MODULE_TOUCH___TUIO_EAR___H__ #define __OPENSPACE_MODULE_TOUCH___TUIO_EAR___H__ -// -Wold-style-cast -#if (defined(__GNUC__) && !defined(__clang__)) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wold-style-cast" -#endif // defined(__GNUC__) && !defined(__clang__) - #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wold-style-cast" -#endif // __clang__ +#elif defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" +#endif #include #include -#if (defined(__GNUC__) && !defined(__clang__)) -#pragma GCC diagnostic pop -#endif // defined(__GNUC__) && !defined(__clang__) #ifdef __clang__ #pragma clang diagnostic pop -#endif // __clang__ +#elif defined(__GNUC__) +#pragma GCC diagnostic pop +#endif #include #include diff --git a/scripts/developer_settings.lua b/scripts/developer_settings.lua new file mode 100644 index 0000000000..8957cd3911 --- /dev/null +++ b/scripts/developer_settings.lua @@ -0,0 +1,4 @@ +if os.getenv("OPENSPACE_DEVELOPER") +then + openspace.setPropertyValueSingle('OpenSpaceEngine.PropertyVisibility', 4) +end diff --git a/src/engine/globals.cpp b/src/engine/globals.cpp index 2589c92acf..f3d5b37ada 100644 --- a/src/engine/globals.cpp +++ b/src/engine/globals.cpp @@ -399,6 +399,7 @@ void initialize() { rootPropertyOwner->addPropertySubOwner(global::dashboard); rootPropertyOwner->addPropertySubOwner(global::userPropertyOwner); + rootPropertyOwner->addPropertySubOwner(global::openSpaceEngine); syncEngine->addSyncable(global::scriptEngine); } diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index 5a28ff9c05..a28ae88408 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -118,12 +118,25 @@ namespace { } } - openspace::properties::Property::PropertyInfo PrintEventsInfo = { + constexpr openspace::properties::Property::PropertyInfo PrintEventsInfo = { "PrintEvents", "Print Events", "If this is enabled, all events that are propagated through the system are " "printed to the log." }; + + constexpr openspace::properties::Property::PropertyInfo VisibilityInfo = { + "PropertyVisibility", + "Property Visibility", + "Hides or displays different settings in the GUI depending on how advanced they " + "are." + }; + + constexpr openspace::properties::Property::PropertyInfo ShowHiddenSceneInfo = { + "ShowHiddenSceneGraphNodes", + "Show Hidden Scene Graph Nodes", + "If checked, hidden scene graph nodes are visible in the UI" + }; } // namespace namespace openspace { @@ -131,7 +144,10 @@ namespace openspace { class Scene; OpenSpaceEngine::OpenSpaceEngine() - : _printEvents(PrintEventsInfo, false) + : properties::PropertyOwner({ "OpenSpaceEngine" }) + , _printEvents(PrintEventsInfo, false) + , _visibility(VisibilityInfo) + , _showHiddenSceneGraphNodes(ShowHiddenSceneInfo, false) { FactoryManager::initialize(); FactoryManager::ref().addFactory("Renderable"); @@ -146,6 +162,19 @@ OpenSpaceEngine::OpenSpaceEngine() SpiceManager::initialize(); TransformationManager::initialize(); + + addProperty(_printEvents); + addProperty(_visibility); + addProperty(_showHiddenSceneGraphNodes); + + using Visibility = openspace::properties::Property::Visibility; + _visibility.addOptions({ + { static_cast(Visibility::NoviceUser), "Novice User" }, + { static_cast(Visibility::User), "User" }, + { static_cast(Visibility::AdvancedUser), "Advanced User" }, + { static_cast(Visibility::Developer), "Developer" }, + { static_cast(Visibility::Hidden), "Everything" }, + }); } OpenSpaceEngine::~OpenSpaceEngine() {} // NOLINT @@ -1192,6 +1221,8 @@ void OpenSpaceEngine::preSynchronization() { if (_isRenderingFirstFrame) { setCameraFromProfile(*global::profile); setAdditionalScriptsFromProfile(*global::profile); + + global::scriptEngine->runScriptFile(absPath("${SCRIPTS}/developer_settings.lua")); } // Handle callback(s) for change in engine mode @@ -1582,6 +1613,14 @@ void OpenSpaceEngine::decode(std::vector data) { global::syncEngine->decodeSyncables(std::move(data)); } +properties::Property::Visibility openspace::OpenSpaceEngine::visibility() const { + return static_cast(_visibility.value()); +} + +bool openspace::OpenSpaceEngine::showHiddenSceneGraphNodes() const { + return _showHiddenSceneGraphNodes; +} + void OpenSpaceEngine::toggleShutdownMode() { if (_shutdown.inShutdown) { // If we are already in shutdown mode, we want to disable it @@ -1676,8 +1715,11 @@ void setCameraFromProfile(const Profile& p) { if (navStateProfile.aim.has_value()) { nav.aim = navStateProfile.aim.value(); } - if (nav.referenceFrame.empty()) { - nav.referenceFrame = "Root"; + if (navStateProfile.referenceFrame.empty()) { + nav.referenceFrame = nav.anchor; + } + else { + nav.referenceFrame = navStateProfile.referenceFrame; } nav.position = navStateProfile.position; if (navStateProfile.up.has_value()) { @@ -1815,7 +1857,8 @@ scripting::LuaLibrary OpenSpaceEngine::luaLibrary() { codegen::lua::RemoveTag, codegen::lua::DownloadFile, codegen::lua::CreateSingleColorImage, - codegen::lua::IsMaster + codegen::lua::IsMaster, + codegen::lua::Version }, { absPath("${SCRIPTS}/core_scripts.lua") diff --git a/src/engine/openspaceengine_lua.inl b/src/engine/openspaceengine_lua.inl index 61ccabcedb..d7f028ba22 100644 --- a/src/engine/openspaceengine_lua.inl +++ b/src/engine/openspaceengine_lua.inl @@ -22,6 +22,8 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ +#include + namespace { /** @@ -170,8 +172,6 @@ namespace { } } -namespace { - /** * Returns whether the current OpenSpace instance is the master node of a cluster * configuration. If this instance is not part of a cluster, this function also returns @@ -181,6 +181,30 @@ namespace { return openspace::global::windowDelegate->isMaster(); } -#include "openspaceengine_lua_codegen.cpp" +/** + * This function returns information about the current OpenSpace version. The resulting + * table has the structure: + * Version = { + * Major = + * Minor = + * Patch = + * }, + * Commit = + * Branch = + */ +[[codegen::luawrap]] ghoul::Dictionary version() { + ghoul::Dictionary res; -} // namespace + ghoul::Dictionary version; + version.setValue("Major", openspace::OPENSPACE_VERSION_MAJOR); + version.setValue("Minor", openspace::OPENSPACE_VERSION_MINOR); + version.setValue("Patch", openspace::OPENSPACE_VERSION_PATCH); + res.setValue("Version", std::move(version)); + + res.setValue("Commit", std::string(openspace::OPENSPACE_GIT_COMMIT)); + res.setValue("Branch", std::string(openspace::OPENSPACE_GIT_BRANCH)); + + return res; +} + +#include "openspaceengine_lua_codegen.cpp" diff --git a/src/navigation/navigationstate.cpp b/src/navigation/navigationstate.cpp index 09df8caa83..a8ef321bae 100644 --- a/src/navigation/navigationstate.cpp +++ b/src/navigation/navigationstate.cpp @@ -106,8 +106,8 @@ CameraPose NavigationState::cameraPose() const { if (!referenceFrameNode) { LERROR(fmt::format( "Could not find scene graph node '{}' used as reference frame.", - referenceFrame) - ); + referenceFrame + )); return CameraPose(); } diff --git a/src/properties/optionproperty.cpp b/src/properties/optionproperty.cpp index 1c04f60191..41fb74aeb6 100644 --- a/src/properties/optionproperty.cpp +++ b/src/properties/optionproperty.cpp @@ -72,6 +72,8 @@ void OptionProperty::addOption(int value, std::string desc) { } } _options.push_back(std::move(option)); + // Set default value to option added first + NumericalProperty::setValue(_options[0].value); } void OptionProperty::addOptions(std::vector> options) { @@ -100,7 +102,7 @@ void OptionProperty::setValue(int value) { // @TODO(abock): This should be setValue(value) instead or otherwise the // stored indices and option values start to drift if the // operator T of the OptionProperty is used - NumericalProperty::setValue(static_cast(i)); + NumericalProperty::setValue(static_cast(value)); return; } } @@ -110,12 +112,26 @@ void OptionProperty::setValue(int value) { } bool OptionProperty::hasOption() const { - return value() >= 0 && value() < static_cast(_options.size()); + auto it = std::find_if( + _options.begin(), + _options.end(), + [setValue = value()](const Option& option) { + return option.value == setValue; + } + ); + return it !=_options.end(); } const OptionProperty::Option& OptionProperty::option() const { - return _options[value()]; + auto it = std::find_if( + _options.begin(), + _options.end(), + [setValue = value()](const Option& option) { + return option.value == setValue; + } + ); + return *it; } std::string OptionProperty::getDescriptionByValue(int value) { diff --git a/src/properties/property.cpp b/src/properties/property.cpp index cc6adf7b3d..573666e9ef 100644 --- a/src/properties/property.cpp +++ b/src/properties/property.cpp @@ -339,9 +339,11 @@ std::string Property::generateBaseJsonDescription() const { std::string Property::generateMetaDataJsonDescription() const { static const std::map VisibilityConverter = { - { Visibility::All, "All" }, - { Visibility::Developer, "Developer" }, + { Visibility::Always, "Always" }, + { Visibility::NoviceUser, "NoviceUser" }, { Visibility::User, "User" }, + { Visibility::AdvancedUser, "AdvancedUser" }, + { Visibility::Developer, "Developer" }, { Visibility::Hidden, "Hidden" } }; Visibility visibility = static_cast( diff --git a/src/rendering/screenspacerenderable.cpp b/src/rendering/screenspacerenderable.cpp index 8fd9c41723..5c8c356e3c 100644 --- a/src/rendering/screenspacerenderable.cpp +++ b/src/rendering/screenspacerenderable.cpp @@ -42,8 +42,8 @@ #include namespace { - constexpr const std::array UniformNames = { - "color", "opacity", "mvpMatrix", "tex", "backgroundColor" + constexpr const std::array UniformNames = { + "color", "opacity", "mvpMatrix", "tex", "backgroundColor", "gamma" }; constexpr openspace::properties::Property::PropertyInfo EnabledInfo = { @@ -150,6 +150,12 @@ namespace { "the camera." }; + constexpr openspace::properties::Property::PropertyInfo GammaInfo = { + "Gamma", + "Gamma Correction", + "Sets the gamma correction of the texture." + }; + float wrap(float value, float min, float max) { return glm::mod(value - min, max - min) + min; } @@ -184,12 +190,15 @@ namespace { // [[codegen::verbatim(CartesianPositionInfo.description)]] std::optional cartesianPosition; - // [[codegen::verbatim(RadiusAzimuthElevationInfo.description)]] + // [[codegen::verbatim(GammaInfo.description)]] std::optional radiusAzimuthElevation; // [[codegen::verbatim(ScaleInfo.description)]] std::optional scale; + // [[codegen::verbatim(UseRadiusAzimuthElevationInfo.description)]] + std::optional gamma; + // [[codegen::verbatim(UsePerspectiveProjectionInfo.description)]] std::optional usePerspectiveProjection; @@ -286,6 +295,7 @@ ScreenSpaceRenderable::ScreenSpaceRenderable(const ghoul::Dictionary& dictionary , _opacity(OpacityInfo, 1.f, 0.f, 1.f) , _fade(FadeInfo, 1.f, 0.f, 1.f) , _delete(DeleteInfo) + , _gamma(GammaInfo, 1.f, 0.000001f, 10.f) { const Parameters p = codegen::bake(dictionary); @@ -303,6 +313,7 @@ ScreenSpaceRenderable::ScreenSpaceRenderable(const ghoul::Dictionary& dictionary addProperty(_faceCamera); addProperty(_cartesianPosition); addProperty(_raePosition); + addProperty(_gamma); // Setting spherical/euclidean onchange handler _useRadiusAzimuthElevation.onChange([this]() { @@ -329,6 +340,8 @@ ScreenSpaceRenderable::ScreenSpaceRenderable(const ghoul::Dictionary& dictionary _backgroundColor.setViewOption(properties::Property::ViewOptions::Color); _enabled = p.enabled.value_or(_enabled); + _gamma = p.gamma.value_or(_gamma); + _useRadiusAzimuthElevation = p.useRadiusAzimuthElevation.value_or(_useRadiusAzimuthElevation); @@ -591,7 +604,7 @@ void ScreenSpaceRenderable::draw(glm::mat4 modelTransform) { _shader->setUniform(_uniformCache.color, _multiplyColor); _shader->setUniform(_uniformCache.opacity, opacity()); _shader->setUniform(_uniformCache.backgroundColor, _backgroundColor); - + _shader->setUniform(_uniformCache.gamma, _gamma); _shader->setUniform( _uniformCache.mvp, global::renderEngine->scene()->camera()->viewProjectionMatrix() * modelTransform diff --git a/support/coding/codegen b/support/coding/codegen index e1923b7ac7..ae8d21e9aa 160000 --- a/support/coding/codegen +++ b/support/coding/codegen @@ -1 +1 @@ -Subproject commit e1923b7ac70d7393483634ef7e2951ff2625f2de +Subproject commit ae8d21e9aa2903c6b13060239ffbb675e92e6a51 diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a067441411..d0076eefbf 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -30,6 +30,7 @@ add_executable( test_distanceconversion.cpp test_configuration.cpp test_documentation.cpp + test_horizons.cpp test_iswamanager.cpp test_jsonformatting.cpp test_latlonpatch.cpp diff --git a/tests/horizonsTest/naif0012.tls b/tests/horizonsTest/naif0012.tls new file mode 100644 index 0000000000..e1afdee1b6 --- /dev/null +++ b/tests/horizonsTest/naif0012.tls @@ -0,0 +1,152 @@ +KPL/LSK + + +LEAPSECONDS KERNEL FILE +=========================================================================== + +Modifications: +-------------- + +2016, Jul. 14 NJB Modified file to account for the leapsecond that + will occur on December 31, 2016. + +2015, Jan. 5 NJB Modified file to account for the leapsecond that + will occur on June 30, 2015. + +2012, Jan. 5 NJB Modified file to account for the leapsecond that + will occur on June 30, 2012. + +2008, Jul. 7 NJB Modified file to account for the leapsecond that + will occur on December 31, 2008. + +2005, Aug. 3 NJB Modified file to account for the leapsecond that + will occur on December 31, 2005. + +1998, Jul 17 WLT Modified file to account for the leapsecond that + will occur on December 31, 1998. + +1997, Feb 22 WLT Modified file to account for the leapsecond that + will occur on June 30, 1997. + +1995, Dec 14 KSZ Corrected date of last leapsecond from 1-1-95 + to 1-1-96. + +1995, Oct 25 WLT Modified file to account for the leapsecond that + will occur on Dec 31, 1995. + +1994, Jun 16 WLT Modified file to account for the leapsecond on + June 30, 1994. + +1993, Feb. 22 CHA Modified file to account for the leapsecond on + June 30, 1993. + +1992, Mar. 6 HAN Modified file to account for the leapsecond on + June 30, 1992. + +1990, Oct. 8 HAN Modified file to account for the leapsecond on + Dec. 31, 1990. + + +Explanation: +------------ + +The contents of this file are used by the routine DELTET to compute the +time difference + +[1] DELTA_ET = ET - UTC + +the increment to be applied to UTC to give ET. + +The difference between UTC and TAI, + +[2] DELTA_AT = TAI - UTC + +is always an integral number of seconds. The value of DELTA_AT was 10 +seconds in January 1972, and increases by one each time a leap second +is declared. Combining [1] and [2] gives + +[3] DELTA_ET = ET - (TAI - DELTA_AT) + + = (ET - TAI) + DELTA_AT + +The difference (ET - TAI) is periodic, and is given by + +[4] ET - TAI = DELTA_T_A + K sin E + +where DELTA_T_A and K are constant, and E is the eccentric anomaly of the +heliocentric orbit of the Earth-Moon barycenter. Equation [4], which ignores +small-period fluctuations, is accurate to about 0.000030 seconds. + +The eccentric anomaly E is given by + +[5] E = M + EB sin M + +where M is the mean anomaly, which in turn is given by + +[6] M = M + M t + 0 1 + +where t is the number of ephemeris seconds past J2000. + +Thus, in order to compute DELTA_ET, the following items are necessary. + + DELTA_TA + K + EB + M0 + M1 + DELTA_AT after each leap second. + +The numbers, and the formulation, are taken from the following sources. + + 1) Moyer, T.D., Transformation from Proper Time on Earth to + Coordinate Time in Solar System Barycentric Space-Time Frame + of Reference, Parts 1 and 2, Celestial Mechanics 23 (1981), + 33-56 and 57-68. + + 2) Moyer, T.D., Effects of Conversion to the J2000 Astronomical + Reference System on Algorithms for Computing Time Differences + and Clock Rates, JPL IOM 314.5--942, 1 October 1985. + +The variable names used above are consistent with those used in the +Astronomical Almanac. + +\begindata + +DELTET/DELTA_T_A = 32.184 +DELTET/K = 1.657D-3 +DELTET/EB = 1.671D-2 +DELTET/M = ( 6.239996D0 1.99096871D-7 ) + +DELTET/DELTA_AT = ( 10, @1972-JAN-1 + 11, @1972-JUL-1 + 12, @1973-JAN-1 + 13, @1974-JAN-1 + 14, @1975-JAN-1 + 15, @1976-JAN-1 + 16, @1977-JAN-1 + 17, @1978-JAN-1 + 18, @1979-JAN-1 + 19, @1980-JAN-1 + 20, @1981-JUL-1 + 21, @1982-JUL-1 + 22, @1983-JUL-1 + 23, @1985-JUL-1 + 24, @1988-JAN-1 + 25, @1990-JAN-1 + 26, @1991-JAN-1 + 27, @1992-JUL-1 + 28, @1993-JUL-1 + 29, @1994-JUL-1 + 30, @1996-JAN-1 + 31, @1997-JUL-1 + 32, @1999-JAN-1 + 33, @2006-JAN-1 + 34, @2009-JAN-1 + 35, @2012-JUL-1 + 36, @2015-JUL-1 + 37, @2017-JAN-1 ) + +\begintext + + diff --git a/tests/horizonsTest/observerFileTest.hrz b/tests/horizonsTest/observerFileTest.hrz new file mode 100644 index 0000000000..fc0bbe7e64 --- /dev/null +++ b/tests/horizonsTest/observerFileTest.hrz @@ -0,0 +1,231 @@ +******************************************************************************* + Revised: Mar 27, 2018 Tesla Roadster (spacecraft) -143205 + (solution #10) + + Tesla Roadster (AKA: Starman, 2018-017A) + + NOTE: + + Visibility: + 20th magnitude until Feb 20, + 22nd magnitude through mid-April + Brighter than 26th magnitude into mid-June + + 2018-Mar-01: Radial non-gravitational acceleration A1 estimated from data + (nominally solar radiation pressure) + 2018-Mar-27: Two reporting sites (J04 & K93) extend data arc one month. + A1 estimate of s10 is reduced 1.2-sigma compared to s9. + + LAUNCHED: + 2018-Feb-06 20:45 UTC by Falcon Heavy (FH-1) from Kennedy Space Center, USA + (launchpad 39A) + + BACKGROUND: + Dummy payload from the first launch of SpaceX Falcon Heavy launch vehicle. + Consists of a standard Tesla Roadster automobile and a spacesuit-wearing + mannequin nicknamed "Starman". + + Also includes a Hot Wheels toy model Roadster on the car's dash with a + mini-Starman inside. A data storage device placed inside the car contains + a copy of Isaac Asimov's "Foundation" novels. A plaque on the attachment + fitting between the Falcon Heavy upper stage and the Tesla is etched with + the names of more than 6,000 SpaceX employees. + + After orbiting the Earth for 5 hours, a third burn by the second stage was + completed at approximately 02:30 UTC Feb 7, placing the dummy payload in a + heliocentric orbit having a perihelion of 0.99 au and aphelion ~1.67 au. + + The object stack consists of a Merlin 1D Vacuum second stage with Extended + Nozzle, Payload Attachment Fitting, and Tesla Roadster on mount. + + Roadster mass: ~1250 kg (with batteries), ~800 kg (without ESS/batteries) + + TRAJECTORY: + This trajectory is based on JPL solution #10, a fit to 364 ground-based + optical astrometric measurements spanning 2018 Feb 8.2 to March 19.1 + + Trajectory name Start (TDB) Stop (TDB) + -------------------------------- ----------------- ----------------- + tesla_s10 2018-Feb-07 03:00 2090-Jan-01 00:00 + + Encounter predictions for s10 (w/radial 1/r^2 non-gravitational acceleration) + + Date (TDB) Body CA Dist MinDist MaxDist Vrel TCA3Sg Nsigs P_i/p + ----------------- ----- ------- ------- ------- ------ ------ ------ ------ + 2018 Feb 08.09690 Moon .000936 .000936 .000936 3.961 0.41 47509. 0.000 + 2020 Oct 07.26768 Mars .049530 .048923 .050242 8.150 27.40 6.63E5 0.000 + 2035 Apr 22.35934 Mars .015504 .004378 .027978 8.219 170.47 31247. 0.000 + 2047 Jan 11.89023 Earth .031919 .031716 .032123 4.493 249.70 78398. 0.000 + 2050 Mar 19.52949 Earth .119113 .113778 .124369 7.397 538.54 2.61E5 0.000 + 2052 Sep 05.15606 Mars .176363 .172469 .180319 5.738 2185.5 8.68E5 0.000 + 2067 Apr 15.90202 Mars .043270 .025712 .061471 7.192 1115.0 42565. 0.000 + 2084 Sep 17.92284 Mars .116962 .093449 .141170 9.753 787.45 6.55E5 0.000 + 2085 Jan 01.96490 Earth .083063 .049368 .112186 6.224 5208.9 1.00E5 0.000 + 2088 Mar 09.95754 Earth .049146 .033491 .063322 5.106 4505.2 1.17E5 0.000 + + Date = Nominal encounter time (Barycentric Dynamical Time) + CA_Dist = Highest probability close approach distance to body, au + MinDist = 3-sigma minimum encounter distance, au + MaxDist = 3-sigma maximum encounter distance, au + Vrel = Relative velocity at nominal encounter time, km/s + TCA3Sg = 3-sigma uncertainty in close encounter time, minutes + Nsigs = Number of sigmas to encounter body at nominal encounter time + P_i/p = Linearized probability of impact + + NOTE: + How to obtain optional statistical uncertainty output & generate an SPK file: + + Since this is a spacecraft and not part of the asteroid and comet database + which normally holds orbit covariance data, some functions like statistical + output and SPK file generation aren't automatically available for this object. + + However, such optional extended output is possible with some extra steps. + + To propagate statistical uncertainties for this object, the full statistical + orbit solution (given below) can be manually input back into Horizons as a + "user-defined object" using the telnet or e-mail interfaces (not possible + with the browser interface). + + To do this and activate statistical or SPK file output ... + + Using the telnet interface (command-line "telnet ssd.jpl.nasa.gov 6775"), + enter ";" to drop into user-input mode then cut-and-paste each line shown + below, one at a time. The lines of numbers after SRC must be in the order + shown. + + For SPK file generation, only the first four lines need be input: the + EPOCH, orbital element lines starting with "EC" and "OM", and the + non-gravitational acceleration model (line starting with "A1"). + + SRC lines are needed only for (optional) statistical output and the + H & G values only for (optional) visual magnitude output. + + EPOCH= 2458164.5 + EC= .2585469914787243 QR= .9860596231806226 TP= 2458153.620483722645 + OM= 317.3549094214575 W = 177.3203028023227 IN= 1.088451292866039 + EST=A1 A1= 2.960683526738534E-9 R0= 1. ALN= 1. NM= 2. NK= 0. + SRC= -2.057839421666802E-7 7.966781900129693E-9 -1.720426606925749E-9 + -4.722542923190676E-7 2.197679131968537E-9 -1.230413802372471E-6 + -2.500290306870021E-7 -3.361070889248183E-9 -1.765963020682463E-5 + -3.047907547965759E-7 -4.640202045440381E-7 -4.271481116360573E-9 + 2.657789409005983E-5 1.726818074599357E-6 -1.359673746135991E-6 + -2.478836748687631E-5 -2.309863204867099E-8 -.0002351644867403515 + -1.875169281895894E-6 -2.063647245529267E-6 -1.670539551586607E-6 + -4.019207817588603E-6 -3.128134469402375E-9 -3.034540373576942E-5 + 1.733661692209129E-7 -7.052327854535979E-7 -2.650181216776434E-7 + -1.310976135791957E-10 + H= 25.289 G= 0.15 + + When done, press a blank return to exit input mode. + + Enter "J" at the prompt to indicate heliocentric J2000 ecliptic data has + been supplied. Then at the next prompt, input an arbitrary name + (i.e., Roadster). + + Horizons will then proceed as usual, but with statistical output and SPK + file generation now available as options. + + A basic and identical tracking ephemeris can be produced without doing any + of this, but statistical uncertainty quantities requested will be marked + "n.a.", meaning not available, and SPK generation won't be an option. + + NOTE: long-term predictions + Over time, trajectory prediction errors could increase more rapidly than + the formal statistics indicate due to unmodeled thermal re-radiation or + outgassing accelerations that are not currently characterized but may exist. +******************************************************************************* + + +******************************************************************************* +Ephemeris / API_USER Mon May 23 04:45:58 2022 Pasadena, USA / Horizons +******************************************************************************* +Target body name: SpaceX Roadster (spacecraft) (-143205) {source: tesla_s10} +Center body name: Solar System Barycenter (0) {source: DE441} +Center-site name: BODYCENTRIC +******************************************************************************* +Start time : A.D. 2022-May-22 00:00:00.0000 UT +Stop time : A.D. 2022-May-23 00:00:00.0000 UT +Step-size : 720 minutes +******************************************************************************* +Target pole/equ : No model available +Target radii : (unavailable) +Center geodetic : 0.00000000,0.00000000,0.0000000 {E-lon(deg),Lat(deg),Alt(km)} +Center cylindric: 0.00000000,0.00000000,0.0000000 {E-lon(deg),Dxy(km),Dz(km)} +Center pole/equ : ICRF +Center radii : (undefined) +Target primary : Earth +Vis. interferer : None +Rel. light bend : Sun {source: DE441} +Rel. lght bnd GM: 1.3271E+11 km^3/s^2 +Atmos refraction: NO (AIRLESS) +RA format : HMS +Time format : CAL +EOP file : eop.220519.p220812 +EOP coverage : DATA-BASED 1962-JAN-20 TO 2022-MAY-19. PREDICTS-> 2022-AUG-11 +Units conversion: 1 au= 149597870.700 km, c= 299792.458 km/s, 1 day= 86400.0 s +Table cut-offs 1: Elevation (-90.0deg=NO ),Airmass n.a. , Daylight (NO ) +Table cut-offs 2: Solar elongation ( 0.0,180.0=NO ),Local Hour Angle( 0.0=NO ) +Table cut-offs 3: RA/DEC angular rate ( 0.0=NO ) +******************************************************************************* + Date__(UT)__HR:MN delta GlxLon GlxLat +************************************************************** +$$SOE + 2022-May-22 00:00 1.8974772217E+08 153.481630 -41.900757 + 2022-May-22 12:00 1.8945940676E+08 153.792612 -41.651777 + 2022-May-23 00:00 1.8917095486E+08 154.102144 -41.401193 +$$EOE +******************************************************************************* +Column meaning: + +TIME + + Times PRIOR to 1962 are UT1, a mean-solar time closely related to the +prior but now-deprecated GMT. Times AFTER 1962 are in UTC, the current +civil or "wall-clock" time-scale. UTC is kept within 0.9 seconds of UT1 +using integer leap-seconds for 1972 and later years. + + Conversion from the internal Barycentric Dynamical Time (TDB) of solar +system dynamics to the non-uniform civil UT time-scale requested for output +has not been determined for UTC times after the next July or January 1st. +Therefore, the last known leap-second is used as a constant over future +intervals. + + Time tags refer to the UT time-scale conversion from TDB on Earth +regardless of observer location within the solar system, although clock +rates may differ due to the local gravity field and no analog to "UT" +may be defined for that location. + + Any 'b' symbol in the 1st-column denotes a B.C. date. First-column blank +(" ") denotes an A.D. date. Calendar dates prior to 1582-Oct-15 are in the +Julian calendar system. Later calendar dates are in the Gregorian system. + + NOTE: "n.a." in output means quantity "not available" at the print-time. + + 'delta' = + Apparent range ("delta", light-time aberrated) of the target center relative +to the observer. Units: KM + + 'GlxLon GlxLat' = + Observer-centered Galactic System II (post WW II) longitude and latitude +of the target centers' apparent position, with light-time, gravitational +deflection of light, and stellar aberrations. Units: DEGREES + +Computations by ... + + Solar System Dynamics Group, Horizons On-Line Ephemeris System + 4800 Oak Grove Drive, Jet Propulsion Laboratory + Pasadena, CA 91109 USA + + General site: https://ssd.jpl.nasa.gov/ + Mailing list: https://ssd.jpl.nasa.gov/email_list.html + System news : https://ssd.jpl.nasa.gov/horizons/news.html + User Guide : https://ssd.jpl.nasa.gov/horizons/manual.html + Connect : browser https://ssd.jpl.nasa.gov/horizons/app.html#/x + API https://ssd-api.jpl.nasa.gov/doc/horizons.html + command-line telnet ssd.jpl.nasa.gov 6775 + e-mail/batch https://ssd.jpl.nasa.gov/ftp/ssd/hrzn_batch.txt + scripts https://ssd.jpl.nasa.gov/ftp/ssd/SCRIPTS + Author : Jon.D.Giorgini@jpl.nasa.gov + +******************************************************************************* + diff --git a/tests/horizonsTest/parse_multiple_observers.hrz b/tests/horizonsTest/parse_multiple_observers.hrz new file mode 100644 index 0000000000..c51de618b3 --- /dev/null +++ b/tests/horizonsTest/parse_multiple_observers.hrz @@ -0,0 +1,148 @@ +******************************************************************************* + Revised: Mar 27, 2018 Tesla Roadster (spacecraft) -143205 + (solution #10) + + Tesla Roadster (AKA: Starman, 2018-017A) + + NOTE: + + Visibility: + 20th magnitude until Feb 20, + 22nd magnitude through mid-April + Brighter than 26th magnitude into mid-June + + 2018-Mar-01: Radial non-gravitational acceleration A1 estimated from data + (nominally solar radiation pressure) + 2018-Mar-27: Two reporting sites (J04 & K93) extend data arc one month. + A1 estimate of s10 is reduced 1.2-sigma compared to s9. + + LAUNCHED: + 2018-Feb-06 20:45 UTC by Falcon Heavy (FH-1) from Kennedy Space Center, USA + (launchpad 39A) + + BACKGROUND: + Dummy payload from the first launch of SpaceX Falcon Heavy launch vehicle. + Consists of a standard Tesla Roadster automobile and a spacesuit-wearing + mannequin nicknamed "Starman". + + Also includes a Hot Wheels toy model Roadster on the car's dash with a + mini-Starman inside. A data storage device placed inside the car contains + a copy of Isaac Asimov's "Foundation" novels. A plaque on the attachment + fitting between the Falcon Heavy upper stage and the Tesla is etched with + the names of more than 6,000 SpaceX employees. + + After orbiting the Earth for 5 hours, a third burn by the second stage was + completed at approximately 02:30 UTC Feb 7, placing the dummy payload in a + heliocentric orbit having a perihelion of 0.99 au and aphelion ~1.67 au. + + The object stack consists of a Merlin 1D Vacuum second stage with Extended + Nozzle, Payload Attachment Fitting, and Tesla Roadster on mount. + + Roadster mass: ~1250 kg (with batteries), ~800 kg (without ESS/batteries) + + TRAJECTORY: + This trajectory is based on JPL solution #10, a fit to 364 ground-based + optical astrometric measurements spanning 2018 Feb 8.2 to March 19.1 + + Trajectory name Start (TDB) Stop (TDB) + -------------------------------- ----------------- ----------------- + tesla_s10 2018-Feb-07 03:00 2090-Jan-01 00:00 + + Encounter predictions for s10 (w/radial 1/r^2 non-gravitational acceleration) + + Date (TDB) Body CA Dist MinDist MaxDist Vrel TCA3Sg Nsigs P_i/p + ----------------- ----- ------- ------- ------- ------ ------ ------ ------ + 2018 Feb 08.09690 Moon .000936 .000936 .000936 3.961 0.41 47509. 0.000 + 2020 Oct 07.26768 Mars .049530 .048923 .050242 8.150 27.40 6.63E5 0.000 + 2035 Apr 22.35934 Mars .015504 .004378 .027978 8.219 170.47 31247. 0.000 + 2047 Jan 11.89023 Earth .031919 .031716 .032123 4.493 249.70 78398. 0.000 + 2050 Mar 19.52949 Earth .119113 .113778 .124369 7.397 538.54 2.61E5 0.000 + 2052 Sep 05.15606 Mars .176363 .172469 .180319 5.738 2185.5 8.68E5 0.000 + 2067 Apr 15.90202 Mars .043270 .025712 .061471 7.192 1115.0 42565. 0.000 + 2084 Sep 17.92284 Mars .116962 .093449 .141170 9.753 787.45 6.55E5 0.000 + 2085 Jan 01.96490 Earth .083063 .049368 .112186 6.224 5208.9 1.00E5 0.000 + 2088 Mar 09.95754 Earth .049146 .033491 .063322 5.106 4505.2 1.17E5 0.000 + + Date = Nominal encounter time (Barycentric Dynamical Time) + CA_Dist = Highest probability close approach distance to body, au + MinDist = 3-sigma minimum encounter distance, au + MaxDist = 3-sigma maximum encounter distance, au + Vrel = Relative velocity at nominal encounter time, km/s + TCA3Sg = 3-sigma uncertainty in close encounter time, minutes + Nsigs = Number of sigmas to encounter body at nominal encounter time + P_i/p = Linearized probability of impact + + NOTE: + How to obtain optional statistical uncertainty output & generate an SPK file: + + Since this is a spacecraft and not part of the asteroid and comet database + which normally holds orbit covariance data, some functions like statistical + output and SPK file generation aren't automatically available for this object. + + However, such optional extended output is possible with some extra steps. + + To propagate statistical uncertainties for this object, the full statistical + orbit solution (given below) can be manually input back into Horizons as a + "user-defined object" using the telnet or e-mail interfaces (not possible + with the browser interface). + + To do this and activate statistical or SPK file output ... + + Using the telnet interface (command-line "telnet ssd.jpl.nasa.gov 6775"), + enter ";" to drop into user-input mode then cut-and-paste each line shown + below, one at a time. The lines of numbers after SRC must be in the order + shown. + + For SPK file generation, only the first four lines need be input: the + EPOCH, orbital element lines starting with "EC" and "OM", and the + non-gravitational acceleration model (line starting with "A1"). + + SRC lines are needed only for (optional) statistical output and the + H & G values only for (optional) visual magnitude output. + + EPOCH= 2458164.5 + EC= .2585469914787243 QR= .9860596231806226 TP= 2458153.620483722645 + OM= 317.3549094214575 W = 177.3203028023227 IN= 1.088451292866039 + EST=A1 A1= 2.960683526738534E-9 R0= 1. ALN= 1. NM= 2. NK= 0. + SRC= -2.057839421666802E-7 7.966781900129693E-9 -1.720426606925749E-9 + -4.722542923190676E-7 2.197679131968537E-9 -1.230413802372471E-6 + -2.500290306870021E-7 -3.361070889248183E-9 -1.765963020682463E-5 + -3.047907547965759E-7 -4.640202045440381E-7 -4.271481116360573E-9 + 2.657789409005983E-5 1.726818074599357E-6 -1.359673746135991E-6 + -2.478836748687631E-5 -2.309863204867099E-8 -.0002351644867403515 + -1.875169281895894E-6 -2.063647245529267E-6 -1.670539551586607E-6 + -4.019207817588603E-6 -3.128134469402375E-9 -3.034540373576942E-5 + 1.733661692209129E-7 -7.052327854535979E-7 -2.650181216776434E-7 + -1.310976135791957E-10 + H= 25.289 G= 0.15 + + When done, press a blank return to exit input mode. + + Enter "J" at the prompt to indicate heliocentric J2000 ecliptic data has + been supplied. Then at the next prompt, input an arbitrary name + (i.e., Roadster). + + Horizons will then proceed as usual, but with statistical output and SPK + file generation now available as options. + + A basic and identical tracking ephemeris can be produced without doing any + of this, but statistical uncertainty quantities requested will be marked + "n.a.", meaning not available, and SPK generation won't be an option. + + NOTE: long-term predictions + Over time, trajectory prediction errors could increase more rapidly than + the formal statistics indicate due to unmodeled thermal re-radiation or + outgassing accelerations that are not currently characterized but may exist. +******************************************************************************* + +******************************************************************************* + Multiple major-bodies match string "EARTH*" + + ID# Name Designation IAU/aliases/other + ------- ---------------------------------- ----------- ------------------- + 3 Earth-Moon Barycenter EMB + 399 Earth Geocenter + + Number of matches = 2. Use ID# to make unique selection. +******************************************************************************* + diff --git a/tests/horizonsTest/parse_multiple_stations.hrz b/tests/horizonsTest/parse_multiple_stations.hrz new file mode 100644 index 0000000000..0b4220831a --- /dev/null +++ b/tests/horizonsTest/parse_multiple_stations.hrz @@ -0,0 +1,152 @@ +******************************************************************************* + Revised: Mar 27, 2018 Tesla Roadster (spacecraft) -143205 + (solution #10) + + Tesla Roadster (AKA: Starman, 2018-017A) + + NOTE: + + Visibility: + 20th magnitude until Feb 20, + 22nd magnitude through mid-April + Brighter than 26th magnitude into mid-June + + 2018-Mar-01: Radial non-gravitational acceleration A1 estimated from data + (nominally solar radiation pressure) + 2018-Mar-27: Two reporting sites (J04 & K93) extend data arc one month. + A1 estimate of s10 is reduced 1.2-sigma compared to s9. + + LAUNCHED: + 2018-Feb-06 20:45 UTC by Falcon Heavy (FH-1) from Kennedy Space Center, USA + (launchpad 39A) + + BACKGROUND: + Dummy payload from the first launch of SpaceX Falcon Heavy launch vehicle. + Consists of a standard Tesla Roadster automobile and a spacesuit-wearing + mannequin nicknamed "Starman". + + Also includes a Hot Wheels toy model Roadster on the car's dash with a + mini-Starman inside. A data storage device placed inside the car contains + a copy of Isaac Asimov's "Foundation" novels. A plaque on the attachment + fitting between the Falcon Heavy upper stage and the Tesla is etched with + the names of more than 6,000 SpaceX employees. + + After orbiting the Earth for 5 hours, a third burn by the second stage was + completed at approximately 02:30 UTC Feb 7, placing the dummy payload in a + heliocentric orbit having a perihelion of 0.99 au and aphelion ~1.67 au. + + The object stack consists of a Merlin 1D Vacuum second stage with Extended + Nozzle, Payload Attachment Fitting, and Tesla Roadster on mount. + + Roadster mass: ~1250 kg (with batteries), ~800 kg (without ESS/batteries) + + TRAJECTORY: + This trajectory is based on JPL solution #10, a fit to 364 ground-based + optical astrometric measurements spanning 2018 Feb 8.2 to March 19.1 + + Trajectory name Start (TDB) Stop (TDB) + -------------------------------- ----------------- ----------------- + tesla_s10 2018-Feb-07 03:00 2090-Jan-01 00:00 + + Encounter predictions for s10 (w/radial 1/r^2 non-gravitational acceleration) + + Date (TDB) Body CA Dist MinDist MaxDist Vrel TCA3Sg Nsigs P_i/p + ----------------- ----- ------- ------- ------- ------ ------ ------ ------ + 2018 Feb 08.09690 Moon .000936 .000936 .000936 3.961 0.41 47509. 0.000 + 2020 Oct 07.26768 Mars .049530 .048923 .050242 8.150 27.40 6.63E5 0.000 + 2035 Apr 22.35934 Mars .015504 .004378 .027978 8.219 170.47 31247. 0.000 + 2047 Jan 11.89023 Earth .031919 .031716 .032123 4.493 249.70 78398. 0.000 + 2050 Mar 19.52949 Earth .119113 .113778 .124369 7.397 538.54 2.61E5 0.000 + 2052 Sep 05.15606 Mars .176363 .172469 .180319 5.738 2185.5 8.68E5 0.000 + 2067 Apr 15.90202 Mars .043270 .025712 .061471 7.192 1115.0 42565. 0.000 + 2084 Sep 17.92284 Mars .116962 .093449 .141170 9.753 787.45 6.55E5 0.000 + 2085 Jan 01.96490 Earth .083063 .049368 .112186 6.224 5208.9 1.00E5 0.000 + 2088 Mar 09.95754 Earth .049146 .033491 .063322 5.106 4505.2 1.17E5 0.000 + + Date = Nominal encounter time (Barycentric Dynamical Time) + CA_Dist = Highest probability close approach distance to body, au + MinDist = 3-sigma minimum encounter distance, au + MaxDist = 3-sigma maximum encounter distance, au + Vrel = Relative velocity at nominal encounter time, km/s + TCA3Sg = 3-sigma uncertainty in close encounter time, minutes + Nsigs = Number of sigmas to encounter body at nominal encounter time + P_i/p = Linearized probability of impact + + NOTE: + How to obtain optional statistical uncertainty output & generate an SPK file: + + Since this is a spacecraft and not part of the asteroid and comet database + which normally holds orbit covariance data, some functions like statistical + output and SPK file generation aren't automatically available for this object. + + However, such optional extended output is possible with some extra steps. + + To propagate statistical uncertainties for this object, the full statistical + orbit solution (given below) can be manually input back into Horizons as a + "user-defined object" using the telnet or e-mail interfaces (not possible + with the browser interface). + + To do this and activate statistical or SPK file output ... + + Using the telnet interface (command-line "telnet ssd.jpl.nasa.gov 6775"), + enter ";" to drop into user-input mode then cut-and-paste each line shown + below, one at a time. The lines of numbers after SRC must be in the order + shown. + + For SPK file generation, only the first four lines need be input: the + EPOCH, orbital element lines starting with "EC" and "OM", and the + non-gravitational acceleration model (line starting with "A1"). + + SRC lines are needed only for (optional) statistical output and the + H & G values only for (optional) visual magnitude output. + + EPOCH= 2458164.5 + EC= .2585469914787243 QR= .9860596231806226 TP= 2458153.620483722645 + OM= 317.3549094214575 W = 177.3203028023227 IN= 1.088451292866039 + EST=A1 A1= 2.960683526738534E-9 R0= 1. ALN= 1. NM= 2. NK= 0. + SRC= -2.057839421666802E-7 7.966781900129693E-9 -1.720426606925749E-9 + -4.722542923190676E-7 2.197679131968537E-9 -1.230413802372471E-6 + -2.500290306870021E-7 -3.361070889248183E-9 -1.765963020682463E-5 + -3.047907547965759E-7 -4.640202045440381E-7 -4.271481116360573E-9 + 2.657789409005983E-5 1.726818074599357E-6 -1.359673746135991E-6 + -2.478836748687631E-5 -2.309863204867099E-8 -.0002351644867403515 + -1.875169281895894E-6 -2.063647245529267E-6 -1.670539551586607E-6 + -4.019207817588603E-6 -3.128134469402375E-9 -3.034540373576942E-5 + 1.733661692209129E-7 -7.052327854535979E-7 -2.650181216776434E-7 + -1.310976135791957E-10 + H= 25.289 G= 0.15 + + When done, press a blank return to exit input mode. + + Enter "J" at the prompt to indicate heliocentric J2000 ecliptic data has + been supplied. Then at the next prompt, input an arbitrary name + (i.e., Roadster). + + Horizons will then proceed as usual, but with statistical output and SPK + file generation now available as options. + + A basic and identical tracking ephemeris can be produced without doing any + of this, but statistical uncertainty quantities requested will be marked + "n.a.", meaning not available, and SPK generation won't be an option. + + NOTE: long-term predictions + Over time, trajectory prediction errors could increase more rapidly than + the formal statistics indicate due to unmodeled thermal re-radiation or + outgassing accelerations that are not currently characterized but may exist. +******************************************************************************* + + + # E. Lon DXY DZ Observatory Name + --- -------- ------- ------- ---------------- + L20 18.3207 +308014 +293859 AG_Sarajevo Observatory, Sarajevo + L21 27.4213 +307050 +294814 Ostrov Observatory, Constanta + L22 27.6695 +295446 +306365 Barlad Observatory + L23 27.8319 +299346 +302574 Schela + L24 27.9289 +383214 -186499 Gauteng + L25 14.4374 +255033 +340528 Smolecin + L26 11.8102 +316937 +284229 Sanderphil Urban Obs., Civitavecchia + L27 5.6470 +307222 +294693 29PREMOTE Obs., Dauban {Soulier] + L28 15.4634 +323190 +277274 ISON-Castelgrande Observatory + L29 18.0169 +391400 -168725 Drebach-South Observatory, Windhoek +Multiple matching stations found. + diff --git a/tests/horizonsTest/parse_multiple_targets.hrz b/tests/horizonsTest/parse_multiple_targets.hrz new file mode 100644 index 0000000000..40f954bc39 --- /dev/null +++ b/tests/horizonsTest/parse_multiple_targets.hrz @@ -0,0 +1,19 @@ +******************************************************************************* + Multiple major-bodies match string "MARS*" + + ID# Name Designation IAU/aliases/other + ------- ---------------------------------- ----------- ------------------- + 4 Mars Barycenter + 499 Mars + -3 Mars Orbiter Mission (MOM) (spacec Mangalyaan + -41 Mars Express (spacecraft) MEX + -53 Mars Odyssey (spacecraft) + -530 Mars Pathfinder (spacecraft) MPF + -74 Mars Reconnaissance Orbiter (space MRO + -76 Mars Science Laboratory (spacecraf Curiosity MSL + -143 ExoMars16 TGO (spacecraft) + -168 Mars2020 (spacecraft) Perserverance Ingenu + + Number of matches = 10. Use ID# to make unique selection. +******************************************************************************* + diff --git a/tests/horizonsTest/timerange_no_time.hrz b/tests/horizonsTest/timerange_no_time.hrz new file mode 100644 index 0000000000..ba8f7f3e5d --- /dev/null +++ b/tests/horizonsTest/timerange_no_time.hrz @@ -0,0 +1,135 @@ +******************************************************************************* + Revised: Apr 21, 2022 Gaia Observatory -139479 + http://sci.esa.int/gaia/ + + BACKGROUND: + Gaia is designed and operated by the European Space Agency. It launched + December 19, 2013 @ 09:12 UTC on a Soyuz launcher from Kourou, French Guiana. + + On 2014-Jan-08, it arrived at its operational Lissajous orbit around the + gravitationally stable Earth-Sun Lagrange-point L2, roughly 1.5 million km + from Earth in the direction opposite the Sun. The orbit is not shadowed by + Earth eclipses. The orbit period is about 180 days; the size of the orbit + is typically 340,000 x 90,000 km. + + MISSION: + Gaia's 5-year primary mission is to ... + + * Measure the positions of ~1 billion stars both in our Galaxy and other + members of the Local Group, with an accuracy down to 24 uas + * Perform spectral and photometric measurements of all objects + * Derive space velocities of the Galaxy's constituent stars using the + stellar distances and motions + * Create a three-dimensional structural map of the Galaxy + + Additional expected results include extrasolar planet detection, brown dwarf + detection, solar system asteroid discoveries, supernova early detection, and + testing of Einstein's general relativity. + + GAIA SPACECRAFT: + Spacecraft dry mass total 1392 kg + Propellant 237 kg + Total launch mass 2029 kg + Power: 12.8 m^2 solar array provides up to 1910 Watts + + SCIENCE INSTRUMENTS: + Single integrated instrument that comprises three major functions: + astrometry, photometry (320-1000 nm) and spectrometry (846-874 nm). + + The three functions use two common telescopes and a shared focal plane, + with each function having a dedicated area on the large 0.5m x 1m CCD + detector array. + + SPACECRAFT TRAJECTORY (from ESA 2022-Apr-19, predicts thereafter) + Trajectory name Start Stop + -------------------------------------------- ----------- ----------- + ORB1_20220419_000001 2013-Dec-19 2026-Sep-14 +******************************************************************************* + + +******************************************************************************* +Ephemeris / API_USER Mon May 23 05:28:00 2022 Pasadena, USA / Horizons +******************************************************************************* +Target body name: Gaia (spacecraft) (-139479) {source: gaia_merged} +Center body name: Earth-Moon Barycenter (3) {source: gaia_merged} +Center-site name: BODY CENTER +******************************************************************************* +Start time : A.D. 2022-May-22 00:00:00.0000 TDB +Stop time : A.D. 2022-May-23 00:00:00.0000 TDB +Step-size : 720 minutes +******************************************************************************* +Center geodetic : 0.00000000,0.00000000,0.0000000 {E-lon(deg),Lat(deg),Alt(km)} +Center cylindric: 0.00000000,0.00000000,0.0000000 {E-lon(deg),Dxy(km),Dz(km)} +Center radii : (undefined) +Output units : KM-S +Output type : GEOMETRIC cartesian states +Output format : 1 (position only) +Reference frame : Ecliptic of J2000.0 +******************************************************************************* +JDTDB + X Y Z +******************************************************************************* +$$SOE +2459721.500000000 = A.D. 2022-May-22 00:00:00.0000 TDB + -1.005869741260714E+06 -1.229636409807553E+06 5.553741267973231E+04 +2459722.000000000 = A.D. 2022-May-22 12:00:00.0000 TDB + -9.976647219177654E+05 -1.235095646685846E+06 5.296169462755765E+04 +2459722.500000000 = A.D. 2022-May-23 00:00:00.0000 TDB + -9.893621107980320E+05 -1.240524898186224E+06 5.037219698871591E+04 +$$EOE +******************************************************************************* + +TIME + + Barycentric Dynamical Time ("TDB" or T_eph) output was requested. This +continuous relativistic coordinate time is equivalent to the relativistic +proper time of a clock at rest in a reference frame comoving with the +solar system barycenter but outside the system's gravity well. It is the +independent variable in the solar system relativistic equations of motion. + + TDB runs at a uniform rate of one SI second per second and is independent +of irregularities in Earth's rotation. + + Calendar dates prior to 1582-Oct-15 are in the Julian calendar system. +Later calendar dates are in the Gregorian system. + +REFERENCE FRAME AND COORDINATES + + Ecliptic at the standard reference epoch + + Reference epoch: J2000.0 + X-Y plane: adopted Earth orbital plane at the reference epoch + Note: IAU76 obliquity of 84381.448 arcseconds wrt ICRF X-Y plane + X-axis : ICRF + Z-axis : perpendicular to the X-Y plane in the directional (+ or -) sense + of Earth's north pole at the reference epoch. + + Symbol meaning: + + JDTDB Julian Day Number, Barycentric Dynamical Time + X X-component of position vector (km) + Y Y-component of position vector (km) + Z Z-component of position vector (km) + +ABERRATIONS AND CORRECTIONS + + Geometric state vectors have NO corrections or aberrations applied. + +Computations by ... + + Solar System Dynamics Group, Horizons On-Line Ephemeris System + 4800 Oak Grove Drive, Jet Propulsion Laboratory + Pasadena, CA 91109 USA + + General site: https://ssd.jpl.nasa.gov/ + Mailing list: https://ssd.jpl.nasa.gov/email_list.html + System news : https://ssd.jpl.nasa.gov/horizons/news.html + User Guide : https://ssd.jpl.nasa.gov/horizons/manual.html + Connect : browser https://ssd.jpl.nasa.gov/horizons/app.html#/x + API https://ssd-api.jpl.nasa.gov/doc/horizons.html + command-line telnet ssd.jpl.nasa.gov 6775 + e-mail/batch https://ssd.jpl.nasa.gov/ftp/ssd/hrzn_batch.txt + scripts https://ssd.jpl.nasa.gov/ftp/ssd/SCRIPTS + Author : Jon.D.Giorgini@jpl.nasa.gov +******************************************************************************* + diff --git a/tests/horizonsTest/timerange_time.hrz b/tests/horizonsTest/timerange_time.hrz new file mode 100644 index 0000000000..fda89b7c35 --- /dev/null +++ b/tests/horizonsTest/timerange_time.hrz @@ -0,0 +1,133 @@ +******************************************************************************* + Revised: Apr 21, 2022 Mars Reconnaisance Orbiter (MRO) / (Sun) -74 + http://marsprogram.jpl.nasa.gov/mro/ + + NOTE (2014-Jun-10): + C/2013 A1 (Siding Spring) will have its closest approach to Mars on Oct 19, + 2014 at a distance of about 135,000 km. + + Location of predicted MRO minimum risk from comet particles + (occultation mid-point): + + Latitude: 7.6083 deg + Time: 19-OCT-2014 20:08:07.182392952 ET (CSS CA + 98 min) + + MISSION LAUNCH DATE: MARS ARRIVAL DATE: + Aug 12, 2005 11:43 UTC (it's up and away) March 10, 2006 + + Notes: Aug 10, 2005: Original launch was scrubbed (gyros) + Aug 11, 2005: Second attemped was launch scrubbed (fueling sensors) + + LAUNCH VEHICLE: + Atlas V two-stage. Separation from Centaur: 2005-Aug-12 12:40:51.68 UTC + + BACKGROUND: + MRO aerobraked for 6 months from the post-insertion 35 hour orbit, saving + 450 kg of fuel. Primary science phase starts in November of 2006 and + nominally operates for 2 Earth years from a 112 minute, near circular polar + orbit. + + SPACECRAFT PHYSICAL PROPERTIES: + Height= 6.5 m Solar panels = 20 m^2 + Width = 13.6 m (tip-to-tip) launch weight= 2180 kg + + SPACECRAFT TRAJECTORY: + Trajectory starts after Centaur launch stage separation (cruise phase). + Trajectory after 2022-Apr-21 is PREDICTION. + + Trajectory files (from MRO Nav., JPL) Start (TDB) End (TDB) + -------------------------------------- ----------------- ----------------- + mro_cruise 2005-Aug-12 12:42 2006-Mar-10 22:06 + mro_ab 2006-Mar-10 22:06 2006-Sep-12 06:40 + misc reconstruction (mro_psp1-62) 2006-Sep-12 06:40 2022-Apr-01 01:01 + mro_psp_rec 2022-Apr-01 01:01 2022-Apr-17 16:34 + mro_psp 2022-Apr-17 16:34 2022-Sep-02 02:55 +******************************************************************************* + + +******************************************************************************* +Ephemeris / API_USER Mon May 23 05:19:05 2022 Pasadena, USA / Horizons +******************************************************************************* +Target body name: Mars Reconnaissance Orbiter (spacecraft) (-74) {source: MRO_MERGED} +Center body name: Mars Barycenter (4) {source: DE441} +Center-site name: BODY CENTER +******************************************************************************* +Start time : A.D. 2022-May-22 00:00:00.0000 TDB +Stop time : A.D. 2022-May-23 00:00:00.0000 TDB +Step-size : 720 minutes +******************************************************************************* +Center geodetic : 0.00000000,0.00000000,0.0000000 {E-lon(deg),Lat(deg),Alt(km)} +Center cylindric: 0.00000000,0.00000000,0.0000000 {E-lon(deg),Dxy(km),Dz(km)} +Center radii : (undefined) +Output units : KM-S +Output type : GEOMETRIC cartesian states +Output format : 1 (position only) +Reference frame : Ecliptic of J2000.0 +******************************************************************************* +JDTDB + X Y Z +******************************************************************************* +$$SOE +2459721.500000000 = A.D. 2022-May-22 00:00:00.0000 TDB + 2.615353755143860E+03 5.410112782583881E+02 -2.491150185148976E+03 +2459722.000000000 = A.D. 2022-May-22 12:00:00.0000 TDB + -3.495159540344693E+03 -5.551069096048225E+02 9.252465537814477E+02 +2459722.500000000 = A.D. 2022-May-23 00:00:00.0000 TDB + 3.491185350937938E+03 4.083500559468409E+02 1.096540860137564E+03 +$$EOE +******************************************************************************* + +TIME + + Barycentric Dynamical Time ("TDB" or T_eph) output was requested. This +continuous relativistic coordinate time is equivalent to the relativistic +proper time of a clock at rest in a reference frame comoving with the +solar system barycenter but outside the system's gravity well. It is the +independent variable in the solar system relativistic equations of motion. + + TDB runs at a uniform rate of one SI second per second and is independent +of irregularities in Earth's rotation. + + Calendar dates prior to 1582-Oct-15 are in the Julian calendar system. +Later calendar dates are in the Gregorian system. + +REFERENCE FRAME AND COORDINATES + + Ecliptic at the standard reference epoch + + Reference epoch: J2000.0 + X-Y plane: adopted Earth orbital plane at the reference epoch + Note: IAU76 obliquity of 84381.448 arcseconds wrt ICRF X-Y plane + X-axis : ICRF + Z-axis : perpendicular to the X-Y plane in the directional (+ or -) sense + of Earth's north pole at the reference epoch. + + Symbol meaning: + + JDTDB Julian Day Number, Barycentric Dynamical Time + X X-component of position vector (km) + Y Y-component of position vector (km) + Z Z-component of position vector (km) + +ABERRATIONS AND CORRECTIONS + + Geometric state vectors have NO corrections or aberrations applied. + +Computations by ... + + Solar System Dynamics Group, Horizons On-Line Ephemeris System + 4800 Oak Grove Drive, Jet Propulsion Laboratory + Pasadena, CA 91109 USA + + General site: https://ssd.jpl.nasa.gov/ + Mailing list: https://ssd.jpl.nasa.gov/email_list.html + System news : https://ssd.jpl.nasa.gov/horizons/news.html + User Guide : https://ssd.jpl.nasa.gov/horizons/manual.html + Connect : browser https://ssd.jpl.nasa.gov/horizons/app.html#/x + API https://ssd-api.jpl.nasa.gov/doc/horizons.html + command-line telnet ssd.jpl.nasa.gov 6775 + e-mail/batch https://ssd.jpl.nasa.gov/ftp/ssd/hrzn_batch.txt + scripts https://ssd.jpl.nasa.gov/ftp/ssd/SCRIPTS + Author : Jon.D.Giorgini@jpl.nasa.gov +******************************************************************************* + diff --git a/tests/horizonsTest/vectorFileTest.hrz b/tests/horizonsTest/vectorFileTest.hrz new file mode 100644 index 0000000000..da8f19521c --- /dev/null +++ b/tests/horizonsTest/vectorFileTest.hrz @@ -0,0 +1,224 @@ +******************************************************************************* + Revised: Mar 27, 2018 Tesla Roadster (spacecraft) -143205 + (solution #10) + + Tesla Roadster (AKA: Starman, 2018-017A) + + NOTE: + + Visibility: + 20th magnitude until Feb 20, + 22nd magnitude through mid-April + Brighter than 26th magnitude into mid-June + + 2018-Mar-01: Radial non-gravitational acceleration A1 estimated from data + (nominally solar radiation pressure) + 2018-Mar-27: Two reporting sites (J04 & K93) extend data arc one month. + A1 estimate of s10 is reduced 1.2-sigma compared to s9. + + LAUNCHED: + 2018-Feb-06 20:45 UTC by Falcon Heavy (FH-1) from Kennedy Space Center, USA + (launchpad 39A) + + BACKGROUND: + Dummy payload from the first launch of SpaceX Falcon Heavy launch vehicle. + Consists of a standard Tesla Roadster automobile and a spacesuit-wearing + mannequin nicknamed "Starman". + + Also includes a Hot Wheels toy model Roadster on the car's dash with a + mini-Starman inside. A data storage device placed inside the car contains + a copy of Isaac Asimov's "Foundation" novels. A plaque on the attachment + fitting between the Falcon Heavy upper stage and the Tesla is etched with + the names of more than 6,000 SpaceX employees. + + After orbiting the Earth for 5 hours, a third burn by the second stage was + completed at approximately 02:30 UTC Feb 7, placing the dummy payload in a + heliocentric orbit having a perihelion of 0.99 au and aphelion ~1.67 au. + + The object stack consists of a Merlin 1D Vacuum second stage with Extended + Nozzle, Payload Attachment Fitting, and Tesla Roadster on mount. + + Roadster mass: ~1250 kg (with batteries), ~800 kg (without ESS/batteries) + + TRAJECTORY: + This trajectory is based on JPL solution #10, a fit to 364 ground-based + optical astrometric measurements spanning 2018 Feb 8.2 to March 19.1 + + Trajectory name Start (TDB) Stop (TDB) + -------------------------------- ----------------- ----------------- + tesla_s10 2018-Feb-07 03:00 2090-Jan-01 00:00 + + Encounter predictions for s10 (w/radial 1/r^2 non-gravitational acceleration) + + Date (TDB) Body CA Dist MinDist MaxDist Vrel TCA3Sg Nsigs P_i/p + ----------------- ----- ------- ------- ------- ------ ------ ------ ------ + 2018 Feb 08.09690 Moon .000936 .000936 .000936 3.961 0.41 47509. 0.000 + 2020 Oct 07.26768 Mars .049530 .048923 .050242 8.150 27.40 6.63E5 0.000 + 2035 Apr 22.35934 Mars .015504 .004378 .027978 8.219 170.47 31247. 0.000 + 2047 Jan 11.89023 Earth .031919 .031716 .032123 4.493 249.70 78398. 0.000 + 2050 Mar 19.52949 Earth .119113 .113778 .124369 7.397 538.54 2.61E5 0.000 + 2052 Sep 05.15606 Mars .176363 .172469 .180319 5.738 2185.5 8.68E5 0.000 + 2067 Apr 15.90202 Mars .043270 .025712 .061471 7.192 1115.0 42565. 0.000 + 2084 Sep 17.92284 Mars .116962 .093449 .141170 9.753 787.45 6.55E5 0.000 + 2085 Jan 01.96490 Earth .083063 .049368 .112186 6.224 5208.9 1.00E5 0.000 + 2088 Mar 09.95754 Earth .049146 .033491 .063322 5.106 4505.2 1.17E5 0.000 + + Date = Nominal encounter time (Barycentric Dynamical Time) + CA_Dist = Highest probability close approach distance to body, au + MinDist = 3-sigma minimum encounter distance, au + MaxDist = 3-sigma maximum encounter distance, au + Vrel = Relative velocity at nominal encounter time, km/s + TCA3Sg = 3-sigma uncertainty in close encounter time, minutes + Nsigs = Number of sigmas to encounter body at nominal encounter time + P_i/p = Linearized probability of impact + + NOTE: + How to obtain optional statistical uncertainty output & generate an SPK file: + + Since this is a spacecraft and not part of the asteroid and comet database + which normally holds orbit covariance data, some functions like statistical + output and SPK file generation aren't automatically available for this object. + + However, such optional extended output is possible with some extra steps. + + To propagate statistical uncertainties for this object, the full statistical + orbit solution (given below) can be manually input back into Horizons as a + "user-defined object" using the telnet or e-mail interfaces (not possible + with the browser interface). + + To do this and activate statistical or SPK file output ... + + Using the telnet interface (command-line "telnet ssd.jpl.nasa.gov 6775"), + enter ";" to drop into user-input mode then cut-and-paste each line shown + below, one at a time. The lines of numbers after SRC must be in the order + shown. + + For SPK file generation, only the first four lines need be input: the + EPOCH, orbital element lines starting with "EC" and "OM", and the + non-gravitational acceleration model (line starting with "A1"). + + SRC lines are needed only for (optional) statistical output and the + H & G values only for (optional) visual magnitude output. + + EPOCH= 2458164.5 + EC= .2585469914787243 QR= .9860596231806226 TP= 2458153.620483722645 + OM= 317.3549094214575 W = 177.3203028023227 IN= 1.088451292866039 + EST=A1 A1= 2.960683526738534E-9 R0= 1. ALN= 1. NM= 2. NK= 0. + SRC= -2.057839421666802E-7 7.966781900129693E-9 -1.720426606925749E-9 + -4.722542923190676E-7 2.197679131968537E-9 -1.230413802372471E-6 + -2.500290306870021E-7 -3.361070889248183E-9 -1.765963020682463E-5 + -3.047907547965759E-7 -4.640202045440381E-7 -4.271481116360573E-9 + 2.657789409005983E-5 1.726818074599357E-6 -1.359673746135991E-6 + -2.478836748687631E-5 -2.309863204867099E-8 -.0002351644867403515 + -1.875169281895894E-6 -2.063647245529267E-6 -1.670539551586607E-6 + -4.019207817588603E-6 -3.128134469402375E-9 -3.034540373576942E-5 + 1.733661692209129E-7 -7.052327854535979E-7 -2.650181216776434E-7 + -1.310976135791957E-10 + H= 25.289 G= 0.15 + + When done, press a blank return to exit input mode. + + Enter "J" at the prompt to indicate heliocentric J2000 ecliptic data has + been supplied. Then at the next prompt, input an arbitrary name + (i.e., Roadster). + + Horizons will then proceed as usual, but with statistical output and SPK + file generation now available as options. + + A basic and identical tracking ephemeris can be produced without doing any + of this, but statistical uncertainty quantities requested will be marked + "n.a.", meaning not available, and SPK generation won't be an option. + + NOTE: long-term predictions + Over time, trajectory prediction errors could increase more rapidly than + the formal statistics indicate due to unmodeled thermal re-radiation or + outgassing accelerations that are not currently characterized but may exist. +******************************************************************************* + + +******************************************************************************* +Ephemeris / API_USER Mon May 23 04:45:55 2022 Pasadena, USA / Horizons +******************************************************************************* +Target body name: SpaceX Roadster (spacecraft) (-143205) {source: tesla_s10} +Center body name: Solar System Barycenter (0) {source: DE441} +Center-site name: BODY CENTER +******************************************************************************* +Start time : A.D. 2022-May-22 00:00:00.0000 TDB +Stop time : A.D. 2022-May-23 00:00:00.0000 TDB +Step-size : 720 minutes +******************************************************************************* +Center geodetic : 0.00000000,0.00000000,0.0000000 {E-lon(deg),Lat(deg),Alt(km)} +Center cylindric: 0.00000000,0.00000000,0.0000000 {E-lon(deg),Dxy(km),Dz(km)} +Center radii : (undefined) +Output units : KM-S +Output type : GEOMETRIC cartesian states +Output format : 1 (position only) +Reference frame : Ecliptic of J2000.0 +******************************************************************************* +JDTDB + X Y Z +******************************************************************************* +$$SOE +2459721.500000000 = A.D. 2022-May-22 00:00:00.0000 TDB + 1.480314826224177E+08 1.186454251209254E+08 3.565654811767541E+06 +2459722.000000000 = A.D. 2022-May-22 12:00:00.0000 TDB + 1.471002499298663E+08 1.193409521750320E+08 3.563269972262323E+06 +2459722.500000000 = A.D. 2022-May-23 00:00:00.0000 TDB + 1.461636830237649E+08 1.200322013312843E+08 3.560758082013868E+06 +$$EOE +******************************************************************************* + +TIME + + Barycentric Dynamical Time ("TDB" or T_eph) output was requested. This +continuous relativistic coordinate time is equivalent to the relativistic +proper time of a clock at rest in a reference frame comoving with the +solar system barycenter but outside the system's gravity well. It is the +independent variable in the solar system relativistic equations of motion. + + TDB runs at a uniform rate of one SI second per second and is independent +of irregularities in Earth's rotation. + + Calendar dates prior to 1582-Oct-15 are in the Julian calendar system. +Later calendar dates are in the Gregorian system. + +REFERENCE FRAME AND COORDINATES + + Ecliptic at the standard reference epoch + + Reference epoch: J2000.0 + X-Y plane: adopted Earth orbital plane at the reference epoch + Note: IAU76 obliquity of 84381.448 arcseconds wrt ICRF X-Y plane + X-axis : ICRF + Z-axis : perpendicular to the X-Y plane in the directional (+ or -) sense + of Earth's north pole at the reference epoch. + + Symbol meaning: + + JDTDB Julian Day Number, Barycentric Dynamical Time + X X-component of position vector (km) + Y Y-component of position vector (km) + Z Z-component of position vector (km) + +ABERRATIONS AND CORRECTIONS + + Geometric state vectors have NO corrections or aberrations applied. + +Computations by ... + + Solar System Dynamics Group, Horizons On-Line Ephemeris System + 4800 Oak Grove Drive, Jet Propulsion Laboratory + Pasadena, CA 91109 USA + + General site: https://ssd.jpl.nasa.gov/ + Mailing list: https://ssd.jpl.nasa.gov/email_list.html + System news : https://ssd.jpl.nasa.gov/horizons/news.html + User Guide : https://ssd.jpl.nasa.gov/horizons/manual.html + Connect : browser https://ssd.jpl.nasa.gov/horizons/app.html#/x + API https://ssd-api.jpl.nasa.gov/doc/horizons.html + command-line telnet ssd.jpl.nasa.gov 6775 + e-mail/batch https://ssd.jpl.nasa.gov/ftp/ssd/hrzn_batch.txt + scripts https://ssd.jpl.nasa.gov/ftp/ssd/SCRIPTS + Author : Jon.D.Giorgini@jpl.nasa.gov +******************************************************************************* + diff --git a/tests/property/test_property_listproperties.cpp b/tests/property/test_property_listproperties.cpp index 52489be958..ca5b1d5d7d 100644 --- a/tests/property/test_property_listproperties.cpp +++ b/tests/property/test_property_listproperties.cpp @@ -221,7 +221,7 @@ TEST_CASE("IntListProperty: Get Lua Value", "[intlistproperty]") { p.getLuaValue(L); CHECK(ghoul::lua::luaValueToString(L, 1) == - "{ [1] = 1.000000, [2] = 2.000000, [3] = 3.000000 }" + "{ [1] = 1, [2] = 2, [3] = 3 }" ); } @@ -324,14 +324,14 @@ TEST_CASE("DoubleListProperty: Invalid Set Lua Value - Not List", "[doublelistpr TEST_CASE("DoubleListProperty: Get Lua Value", "[doublelistproperty]") { openspace::properties::DoubleListProperty p({ "id", "gui", "desc" }); - const std::vector list{ 1.0, 2.0, 3.0 }; + const std::vector list{ 1.0, 2.1, 3.2 }; p.setValue(list); ghoul::lua::LuaState L; p.getLuaValue(L); CHECK(ghoul::lua::luaValueToString(L, 1) == - "{ [1] = 1.000000, [2] = 2.000000, [3] = 3.000000 }" + "{ [1] = 1, [2] = 2.1, [3] = 3.2 }" ); } diff --git a/tests/test_horizons.cpp b/tests/test_horizons.cpp new file mode 100644 index 0000000000..7275a8cf04 --- /dev/null +++ b/tests/test_horizons.cpp @@ -0,0 +1,830 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2022 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include "catch2/catch.hpp" + +#include +#include +#include +#include + +#ifdef OPENSPACE_MODULE_SPACE_ENABLED +#include +#endif // OPENSPACE_MODULE_SPACE_ENABLED + +using namespace openspace; +using json = nlohmann::json; + +// Struct to hold the data for some of the tests +struct HorizonsTestData { + std::string observer, target, start, stop, step, unit; +}; + +// Avoid repetitive code by using these functions +#ifdef OPENSPACE_MODULE_SPACE_ENABLED +void testHorizonsAnswer(const HorizonsTestData& data, HorizonsType type, + std::filesystem::path filePath, + HorizonsResultCode expectedAnswerCode) +{ + std::string url = constructHorizonsUrl( + type, + data.target, + data.observer, + data.start, + data.stop, + data.step, + data.unit + ); + json answer = sendHorizonsRequest(url, filePath); + HorizonsResultCode code = isValidHorizonsAnswer(answer); + CHECK(code == expectedAnswerCode); + + CHECK(std::filesystem::is_regular_file(filePath)); + std::filesystem::remove(filePath); + CHECK(!std::filesystem::is_regular_file(filePath)); +} + +void testHorizonsAnswerAndResult(const HorizonsTestData& data, HorizonsType type, + std::filesystem::path filePath, + HorizonsResultCode expectedAnswerCode, + HorizonsResultCode expectedResultCode, + bool shouldDeleteFile = true) +{ + std::string url = constructHorizonsUrl( + type, + data.target, + data.observer, + data.start, + data.stop, + data.step, + data.unit + ); + json answer = sendHorizonsRequest(url, filePath); + HorizonsResultCode answerCode = isValidHorizonsAnswer(answer); + CHECK(answerCode == expectedAnswerCode); + + // Extract the result from the json object and test it + auto result = answer.find("result"); + CHECK(result != answer.end()); + + HorizonsFile horizonsFile(filePath, *result); + HorizonsResultCode resultCode = isValidHorizonsFile(horizonsFile.file()); + CHECK(resultCode == expectedResultCode); + + CHECK(std::filesystem::is_regular_file(filePath)); + if (shouldDeleteFile) { + std::filesystem::remove(filePath); + CHECK(!std::filesystem::is_regular_file(filePath)); + } +} + +void testReadingHorizons(HorizonsType type, std::filesystem::path filePath, + const double t0, const double x0, const double y0, const double z0, + const double t1, const double x1, const double y1, const double z1, + const double t2, const double x2, const double y2, const double z2) +{ + // Get files and make sure they exist + std::filesystem::path kernel = absPath("${TESTDIR}/horizonsTest/naif0012.tls"); + CHECK(std::filesystem::is_regular_file(kernel)); + CHECK(std::filesystem::is_regular_file(filePath)); + + // Initialize SpiceManager and load leap second kernel + SpiceManager::initialize(); + openspace::SpiceManager::ref().loadKernel(kernel.string()); + + // Read the file + HorizonsResult result = readHorizonsFile(filePath); + + // Check the result + CHECK(result.type == type); + CHECK(result.errorCode == HorizonsResultCode::Valid); + + std::vector data = result.data; + REQUIRE(data.size() == 3); + + CHECK(data[0].time == Approx(t0)); + CHECK(data[0].position.x == Approx(x0)); + CHECK(data[0].position.y == Approx(y0)); + CHECK(data[0].position.z == Approx(z0)); + + + CHECK(data[1].time == Approx(t1)); + CHECK(data[1].position.x == Approx(x1)); + CHECK(data[1].position.y == Approx(y1)); + CHECK(data[1].position.z == Approx(z1)); + + + CHECK(data[2].time == Approx(t2)); + CHECK(data[2].position.x == Approx(x2)); + CHECK(data[2].position.y == Approx(y2)); + CHECK(data[2].position.z == Approx(z2)); + + // Clean up + openspace::SpiceManager::ref().unloadKernel(kernel.string()); + openspace::SpiceManager::deinitialize(); +} +#endif // OPENSPACE_MODULE_SPACE_ENABLED + +// Test if the space module is enable or not +TEST_CASE("HorizonsFile: Space module", "[horizonsfile]") { +#ifdef OPENSPACE_MODULE_SPACE_ENABLED + CHECK(true); + LINFOC("test_horizons", "Downloading Horizons test data ..."); +#else + LERRORC("test_horizons", "These tests requires the Space module to be enabled"); + CHECK(false); +#endif // OPENSPACE_MODULE_SPACE_ENABLED +} + +// Test Horizons requests and error handling +// Test the errors that are captured by the error field in the json result +TEST_CASE("HorizonsFile: File size too large", "[horizonsfile]") { +#ifdef OPENSPACE_MODULE_SPACE_ENABLED + HorizonsTestData data; + data.observer = "@ssb"; + data.target = "-74"; // MRO + data.start = "2005-08-13 00:00:00"; + data.stop = "2022-07-01 00:00:00"; + data.step = "1"; + data.unit = "m"; + std::filesystem::path filePath = absPath("${TESTDIR}/horizonsTest/horizonstest_1.hrz"); + HorizonsResultCode expectedAnswerCode = HorizonsResultCode::ErrorSize; + + // Test Vector format + HorizonsType type = HorizonsType::Vector; + testHorizonsAnswer(data, type, filePath, expectedAnswerCode); + + // Test Observer format + type = HorizonsType::Observer; + testHorizonsAnswer(data, type, filePath, expectedAnswerCode); +#endif // OPENSPACE_MODULE_SPACE_ENABLED +} + +TEST_CASE("HorizonsFile: Time steps too large", "[horizonsfile]") { +#ifdef OPENSPACE_MODULE_SPACE_ENABLED + HorizonsTestData data; + data.observer = "@ssb"; + data.target = "-74"; // MRO + data.start = "2005-08-13 00:00:00"; + data.stop = "2022-07-01 00:00:00"; + data.step = "1111111111"; + data.unit = "d"; + std::filesystem::path filePath = absPath("${TESTDIR}/horizonsTest/horizonstest_2.hrz"); + HorizonsResultCode expectedAnswerCode = HorizonsResultCode::ErrorSpan; + + // Test Vector format + HorizonsType type = HorizonsType::Vector; + testHorizonsAnswer(data, type, filePath, expectedAnswerCode); + + // Test Observer format + type = HorizonsType::Observer; + testHorizonsAnswer(data,type, filePath, expectedAnswerCode); +#endif // OPENSPACE_MODULE_SPACE_ENABLED +} + +TEST_CASE("HorizonsFile: Outside available time range", "[horizonsfile]") { +#ifdef OPENSPACE_MODULE_SPACE_ENABLED + HorizonsTestData data; + data.observer = "@ssb"; + data.target = "Tesla"; + data.start = "1950-05-19 00:00:00"; + data.stop = "2000-05-19 00:00:00"; + data.step = "1"; + data.unit = "d"; + std::filesystem::path filePath = absPath("${TESTDIR}/horizonsTest/horizonstest_3.hrz"); + HorizonsResultCode expectedAnswerCode = HorizonsResultCode::ErrorTimeRange; + + // Test Vector format + HorizonsType type = HorizonsType::Vector; + testHorizonsAnswer(data, type, filePath, expectedAnswerCode); + + // Test Observer format + type = HorizonsType::Observer; + testHorizonsAnswer(data, type, filePath, expectedAnswerCode); +#endif // OPENSPACE_MODULE_SPACE_ENABLED +} + +TEST_CASE("HorizonsFile: No observer", "[horizonsfile]") { +#ifdef OPENSPACE_MODULE_SPACE_ENABLED + HorizonsTestData data; + data.observer = "abcdefghijkl"; + data.target = "Tesla"; + data.start = "2021-05-19 00:00:00"; + data.stop = "2022-05-19 00:00:00"; + data.step = "1"; + data.unit = "d"; + std::filesystem::path filePath = absPath("${TESTDIR}/horizonsTest/horizonstest_4.hrz"); + HorizonsResultCode expectedAnswerCode = HorizonsResultCode::ErrorNoObserver; + + // Test Vector format + HorizonsType type = HorizonsType::Vector; + testHorizonsAnswer(data, type, filePath, expectedAnswerCode); + + // Test Observer format + type = HorizonsType::Observer; + testHorizonsAnswer(data, type, filePath, expectedAnswerCode); +#endif // OPENSPACE_MODULE_SPACE_ENABLED +} + +TEST_CASE("HorizonsFile: Observer and target same", "[horizonsfile]") { +#ifdef OPENSPACE_MODULE_SPACE_ENABLED + HorizonsTestData data; + data.observer = "500@4"; // Mars barycenter + data.target = "4"; // Mars barycenter + data.start = "2021-05-19 00:00:00"; + data.stop = "2022-05-19 00:00:00"; + data.step = "1"; + data.unit = "d"; + std::filesystem::path filePath = absPath("${TESTDIR}/horizonsTest/horizonstest_5.hrz"); + HorizonsResultCode expectedAnswerCode = HorizonsResultCode::ErrorObserverTargetSame; + + // This test is only for Observer type format + HorizonsType type = HorizonsType::Observer; + testHorizonsAnswer(data, type, filePath, expectedAnswerCode); +#endif // OPENSPACE_MODULE_SPACE_ENABLED +} + +TEST_CASE("HorizonsFile: Multiple observer stations", "[horizonsfile]") { +#ifdef OPENSPACE_MODULE_SPACE_ENABLED + HorizonsTestData data; + data.observer = "l2"; + data.target = "Tesla"; + data.start = "2021-05-19 00:00:00"; + data.stop = "2022-05-19 00:00:00"; + data.step = "1"; + data.unit = "d"; + std::filesystem::path filePath = absPath("${TESTDIR}/horizonsTest/horizonstest_6.hrz"); + HorizonsResultCode expectedAnswerCode = HorizonsResultCode::MultipleObserverStations; + + // Test Vector format + HorizonsType type = HorizonsType::Vector; + testHorizonsAnswer(data, type, filePath, expectedAnswerCode); + + // Test Observer format + type = HorizonsType::Observer; + testHorizonsAnswer(data, type, filePath, expectedAnswerCode); +#endif // OPENSPACE_MODULE_SPACE_ENABLED +} + + +// Test errors that are nat captured by the error field in the json result +TEST_CASE("HorizonsFile: Multiple observers", "[horizonsfile]") { +#ifdef OPENSPACE_MODULE_SPACE_ENABLED + HorizonsTestData data; + data.observer = "@mars"; + data.target = "Tesla"; + data.start = "2021-05-19 00:00:00"; + data.stop = "2022-05-19 00:00:00"; + data.step = "1"; + data.unit = "d"; + std::filesystem::path filePath = absPath("${TESTDIR}/horizonsTest/horizonstest_7.hrz"); + HorizonsResultCode expectedAnswerCode = HorizonsResultCode::Valid; + HorizonsResultCode expectedResultCode = HorizonsResultCode::MultipleObserver; + + // Test Vector format + HorizonsType type = HorizonsType::Vector; + testHorizonsAnswerAndResult( + data, + type, + filePath, + expectedAnswerCode, + expectedResultCode + ); + + // Test Observer format + type = HorizonsType::Observer; + testHorizonsAnswerAndResult( + data, + type, + filePath, + expectedAnswerCode, + expectedResultCode + ); +#endif // OPENSPACE_MODULE_SPACE_ENABLED +} + +TEST_CASE("HorizonsFile: No target", "[horizonsfile]") { +#ifdef OPENSPACE_MODULE_SPACE_ENABLED + HorizonsTestData data; + data.observer = "@ssb"; + data.target = "abcdefghijkl"; + data.start = "2021-05-20 00:00:00"; + data.stop = "2022-05-20 00:00:00"; + data.step = "1"; + data.unit = "d"; + std::filesystem::path filePath = absPath("${TESTDIR}/horizonsTest/horizonstest_8.hrz"); + HorizonsResultCode expectedAnswerCode = HorizonsResultCode::Valid; + HorizonsResultCode expectedResultCode = HorizonsResultCode::ErrorNoTarget; + + // Test Vector format + HorizonsType type = HorizonsType::Vector; + testHorizonsAnswerAndResult( + data, + type, + filePath, + expectedAnswerCode, + expectedResultCode + ); + + // Test Observer format + type = HorizonsType::Observer; + testHorizonsAnswerAndResult( + data, + type, + filePath, + expectedAnswerCode, + expectedResultCode + ); +#endif // OPENSPACE_MODULE_SPACE_ENABLED +} + +TEST_CASE("HorizonsFile: Multiple targets (major bodies)", "[horizonsfile]") { +#ifdef OPENSPACE_MODULE_SPACE_ENABLED + HorizonsTestData data; + data.observer = "@ssb"; + data.target = "mars"; + data.start = "2021-05-20 00:00:00"; + data.stop = "2022-05-20 00:00:00"; + data.step = "1"; + data.unit = "d"; + std::filesystem::path filePath = absPath("${TESTDIR}/horizonsTest/horizonstest_9.hrz"); + HorizonsResultCode expectedAnswerCode = HorizonsResultCode::Valid; + HorizonsResultCode expectedResultCode = HorizonsResultCode::MultipleTarget; + + // Test Vector format + HorizonsType type = HorizonsType::Vector; + testHorizonsAnswerAndResult( + data, + type, + filePath, + expectedAnswerCode, + expectedResultCode + ); + + // Test Observer format + type = HorizonsType::Observer; + testHorizonsAnswerAndResult( + data, + type, + filePath, + expectedAnswerCode, + expectedResultCode + ); +#endif // OPENSPACE_MODULE_SPACE_ENABLED +} + +TEST_CASE("HorizonsFile: Multiple targets (minor bodies case 1)", "[horizonsfile]") { +#ifdef OPENSPACE_MODULE_SPACE_ENABLED + HorizonsTestData data; + data.observer = "@ssb"; + data.target = "DES = 141P;"; + data.start = "2021-05-20 00:00:00"; + data.stop = "2022-05-20 00:00:00"; + data.step = "1"; + data.unit = "d"; + std::filesystem::path filePath = absPath("${TESTDIR}/horizonsTest/horizonstest_10.hrz"); + HorizonsResultCode expectedAnswerCode = HorizonsResultCode::Valid; + HorizonsResultCode expectedResultCode = HorizonsResultCode::MultipleTarget; + + // Test Vector format + HorizonsType type = HorizonsType::Vector; + testHorizonsAnswerAndResult( + data, + type, + filePath, + expectedAnswerCode, + expectedResultCode + ); + + // Test Observer format + type = HorizonsType::Observer; + testHorizonsAnswerAndResult( + data, + type, + filePath, + expectedAnswerCode, + expectedResultCode + ); +#endif // OPENSPACE_MODULE_SPACE_ENABLED +} + +TEST_CASE("HorizonsFile: Multiple targets (minor bodies case 2)", "[horizonsfile]") { +#ifdef OPENSPACE_MODULE_SPACE_ENABLED + HorizonsTestData data; + data.observer = "@ssb"; + data.target = "borisov"; + data.start = "2021-05-20 00:00:00"; + data.stop = "2022-05-20 00:00:00"; + data.step = "1"; + data.unit = "d"; + std::filesystem::path filePath = absPath("${TESTDIR}/horizonsTest/horizonstest_11.hrz"); + HorizonsResultCode expectedAnswerCode = HorizonsResultCode::Valid; + HorizonsResultCode expectedResultCode = HorizonsResultCode::MultipleTarget; + + // Test Vector format + HorizonsType type = HorizonsType::Vector; + testHorizonsAnswerAndResult( + data, + type, + filePath, + expectedAnswerCode, + expectedResultCode + ); + + // Test Observer format + type = HorizonsType::Observer; + testHorizonsAnswerAndResult( + data, + type, + filePath, + expectedAnswerCode, + expectedResultCode + ); +#endif // OPENSPACE_MODULE_SPACE_ENABLED +} + +TEST_CASE("HorizonsFile: Detect multiple observers or targets", "[horizonsfile]") { +#ifdef OPENSPACE_MODULE_SPACE_ENABLED + HorizonsTestData data; + data.observer = "@l2"; + data.target = "90001048"; // 141P Machholz 2 epoch 2019 + data.start = "2021-05-23 00:00:00"; + data.stop = "2022-05-23 00:00:00"; + data.step = "1"; + data.unit = "d"; + std::filesystem::path filePath = absPath("${TESTDIR}/horizonsTest/horizonstest_12.hrz"); + HorizonsResultCode expectedAnswerCode = HorizonsResultCode::Valid; + HorizonsResultCode expectedResultCode = HorizonsResultCode::MultipleObserver; + + // Test Vector format + HorizonsType type = HorizonsType::Vector; + testHorizonsAnswerAndResult( + data, + type, + filePath, + expectedAnswerCode, + expectedResultCode + ); + + // Test Observer format + type = HorizonsType::Observer; + testHorizonsAnswerAndResult( + data, + type, + filePath, + expectedAnswerCode, + expectedResultCode + ); +#endif // OPENSPACE_MODULE_SPACE_ENABLED +} + +TEST_CASE("HorizonsFile: Valid request and response", "[horizonsfile]") { +#ifdef OPENSPACE_MODULE_SPACE_ENABLED + HorizonsTestData data; + data.observer = "@ssb"; + data.target = "Tesla"; + data.start = "2022-05-22 00:00:00"; + data.stop = "2022-05-23 00:00:00"; + data.step = "12"; + data.unit = "h"; + std::filesystem::path filePathVector = absPath("${TESTDIR}/horizonsTest/validVectorFile.hrz"); + std::filesystem::path filePathObserver = absPath("${TESTDIR}/horizonsTest/validObserverFile.hrz"); + HorizonsResultCode expectedAnswerCode = HorizonsResultCode::Valid; + HorizonsResultCode expectedResultCode = HorizonsResultCode::Valid; + + // Test Vector format + HorizonsType type = HorizonsType::Vector; + testHorizonsAnswerAndResult( + data, + type, + filePathVector, + expectedAnswerCode, + expectedResultCode, + false + ); + + // Test Observer format + type = HorizonsType::Observer; + testHorizonsAnswerAndResult( + data, + type, + filePathObserver, + expectedAnswerCode, + expectedResultCode, + false + ); +#endif // OPENSPACE_MODULE_SPACE_ENABLED +} + + +// Test parsing of timeranges +// Since data can get updated this is tested towards stored files +TEST_CASE("HorizonsFile: Parsing time range with time", "[horizonsfile]") { +#ifdef OPENSPACE_MODULE_SPACE_ENABLED + std::filesystem::path filePath = + absPath("${TESTDIR}/horizonsTest/timerange_time.hrz"); + HorizonsFile horizonsFile(filePath); + + // Parse time range + std::pair timeRange = horizonsFile.parseValidTimeRange( + "Trajectory files", + "************", + "Trajectory name" + ); + + CHECK(timeRange.first == "2005-Aug-12 T 12:42"); + CHECK(timeRange.second == "2022-Sep-02 T 02:55"); +#endif // OPENSPACE_MODULE_SPACE_ENABLED +} + +TEST_CASE("HorizonsFile: Parsing time range without time", "[horizonsfile]") { +#ifdef OPENSPACE_MODULE_SPACE_ENABLED + std::filesystem::path filePath = + absPath("${TESTDIR}/horizonsTest/timerange_no_time.hrz"); + HorizonsFile horizonsFile(filePath); + + // Parse time range + std::pair timeRange = horizonsFile.parseValidTimeRange( + "Trajectory files", + "************", + "Trajectory name", + false + ); + + CHECK(timeRange.first == "2013-Dec-19"); + CHECK(timeRange.second == "2026-Sep-14"); +#endif // OPENSPACE_MODULE_SPACE_ENABLED +} + + +// Test parsing of matches +// Since data can get updated this is tested towards stored files +TEST_CASE("HorizonsFile: Parsing multiple matching observers", "[horizonsfile]") { +#ifdef OPENSPACE_MODULE_SPACE_ENABLED + std::filesystem::path filePath = + absPath("${TESTDIR}/horizonsTest/parse_multiple_observers.hrz"); + HorizonsFile horizonsFile(filePath); + + // Parse matches + std::vector matches = + horizonsFile.parseMatches("Name", "matches", ">MATCH NAME<"); + + REQUIRE(matches.size() == 3); + CHECK(matches[0] == + " ID# Name Designation IAU/aliases/other " + ); + CHECK(matches[1] == + " 3 Earth-Moon Barycenter EMB " + ); + CHECK(matches[2] == + " 399 Earth Geocenter " + ); +#endif // OPENSPACE_MODULE_SPACE_ENABLED +} + +TEST_CASE("HorizonsFile: Parsing multiple matching targets", "[horizonsfile]") { +#ifdef OPENSPACE_MODULE_SPACE_ENABLED + std::filesystem::path filePath = + absPath("${TESTDIR}/horizonsTest/parse_multiple_targets.hrz"); + HorizonsFile horizonsFile(filePath); + + // Parse matches + std::vector matches = + horizonsFile.parseMatches("Name", "matches", ">MATCH NAME<"); + + REQUIRE(matches.size() == 11); + CHECK(matches[0] == + " ID# Name Designation IAU/aliases/other " + ); + CHECK(matches[1] == + " 4 Mars Barycenter " + ); + CHECK(matches[2] == + " 499 Mars " + ); + CHECK(matches[3] == + " -3 Mars Orbiter Mission (MOM) (spacec Mangalyaan " + ); + CHECK(matches[4] == + " -41 Mars Express (spacecraft) MEX " + ); + CHECK(matches[5] == + " -53 Mars Odyssey (spacecraft) " + ); + CHECK(matches[6] == + " -530 Mars Pathfinder (spacecraft) MPF " + ); + CHECK(matches[7] == + " -74 Mars Reconnaissance Orbiter (space MRO " + ); + CHECK(matches[8] == + " -76 Mars Science Laboratory (spacecraf Curiosity MSL " + ); + CHECK(matches[9] == + " -143 ExoMars16 TGO (spacecraft) " + ); + CHECK(matches[10] == + " -168 Mars2020 (spacecraft) Perserverance Ingenu " + ); +#endif // OPENSPACE_MODULE_SPACE_ENABLED +} + +TEST_CASE("HorizonsFile: Parsing multiple matching stations", "[horizonsfile]") { +#ifdef OPENSPACE_MODULE_SPACE_ENABLED + std::filesystem::path filePath = + absPath("${TESTDIR}/horizonsTest/parse_multiple_stations.hrz"); + CHECK(std::filesystem::is_regular_file(filePath)); + HorizonsFile horizonsFile(filePath); + + // Parse matches + std::vector matches = + horizonsFile.parseMatches("Observatory Name", "Multiple matching stations found"); + + REQUIRE(matches.size() == 11); + CHECK(matches[0] == + " # E. Lon DXY DZ Observatory Name" + ); + CHECK(matches[1] == + " L20 18.3207 +308014 +293859 AG_Sarajevo Observatory, Sarajevo" + ); + CHECK(matches[2] == + " L21 27.4213 +307050 +294814 Ostrov Observatory, Constanta" + ); + CHECK(matches[3] == + " L22 27.6695 +295446 +306365 Barlad Observatory" + ); + CHECK(matches[4] == + " L23 27.8319 +299346 +302574 Schela" + ); + CHECK(matches[5] == + " L24 27.9289 +383214 -186499 Gauteng" + ); + CHECK(matches[6] == + " L25 14.4374 +255033 +340528 Smolecin" + ); + CHECK(matches[7] == + " L26 11.8102 +316937 +284229 Sanderphil Urban Obs., Civitavecchia" + ); + CHECK(matches[8] == + " L27 5.6470 +307222 +294693 29PREMOTE Obs., Dauban {Soulier]" + ); + CHECK(matches[9] == + " L28 15.4634 +323190 +277274 ISON-Castelgrande Observatory" + ); + CHECK(matches[10] == + " L29 18.0169 +391400 -168725 Drebach-South Observatory, Windhoek" + ); +#endif // OPENSPACE_MODULE_SPACE_ENABLED +} + + +// Test reading of data and compare a recent request with a stored file +TEST_CASE("HorizonsFile: Reading Vector data from request", "[horizonsfile]") { +#ifdef OPENSPACE_MODULE_SPACE_ENABLED + HorizonsType type = HorizonsType::Vector; + std::filesystem::path filePathVector = + absPath("${TESTDIR}/horizonsTest/validVectorFile.hrz"); + + const double t0 = 706449669.18513119; + const double x0 = -126379670172.70331; + const double y0 = 63049830070.652786; + const double z0 = -126710964556.55870; + + const double t1 = 706492869.18512082; + const double x1 = -127019567853.94952; + const double y1 = 62510445746.414017; + const double z1 = -125904395646.64995; + + const double t2 = 706536069.18511045; + const double x2 = -127654909093.56494; + const double y2 = 61968790989.645737; + const double z2 = -125093260079.10854; + + testReadingHorizons( + type, filePathVector, + t0, x0, y0, z0, + t1, x1, y1, z1, + t2, x2, y2, z2 + ); + + // Clean up + std::filesystem::remove(filePathVector); + CHECK(!std::filesystem::is_regular_file(filePathVector)); +#endif // OPENSPACE_MODULE_SPACE_ENABLED +} + +TEST_CASE("HorizonsFile: Reading Observer data from request", "[horizonsfile]") { +#ifdef OPENSPACE_MODULE_SPACE_ENABLED + HorizonsType type = HorizonsType::Observer; + std::filesystem::path filePathObserver = + absPath("${TESTDIR}/horizonsTest/validObserverFile.hrz"); + + const double t0 = 706449669.18513119; + const double x0 = -126371142157.29857; + const double y0 = 63056923889.044579; + const double z0 = -126721572150.18513; + + const double t1 = 706492869.18512082; + const double x1 = -127011112787.76295; + const double y1 = 62517559574.749786; + const double z1 = -125915045896.36182; + + const double t2 = 706536069.18511045; + const double x2 = -127646529740.40393; + const double y2 = 61975921972.090714; + const double z2 = -125103951590.60988; + + testReadingHorizons( + type, filePathObserver, + t0, x0, y0, z0, + t1, x1, y1, z1, + t2, x2, y2, z2 + ); + + // Clean up + std::filesystem::remove(filePathObserver); + CHECK(!std::filesystem::is_regular_file(filePathObserver)); +#endif // OPENSPACE_MODULE_SPACE_ENABLED +} + + +TEST_CASE("HorizonsFile: Reading Vector data from file", "[horizonsfile]") { +#ifdef OPENSPACE_MODULE_SPACE_ENABLED + HorizonsType type = HorizonsType::Vector; + std::filesystem::path filePathVector = + absPath("${TESTDIR}/horizonsTest/vectorFileTest.hrz"); + + const double t0 = 706449669.18513119; + const double x0 = -126379670172.70331; + const double y0 = 63049830070.652786; + const double z0 = -126710964556.55870; + + const double t1 = 706492869.18512082; + const double x1 = -127019567853.94952; + const double y1 = 62510445746.414017; + const double z1 = -125904395646.64995; + + const double t2 = 706536069.18511045; + const double x2 = -127654909093.56494; + const double y2 = 61968790989.645737; + const double z2 = -125093260079.10854; + + testReadingHorizons( + type, filePathVector, + t0, x0, y0, z0, + t1, x1, y1, z1, + t2, x2, y2, z2 + ); +#endif // OPENSPACE_MODULE_SPACE_ENABLED +} + +TEST_CASE("HorizonsFile: Reading Observer data from file", "[horizonsfile]") { +#ifdef OPENSPACE_MODULE_SPACE_ENABLED + HorizonsType type = HorizonsType::Observer; + std::filesystem::path filePathObserver = + absPath("${TESTDIR}/horizonsTest/observerFileTest.hrz"); + + const double t0 = 706449669.18513119; + const double x0 = -126371142157.29857; + const double y0 = 63056923889.044579; + const double z0 = -126721572150.18513; + + const double t1 = 706492869.18512082; + const double x1 = -127011112787.76295; + const double y1 = 62517559574.749786; + const double z1 = -125915045896.36182; + + const double t2 = 706536069.18511045; + const double x2 = -127646529740.40393; + const double y2 = 61975921972.090714; + const double z2 = -125103951590.60988; + + testReadingHorizons( + type, filePathObserver, + t0, x0, y0, z0, + t1, x1, y1, z1, + t2, x2, y2, z2 + ); +#endif // OPENSPACE_MODULE_SPACE_ENABLED +}