mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-04 10:40:09 -06:00
Feature/satellites (#2185)
* Remove planet geometry and simplespheregeometry * Only use a single TLE loading implementation * Add caching to the satellite loader; Add Lua function to load kepler file * Fix RenderablePlanetProjection specification * Add OMM loading funtion; Remove mean motion from Kepler parameters * Replace TLETranslation class with GPTranslation and support OMM files * Support loading SMDB files in kepler functions * Merge RenderableSatellites and RenderableSmallBody with RenderableOrbitalKepler * Update submodules * Adapt existing satellites to new OMM file type * Remove TLE helper * Remove SSSB shared file and adapt sssb assets
This commit is contained in:
@@ -87,7 +87,7 @@ void FileSystemAccess::parseChildFile(std::string filename, bool& hasDirHeaderBe
|
||||
else {
|
||||
std::string extension = filename.substr(filename.length()
|
||||
- _fileExtension.length());
|
||||
if (extension.compare(_fileExtension) != 0) {
|
||||
if (extension != _fileExtension) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,7 +352,7 @@ void PropertiesDialog::editBoxDisabled(bool disabled) {
|
||||
|
||||
void PropertiesDialog::parseSelections() {
|
||||
// Handle case with only one remaining but empty line
|
||||
if ((_propertyData.size() == 1) && (_propertyData.at(0).name.compare("") == 0)) {
|
||||
if ((_propertyData.size() == 1) && _propertyData.at(0).name.empty()) {
|
||||
_propertyData.clear();
|
||||
}
|
||||
*_properties = std::move(_propertyData);
|
||||
|
||||
@@ -1,21 +1,50 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Amateur Radio",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Amateur Radio)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_amateur_radio",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=amateur&FORMAT=kvn",
|
||||
Filename = "amateur.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=amateur&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "amateur",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "amateur.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Amateur Radio",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
Name = "Satellites Communications - Amateur Radio",
|
||||
Version = "1.0",
|
||||
Description = [[Satellites asset for Communications - Amateur Radio. Data from
|
||||
Celestrak]],
|
||||
Description = [[Satellites asset for Communications - Amateur Radio. Data from
|
||||
Celestrak]],
|
||||
Author = "OpenSpace Team",
|
||||
URL = "https://celestrak.com/NORAD/elements/",
|
||||
License = "Celestrak"
|
||||
|
||||
@@ -1,21 +1,49 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Experimental",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Experimental)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_x-comm",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=x-comm&FORMAT=kvn",
|
||||
Filename = "x-comm.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=x-comm&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "x-comm",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "x-comm.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Experimental",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
Name = "Satellites Communications - Experimental",
|
||||
Version = "1.0",
|
||||
Description = [[Satellites asset for Communications - Experimental. Data from
|
||||
Celestrak]],
|
||||
Description = "Satellites asset for Communications - Experimental. Data from Celestrak",
|
||||
Author = "OpenSpace Team",
|
||||
URL = "https://celestrak.com/NORAD/elements/",
|
||||
License = "Celestrak"
|
||||
|
||||
@@ -1,22 +1,51 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Geostationary",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Geostationary)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_geo",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=geo&FORMAT=kvn",
|
||||
Filename = "geo.txt",
|
||||
Url = "https://celestrak.com/NORAD/elements/gp.php?GROUP=geo&FORMAT=TLE",
|
||||
TrailColor = { 0.9, 0.9, 0.0 },
|
||||
Description = [[Satellites that are currently active and in a Geosynchronous orbit, meaning
|
||||
their orbital period matches Earth's rotation]]
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "geo",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "geo.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.9, 0.9, 0.0 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Geostationary",
|
||||
Path = "/Solar System/Planets/Earth/Satellites",
|
||||
Description = [[Satellites that are currently active and in a Geosynchronous orbit,
|
||||
meaning their orbital period matches Earth's rotation.]]
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
Name = "Satellites Communications - Geostationary",
|
||||
Version = "1.0",
|
||||
Description = [[Satellites asset for Communications - Geostationary. Data from
|
||||
Description = [[Satellites asset for Communications - Geostationary. Data from
|
||||
Celestrak]],
|
||||
Author = "OpenSpace Team",
|
||||
URL = "https://celestrak.com/NORAD/elements/",
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "GlobalStar",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (GlobalStar)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_globalstar",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=globalstar&FORMAT=kvn",
|
||||
Filename = "globalstar.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=globalstar&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "globalstar",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "globalstar.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "GlobalStar",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Gorizont",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Gorizont)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_gorizont",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=gorizont&FORMAT=kvn",
|
||||
Filename = "gorizont.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=gorizont&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "gorizont",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "gorizont.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Gorizont",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Intelsat",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Intelsat)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_intelsat",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=intelsat&FORMAT=kvn",
|
||||
Filename = "intelsat.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=intelsat&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "intelsat",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "intelsat.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Intelsat",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Iridium",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Iridium)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_iridium",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=iridium&FORMAT=kvn",
|
||||
Filename = "iridium.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=iridium&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "iridium",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "iridium.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Iridium",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Iridium NEXT",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Iridium NEXT)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_iridium-NEXT",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=iridium-NEXT&FORMAT=kvn",
|
||||
Filename = "iridium-NEXT.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=iridium-NEXT&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "iridium-NEXT",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "iridium-NEXT.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Iridium NEXT",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Molniya",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Molniya)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_molniya",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=molniya&FORMAT=kvn",
|
||||
Filename = "molniya.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=molniya&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "molniya",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "molniya.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Molniya",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Orbcomm",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Orbcomm)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_orbcomm",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=orbcomm&FORMAT=kvn",
|
||||
Filename = "orbcomm.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=orbcomm&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "orbcomm",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "orbcomm.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Orbcomm",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Other comm",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Other comm)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_other-comm",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=other-comm&FORMAT=kvn",
|
||||
Filename = "other-comm.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=other-comm&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "other-comm",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "other-comm.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Other comm",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Raduga",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Raduga)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_raduga",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=raduga&FORMAT=kvn",
|
||||
Filename = "raduga.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=raduga&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "raduga",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "raduga.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Raduga",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "SES",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (SES)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_ses",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=ses&FORMAT=kvn",
|
||||
Filename = "ses.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=ses&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "ses",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "ses.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "SES",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,16 +1,45 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Starlink",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Starlink)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_starlink",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=starlink&FORMAT=kvn",
|
||||
Filename = "starlink.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=starlink&FORMAT=TLE",
|
||||
TrailColor = { 0.65, 0.55, 0.55 },
|
||||
Description = [[LEO satellite constellation launched by SpaceX to provide
|
||||
broadband internet access]]
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "starlink",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "starlink.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.65, 0.55, 0.55 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Starlink",
|
||||
Path = "/Solar System/Planets/Earth/Satellites",
|
||||
Description = [[LEO satellite constellation launched by SpaceX to provide broadband
|
||||
internet access.]]
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Indian ASAT test Debris",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Indian ASAT test Debris)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_2019-006",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?INTDES=2019-006&FORMAT=kvn",
|
||||
Filename = "2019-006.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?INTDES=2019-006&FORMAT=TLE",
|
||||
TrailColor = { 0.25, 0.35, 0.45 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "2019-006",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "2019-006.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.25, 0.35, 0.45 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Indian ASAT test Debris",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Breeze-M Breakup",
|
||||
Filename = "2021-044.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?INTDES=2012-044&FORMAT=TLE",
|
||||
TrailColor = { 0.25, 0.35, 0.45 }
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Breeze-M Breakup)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_2012-044",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?INTDES=2012-044&FORMAT=kvn",
|
||||
Filename = "2012-044.txt",
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "2012-044",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "2012-044.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.25, 0.35, 0.45 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Breeze-M Breakup",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Fengyun Debris",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Fengyun Debris)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_1999-025",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?INTDES=1999-025&FORMAT=kvn",
|
||||
Filename = "1999-025.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?INTDES=1999-025&FORMAT=TLE",
|
||||
TrailColor = { 0.784, 1.0, 0.737 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "1999-025",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "1999-025.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.784, 1.0, 0.737 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Fengyun Debris",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Iridium 33 Debris",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Iridium 33 Debris)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_iridium-33-debris",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=iridium-33-debris&FORMAT=kvn",
|
||||
Filename = "iridium-33-debris.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=iridium-33-debris&FORMAT=TLE",
|
||||
TrailColor = { 0.8, 0.0, 0.3 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "iridium-33-debris",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "iridium-33-debris.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.8, 0.0, 0.3 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Iridium 33 Debris",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Kosmos 2251 Debris",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Kosmos 2251 Debris)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_cosmos-2251-debris",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=cosmos-2251-debris&FORMAT=kvn",
|
||||
Filename = "cosmos-2251-debris.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=cosmos-2251-debris&FORMAT=TLE",
|
||||
TrailColor = { 0.66, 0.8, 0.5 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "cosmos-2251-debris",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "cosmos-2251-debris.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.66, 0.8, 0.5 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Kosmos 2251 Debris",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,15 +1,44 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Active",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Active)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_active",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=active&FORMAT=kvn",
|
||||
Filename = "active.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=active&FORMAT=TLE",
|
||||
TrailColor = { 0.45, 0.25, 0.45 },
|
||||
Description = "Satellites that employ active communication"
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "active",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "active.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.45, 0.25, 0.45 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Active",
|
||||
Path = "/Solar System/Planets/Earth/Satellites",
|
||||
Description = [[Satellites that employ active communication.]]
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,16 +1,45 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "100 Brightest",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (100 Brightest)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_visual",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=visual&FORMAT=kvn",
|
||||
Filename = "visual.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=visual&FORMAT=TLE",
|
||||
TrailColor = { 0.55, 0.25, 0.65 },
|
||||
Description = [[The 100 (or so) satellites that will appear brightest when viewed
|
||||
from Earth]]
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "visual",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "visual.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.55, 0.25, 0.65 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "100 Brightest",
|
||||
Path = "/Solar System/Planets/Earth/Satellites",
|
||||
Description = [[The 100 (or so) satellites that will appear brightest when viewed
|
||||
from Earth.]]
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "CubeSat",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (CubeSat)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_cubesat",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=cubesat&FORMAT=kvn",
|
||||
Filename = "cubesat.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=cubesat&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "cubesat",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "cubesat.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "CubeSat",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,83 +1,78 @@
|
||||
local transforms = asset.require('scene/solarsystem/planets/earth/transforms')
|
||||
local satelliteHelper = asset.require('util/tle_helper')
|
||||
|
||||
local url = "https://celestrak.com/NORAD/elements/gp.php?CATNR=20580"
|
||||
local identifier = "HST"
|
||||
local filename = "HST.txt"
|
||||
local nodes = {}
|
||||
local tle = satelliteHelper.downloadTLEFile(asset, url, identifier, filename)
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Hubble)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_hst",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?CATNR=20580&FORMAT=kvn",
|
||||
Filename = "hst.txt",
|
||||
Override = true
|
||||
})
|
||||
|
||||
local initializeAndAddNodes = function()
|
||||
local lineElement = satelliteHelper.makeSingleLineElement(tle, filename)
|
||||
local period = satelliteHelper.getPeriodFromElement(lineElement)
|
||||
local path = tle .. "/" .. filename
|
||||
|
||||
local HubblePosition = {
|
||||
Identifier = "HubblePosition",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "TLETranslation",
|
||||
Body = identifier,
|
||||
Observer = transforms.EarthInertial.Identifier,
|
||||
File = path,
|
||||
LineNumber = 1
|
||||
},
|
||||
Rotation = {
|
||||
Type = "SpiceRotation",
|
||||
SourceFrame = "GALACTIC",
|
||||
DestinationFrame = "J2000",
|
||||
}
|
||||
local HubblePosition = {
|
||||
Identifier = "HubblePosition",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "GPTranslation",
|
||||
Observer = transforms.EarthInertial.Identifier,
|
||||
File = omm .. "hst.txt",
|
||||
Format = "OMM"
|
||||
},
|
||||
Tag = { "earth_satellite", "hubble" },
|
||||
GUI = {
|
||||
Name = "Hubble Position",
|
||||
Path = "/Solar System/Planets/Earth/Satellites/Hubble",
|
||||
Hidden = true
|
||||
Rotation = {
|
||||
Type = "SpiceRotation",
|
||||
SourceFrame = "GALACTIC",
|
||||
DestinationFrame = "J2000",
|
||||
}
|
||||
},
|
||||
Tag = { "earth_satellite", "hubble" },
|
||||
GUI = {
|
||||
Name = "Hubble Position",
|
||||
Path = "/Solar System/Planets/Earth/Satellites/Hubble",
|
||||
Hidden = true
|
||||
}
|
||||
}
|
||||
|
||||
local HubbleTrail = {
|
||||
Identifier = "HubbleTrail",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableTrailOrbit",
|
||||
Translation = {
|
||||
Type = "TLETranslation",
|
||||
Body = identifier,
|
||||
Observer = transforms.EarthInertial.Identifier,
|
||||
File = path,
|
||||
LineNumber = 1
|
||||
},
|
||||
RenderBinMode = "PostDeferredTransparent",
|
||||
Color = { 0.0, 0.902, 0.6},
|
||||
Fade = 1.5,
|
||||
Period = period,
|
||||
Resolution = 320
|
||||
local HubbleTrail = {
|
||||
Identifier = "HubbleTrail",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableTrailOrbit",
|
||||
Translation = {
|
||||
Type = "GPTranslation",
|
||||
Observer = transforms.EarthInertial.Identifier,
|
||||
File = omm .. "hst.txt",
|
||||
Format = "OMM"
|
||||
},
|
||||
Tag = { "earth_satellite", "hubble" },
|
||||
GUI = {
|
||||
Name = "Hubble Trail",
|
||||
Path = "/Solar System/Planets/Earth/Satellites/Hubble"
|
||||
}
|
||||
RenderBinMode = "PostDeferredTransparent",
|
||||
Color = { 0.0, 0.902, 0.6},
|
||||
Fade = 1.5,
|
||||
Resolution = 320
|
||||
},
|
||||
Tag = { "earth_satellite", "hubble" },
|
||||
GUI = {
|
||||
Name = "Hubble Trail",
|
||||
Path = "/Solar System/Planets/Earth/Satellites/Hubble"
|
||||
}
|
||||
|
||||
return { HubblePosition, HubbleTrail }
|
||||
end
|
||||
}
|
||||
|
||||
asset.onInitialize(function ()
|
||||
nodes = initializeAndAddNodes()
|
||||
for _, node in ipairs(nodes) do
|
||||
openspace.addSceneGraphNode(node)
|
||||
end
|
||||
local hubble = openspace.space.readKeplerFile(omm .. "hst.txt", "OMM")
|
||||
HubbleTrail.Renderable.Period = hubble[0].Period / (60 * 60 * 24)
|
||||
|
||||
openspace.addSceneGraphNode(HubblePosition)
|
||||
openspace.addSceneGraphNode(HubbleTrail)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function ()
|
||||
for i=1, #nodes do
|
||||
openspace.removeSceneGraphNode(nodes[#nodes + 1 - i].Identifier)
|
||||
end
|
||||
openspace.removeSceneGraphNode(HubbleTrail)
|
||||
openspace.removeSceneGraphNode(HubblePosition)
|
||||
end)
|
||||
|
||||
asset.export(HubblePosition)
|
||||
asset.export(HubbleTrail)
|
||||
|
||||
asset.meta = {
|
||||
Name = "Hubble Space Telescope Trail",
|
||||
Version = "1.0",
|
||||
|
||||
@@ -1,145 +1,142 @@
|
||||
local satelliteHelper = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
local sun = asset.require("scene/solarsystem/sun/sun")
|
||||
|
||||
local url = "http://celestrak.com/NORAD/elements/gp.php?CATNR=25544"
|
||||
local identifier = "ISS"
|
||||
local filename = "ISS.txt"
|
||||
local nodes = {}
|
||||
local tle = satelliteHelper.downloadTLEFile(asset, url, identifier, filename)
|
||||
|
||||
local models = asset.syncedResource({
|
||||
Name = "ISS Models",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "iss_model",
|
||||
Version = 3
|
||||
Name = "ISS Models",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "iss_model",
|
||||
Version = 3
|
||||
})
|
||||
|
||||
local initializeAndAddNodes = function()
|
||||
local lineElement = satelliteHelper.makeSingleLineElement(tle, filename)
|
||||
local period = satelliteHelper.getPeriodFromElement(lineElement)
|
||||
local path = tle .. filename
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (ISS)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_iss",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?CATNR=25544&FORMAT=kvn",
|
||||
Filename = "ISS.txt",
|
||||
Override = true
|
||||
})
|
||||
|
||||
local iss = {
|
||||
Identifier = "ISS",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
BoundingSphere = 54.5, -- half the width
|
||||
InteractionSphere = 30,
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "TLETranslation",
|
||||
Body = identifier,
|
||||
Observer = transforms.EarthInertial.Identifier,
|
||||
File = path,
|
||||
LineNumber = 1
|
||||
},
|
||||
Rotation = {
|
||||
Type = "SpiceRotation",
|
||||
SourceFrame = "GALACTIC",
|
||||
DestinationFrame = "J2000",
|
||||
}
|
||||
local iss = {
|
||||
Identifier = "ISS",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
BoundingSphere = 54.5, -- half the width
|
||||
InteractionSphere = 30,
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "GPTranslation",
|
||||
Observer = transforms.EarthInertial.Identifier,
|
||||
File = omm .. "ISS.txt",
|
||||
Format = "OMM"
|
||||
},
|
||||
Tag = { "earth_satellite", "ISS" },
|
||||
GUI = {
|
||||
Path = "/Solar System/Planets/Earth/Satellites/ISS"
|
||||
Rotation = {
|
||||
Type = "SpiceRotation",
|
||||
SourceFrame = "GALACTIC",
|
||||
DestinationFrame = "J2000",
|
||||
}
|
||||
},
|
||||
Tag = { "earth_satellite", "ISS" },
|
||||
GUI = {
|
||||
Name = "ISS",
|
||||
Path = "/Solar System/Planets/Earth/Satellites/ISS"
|
||||
}
|
||||
}
|
||||
|
||||
local parentNode = {
|
||||
Identifier = "ISSModel",
|
||||
Parent = iss.Identifier,
|
||||
Transform = {
|
||||
Rotation = {
|
||||
Type = "FixedRotation",
|
||||
Attached = "ISSModel",
|
||||
XAxis = { 0.01, -1.0, 0.56 },
|
||||
XAxisOrthogonal = true,
|
||||
YAxis = transforms.EarthInertial.Identifier
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderableModel",
|
||||
GeometryFile = models .. "ISS.fbx",
|
||||
ModelScale = "Centimeter",
|
||||
LightSources = {
|
||||
sun.LightSource
|
||||
},
|
||||
PerformShading = true,
|
||||
DisableFaceCulling = true
|
||||
},
|
||||
GUI = {
|
||||
Name = "ISS Model",
|
||||
Path = "/Solar System/Planets/Earth/Satellites/ISS"
|
||||
local parentNode = {
|
||||
Identifier = "ISSModel",
|
||||
Parent = iss.Identifier,
|
||||
Transform = {
|
||||
Rotation = {
|
||||
Type = "FixedRotation",
|
||||
Attached = "ISSModel",
|
||||
XAxis = { 0.01, -1.0, 0.56 },
|
||||
XAxisOrthogonal = true,
|
||||
YAxis = transforms.EarthInertial.Identifier
|
||||
}
|
||||
}
|
||||
|
||||
local issTrail = {
|
||||
Identifier = identifier .. "_trail",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableTrailOrbit",
|
||||
Translation = {
|
||||
Type = "TLETranslation",
|
||||
Body = identifier,
|
||||
Observer = transforms.EarthInertial.Identifier,
|
||||
File = path,
|
||||
LineNumber = 1,
|
||||
},
|
||||
RenderBinMode = "PostDeferredTransparent",
|
||||
Color = { 0.9, 0.6715, 0.0 },
|
||||
Fade = 1.5,
|
||||
Period = period,
|
||||
Resolution = 320
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderableModel",
|
||||
GeometryFile = models .. "ISS.fbx",
|
||||
ModelScale = "Centimeter",
|
||||
LightSources = {
|
||||
sun.LightSource
|
||||
},
|
||||
Tag = { "earth_satellite", "ISS" },
|
||||
GUI = {
|
||||
Name = "ISS Trail",
|
||||
Path = "/Solar System/Planets/Earth/Satellites/ISS"
|
||||
}
|
||||
PerformShading = true,
|
||||
DisableFaceCulling = true
|
||||
},
|
||||
GUI = {
|
||||
Name = "ISS Model",
|
||||
Path = "/Solar System/Planets/Earth/Satellites/ISS"
|
||||
}
|
||||
}
|
||||
|
||||
-- @TODO (emmbr, 2021-05-27) add to scene when label rendering issues have been fixed
|
||||
local IssLabel = {
|
||||
Identifier = "IssLabel",
|
||||
Parent = iss.Identifier,
|
||||
Renderable = {
|
||||
Enabled = false,
|
||||
Type = "RenderableLabels",
|
||||
Text = "ISS",
|
||||
FontSize = 70.0,
|
||||
Size = 3.4,
|
||||
MinMaxSize = { 1, 100 },
|
||||
OrientationOption = "Camera View Direction",
|
||||
BlendMode = "Additive",
|
||||
EnableFading = true,
|
||||
FadeDistances = { 0.15, 15.0 },
|
||||
FadeWidths = { 1.0, 25.0 }
|
||||
local issTrail = {
|
||||
Identifier = "ISS_trail",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableTrailOrbit",
|
||||
Translation = {
|
||||
Type = "GPTranslation",
|
||||
Observer = transforms.EarthInertial.Identifier,
|
||||
File = omm .. "ISS.txt",
|
||||
Format = "OMM"
|
||||
},
|
||||
Tag = { "solarsystem_labels" },
|
||||
GUI = {
|
||||
Name = "ISS Label",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
RenderBinMode = "PostDeferredTransparent",
|
||||
Color = { 0.9, 0.6715, 0.0 },
|
||||
Fade = 1.5,
|
||||
Resolution = 320
|
||||
},
|
||||
Tag = { "earth_satellite", "ISS" },
|
||||
GUI = {
|
||||
Name = "ISS Trail",
|
||||
Path = "/Solar System/Planets/Earth/Satellites/ISS"
|
||||
}
|
||||
}
|
||||
|
||||
return { iss, parentNode, issTrail }
|
||||
end
|
||||
-- @TODO (emmbr, 2021-05-27) add to scene when label rendering issues have been fixed
|
||||
local IssLabel = {
|
||||
Identifier = "IssLabel",
|
||||
Parent = iss.Identifier,
|
||||
Renderable = {
|
||||
Enabled = false,
|
||||
Type = "RenderableLabels",
|
||||
Text = "ISS",
|
||||
FontSize = 70.0,
|
||||
Size = 3.4,
|
||||
MinMaxSize = { 1, 100 },
|
||||
OrientationOption = "Camera View Direction",
|
||||
BlendMode = "Additive",
|
||||
EnableFading = true,
|
||||
FadeDistances = { 0.15, 15.0 },
|
||||
FadeWidths = { 1.0, 25.0 }
|
||||
},
|
||||
Tag = { "solarsystem_labels" },
|
||||
GUI = {
|
||||
Name = "ISS Label",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function ()
|
||||
nodes = initializeAndAddNodes()
|
||||
for _, node in ipairs(nodes) do
|
||||
openspace.addSceneGraphNode(node)
|
||||
end
|
||||
local i = openspace.space.readKeplerFile(omm .. "ISS.txt", "OMM")
|
||||
issTrail.Renderable.Period = i[0].Period / (60 * 60 * 24)
|
||||
|
||||
openspace.addSceneGraphNode(iss)
|
||||
openspace.addSceneGraphNode(parentNode)
|
||||
openspace.setPropertyValueSingle("Scene.ISSModel.Rotation.yAxisInvertObject", true)
|
||||
openspace.addSceneGraphNode(issTrail)
|
||||
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function ()
|
||||
for i=1, #nodes do
|
||||
openspace.removeSceneGraphNode(nodes[#nodes + 1 - i].Identifier)
|
||||
end
|
||||
openspace.removeSceneGraphNode(issTrail)
|
||||
openspace.removeSceneGraphNode(parentNode)
|
||||
openspace.removeSceneGraphNode(iss)
|
||||
end)
|
||||
|
||||
asset.export(issTrail)
|
||||
asset.export(parentNode)
|
||||
asset.export(iss)
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Military",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Military)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_military",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=military&FORMAT=kvn",
|
||||
Filename = "military.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=military&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "military",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "military.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Military",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Other",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Other)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_other",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=other&FORMAT=kvn",
|
||||
Filename = "other.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=other&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "other",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "other.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Other",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Radar Calibration",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Radar Calibration)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_radar",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=radar&FORMAT=kvn",
|
||||
Filename = "radar.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=radar&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "radar",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "radar.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Radar Calibration",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,17 +1,46 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "SpaceStations",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (SpaceStations)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_stations",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=stations&FORMAT=kvn",
|
||||
Filename = "stations.txt",
|
||||
Url = "https://celestrak.com/NORAD/elements/gp.php?GROUP=stations&FORMAT=TLE",
|
||||
TrailColor = { 0.9, 0.1, 0.0 },
|
||||
Description = [[A collection of space stations (including the ISS and China's
|
||||
Tiangong), along with certain cubesats and satellite constellations from space
|
||||
agencies]]
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "stations",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "stations.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.9, 0.1, 0.0 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "SpaceStations",
|
||||
Path = "/Solar System/Planets/Earth/Satellites",
|
||||
Description = [[A collection of space stations (including the ISS and China's
|
||||
Tiangong), along with certain cubesats and satellite constellations from space
|
||||
agencies.]]
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,15 +1,44 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Last 30 Days",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Last 30 Days)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_tle-new",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=last-30-days&FORMAT=kvn",
|
||||
Filename = "tle-new.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=last-30-days&FORMAT=TLE",
|
||||
TrailColor = { 0.65, 0.25, 0.45 },
|
||||
Description = [[All the satellites that have been launched in the last 30 days]]
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "tle-new",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "tle-new.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.65, 0.25, 0.45 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Last 30 Days",
|
||||
Path = "/Solar System/Planets/Earth/Satellites",
|
||||
Description = [[All the satellites that have been launched in the last 30 days.]]
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Beidou",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Beidou)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_beidou",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=beidou&FORMAT=kvn",
|
||||
Filename = "beidou.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=beidou&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "beidou",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "beidou.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Beidou",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Galileo",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Galileo)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_galileo",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=galileo&FORMAT=kvn",
|
||||
Filename = "galileo.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=galileo&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local galileo = {
|
||||
Identifier = "galileo",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "galileo.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Galileo",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(galileo)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(galileo)
|
||||
end)
|
||||
|
||||
asset.export(galileo)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Glosnass",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Glosnass)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_glo-ops",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=glo-ops&FORMAT=kvn",
|
||||
Filename = "glo-ops.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=glo-ops&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "glo-ops",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "glo-ops.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Glosnass",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,15 +1,44 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "GPS",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (GPS)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_gps-ops",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=gps-ops&FORMAT=kvn",
|
||||
Filename = "gps-ops.txt",
|
||||
Url = "https://celestrak.com/NORAD/elements/gp.php?GROUP=gps-ops&FORMAT=TLE",
|
||||
TrailColor = { 0.9, 0.5, 0.0 },
|
||||
Description = "The GPS satellites that give us our precise locations back here on Earth"
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "gps-ops",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "gps-ops.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.9, 0.5, 0.0 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "GPS",
|
||||
Path = "/Solar System/Planets/Earth/Satellites",
|
||||
Description = [[The GPS satellites that give us our precise locations back on Earth.]]
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Russian LEO Navigation",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Russian LEO Navigation)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_musson",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=musson&FORMAT=kvn",
|
||||
Filename = "musson.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=musson&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "musson",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "musson.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Russian LEO Navigation",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,44 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Navy Navigation Satellite System",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Navy Navigation Satellite System)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_nnss",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=nnss&FORMAT=kvn",
|
||||
Filename = "nnss.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=nnss&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "nnss",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "nnss.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Navy Navigation Satellite System",
|
||||
Path = "/Solar System/Planets/Earth/Satellites",
|
||||
Description = [[The first satellite navigation system to be used operationally.]]
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Satellite Based Augmentation System",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Satellite Based Augmentation System)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_sbas",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=sbas&FORMAT=kvn",
|
||||
Filename = "sbas.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=sbas&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "sbas",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "sbas.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Satellite Based Augmentation System",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Education",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Education)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_education",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=education&FORMAT=kvn",
|
||||
Filename = "education.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=education&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "education",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "education.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Education",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Engineering",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Engineering)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_engineering",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=engineering&FORMAT=kvn",
|
||||
Filename = "engineering.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=engineering&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "engineering",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "engineering.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Engineering",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Geodect",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Geodetic)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_geodetic",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=geodetic&FORMAT=kvn",
|
||||
Filename = "geodetic.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=geodetic&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "geodetic",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "geodetic.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Geodetic",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,21 +1,49 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Space & Earth Science",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Space & Earth Science)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_science",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=science&FORMAT=kvn",
|
||||
Filename = "science.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=science&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "science",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "science.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Space & Earth Science",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
Name = "Satellites Science Space & Earth Science",
|
||||
Version = "1.0",
|
||||
Description = [[Satellites asset for Science Space & Earth Science. Data from
|
||||
Celestrak]],
|
||||
Description = "Satellites asset for Science Space & Earth Science. Data from Celestrak",
|
||||
Author = "OpenSpace Team",
|
||||
URL = "https://celestrak.com/NORAD/elements/",
|
||||
License = "Celestrak"
|
||||
|
||||
@@ -1,111 +1,105 @@
|
||||
local satelliteHelper = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
local sunTransforms = asset.require("scene/solarsystem/sun/transforms")
|
||||
|
||||
local url = "http://celestrak.com/NORAD/elements/gp.php?CATNR=27424"
|
||||
local identifier = "Aqua"
|
||||
local filename = "Aqua.txt"
|
||||
local nodes = {}
|
||||
local tle = satelliteHelper.downloadTLEFile(asset, url, identifier, filename)
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Aqua)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_aqua",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?CATNR=27424&FORMAT=kvn",
|
||||
Filename = "Aqua.txt",
|
||||
Override = true
|
||||
})
|
||||
|
||||
local Aqua = {
|
||||
Identifier = "Aqua",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
InteractionSphere = 30,
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "GPTranslation",
|
||||
Observer = transforms.EarthInertial.Identifier,
|
||||
File = omm .. "Aqua.txt",
|
||||
Format = "OMM"
|
||||
},
|
||||
Rotation = {
|
||||
Type = "SpiceRotation",
|
||||
SourceFrame = "GALACTIC",
|
||||
DestinationFrame = "J2000",
|
||||
}
|
||||
},
|
||||
Tag = { "earth_satellite", "Aqua" },
|
||||
GUI = {
|
||||
Name = "Aqua",
|
||||
Path = "/Solar System/Planets/Earth/Satellites/Aqua"
|
||||
}
|
||||
}
|
||||
|
||||
local AquaTrail = {
|
||||
Identifier = "Aqua_trail",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableTrailOrbit",
|
||||
Translation = {
|
||||
Type = "GPTranslation",
|
||||
Observer = transforms.EarthInertial.Identifier,
|
||||
File = omm .. "Aqua.txt",
|
||||
Format = "OMM",
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Color = { 0.9, 0.6715, 0.0 },
|
||||
Fade = 1.5,
|
||||
Resolution = 320
|
||||
},
|
||||
Tag = { "earth_satellite", "Aqua" },
|
||||
GUI = {
|
||||
Name = "Aqua Trail",
|
||||
Path = "/Solar System/Planets/Earth/Satellites/Aqua"
|
||||
}
|
||||
}
|
||||
|
||||
-- @TODO (emmbr, 2021-05-27) this label is not visible. Too large fade distances?
|
||||
-- Might also be affected by the rendering issues for labels
|
||||
local AquaLabel = {
|
||||
Identifier = "AquaLabel",
|
||||
Parent = Aqua.Identifier,
|
||||
Renderable = {
|
||||
Enabled = false,
|
||||
Type = "RenderableLabels",
|
||||
Text = "Aqua",
|
||||
FontSize = 70.0,
|
||||
Size = 4.0,
|
||||
MinMaxSize = { 1, 100 },
|
||||
OrientationOption = "Camera View Direction",
|
||||
BlendMode = "Additive",
|
||||
EnableFading = true,
|
||||
FadeUnit = "au",
|
||||
FadeDistances = { 1.5, 15.0 },
|
||||
FadeWidths = { 1.0, 25.0 }
|
||||
},
|
||||
Tag = { "solarsystem_labels" },
|
||||
GUI = {
|
||||
Name = "Aqua Label",
|
||||
Path = "/Solar System/Planets/Earth"
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function ()
|
||||
local lineElement = satelliteHelper.makeSingleLineElement(tle, filename)
|
||||
local period = satelliteHelper.getPeriodFromElement(lineElement)
|
||||
local path = tle .. "/" .. filename
|
||||
local a = openspace.space.readKeplerFile(omm .. "Aqua.txt", "OMM")
|
||||
AquaTrail.Renderable.Period = a[0].Period / (60 * 60 * 24)
|
||||
|
||||
local Aqua = {
|
||||
Identifier = "Aqua",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
InteractionSphere = 30,
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "TLETranslation",
|
||||
Body = identifier,
|
||||
Observer = transforms.EarthInertial.Identifier,
|
||||
File = path,
|
||||
LineNumber = 1
|
||||
},
|
||||
Rotation = {
|
||||
Type = "SpiceRotation",
|
||||
SourceFrame = "GALACTIC",
|
||||
DestinationFrame = "J2000",
|
||||
}
|
||||
},
|
||||
Tag = { "earth_satellite", "Aqua" },
|
||||
GUI = {
|
||||
Path = "/Solar System/Planets/Earth/Satellites/Aqua"
|
||||
}
|
||||
}
|
||||
|
||||
local AquaTrail = {
|
||||
Identifier = identifier .. "_trail",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableTrailOrbit",
|
||||
Translation = {
|
||||
Type = "TLETranslation",
|
||||
Body = identifier,
|
||||
Observer = transforms.EarthInertial.Identifier,
|
||||
File = path,
|
||||
LineNumber = 1,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Color = { 0.9, 0.6715, 0.0 },
|
||||
Fade = 1.5,
|
||||
Period = period,
|
||||
Resolution = 320
|
||||
},
|
||||
Tag = { "earth_satellite", "Aqua" },
|
||||
GUI = {
|
||||
Name = "Aqua Trail",
|
||||
Path = "/Solar System/Planets/Earth/Satellites/Aqua"
|
||||
}
|
||||
}
|
||||
|
||||
-- @TODO (emmbr, 2021-05-27) this label is not visible. Too large fade distances?
|
||||
-- Might also be affected by the rendering issues for labels
|
||||
local AquaLabel = {
|
||||
Identifier = "AquaLabel",
|
||||
Parent = Aqua.Identifier,
|
||||
Renderable = {
|
||||
Enabled = false,
|
||||
Type = "RenderableLabels",
|
||||
Text = "Aqua",
|
||||
FontSize = 70.0,
|
||||
Size = 4.0,
|
||||
MinMaxSize = { 1, 100 },
|
||||
OrientationOption = "Camera View Direction",
|
||||
BlendMode = "Additive",
|
||||
EnableFading = true,
|
||||
FadeUnit = "au",
|
||||
FadeDistances = { 1.5, 15.0 },
|
||||
FadeWidths = { 1.0, 25.0 }
|
||||
},
|
||||
Tag = { "solarsystem_labels" },
|
||||
GUI = {
|
||||
Name = "Aqua Label",
|
||||
Path = "/Solar System/Planets/Earth"
|
||||
}
|
||||
}
|
||||
|
||||
table.insert(nodes, Aqua)
|
||||
table.insert(nodes, AquaTrail)
|
||||
table.insert(nodes, AquaLabel)
|
||||
for _, node in ipairs(nodes) do
|
||||
openspace.addSceneGraphNode(node)
|
||||
end
|
||||
openspace.addSceneGraphNode(Aqua)
|
||||
openspace.addSceneGraphNode(AquaTrail)
|
||||
openspace.addSceneGraphNode(AquaLabel)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function ()
|
||||
for _, node in ipairs(nodes) do
|
||||
openspace.removeSceneGraphNode(node)
|
||||
end
|
||||
openspace.removeSceneGraphNode(AquaLabel)
|
||||
openspace.removeSceneGraphNode(AquaTrail)
|
||||
openspace.removeSceneGraphNode(Aqua)
|
||||
end)
|
||||
|
||||
for _, node in ipairs(nodes) do
|
||||
asset.export(node)
|
||||
end
|
||||
asset.export(Aqua)
|
||||
asset.export(AquaTrail)
|
||||
asset.export(AquaLabel)
|
||||
|
||||
asset.meta = {
|
||||
Name = "Aqua",
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "ARGOS",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (ARGOS)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_argos",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=argos&FORMAT=kvn",
|
||||
Filename = "argos.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=argos&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "argos",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "argos.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "ARGOS",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,21 +1,49 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Disaster Monitoring",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Disaster Monitoring)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_dmc",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=dmc&FORMAT=kvn",
|
||||
Filename = "dmc.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=dmc&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "dmc",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "dmc.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Disaster Monitoring",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
Name = "Satellites Weather - Disaster Monitoring",
|
||||
Version = "1.0",
|
||||
Description = [[Satellites asset for Weather - Disaster Monitoring. Data from
|
||||
Celestrak]],
|
||||
Description = "Satellites asset for Weather - Disaster Monitoring. Data from Celestrak",
|
||||
Author = "OpenSpace Team",
|
||||
URL = "https://celestrak.com/NORAD/elements/",
|
||||
License = "Celestrak"
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Earth Resources",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Earth Resources)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_resource",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=resource&FORMAT=kvn",
|
||||
Filename = "resource.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=resource&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "resource",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "resource.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Earth Resources",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "GOES",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (GOES)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_goes",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=goes&FORMAT=kvn",
|
||||
Filename = "goes.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=goes&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "goes",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "goes.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "GOES",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "NOAA",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (NOAA)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_noaa",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=noaa&FORMAT=kvn",
|
||||
Filename = "noaa.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=noaa&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "noaa",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "noaa.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "NOAA",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Planet",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Planet)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_planet",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=planet&FORMAT=kvn",
|
||||
Filename = "planet.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=planet&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "planet",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "planet.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Planet",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Search & Rescue (SARSAT)",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Search & Rescue (SARSAT))",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_sarsat",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=sarsat&FORMAT=kvn",
|
||||
Filename = "sarsat.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=sarsat&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "sarsat",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "sarsat.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Search & Rescue (SARSAT)",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,110 +1,104 @@
|
||||
local satelliteHelper = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
local sunTransforms = asset.require("scene/solarsystem/sun/transforms")
|
||||
|
||||
local url = "http://celestrak.com/NORAD/elements/gp.php?CATNR=37849"
|
||||
local identifier = "SNPP"
|
||||
local filename = "SNPP.txt"
|
||||
local nodes = {}
|
||||
local tle = satelliteHelper.downloadTLEFile(asset, url, identifier, filename)
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (SNPP)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_snpp",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?CATNR=37849&FORMAT=kvn",
|
||||
Filename = "SNPP.txt",
|
||||
Override = true
|
||||
})
|
||||
|
||||
local SNPP = {
|
||||
Identifier = "SNPP",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
InteractionSphere = 30,
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "GPTranslation",
|
||||
Observer = transforms.EarthInertial.Identifier,
|
||||
File = omm .. "SNPP.txt",
|
||||
Format = "OMM"
|
||||
},
|
||||
Rotation = {
|
||||
Type = "SpiceRotation",
|
||||
SourceFrame = "GALACTIC",
|
||||
DestinationFrame = "J2000",
|
||||
}
|
||||
},
|
||||
Tag = { "earth_satellite", "SNPP" },
|
||||
GUI = {
|
||||
Name = "SNPP",
|
||||
Path = "/Solar System/Planets/Earth/Satellites/SNPP"
|
||||
}
|
||||
}
|
||||
|
||||
local SNPPTrail = {
|
||||
Identifier = "SNPP_trail",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableTrailOrbit",
|
||||
Translation = {
|
||||
Type = "GPTranslation",
|
||||
Observer = transforms.EarthInertial.Identifier,
|
||||
File = omm .. "SNPP.txt",
|
||||
Format = "OMM",
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Color = { 0.9, 0.6715, 0.0 },
|
||||
Fade = 1.5,
|
||||
Resolution = 320
|
||||
},
|
||||
Tag = { "earth_satellite", "SNPP" },
|
||||
GUI = {
|
||||
Name = "SNPP Trail",
|
||||
Path = "/Solar System/Planets/Earth/Satellites/SNPP"
|
||||
}
|
||||
}
|
||||
|
||||
local SNPPLabel = {
|
||||
Identifier = "SNPPLabel",
|
||||
Parent = SNPP.Identifier,
|
||||
Renderable = {
|
||||
Enabled = false,
|
||||
Type = "RenderableLabels",
|
||||
Text = "SNPP",
|
||||
FontSize = 70.0,
|
||||
Size = 4.0,
|
||||
MinMaxSize = { 1, 100 },
|
||||
OrientationOption = "Camera View Direction",
|
||||
BlendMode = "Additive",
|
||||
EnableFading = true,
|
||||
FadeUnit = "au",
|
||||
FadeDistances = { 1.5, 15.0 },
|
||||
FadeWidths = { 1.0, 25.0 }
|
||||
},
|
||||
Tag = { "solarsystem_labels" },
|
||||
GUI = {
|
||||
Name = "SNPP Label",
|
||||
Path = "/Solar System/Planets/Earth"
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function ()
|
||||
local lineElement = satelliteHelper.makeSingleLineElement(tle, filename)
|
||||
local period = satelliteHelper.getPeriodFromElement(lineElement)
|
||||
local path = tle .. "/" .. filename
|
||||
|
||||
local SNPP = {
|
||||
Identifier = "SNPP",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
InteractionSphere = 30,
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "TLETranslation",
|
||||
Body = identifier,
|
||||
Observer = transforms.EarthInertial.Identifier,
|
||||
File = path,
|
||||
LineNumber = 1
|
||||
},
|
||||
Rotation = {
|
||||
Type = "SpiceRotation",
|
||||
SourceFrame = "GALACTIC",
|
||||
DestinationFrame = "J2000",
|
||||
}
|
||||
},
|
||||
Tag = { "earth_satellite", "SNPP" },
|
||||
GUI = {
|
||||
Path = "/Solar System/Planets/Earth/Satellites/SNPP"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
local SNPPTrail = {
|
||||
Identifier = identifier .. "_trail",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableTrailOrbit",
|
||||
Translation = {
|
||||
Type = "TLETranslation",
|
||||
Body = identifier,
|
||||
Observer = transforms.EarthInertial.Identifier,
|
||||
File = path,
|
||||
LineNumber = 1,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Color = { 0.9, 0.6715, 0.0 },
|
||||
Fade = 1.5,
|
||||
Period = period,
|
||||
Resolution = 320
|
||||
},
|
||||
Tag = { "earth_satellite", "SNPP" },
|
||||
GUI = {
|
||||
Name = "SNPP Trail",
|
||||
Path = "/Solar System/Planets/Earth/Satellites/SNPP"
|
||||
}
|
||||
}
|
||||
|
||||
local SNPPLabel = {
|
||||
Identifier = "SNPPLabel",
|
||||
Parent = SNPP.Identifier,
|
||||
|
||||
Renderable = {
|
||||
Enabled = false,
|
||||
Type = "RenderableLabels",
|
||||
Text = "SNPP",
|
||||
FontSize = 70.0,
|
||||
Size = 4.0,
|
||||
MinMaxSize = { 1, 100 },
|
||||
OrientationOption = "Camera View Direction",
|
||||
BlendMode = "Additive",
|
||||
EnableFading = true,
|
||||
FadeUnit = "au",
|
||||
FadeDistances = { 1.5, 15.0 },
|
||||
FadeWidths = { 1.0, 25.0 }
|
||||
},
|
||||
Tag = { "solarsystem_labels" },
|
||||
GUI = {
|
||||
Name = "SNPP Label",
|
||||
Path = "/Solar System/Planets/Earth"
|
||||
}
|
||||
}
|
||||
|
||||
table.insert(nodes, SNPP)
|
||||
table.insert(nodes, SNPPTrail)
|
||||
table.insert(nodes, SNPPLabel)
|
||||
for _, node in ipairs(nodes) do
|
||||
openspace.addSceneGraphNode(node)
|
||||
end
|
||||
local s = openspace.space.readKeplerFile(omm .. "SNPP.txt", "OMM")
|
||||
SNPPTrail.Renderable.Period = s[0].Period / (60 * 60 * 24)
|
||||
|
||||
openspace.addSceneGraphNode(SNPP)
|
||||
openspace.addSceneGraphNode(SNPPTrail)
|
||||
openspace.addSceneGraphNode(SNPPLabel)
|
||||
end)
|
||||
|
||||
|
||||
asset.onDeinitialize(function ()
|
||||
for _, node in ipairs(nodes) do
|
||||
openspace.removeSceneGraphNode(node)
|
||||
end
|
||||
openspace.removeSceneGraphNode(SNPPLabel)
|
||||
openspace.removeSceneGraphNode(SNPPTrail)
|
||||
openspace.removeSceneGraphNode(SNPP)
|
||||
end)
|
||||
|
||||
asset.export(SNPP)
|
||||
asset.export(SNPPTrail)
|
||||
asset.export(SNPPLabel)
|
||||
|
||||
|
||||
asset.meta = {
|
||||
Name = "SNPP",
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Spire",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Spire)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_spire",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=spire&FORMAT=kvn",
|
||||
Filename = "spire.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=spire&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "spire",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "spire.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Spire",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Tracking and Data Relay Satellite System (TDRSS)",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Tracking and Data Relay Satellite System (TDRSS))",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_tdrss",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=tdrss&FORMAT=kvn",
|
||||
Filename = "tdrss.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=tdrss&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "tdrss",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "tdrss.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Tracking and Data Relay Satellite System (TDRSS)",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,110 +1,107 @@
|
||||
local satelliteHelper = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
local sunTransforms = asset.require("scene/solarsystem/sun/transforms")
|
||||
|
||||
local url = "http://celestrak.com/NORAD/elements/gp.php?CATNR=25994"
|
||||
local identifier = "Terra"
|
||||
local filename = "Terra.txt"
|
||||
local nodes = {}
|
||||
local tle = satelliteHelper.downloadTLEFile(asset, url, identifier, filename)
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Terra)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_terra",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?CATNR=25994&FORMAT=kvn",
|
||||
Filename = "Terra.txt",
|
||||
Override = true
|
||||
})
|
||||
|
||||
|
||||
asset.onInitialize(function ()
|
||||
local lineElement = satelliteHelper.makeSingleLineElement(tle, filename)
|
||||
local period = satelliteHelper.getPeriodFromElement(lineElement)
|
||||
local path = tle .. "/" .. filename
|
||||
|
||||
local Terra = {
|
||||
Identifier = "Terra",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
InteractionSphere = 30,
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "TLETranslation",
|
||||
Body = identifier,
|
||||
Observer = transforms.EarthInertial.Identifier,
|
||||
File = path,
|
||||
LineNumber = 1
|
||||
},
|
||||
Rotation = {
|
||||
Type = "SpiceRotation",
|
||||
SourceFrame = "GALACTIC",
|
||||
DestinationFrame = "J2000",
|
||||
}
|
||||
local Terra = {
|
||||
Identifier = "Terra",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
InteractionSphere = 30,
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "GPTranslation",
|
||||
Observer = transforms.EarthInertial.Identifier,
|
||||
File = omm .. "Terra.txt",
|
||||
Format = "OMM"
|
||||
},
|
||||
Tag = { "earth_satellite", "Terra" },
|
||||
GUI = {
|
||||
Path = "/Solar System/Planets/Earth/Satellites/Terra"
|
||||
Rotation = {
|
||||
Type = "SpiceRotation",
|
||||
SourceFrame = "GALACTIC",
|
||||
DestinationFrame = "J2000",
|
||||
}
|
||||
},
|
||||
Tag = { "earth_satellite", "Terra" },
|
||||
GUI = {
|
||||
Name = "Terra",
|
||||
Path = "/Solar System/Planets/Earth/Satellites/Terra"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
local TerraTrail = {
|
||||
Identifier = identifier .. "_trail",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableTrailOrbit",
|
||||
Translation = {
|
||||
Type = "TLETranslation",
|
||||
Body = identifier,
|
||||
Observer = transforms.EarthInertial.Identifier,
|
||||
File = path,
|
||||
LineNumber = 1,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Color = { 0.9, 0.6715, 0.0 },
|
||||
Fade = 1.5,
|
||||
Period = period,
|
||||
Resolution = 320
|
||||
local TerraTrail = {
|
||||
Identifier = "Terra_trail",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableTrailOrbit",
|
||||
Translation = {
|
||||
Type = "GPTranslation",
|
||||
Observer = transforms.EarthInertial.Identifier,
|
||||
File = omm .. "Terra.txt",
|
||||
Format = "OMM",
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellite", "Terra" },
|
||||
GUI = {
|
||||
Name = "Terra Trail",
|
||||
Path = "/Solar System/Planets/Earth/Satellites/Terra"
|
||||
}
|
||||
Color = { 0.9, 0.6715, 0.0 },
|
||||
Fade = 1.5,
|
||||
Resolution = 320
|
||||
},
|
||||
Tag = { "earth_satellite", "Terra" },
|
||||
GUI = {
|
||||
Name = "Terra Trail",
|
||||
Path = "/Solar System/Planets/Earth/Satellites/Terra"
|
||||
}
|
||||
}
|
||||
|
||||
-- @TODO (emmbr, 2021-05-27) this label is not visible. Too large fade distances?
|
||||
-- Might also be affected by the rendering issues for labels
|
||||
local TerraLabel = {
|
||||
Identifier = "TerraLabel",
|
||||
Parent = Terra.Identifier,
|
||||
Renderable = {
|
||||
Enabled = false,
|
||||
Type = "RenderableLabels",
|
||||
Text = "Terra",
|
||||
FontSize = 70.0,
|
||||
Size = 4.0,
|
||||
MinMaxSize = { 1, 100 },
|
||||
OrientationOption = "Camera View Direction",
|
||||
BlendMode = "Additive",
|
||||
EnableFading = true,
|
||||
FadeUnit = "au",
|
||||
FadeDistances = { 1.5, 15.0 },
|
||||
FadeWidths = { 1.0, 25.0 }
|
||||
},
|
||||
Tag = { "solarsystem_labels" },
|
||||
GUI = {
|
||||
Name = "Terra Label",
|
||||
Path = "/Solar System/Planets/Earth"
|
||||
}
|
||||
-- @TODO (emmbr, 2021-05-27) this label is not visible. Too large fade distances?
|
||||
-- Might also be affected by the rendering issues for labels
|
||||
local TerraLabel = {
|
||||
Identifier = "TerraLabel",
|
||||
Parent = Terra.Identifier,
|
||||
Renderable = {
|
||||
Enabled = false,
|
||||
Type = "RenderableLabels",
|
||||
Text = "Terra",
|
||||
FontSize = 70.0,
|
||||
Size = 4.0,
|
||||
MinMaxSize = { 1, 100 },
|
||||
OrientationOption = "Camera View Direction",
|
||||
BlendMode = "Additive",
|
||||
EnableFading = true,
|
||||
FadeUnit = "au",
|
||||
FadeDistances = { 1.5, 15.0 },
|
||||
FadeWidths = { 1.0, 25.0 }
|
||||
},
|
||||
Tag = { "solarsystem_labels" },
|
||||
GUI = {
|
||||
Name = "Terra Label",
|
||||
Path = "/Solar System/Planets/Earth"
|
||||
}
|
||||
}
|
||||
|
||||
table.insert(nodes, Terra)
|
||||
table.insert(nodes, TerraTrail)
|
||||
table.insert(nodes, TerraLabel)
|
||||
for _, node in ipairs(nodes) do
|
||||
openspace.addSceneGraphNode(node)
|
||||
end
|
||||
asset.onInitialize(function()
|
||||
local t = openspace.space.readKeplerFile(omm .. "Terra.txt", "OMM")
|
||||
TerraTrail.Renderable.Period = t[0].Period / (60 * 60 * 24)
|
||||
|
||||
openspace.addSceneGraphNode(Terra)
|
||||
openspace.addSceneGraphNode(TerraTrail)
|
||||
openspace.addSceneGraphNode(TerraLabel)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function ()
|
||||
for _, node in ipairs(nodes) do
|
||||
openspace.removeSceneGraphNode(node)
|
||||
end
|
||||
openspace.removeSceneGraphNode(TerraLabel)
|
||||
openspace.removeSceneGraphNode(TerraTrail)
|
||||
openspace.removeSceneGraphNode(Terra)
|
||||
end)
|
||||
|
||||
asset.export(Terra)
|
||||
asset.export(TerraTrail)
|
||||
asset.export(TerraLabel)
|
||||
|
||||
|
||||
asset.meta = {
|
||||
Name = "Terra",
|
||||
|
||||
@@ -1,14 +1,43 @@
|
||||
local shared = asset.require("util/tle_helper")
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
local group = {
|
||||
Title = "Weather",
|
||||
local omm = asset.syncedResource({
|
||||
Name = "Satellite OMM Data (Weather)",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_omm_data_weather",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=weather&FORMAT=kvn",
|
||||
Filename = "weather.txt",
|
||||
Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=weather&FORMAT=TLE",
|
||||
TrailColor = { 0.75, 0.75, 0.35 }
|
||||
Override = true
|
||||
})
|
||||
|
||||
local satellites = {
|
||||
Identifier = "weather",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = omm .. "weather.txt",
|
||||
Format = "OMM",
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.75, 0.75, 0.35 },
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = "Weather",
|
||||
Path = "/Solar System/Planets/Earth/Satellites"
|
||||
}
|
||||
}
|
||||
|
||||
local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename)
|
||||
shared.registerSatelliteGroupObjects(asset, group, tle, true)
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(satellites)
|
||||
end)
|
||||
|
||||
asset.export(satellites)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,16 +1,31 @@
|
||||
local sharedSssb = asset.require("./sssb_shared")
|
||||
local transforms = asset.require("scene/solarsystem/sun/transforms")
|
||||
|
||||
local filepath = sharedSssb.downloadSssbDatabaseFile(asset, "amor_asteroid",
|
||||
"sssb_data_amor_asteroid")
|
||||
local object = sharedSssb.createSssbGroupObject("sssb_data_amor_asteroid.csv",
|
||||
"Amor Asteroids", filepath, { 1.0, 1.0, 1.0 })
|
||||
object.Renderable.Enabled = false
|
||||
object.Renderable.SegmentQuality = 4
|
||||
object.Renderable.TrailFade = 11
|
||||
|
||||
object.GUI.Description = [[Earth-approaching Near-Earth-Asteroids with orbits exterior to
|
||||
Earth's but interior to Mars']]
|
||||
local sssb = asset.syncedResource({
|
||||
Name = "Small SolarSystem Body Data (Amor Asteroid)",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "sssb_data_amor_asteroid",
|
||||
Version = 1
|
||||
})
|
||||
|
||||
local object = {
|
||||
Identifier = "sssb_amor_asteroid",
|
||||
Parent = transforms.SunECLIPJ2000.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = sssb .. "sssb_data_amor_asteroid.csv",
|
||||
Format = "SBDB",
|
||||
Segments = 200,
|
||||
SegmentQuality = 4,
|
||||
Color = { 1.0, 1.0, 1.0 },
|
||||
TrailFade = 11
|
||||
},
|
||||
GUI = {
|
||||
Name = "Amor Asteroids",
|
||||
Path = "/Solar System/Small Bodies",
|
||||
Description = [[Earth-approaching Near-Earth-Asteroids with orbits exterior to
|
||||
Earth's but interior to Mars'.]]
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(object)
|
||||
|
||||
@@ -1,15 +1,31 @@
|
||||
local sharedSssb = asset.require("./sssb_shared")
|
||||
local transforms = asset.require("scene/solarsystem/sun/transforms")
|
||||
|
||||
local filepath = sharedSssb.downloadSssbDatabaseFile(asset, "apollo_asteroid",
|
||||
"sssb_data_apollo_asteroid")
|
||||
local object = sharedSssb.createSssbGroupObject("sssb_data_apollo_asteroid.csv",
|
||||
"Apollo Asteroids", filepath, { 0.7, 0.7, 1.0 })
|
||||
object.Renderable.Enabled = false
|
||||
object.Renderable.SegmentQuality = 6
|
||||
object.Renderable.TrailFade = 10
|
||||
local sssb = asset.syncedResource({
|
||||
Name = "Small SolarSystem Body Data (Apollo Asteroid)",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "sssb_data_apollo_asteroid",
|
||||
Version = 1
|
||||
})
|
||||
|
||||
object.GUI.Description = [[Earth-crossing Near-Earth-Asteroids with semi-major axes
|
||||
larger than Earth's. ]]
|
||||
local object = {
|
||||
Identifier = "sssb_apollo_asteroid",
|
||||
Parent = transforms.SunECLIPJ2000.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = sssb .. "sssb_data_apollo_asteroid.csv",
|
||||
Format = "SBDB",
|
||||
Segments = 200,
|
||||
SegmentQuality = 6,
|
||||
Color = { 0.7, 0.7, 1.0 },
|
||||
TrailFade = 10
|
||||
},
|
||||
GUI = {
|
||||
Name = "Apollo Asteroids",
|
||||
Path = "/Solar System/Small Bodies",
|
||||
Description = [[Earth-crossing Near-Earth-Asteroids with semi-major axes larger than
|
||||
Earth's.]]
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(object)
|
||||
|
||||
@@ -1,16 +1,31 @@
|
||||
local sharedSssb = asset.require("./sssb_shared")
|
||||
local transforms = asset.require("scene/solarsystem/sun/transforms")
|
||||
|
||||
local filepath = sharedSssb.downloadSssbDatabaseFile(asset, "aten_asteroid",
|
||||
"sssb_data_aten_asteroid")
|
||||
local object = sharedSssb.createSssbGroupObject("sssb_data_aten_asteroid.csv",
|
||||
"Aten Asteroids", filepath, { 0.15, 0.15, 1.0 })
|
||||
object.Renderable.Enabled = false
|
||||
object.Renderable.SegmentQuality = 2
|
||||
object.Renderable.TrailFade = 18
|
||||
|
||||
object.GUI.Description = [[ Earth-crossing Near-Earth-Asteroids with semi-major axes
|
||||
smaller than Earth's. ]]
|
||||
local sssb = asset.syncedResource({
|
||||
Name = "Small SolarSystem Body Data (Aten Asteroid)",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "sssb_data_aten_asteroid",
|
||||
Version = 1
|
||||
})
|
||||
|
||||
local object = {
|
||||
Identifier = "sssb_aten_asteroid",
|
||||
Parent = transforms.SunECLIPJ2000.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = sssb .. "sssb_data_aten_asteroid.csv",
|
||||
Format = "SBDB",
|
||||
Segments = 200,
|
||||
SegmentQuality = 2,
|
||||
Color = { 0.15, 0.15, 1.0 },
|
||||
TrailFade = 18
|
||||
},
|
||||
GUI = {
|
||||
Name = "Aten Asteroids",
|
||||
Path = "/Solar System/Small Bodies",
|
||||
Description = [[Earth-crossing Near-Earth-Asteroids with semi-major axes smaller than
|
||||
Earth's.]]
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(object)
|
||||
|
||||
@@ -1,16 +1,31 @@
|
||||
local sharedSssb = asset.require("./sssb_shared")
|
||||
local transforms = asset.require("scene/solarsystem/sun/transforms")
|
||||
|
||||
local filepath = sharedSssb.downloadSssbDatabaseFile(asset, "atira_asteroid",
|
||||
"sssb_data_atira_asteroid")
|
||||
local object = sharedSssb.createSssbGroupObject("sssb_data_atira_asteroid.csv",
|
||||
"Atira Asteroids", filepath, { 0.5, 0.8, 1.0 })
|
||||
object.Renderable.Enabled = false
|
||||
object.Renderable.SegmentQuality = 2
|
||||
object.Renderable.TrailFade = 25
|
||||
|
||||
object.GUI.Description = [[ Near-Earth-Asteroids whose orbits are contained entirely
|
||||
within the orbit of the Earth. ]]
|
||||
local sssb = asset.syncedResource({
|
||||
Name = "Small SolarSystem Body Data (Atira Asteroid)",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "sssb_data_atira_asteroid",
|
||||
Version = 1
|
||||
})
|
||||
|
||||
local object = {
|
||||
Identifier = "sssb_atira_asteroid",
|
||||
Parent = transforms.SunECLIPJ2000.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = sssb .. "sssb_data_atira_asteroid.csv",
|
||||
Format = "SBDB",
|
||||
Segments = 200,
|
||||
SegmentQuality = 2,
|
||||
Color = { 0.5, 0.8, 1.0 },
|
||||
TrailFade = 25
|
||||
},
|
||||
GUI = {
|
||||
Name = "Atira Asteroids",
|
||||
Path = "/Solar System/Small Bodies",
|
||||
Description = [[Near-Earth-Asteroids whose orbits are contained entirely within the
|
||||
orbit of the Earth.]]
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(object)
|
||||
|
||||
@@ -68,7 +68,7 @@ asset.export(C2019Y4AtlasTrail)
|
||||
asset.meta = {
|
||||
Name = "C/2019 Y4 Atlas",
|
||||
Version = "1.2",
|
||||
Description = [[This asset contains the trail and position of C/2019 Y4 Atlas from
|
||||
Description = [[This asset contains the trail and position of C/2019 Y4 Atlas from
|
||||
1950 JAN 01 00:00:00 to 2100 JAN 01 00:00:00. Data from JPL Horizons]],
|
||||
Author = "OpenSpace Team",
|
||||
URL = "https://ssd.jpl.nasa.gov/horizons.cgi",
|
||||
|
||||
@@ -1,16 +1,31 @@
|
||||
local sharedSssb = asset.require("./sssb_shared")
|
||||
local transforms = asset.require("scene/solarsystem/sun/transforms")
|
||||
|
||||
local filepath = sharedSssb.downloadSssbDatabaseFile(asset, "centaur_asteroid",
|
||||
"sssb_data_centaur_asteroid")
|
||||
local object = sharedSssb.createSssbGroupObject("sssb_data_centaur_asteroid.csv",
|
||||
"Centaur Asteroids", filepath, { 0.94, 0.96, 0.94 })
|
||||
object.Renderable.Enabled = false
|
||||
object.Renderable.SegmentQuality = 6
|
||||
object.Renderable.TrailFade = 18
|
||||
|
||||
object.GUI.Description = [[ Asteroids with either a perihelion or a semi-major axis
|
||||
between those of the four outer planets. ]]
|
||||
local sssb = asset.syncedResource({
|
||||
Name = "Small SolarSystem Body Data (Centaur Asteroid)",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "sssb_data_centaur_asteroid",
|
||||
Version = 1
|
||||
})
|
||||
|
||||
local object = {
|
||||
Identifier = "sssb_centaur_asteroid",
|
||||
Parent = transforms.SunECLIPJ2000.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = sssb .. "sssb_data_centaur_asteroid.csv",
|
||||
Format = "SBDB",
|
||||
Segments = 200,
|
||||
SegmentQuality = 6,
|
||||
Color = { 0.94, 0.96, 0.94 },
|
||||
TrailFade = 18
|
||||
},
|
||||
GUI = {
|
||||
Name = "Centaur Asteroids",
|
||||
Path = "/Solar System/Small Bodies",
|
||||
Description = [[Asteroids with either a perihelion or a semi-major axis between those
|
||||
of the four outer planets.]]
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(object)
|
||||
|
||||
@@ -1,16 +1,31 @@
|
||||
local sharedSssb = asset.require("./sssb_shared")
|
||||
local transforms = asset.require("scene/solarsystem/sun/transforms")
|
||||
|
||||
local filepath = sharedSssb.downloadSssbDatabaseFile(asset, "chiron-type_comet",
|
||||
"sssb_data_chiron-type_comet")
|
||||
local object = sharedSssb.createSssbGroupObject("sssb_data_chiron-type_comet.csv",
|
||||
"Chiron-type Comets", filepath, { 0.15 ,0.1 ,1.0 })
|
||||
object.Renderable.Enabled = false
|
||||
object.Renderable.SegmentQuality = 10
|
||||
object.Renderable.TrailFade = 25
|
||||
|
||||
object.GUI.Description = [[ Comets with a Tisserand's parameter with respect to Jupiter of
|
||||
greater than 3 and a semi-major axis greater than that of Jupiter. ]]
|
||||
local sssb = asset.syncedResource({
|
||||
Name = "Small SolarSystem Body Data (Chiron-type Comet)",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "sssb_data_chiron-type_comet",
|
||||
Version = 1
|
||||
})
|
||||
|
||||
local object = {
|
||||
Identifier = "sssb_chiron-type_comet",
|
||||
Parent = transforms.SunECLIPJ2000.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = sssb .. "sssb_data_chiron-type_comet.csv",
|
||||
Format = "SBDB",
|
||||
Segments = 200,
|
||||
SegmentQuality = 10,
|
||||
Color = { 0.15, 0.1, 1.0 },
|
||||
TrailFade = 25
|
||||
},
|
||||
GUI = {
|
||||
Name = "Chiron-type Comets",
|
||||
Path = "/Solar System/Small Bodies",
|
||||
Description = [[Comets with a Tisserand's parameter with respect to Jupiter of
|
||||
greater than 3 and a semi-major axis greater than that of Jupiter.]]
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(object)
|
||||
|
||||
@@ -1,16 +1,31 @@
|
||||
local sharedSssb = asset.require("./sssb_shared")
|
||||
local transforms = asset.require("scene/solarsystem/sun/transforms")
|
||||
|
||||
local filepath = sharedSssb.downloadSssbDatabaseFile(asset, "encke-type_comet",
|
||||
"sssb_data_encke-type_comet")
|
||||
local object = sharedSssb.createSssbGroupObject("sssb_data_encke-type_comet.csv",
|
||||
"Encke-type Comets", filepath, { 0.8, 0.34, 1.0 })
|
||||
object.Renderable.Enabled = false
|
||||
object.Renderable.SegmentQuality = 2
|
||||
object.Renderable.TrailFade = 23
|
||||
|
||||
object.GUI.Description = [[ Comets with a Tisserand's parameter with respect to Jupiter of
|
||||
greater than 3 and a semi-major axis less than that of Jupiter. ]]
|
||||
local sssb = asset.syncedResource({
|
||||
Name = "Small SolarSystem Body Data (Encke-type Comet)",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "sssb_data_encke-type_comet",
|
||||
Version = 1
|
||||
})
|
||||
|
||||
local object = {
|
||||
Identifier = "sssb_encke-type_comet",
|
||||
Parent = transforms.SunECLIPJ2000.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = sssb .. "sssb_data_encke-type_comet.csv",
|
||||
Format = "SBDB",
|
||||
Segments = 200,
|
||||
SegmentQuality = 2,
|
||||
Color = { 0.8, 0.34, 1.0 },
|
||||
TrailFade = 23
|
||||
},
|
||||
GUI = {
|
||||
Name = "Encke-type Comets",
|
||||
Path = "/Solar System/Small Bodies",
|
||||
Description = [[Comets with a Tisserand's parameter with respect to Jupiter of
|
||||
greater than 3 and a semi-major axis less than that of Jupiter.]]
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(object)
|
||||
|
||||
@@ -1,15 +1,30 @@
|
||||
local sharedSssb = asset.require("./sssb_shared")
|
||||
local transforms = asset.require("scene/solarsystem/sun/transforms")
|
||||
|
||||
local filepath = sharedSssb.downloadSssbDatabaseFile(asset, "halley-type_comet",
|
||||
"sssb_data_halley-type_comet")
|
||||
local object = sharedSssb.createSssbGroupObject("sssb_data_halley-type_comet.csv",
|
||||
"Halley-type Comets", filepath, { 0.66, 0.66, 0.66 })
|
||||
object.Renderable.Enabled = false
|
||||
object.Renderable.SegmentQuality = 9
|
||||
object.Renderable.TrailFade = 18
|
||||
local sssb = asset.syncedResource({
|
||||
Name = "Small SolarSystem Body Data (Halley-type Comet)",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "sssb_data_halley-type_comet",
|
||||
Version = 1
|
||||
})
|
||||
|
||||
object.GUI.Description = [[ Periodic comets with an orbital period between 20 and 200
|
||||
years. ]]
|
||||
local object = {
|
||||
Identifier = "sssb_halley-type_comet",
|
||||
Parent = transforms.SunECLIPJ2000.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = sssb .. "sssb_data_halley-type_comet.csv",
|
||||
Format = "SBDB",
|
||||
Segments = 200,
|
||||
SegmentQuality = 9,
|
||||
Color = { 0.66, 0.66, 0.66 },
|
||||
TrailFade = 18
|
||||
},
|
||||
GUI = {
|
||||
Name = "Halley-type Comets",
|
||||
Path = "/Solar System/Small Bodies",
|
||||
Description = "Periodic comets with an orbital period between 20 and 200 years."
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(object)
|
||||
|
||||
@@ -1,16 +1,31 @@
|
||||
local sharedSssb = asset.require("./sssb_shared")
|
||||
local transforms = asset.require("scene/solarsystem/sun/transforms")
|
||||
|
||||
local filepath = sharedSssb.downloadSssbDatabaseFile(asset, "inner_main_belt_asteroid",
|
||||
"sssb_data_inner_main_belt_asteroid")
|
||||
local object = sharedSssb.createSssbGroupObject("sssb_data_inner_main_belt_asteroid.csv",
|
||||
"Inner Main Asteroid Belt", filepath, { 1.0, 1.0, 0.0 })
|
||||
object.Renderable.Enabled = false
|
||||
object.Renderable.SegmentQuality = 1
|
||||
object.Renderable.TrailFade = 0.5
|
||||
|
||||
object.GUI.Description = [[ Asteroids with a semi-major axis less than 2.0 au and a
|
||||
perihelion distance greater than 1.666 au. ]]
|
||||
local sssb = asset.syncedResource({
|
||||
Name = "Small SolarSystem Body Data (Inner Main Belt Asteroid)",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "sssb_data_inner_main_belt_asteroid",
|
||||
Version = 1
|
||||
})
|
||||
|
||||
local object = {
|
||||
Identifier = "sssb_inner_main_belt_asteroid",
|
||||
Parent = transforms.SunECLIPJ2000.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = sssb .. "sssb_data_inner_main_belt_asteroid.csv",
|
||||
Format = "SBDB",
|
||||
Segments = 200,
|
||||
SegmentQuality = 1,
|
||||
Color = { 1.0, 1.0, 0.0 },
|
||||
TrailFade = 0.5
|
||||
},
|
||||
GUI = {
|
||||
Name = "Inner Main Asteroid Belt",
|
||||
Path = "/Solar System/Small Bodies",
|
||||
Description = [[Asteroids with a semi-major axis less than 2.0 AU and a perihelion
|
||||
distance greater than 1.666 AU.]]
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(object)
|
||||
|
||||
@@ -75,7 +75,7 @@ local ItokawaModel = {
|
||||
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/]]
|
||||
https://solarsystem.nasa.gov/resources/2377/asteroid-itokawa-3d-model]]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,31 @@
|
||||
local sharedSssb = asset.require("./sssb_shared")
|
||||
local transforms = asset.require("scene/solarsystem/sun/transforms")
|
||||
|
||||
local filepath = sharedSssb.downloadSssbDatabaseFile(asset, "jupiter-family_comet",
|
||||
"sssb_data_jupiter-family_comet")
|
||||
local object = sharedSssb.createSssbGroupObject("sssb_data_jupiter-family_comet.csv",
|
||||
"Jupiter-family Comets", filepath, { 0.2, 0.8, 0.2 })
|
||||
object.Renderable.Enabled = false
|
||||
object.Renderable.SegmentQuality = 10
|
||||
object.Renderable.TrailFade = 28
|
||||
|
||||
object.GUI.Description = [[ Comets with a Tisserand's parameter with respect to Jupiter of
|
||||
between 2 and 3. ]]
|
||||
local sssb = asset.syncedResource({
|
||||
Name = "Small SolarSystem Body Data (Jupiter Family Comet)",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "sssb_data_jupiter-family_comet",
|
||||
Version = 1
|
||||
})
|
||||
|
||||
local object = {
|
||||
Identifier = "sssb_jupiter-family_comet",
|
||||
Parent = transforms.SunECLIPJ2000.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = sssb .. "sssb_data_jupiter-family_comet.csv",
|
||||
Format = "SBDB",
|
||||
Segments = 200,
|
||||
SegmentQuality = 10,
|
||||
Color = { 0.2, 0.8, 0.2 },
|
||||
TrailFade = 28
|
||||
},
|
||||
GUI = {
|
||||
Name = "Jupiter-family Comets",
|
||||
Path = "/Solar System/Small Bodies",
|
||||
Description = [[Comets with a Tisserand's parameter with respect to Jupiter of between
|
||||
2 and 3.]]
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(object)
|
||||
|
||||
@@ -1,16 +1,31 @@
|
||||
local sharedSssb = asset.require("./sssb_shared")
|
||||
local transforms = asset.require("scene/solarsystem/sun/transforms")
|
||||
|
||||
local filepath = sharedSssb.downloadSssbDatabaseFile(asset, "jupiter_trojan_asteroid",
|
||||
"sssb_data_jupiter_trojan_asteroid")
|
||||
local object = sharedSssb.createSssbGroupObject("sssb_data_jupiter_trojan_asteroid.csv",
|
||||
"Jupiter Trojan Asteroids", filepath, { 0.5, 0.8, 0.5 })
|
||||
object.Renderable.Enabled = false
|
||||
object.Renderable.SegmentQuality = 1
|
||||
object.Renderable.TrailFade = 5
|
||||
|
||||
object.GUI.Description = [[ Asteroids trapped in Jupiter's L4/L5 Lagrange points
|
||||
(semimajor axis of between 4.6 and 5.5 au), with an eccentricity of less than 0.3. ]]
|
||||
local sssb = asset.syncedResource({
|
||||
Name = "Small SolarSystem Body Data (Jupiter Trojan Asteroid)",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "sssb_data_jupiter_trojan_asteroid",
|
||||
Version = 1
|
||||
})
|
||||
|
||||
local object = {
|
||||
Identifier = "sssb_jupiter_trojan_asteroid",
|
||||
Parent = transforms.SunECLIPJ2000.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = sssb .. "sssb_data_jupiter_trojan_asteroid.csv",
|
||||
Format = "SBDB",
|
||||
Segments = 200,
|
||||
SegmentQuality = 1,
|
||||
Color = { 0.5, 0.8, 0.5 },
|
||||
TrailFade = 5
|
||||
},
|
||||
GUI = {
|
||||
Name = "Jupiter Trojan Asteroids",
|
||||
Path = "/Solar System/Small Bodies",
|
||||
Description = [[Asteroids trapped in Jupiter's L4/L5 Lagrange points (semimajor axis
|
||||
of between 4.6 and 5.5 AU), with an eccentricity of less than 0.3.]]
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(object)
|
||||
|
||||
@@ -1,17 +1,32 @@
|
||||
local sharedSssb = asset.require("./sssb_shared")
|
||||
local transforms = asset.require("scene/solarsystem/sun/transforms")
|
||||
|
||||
local filepath = sharedSssb.downloadSssbDatabaseFile(asset, "main_belt_asteroid",
|
||||
"sssb_data_main_belt_asteroid")
|
||||
local object = sharedSssb.createSssbGroupObject("sssb_data_main_belt_asteroid.csv",
|
||||
"Main Asteroid Belt", filepath, { 0.0, 0.5, 0.0 })
|
||||
object.Renderable.Enabled = false
|
||||
object.Renderable.SegmentQuality = 1
|
||||
object.Renderable.TrailFade = 0.1
|
||||
object.Renderable.UpperLimit = 50000
|
||||
|
||||
object.GUI.Description = [[ Asteroids with a semi-major axis of between 2.0 and 3.2 au,
|
||||
and a perihelion distance greater than 1.666 au. ]]
|
||||
local sssb = asset.syncedResource({
|
||||
Name = "Small SolarSystem Body Data (Main Belt Asteroid)",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "sssb_data_main_belt_asteroid",
|
||||
Version = 1
|
||||
})
|
||||
|
||||
local object = {
|
||||
Identifier = "sssb_main_belt_asteroid",
|
||||
Parent = transforms.SunECLIPJ2000.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = sssb .. "sssb_data_main_belt_asteroid.csv",
|
||||
Format = "SBDB",
|
||||
Segments = 200,
|
||||
SegmentQuality = 1,
|
||||
Color = { 0.0, 0.5, 0.0 },
|
||||
TrailFade = 0.1,
|
||||
RenderSize = 50000
|
||||
},
|
||||
GUI = {
|
||||
Name = "Main Asteroid Belt",
|
||||
Path = "/Solar System/Small Bodies",
|
||||
Description = [[Asteroids with a semi-major axis of between 2.0 and 3.2 AU,
|
||||
and a perihelion distance greater than 1.666 AU.]]
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(object)
|
||||
|
||||
@@ -1,16 +1,31 @@
|
||||
local sharedSssb = asset.require("./sssb_shared")
|
||||
local transforms = asset.require("scene/solarsystem/sun/transforms")
|
||||
|
||||
local filepath = sharedSssb.downloadSssbDatabaseFile(asset, "mars-crossing_asteroid",
|
||||
"sssb_data_mars-crossing_asteroid")
|
||||
local object = sharedSssb.createSssbGroupObject("sssb_data_mars-crossing_asteroid.csv",
|
||||
"Mars-crossing Asteroids", filepath, { 0.814, 0.305, 0.220 })
|
||||
object.Renderable.Enabled = false
|
||||
object.Renderable.SegmentQuality = 1
|
||||
object.Renderable.TrailFade = 13
|
||||
|
||||
object.GUI.Description = [[ Asteroids that cross the orbit of Mars, with a semi-major axis
|
||||
of less than 3.2 au, and a perihelion distance of between 1.3 and 1.666 au. ]]
|
||||
local sssb = asset.syncedResource({
|
||||
Name = "Small SolarSystem Body Data (Mars-Crossing Asteroid)",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "sssb_data_mars-crossing_asteroid",
|
||||
Version = 1
|
||||
})
|
||||
|
||||
local object = {
|
||||
Identifier = "sssb_mars-crossing_asteroid",
|
||||
Parent = transforms.SunECLIPJ2000.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = sssb .. "sssb_data_mars-crossing_asteroid.csv",
|
||||
Format = "SBDB",
|
||||
Segments = 200,
|
||||
SegmentQuality = 1,
|
||||
Color = { 0.814, 0.305, 0.22 },
|
||||
TrailFade = 13
|
||||
},
|
||||
GUI = {
|
||||
Name = "Mars-crossing Asteroids",
|
||||
Path = "/Solar System/Small Bodies",
|
||||
Description = [[Asteroids that cross the orbit of Mars, with a semi-major axis
|
||||
of less than 3.2 AU, and a perihelion distance of between 1.3 and 1.666 AU.]]
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(object)
|
||||
|
||||
@@ -1,21 +1,30 @@
|
||||
local sharedSssb = asset.require("./sssb_shared")
|
||||
local transforms = asset.require("scene/solarsystem/sun/transforms")
|
||||
|
||||
local filepath = sharedSssb.downloadSssbDatabaseFile(
|
||||
asset,
|
||||
"outer_main_belt_asteroid",
|
||||
"sssb_data_outer_main_belt_asteroid"
|
||||
)
|
||||
local object = sharedSssb.createSssbGroupObject(
|
||||
"sssb_data_outer_main_belt_asteroid.csv",
|
||||
"Outer Main Asteroid Belt",
|
||||
filepath,
|
||||
{ 0.4, 0.4, 1.0 }
|
||||
)
|
||||
object.Renderable.Enabled = false
|
||||
object.Renderable.SegmentQuality = 1
|
||||
object.Renderable.TrailFade = 2
|
||||
local sssb = asset.syncedResource({
|
||||
Name = "Small SolarSystem Body Data (Outer Main Belt Asteroid)",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "sssb_data_outer_main_belt_asteroid",
|
||||
Version = 1
|
||||
})
|
||||
|
||||
object.GUI.Description = [[ Asteroids with a semi-major axis of between 3.2 and 4.6 au. ]]
|
||||
local object = {
|
||||
Identifier = "sssb_outer_main_belt_asteroid",
|
||||
Parent = transforms.SunECLIPJ2000.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = sssb .. "sssb_data_outer_main_belt_asteroid.csv",
|
||||
Format = "SBDB",
|
||||
Segments = 200,
|
||||
SegmentQuality = 1,
|
||||
Color = { 0.4, 0.4, 1.0 },
|
||||
TrailFade = 2
|
||||
},
|
||||
GUI = {
|
||||
Name = "Outer Main Asteroid Belt",
|
||||
Path = "/Solar System/Small Bodies",
|
||||
Description = [[Asteroids with a semi-major axis of between 3.2 and 4.6 AU.]]
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(object)
|
||||
|
||||
@@ -1,20 +1,33 @@
|
||||
local sharedSssb = asset.require("./sssb_shared")
|
||||
local transforms = asset.require("scene/solarsystem/sun/transforms")
|
||||
|
||||
local filepath = sharedSssb.downloadSssbDatabaseFile(asset, "pha", "sssb_data_pha")
|
||||
local object = sharedSssb.createSssbGroupObject("sssb_data_pha.csv",
|
||||
"Potentially Hazardous Asteroids",
|
||||
filepath,
|
||||
{ 0.98, 0.09, 0.06 }
|
||||
)
|
||||
object.Renderable.Enabled = false
|
||||
object.Renderable.SegmentQuality = 3
|
||||
object.Renderable.TrailFade = 17
|
||||
|
||||
object.GUI.Description = [[ Asteroids that are deemed potentially hazardous to Earth
|
||||
based on their close approaches. All asteroids with an Earth Minimum Orbit
|
||||
Intersection Distance (MOID) of 0.05 au or less, and with an absolute magnitude (H)
|
||||
of 22.0 or less. ]]
|
||||
local sssb = asset.syncedResource({
|
||||
Name = "Small SolarSystem Body Data (Potentially hazardous Asteroids)",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "sssb_data_pha",
|
||||
Version = 1
|
||||
})
|
||||
|
||||
local object = {
|
||||
Identifier = "sssb_pha",
|
||||
Parent = transforms.SunECLIPJ2000.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = sssb .. "sssb_data_pha.csv",
|
||||
Format = "SBDB",
|
||||
Segments = 200,
|
||||
SegmentQuality = 3,
|
||||
Color = { 0.98, 0.09, 0.06 },
|
||||
TrailFade = 17
|
||||
},
|
||||
GUI = {
|
||||
Name = "Potentially Hazardous Asteroids",
|
||||
Path = "/Solar System/Small Bodies",
|
||||
Description = [[Asteroids that are deemed potentially hazardous to Earth based on
|
||||
their close approaches. All asteroids with an Earth Minimum Orbit Intersection
|
||||
Distance (MOID) of 0.05 AU or less, and with an absolute magnitude (H) of 22.0 or
|
||||
less.]]
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(object)
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
local transforms = asset.require("scene/solarsystem/sun/transforms")
|
||||
|
||||
function downloadSssbDatabaseFile(sceneAsset, name, identifier)
|
||||
assert(sceneAsset, "'asset' needs to be provided")
|
||||
assert(name, "'name' needs to be provided")
|
||||
assert(identifier, "'identifier'needs to be provided")
|
||||
|
||||
return sceneAsset.syncedResource({
|
||||
Name = "Small SolarSystem Body Data (" .. name .. ")",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = identifier,
|
||||
Version = 1
|
||||
})
|
||||
end
|
||||
|
||||
local createSssbGroupObject = function(filename, guiName, sssbFolder, trailColor)
|
||||
assert(filename, "'filename' needs to be provided")
|
||||
assert(sssbFolder, "'sssbFolder' needs to be provided")
|
||||
trailColor = trailColor or { 0.75, 0.1, 0.1 }
|
||||
|
||||
local filenameSansExt = filename:gsub(filename:match("(%.%w+)$"), "")
|
||||
return {
|
||||
Identifier = "sssb_" .. filenameSansExt,
|
||||
Parent = transforms.SunECLIPJ2000.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableSmallBody",
|
||||
Path = sssbFolder .. filename,
|
||||
Segments = 200,
|
||||
Color = trailColor,
|
||||
TrailFade = 0.5,
|
||||
},
|
||||
GUI = {
|
||||
Path = "/Solar System/Small Bodies",
|
||||
Name = guiName
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
asset.export("downloadSssbDatabaseFile", downloadSssbDatabaseFile)
|
||||
asset.export("createSssbGroupObject", createSssbGroupObject)
|
||||
|
||||
|
||||
asset.meta = {
|
||||
Name = "SSSB shared",
|
||||
Version = "1.0",
|
||||
Description = [[ UTILITY ASSET; This asset is for builders and coders]],
|
||||
Author = "OpenSpace Team",
|
||||
URL = "http://openspaceproject.com",
|
||||
License = "MIT license"
|
||||
}
|
||||
@@ -1,22 +1,31 @@
|
||||
local sharedSssb = asset.require("./sssb_shared")
|
||||
local transforms = asset.require("scene/solarsystem/sun/transforms")
|
||||
|
||||
local filepath = sharedSssb.downloadSssbDatabaseFile(asset,
|
||||
"transneptunian_object_asteroid",
|
||||
"sssb_data_transneptunian_object_asteroid"
|
||||
)
|
||||
local object = sharedSssb.createSssbGroupObject(
|
||||
"sssb_data_transneptunian_object_asteroid.csv",
|
||||
"Transneptunian Object Asteroids",
|
||||
filepath,
|
||||
{ 0.56, 0.64, 0.95 }
|
||||
)
|
||||
object.Renderable.Enabled = false
|
||||
object.Renderable.SegmentQuality = 8
|
||||
object.Renderable.TrailFade = 10
|
||||
|
||||
object.GUI.Description = [[ Any minor or dwarf planets in the solar system that orbit
|
||||
the Sun at a greater average distance than Neptune (semi-major axis of 30.1 AU). ]]
|
||||
local sssb = asset.syncedResource({
|
||||
Name = "Small SolarSystem Body Data (Trans-Neptunian Object Asteroid)",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "sssb_data_transneptunian_object_asteroid",
|
||||
Version = 1
|
||||
})
|
||||
|
||||
local object = {
|
||||
Identifier = "sssb_transneptunian_object_asteroid",
|
||||
Parent = transforms.SunECLIPJ2000.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableOrbitalKepler",
|
||||
Path = sssb .. "sssb_data_transneptunian_object_asteroid.csv",
|
||||
Format = "SBDB",
|
||||
Segments = 200,
|
||||
SegmentQuality = 8,
|
||||
Color = { 0.56, 0.64, 0.95 },
|
||||
TrailFade = 10
|
||||
},
|
||||
GUI = {
|
||||
Name = "Transneptunian Object Asteroids",
|
||||
Path = "/Solar System/Small Bodies",
|
||||
Description = [[Any minor or dwarf planets in the solar system that orbit the Sun at a
|
||||
greater average distance than Neptune (semi-major axis of 30.1 AU).]]
|
||||
}
|
||||
}
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(object)
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
|
||||
|
||||
function downloadTLEFile(sceneAsset, url, name, filename)
|
||||
local identifier = name
|
||||
identifier = identifier:gsub(" ", "")
|
||||
identifier = identifier:gsub("&", "")
|
||||
identifier = identifier:gsub("-", "")
|
||||
|
||||
local urlSyncTable = {
|
||||
Name = "Satellite TLE Data (" .. name .. ")",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "satellite_tle_data_" .. identifier,
|
||||
Url = url,
|
||||
Override = true
|
||||
}
|
||||
|
||||
if (filename ~= "") then
|
||||
urlSyncTable.Filename = filename
|
||||
end
|
||||
|
||||
return sceneAsset.syncedResource(urlSyncTable)
|
||||
end
|
||||
|
||||
-- Check format of a set of 3 TLE file lines and return nonzero if there is a format error
|
||||
function isValidTLEFileFormat(lineArr)
|
||||
local function isEmpty(s) return s == nil or s == "" end
|
||||
|
||||
if isEmpty(lineArr[1]) or isEmpty(lineArr[2]) or isEmpty(lineArr[3]) then
|
||||
return false
|
||||
end
|
||||
if string.sub(lineArr[2], 1, 2) ~= "1 " then
|
||||
return false
|
||||
end
|
||||
if string.sub(lineArr[3], 1, 2) ~= "2 " then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local makeSingleLineElement = function(tle, filename)
|
||||
local path = tle .. "/" .. filename
|
||||
local file = io.open(path, "r")
|
||||
assert(file, "File not found: " .. path)
|
||||
|
||||
local line = {
|
||||
file:read("*l"), --title line
|
||||
file:read("*l"),
|
||||
file:read("*l")
|
||||
}
|
||||
|
||||
assert(isValidTLEFileFormat(line), "TLE file syntax error on line " .. 1 .. ": " .. path)
|
||||
|
||||
-- Trim string
|
||||
line[1] = line[1]:gsub("^%s*(.-)%s*$", "%1")
|
||||
line[1] = line[1]:gsub("%s+", "_")
|
||||
line[1] = line[1]:gsub("[%-()]", "")
|
||||
--local title = line[1]
|
||||
|
||||
return line
|
||||
end
|
||||
|
||||
function numLinesInFile(filename)
|
||||
local ctr = 0
|
||||
for _ in io.lines(filename) do ctr = ctr + 1 end
|
||||
return ctr
|
||||
end
|
||||
|
||||
local getPeriodFromElement = function(element)
|
||||
-- Get period from correct location of the string
|
||||
local per = tonumber(string.sub(element[3], 53, 63))
|
||||
-- Trail for 2x a single revolution
|
||||
per = 1.0 / per
|
||||
|
||||
return per
|
||||
end
|
||||
|
||||
function satellites(title, file, color, group)
|
||||
return {
|
||||
Identifier = title,
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableSatellites",
|
||||
Path = file,
|
||||
SegmentQuality = 3,
|
||||
Color = color,
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent",
|
||||
StartRenderIdx = group.StartRenderIdx,
|
||||
RenderSize = group.RenderSize
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
Name = group.Title,
|
||||
Path = "/Solar System/Planets/Earth/Satellites",
|
||||
Description = group.Description
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
local registerSatelliteGroupObjects = function(containingAsset, group, tleFolder, shouldAddDuplicates)
|
||||
local filename = group.Filename
|
||||
local filenameSansExt = filename:gsub(filename:match("(%.%w+)$"), "")
|
||||
|
||||
local path = tleFolder .. "/" .. filename
|
||||
|
||||
local SatelliteBatch = satellites(filenameSansExt, path, group.TrailColor, group)
|
||||
|
||||
containingAsset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(SatelliteBatch)
|
||||
end)
|
||||
|
||||
containingAsset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(SatelliteBatch)
|
||||
end)
|
||||
|
||||
containingAsset.export(SatelliteBatch)
|
||||
end
|
||||
|
||||
asset.export("downloadTLEFile", downloadTLEFile)
|
||||
asset.export("isValidTLEFileFormat", isValidTLEFileFormat)
|
||||
asset.export("numLinesInFile", numLinesInFile)
|
||||
asset.export("makeSingleLineElement", makeSingleLineElement)
|
||||
asset.export("getPeriodFromElement", getPeriodFromElement)
|
||||
asset.export("registerSatelliteGroupObjects", registerSatelliteGroupObjects)
|
||||
Submodule modules/fitsfilereader/ext/CCfits updated: 27f655a80f...3c16ca3f1e
Submodule modules/fitsfilereader/ext/cfitsio updated: e8fc91cc4b...8d98f1495b
Submodule modules/kameleon/ext/kameleon updated: e6978911c5...606edb945b
@@ -26,19 +26,18 @@ include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake)
|
||||
|
||||
set(HEADER_FILES
|
||||
horizonsfile.h
|
||||
kepler.h
|
||||
speckloader.h
|
||||
rendering/renderableconstellationbounds.h
|
||||
rendering/renderablefluxnodes.h
|
||||
rendering/renderablehabitablezone.h
|
||||
rendering/renderablerings.h
|
||||
rendering/renderableorbitalkepler.h
|
||||
rendering/renderablesatellites.h
|
||||
rendering/renderablesmallbody.h
|
||||
rendering/renderablestars.h
|
||||
rendering/renderabletravelspeed.h
|
||||
translation/gptranslation.h
|
||||
translation/keplertranslation.h
|
||||
translation/spicetranslation.h
|
||||
translation/tletranslation.h
|
||||
translation/horizonstranslation.h
|
||||
rotation/spicerotation.h
|
||||
)
|
||||
@@ -46,6 +45,7 @@ source_group("Header Files" FILES ${HEADER_FILES})
|
||||
|
||||
set(SOURCE_FILES
|
||||
horizonsfile.cpp
|
||||
kepler.cpp
|
||||
spacemodule_lua.inl
|
||||
speckloader.cpp
|
||||
rendering/renderableconstellationbounds.cpp
|
||||
@@ -53,13 +53,11 @@ set(SOURCE_FILES
|
||||
rendering/renderablehabitablezone.cpp
|
||||
rendering/renderablerings.cpp
|
||||
rendering/renderableorbitalkepler.cpp
|
||||
rendering/renderablesatellites.cpp
|
||||
rendering/renderablesmallbody.cpp
|
||||
rendering/renderablestars.cpp
|
||||
rendering/renderabletravelspeed.cpp
|
||||
translation/gptranslation.cpp
|
||||
translation/keplertranslation.cpp
|
||||
translation/spicetranslation.cpp
|
||||
translation/tletranslation.cpp
|
||||
translation/horizonstranslation.cpp
|
||||
rotation/spicerotation.cpp
|
||||
)
|
||||
|
||||
751
modules/space/kepler.cpp
Normal file
751
modules/space/kepler.cpp
Normal file
@@ -0,0 +1,751 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* 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 <modules/space/kepler.h>
|
||||
|
||||
#include <ghoul/filesystem/cachemanager.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/misc/misc.h>
|
||||
#include <scn/scn.h>
|
||||
#include <scn/tuple_return.h>
|
||||
#include <fstream>
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
|
||||
namespace {
|
||||
constexpr std::string_view _loggerCat = "Kepler";
|
||||
constexpr int8_t CurrentCacheVersion = 1;
|
||||
|
||||
// The list of leap years only goes until 2056 as we need to touch this file then
|
||||
// again anyway ;)
|
||||
constexpr const std::array<int, 36> LeapYears = {
|
||||
1956, 1960, 1964, 1968, 1972, 1976, 1980, 1984, 1988, 1992, 1996,
|
||||
2000, 2004, 2008, 2012, 2016, 2020, 2024, 2028, 2032, 2036, 2040,
|
||||
2044, 2048, 2052, 2056
|
||||
};
|
||||
constexpr const std::array<int, 12> DaysOfMonths = {
|
||||
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
|
||||
};
|
||||
|
||||
// Count the number of full days since the beginning of 2000 to the beginning of
|
||||
// the parameter 'year'
|
||||
int countDays(int year) {
|
||||
// Find the position of the current year in the vector, the difference
|
||||
// between its position and the position of 2000 (for J2000) gives the
|
||||
// number of leap years
|
||||
constexpr const int Epoch = 2000;
|
||||
constexpr const int DaysRegularYear = 365;
|
||||
constexpr const int DaysLeapYear = 366;
|
||||
|
||||
if (year == Epoch) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get the position of the most recent leap year
|
||||
const auto lb = std::lower_bound(LeapYears.begin(), LeapYears.end(), year);
|
||||
|
||||
// Get the position of the epoch
|
||||
const auto y2000 = std::find(LeapYears.begin(), LeapYears.end(), Epoch);
|
||||
|
||||
// The distance between the two iterators gives us the number of leap years
|
||||
const int nLeapYears = static_cast<int>(std::abs(std::distance(y2000, lb)));
|
||||
|
||||
const int nYears = std::abs(year - Epoch);
|
||||
const int nRegularYears = nYears - nLeapYears;
|
||||
|
||||
// Get the total number of days as the sum of leap years + non leap years
|
||||
const int result = nRegularYears * DaysRegularYear + nLeapYears * DaysLeapYear;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns the number of leap seconds that lie between the {year, dayOfYear}
|
||||
// time point and { 2000, 1 }
|
||||
int countLeapSeconds(int year, int dayOfYear) {
|
||||
// Find the position of the current year in the vector; its position in the vector
|
||||
// gives the number of leap seconds
|
||||
struct LeapSecond {
|
||||
int year;
|
||||
int dayOfYear;
|
||||
bool operator<(const LeapSecond& rhs) const {
|
||||
return std::tie(year, dayOfYear) < std::tie(rhs.year, rhs.dayOfYear);
|
||||
}
|
||||
};
|
||||
|
||||
constexpr const LeapSecond LeapEpoch = { 2000, 1 };
|
||||
|
||||
// List taken from: https://www.ietf.org/timezones/data/leap-seconds.list
|
||||
constexpr const std::array<LeapSecond, 28> LeapSeconds = {
|
||||
LeapSecond{ 1972, 1 },
|
||||
LeapSecond{ 1972, 183 },
|
||||
LeapSecond{ 1973, 1 },
|
||||
LeapSecond{ 1974, 1 },
|
||||
LeapSecond{ 1975, 1 },
|
||||
LeapSecond{ 1976, 1 },
|
||||
LeapSecond{ 1977, 1 },
|
||||
LeapSecond{ 1978, 1 },
|
||||
LeapSecond{ 1979, 1 },
|
||||
LeapSecond{ 1980, 1 },
|
||||
LeapSecond{ 1981, 182 },
|
||||
LeapSecond{ 1982, 182 },
|
||||
LeapSecond{ 1983, 182 },
|
||||
LeapSecond{ 1985, 182 },
|
||||
LeapSecond{ 1988, 1 },
|
||||
LeapSecond{ 1990, 1 },
|
||||
LeapSecond{ 1991, 1 },
|
||||
LeapSecond{ 1992, 183 },
|
||||
LeapSecond{ 1993, 182 },
|
||||
LeapSecond{ 1994, 182 },
|
||||
LeapSecond{ 1996, 1 },
|
||||
LeapSecond{ 1997, 182 },
|
||||
LeapSecond{ 1999, 1 },
|
||||
LeapSecond{ 2006, 1 },
|
||||
LeapSecond{ 2009, 1 },
|
||||
LeapSecond{ 2012, 183 },
|
||||
LeapSecond{ 2015, 182 },
|
||||
LeapSecond{ 2017, 1 }
|
||||
};
|
||||
// Get the position of the last leap second before the desired date
|
||||
LeapSecond date{ year, dayOfYear };
|
||||
const auto it = std::lower_bound(LeapSeconds.begin(), LeapSeconds.end(), date);
|
||||
|
||||
// Get the position of the Epoch
|
||||
const auto y2000 = std::lower_bound(
|
||||
LeapSeconds.begin(),
|
||||
LeapSeconds.end(),
|
||||
LeapEpoch
|
||||
);
|
||||
|
||||
// The distance between the two iterators gives us the number of leap years
|
||||
const int nLeapSeconds = static_cast<int>(std::abs(std::distance(y2000, it)));
|
||||
return nLeapSeconds;
|
||||
}
|
||||
|
||||
int daysIntoGivenYear(int year, int month, int dayOfMonth) {
|
||||
// month and dayCount are zero-based.
|
||||
month -= 1;
|
||||
int dayCount = dayOfMonth - 1;
|
||||
constexpr int February = 1;
|
||||
const bool isInLeapYear =
|
||||
std::find(LeapYears.begin(), LeapYears.end(), year) != LeapYears.end();
|
||||
|
||||
for (int m = 0; m < month; ++m) {
|
||||
dayCount += DaysOfMonths[m];
|
||||
if (m == February && isInLeapYear) {
|
||||
dayCount += 1;
|
||||
}
|
||||
}
|
||||
return dayCount;
|
||||
}
|
||||
|
||||
double calculateSemiMajorAxis(double meanMotion) {
|
||||
constexpr const double GravitationalConstant = 6.6740831e-11;
|
||||
constexpr const double MassEarth = 5.9721986e24;
|
||||
constexpr const double muEarth = GravitationalConstant * MassEarth;
|
||||
|
||||
// Use Kepler's 3rd law to calculate semimajor axis
|
||||
// a^3 / P^2 = mu / (2pi)^2
|
||||
// <=> a = ((mu * P^2) / (2pi^2))^(1/3)
|
||||
// with a = semimajor axis
|
||||
// P = period in seconds
|
||||
// mu = G*M_earth
|
||||
const double period =
|
||||
std::chrono::seconds(std::chrono::hours(24)).count() / meanMotion;
|
||||
|
||||
constexpr const double pisq = glm::pi<double>() * glm::pi<double>();
|
||||
const double semiMajorAxis = pow(
|
||||
(muEarth * period * period) / (4 * pisq),
|
||||
1.0 / 3.0
|
||||
);
|
||||
|
||||
// We need the semi major axis in km instead of m
|
||||
return semiMajorAxis / 1000.0;
|
||||
}
|
||||
|
||||
|
||||
double epochFromSubstring(const std::string& epoch) {
|
||||
// The epochString is in the form:
|
||||
// YYDDD.DDDDDDDD
|
||||
// With YY being the last two years of the launch epoch, the first DDD the day of
|
||||
// the year and the remaning a fractional part of the day
|
||||
|
||||
// The main overview of this function:
|
||||
// 1. Reconstruct the full year from the YY part
|
||||
// 2. Calculate the number of days since the beginning of the year
|
||||
// 3. Convert the number of days to a number of seconds
|
||||
// 4. Get the number of leap seconds since January 1st, 2000 and remove them
|
||||
// 5. Adjust for the fact the epoch starts on 1st Januaray at 12:00:00, not
|
||||
// midnight
|
||||
|
||||
// According to https://celestrak.com/columns/v04n03/
|
||||
// Apparently, US Space Command sees no need to change the two-line element set
|
||||
// format yet since no artificial earth satellites existed prior to 1957. By their
|
||||
// reasoning, two-digit years from 57-99 correspond to 1957-1999 and those from
|
||||
// 00-56 correspond to 2000-2056. We'll see each other again in 2057!
|
||||
|
||||
// 1,2. Get the full year and days
|
||||
auto [res, year, daysInYear] = scn::scan_tuple<int, double>(epoch, "{:2}{}");
|
||||
if (!res) {
|
||||
throw ghoul::RuntimeError(fmt::format("Error parsing epoch '{}'", epoch));
|
||||
}
|
||||
year += year > 57 ? 1900 : 2000;
|
||||
const int daysSince2000 = countDays(year);
|
||||
|
||||
// 3
|
||||
using namespace std::chrono;
|
||||
const int SecondsPerDay = static_cast<int>(seconds(hours(24)).count());
|
||||
//Need to subtract 1 from daysInYear since it is not a zero-based count
|
||||
const double nSecondsSince2000 = (daysSince2000 + daysInYear - 1) * SecondsPerDay;
|
||||
|
||||
// 4
|
||||
// We need to remove additional leap seconds past 2000 and add them prior to
|
||||
// 2000 to sync up the time zones
|
||||
const double nLeapSecondsOffset = countLeapSeconds(
|
||||
year,
|
||||
static_cast<int>(std::floor(daysInYear))
|
||||
);
|
||||
|
||||
// 5
|
||||
const double nSecondsEpochOffset =
|
||||
static_cast<double>(seconds(hours(12)).count());
|
||||
|
||||
// Combine all of the values
|
||||
return nSecondsSince2000 - nLeapSecondsOffset - nSecondsEpochOffset;
|
||||
}
|
||||
|
||||
double epochFromYMDdSubstring(const std::string& epoch) {
|
||||
// The epochString is in the form:
|
||||
// YYYYMMDD.ddddddd
|
||||
// With YYYY as the year, MM the month (1 - 12), DD the day of month (1-31),
|
||||
// and dddd the fraction of that day.
|
||||
|
||||
// The main overview of this function:
|
||||
// 1. Read the year value
|
||||
// 2. Calculate the number of days since the beginning of the year
|
||||
// 3. Convert the number of days to a number of seconds
|
||||
// 4. Get the number of leap seconds since January 1st, 2000 and remove them
|
||||
// 5. Adjust for the fact the epoch starts on 1st January at 12:00:00, not
|
||||
// midnight
|
||||
|
||||
// 1, 2
|
||||
auto [res, year, monthNum, dayOfMonthNum, fractionOfDay] =
|
||||
scn::scan_tuple<int, int, int, double>(epoch, "{:4}{:2}{:2}{}");
|
||||
if (!res) {
|
||||
throw ghoul::RuntimeError(fmt::format("Error parsing epoch '{}'", epoch));
|
||||
}
|
||||
const int daysSince2000 = countDays(year);
|
||||
int wholeDaysInto = daysIntoGivenYear(year, monthNum, dayOfMonthNum);
|
||||
double daysInYear = static_cast<double>(wholeDaysInto) + fractionOfDay;
|
||||
|
||||
// 3
|
||||
using namespace std::chrono;
|
||||
const int SecondsPerDay = static_cast<int>(seconds(hours(24)).count());
|
||||
//Need to subtract 1 from daysInYear since it is not a zero-based count
|
||||
const double nSecondsSince2000 = (daysSince2000 + daysInYear - 1) * SecondsPerDay;
|
||||
|
||||
// 4
|
||||
// We need to remove additional leap seconds past 2000 and add them prior to
|
||||
// 2000 to sync up the time zones
|
||||
const double nLeapSecondsOffset = -countLeapSeconds(
|
||||
year,
|
||||
static_cast<int>(std::floor(daysInYear))
|
||||
);
|
||||
|
||||
// 5
|
||||
const double offset = static_cast<double>(seconds(hours(12)).count());
|
||||
|
||||
// Combine all of the values
|
||||
return nSecondsSince2000 + nLeapSecondsOffset - offset;
|
||||
}
|
||||
|
||||
double epochFromOmmString(const std::string& epoch) {
|
||||
// The epochString is in the form:
|
||||
// YYYY-MM-DDThh:mm:ss[.d->d][Z]
|
||||
// or
|
||||
// YYYY-DDDThh:mm:ss[.d->d][Z]
|
||||
|
||||
// The main overview of this function:
|
||||
// 0. Determine which type it is
|
||||
// 1. Read the year value
|
||||
// 2. Calculate the number of days since the beginning of the year
|
||||
// 3. Convert the number of days to a number of seconds
|
||||
// 4. Get the number of leap seconds since January 1st, 2000 and remove them
|
||||
// 5. Add the hh:mm:ss component
|
||||
// 6. Adjust for the fact the epoch starts on 1st January at 12:00:00, not
|
||||
// midnight
|
||||
|
||||
std::string e = epoch;
|
||||
if (e.back() == 'Z') {
|
||||
e.pop_back();
|
||||
}
|
||||
|
||||
struct {
|
||||
int year;
|
||||
int nDays;
|
||||
int hours;
|
||||
int minutes;
|
||||
double seconds;
|
||||
} date;
|
||||
|
||||
// 1, 2
|
||||
const size_t pos = epoch.find('T');
|
||||
if (pos == 10) {
|
||||
// We have the first form
|
||||
|
||||
int month;
|
||||
int days;
|
||||
auto res = scn::scan(
|
||||
epoch, "{:4}-{:2}-{:2}T{:2}:{:2}:{}",
|
||||
date.year, month, days, date.hours, date.minutes, date.seconds
|
||||
);
|
||||
if (!res) {
|
||||
throw ghoul::RuntimeError(fmt::format("Error parsing epoch '{}'", epoch));
|
||||
}
|
||||
date.nDays = daysIntoGivenYear(date.year, month, days);
|
||||
}
|
||||
else if (pos == 8) {
|
||||
// We have the second form
|
||||
|
||||
auto res = scn::scan(
|
||||
epoch, "{:4}-{:3}T{:2}:{:2}:{}",
|
||||
date.year, date.nDays, date.hours, date.minutes, date.seconds
|
||||
);
|
||||
if (!res) {
|
||||
throw ghoul::RuntimeError(fmt::format("Error parsing epoch '{}'", epoch));
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw ghoul::RuntimeError(fmt::format("Malformed epoch string '{}'", epoch));
|
||||
}
|
||||
|
||||
const int daysSince2000 = countDays(date.year);
|
||||
|
||||
// 3
|
||||
using namespace std::chrono;
|
||||
const int SecondsPerDay = static_cast<int>(seconds(hours(24)).count());
|
||||
const double nSecondsSince2000 = (daysSince2000 + date.nDays) * SecondsPerDay;
|
||||
|
||||
// 4
|
||||
// We need to remove additional leap seconds past 2000 and add them prior to
|
||||
// 2000 to sync up the time zones
|
||||
const double nLeapSecondsOffset = -countLeapSeconds(
|
||||
date.year,
|
||||
static_cast<int>(std::floor(date.nDays))
|
||||
);
|
||||
|
||||
// 5
|
||||
const long long totalSeconds =
|
||||
std::chrono::seconds(std::chrono::hours(date.hours)).count() +
|
||||
std::chrono::seconds(std::chrono::minutes(date.minutes)).count();
|
||||
|
||||
// 6
|
||||
const long long offset = std::chrono::seconds(std::chrono::hours(12)).count();
|
||||
|
||||
// Combine all of the values
|
||||
return
|
||||
nSecondsSince2000 + totalSeconds + nLeapSecondsOffset - offset + date.seconds;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace openspace::kepler {
|
||||
|
||||
std::vector<Parameters> readTleFile(std::filesystem::path file) {
|
||||
ghoul_assert(std::filesystem::is_regular_file(file), "File must exist");
|
||||
|
||||
std::vector<Parameters> result;
|
||||
|
||||
std::ifstream f;
|
||||
f.open(file);
|
||||
|
||||
int lineNum = 1;
|
||||
|
||||
std::string header;
|
||||
while (std::getline(f, header)) {
|
||||
Parameters p;
|
||||
|
||||
// Header
|
||||
p.name = header;
|
||||
|
||||
// First line
|
||||
// Field Columns Content
|
||||
// 1 01-01 Line number
|
||||
// 2 03-07 Satellite number
|
||||
// 3 08-08 Classification (U = Unclassified)
|
||||
// 4 10-11 International Designator (Last two digits of launch year)
|
||||
// 5 12-14 International Designator (Launch number of the year)
|
||||
// 6 15-17 International Designator(piece of the launch) A
|
||||
// 7 19-20 Epoch Year(last two digits of year)
|
||||
// 8 21-32 Epoch(day of the year and fractional portion of the day)
|
||||
// 9 34-43 First Time Derivative of the Mean Motion divided by two
|
||||
// 10 45-52 Second Time Derivative of Mean Motion divided by six
|
||||
// 11 54-61 BSTAR drag term(decimal point assumed)[10] - 11606 - 4
|
||||
// 12 63-63 The "Ephemeris type"
|
||||
// 13 65-68 Element set number.Incremented when a new TLE is generated
|
||||
// 14 69-69 Checksum (modulo 10)
|
||||
std::string firstLine;
|
||||
std::getline(f, firstLine);
|
||||
if (f.bad() || firstLine[0] != '1') {
|
||||
throw ghoul::RuntimeError(fmt::format(
|
||||
"Malformed TLE file '{}' at line {}", file, lineNum + 1
|
||||
));
|
||||
}
|
||||
// The id only contains the last two digits of the launch year, so we have to
|
||||
// patch it to the full year
|
||||
{
|
||||
std::string id = firstLine.substr(9, 6);
|
||||
std::string prefix = [y = id.substr(0, 2)](){
|
||||
int year = std::atoi(y.c_str());
|
||||
return year >= 57 ? "19" : "20";
|
||||
}();
|
||||
p.id = fmt::format("{}{}-{}", prefix, id.substr(0, 2), id.substr(3));
|
||||
}
|
||||
p.epoch = epochFromSubstring(firstLine.substr(18, 14)); // should be 13?
|
||||
|
||||
|
||||
// Second line
|
||||
// Field Columns Content
|
||||
// 1 01-01 Line number
|
||||
// 2 03-07 Satellite number
|
||||
// 3 09-16 Inclination (degrees)
|
||||
// 4 18-25 Right ascension of the ascending node (degrees)
|
||||
// 5 27-33 Eccentricity (decimal point assumed)
|
||||
// 6 35-42 Argument of perigee (degrees)
|
||||
// 7 44-51 Mean Anomaly (degrees)
|
||||
// 8 53-63 Mean Motion (revolutions per day)
|
||||
// 9 64-68 Revolution number at epoch (revolutions)
|
||||
// 10 69-69 Checksum (modulo 10)
|
||||
std::string secondLine;
|
||||
std::getline(f, secondLine);
|
||||
if (f.bad() || secondLine[0] != '2') {
|
||||
throw ghoul::RuntimeError(fmt::format(
|
||||
"Malformed TLE file '{}' at line {}", file, lineNum + 1
|
||||
));
|
||||
}
|
||||
|
||||
std::stringstream stream;
|
||||
stream.exceptions(std::ios::failbit);
|
||||
|
||||
// Get inclination
|
||||
stream.str(secondLine.substr(8, 8));
|
||||
stream >> p.inclination;
|
||||
stream.clear();
|
||||
|
||||
// Get Right ascension of the ascending node
|
||||
stream.str(secondLine.substr(17, 8));
|
||||
stream >> p.ascendingNode;
|
||||
stream.clear();
|
||||
|
||||
// Get Eccentricity
|
||||
stream.str("0." + secondLine.substr(26, 7));
|
||||
stream >> p.eccentricity;
|
||||
stream.clear();
|
||||
|
||||
// Get argument of periapsis
|
||||
stream.str(secondLine.substr(34, 8));
|
||||
stream >> p.argumentOfPeriapsis;
|
||||
stream.clear();
|
||||
|
||||
// Get mean anomaly
|
||||
stream.str(secondLine.substr(43, 8));
|
||||
stream >> p.meanAnomaly;
|
||||
stream.clear();
|
||||
|
||||
// Get mean motion
|
||||
stream.str(secondLine.substr(52, 11));
|
||||
float meanMotion;
|
||||
stream >> meanMotion;
|
||||
|
||||
p.semiMajorAxis = calculateSemiMajorAxis(meanMotion);
|
||||
p.period = std::chrono::seconds(std::chrono::hours(24)).count() / meanMotion;
|
||||
|
||||
result.push_back(p);
|
||||
|
||||
lineNum = lineNum + 3;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<Parameters> readOmmFile(std::filesystem::path file) {
|
||||
ghoul_assert(std::filesystem::is_regular_file(file), "File must exist");
|
||||
|
||||
std::vector<Parameters> result;
|
||||
|
||||
std::ifstream f;
|
||||
f.open(file);
|
||||
|
||||
int lineNum = 1;
|
||||
std::optional<Parameters> current = std::nullopt;
|
||||
std::string line;
|
||||
while (std::getline(f, line)) {
|
||||
if (line.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Tokenize the line
|
||||
std::vector<std::string> parts = ghoul::tokenizeString(line, '=');
|
||||
for (std::string& p : parts) {
|
||||
ghoul::trimWhitespace(p);
|
||||
}
|
||||
|
||||
if (parts.size() != 2) {
|
||||
throw ghoul::RuntimeError(fmt::format(
|
||||
"Malformed line '{}' at {}", line, lineNum
|
||||
));
|
||||
}
|
||||
|
||||
if (parts[0] == "CCSDS_OMM_VERS") {
|
||||
if (parts[1] != "2.0") {
|
||||
LWARNINGC(
|
||||
"OMM",
|
||||
fmt::format(
|
||||
"Only version 2.0 is currently supported but found {}. "
|
||||
"Parsing might fail",
|
||||
parts[1]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// We start a new value so we need to store the last one...
|
||||
if (current.has_value()) {
|
||||
result.push_back(*current);
|
||||
}
|
||||
|
||||
// ... and start a new one
|
||||
current = Parameters();
|
||||
}
|
||||
|
||||
ghoul_assert(current.has_value(), "No current element");
|
||||
|
||||
if (parts[0] == "OBJECT_NAME") {
|
||||
current->name = parts[1];
|
||||
}
|
||||
else if (parts[0] == "OBJECT_ID") {
|
||||
current->id = parts[1];
|
||||
}
|
||||
else if (parts[0] == "EPOCH") {
|
||||
current->epoch = epochFromOmmString(parts[1]);
|
||||
}
|
||||
else if (parts[0] == "MEAN_MOTION") {
|
||||
float mm = std::stof(parts[1]);
|
||||
current->semiMajorAxis = calculateSemiMajorAxis(mm);
|
||||
current->period = std::chrono::seconds(std::chrono::hours(24)).count() / mm;
|
||||
}
|
||||
else if (parts[0] == "SEMI_MAJOR_AXIS") {
|
||||
|
||||
}
|
||||
else if (parts[0] == "ECCENTRICITY") {
|
||||
current->eccentricity = std::stof(parts[1]);
|
||||
}
|
||||
else if (parts[0] == "INCLINATION") {
|
||||
current->inclination = std::stof(parts[1]);
|
||||
}
|
||||
else if (parts[0] == "RA_OF_ASC_NODE") {
|
||||
current->ascendingNode = std::stof(parts[1]);
|
||||
}
|
||||
else if (parts[0] == "ARG_OF_PERICENTER") {
|
||||
current->argumentOfPeriapsis = std::stof(parts[1]);
|
||||
}
|
||||
else if (parts[0] == "MEAN_ANOMALY") {
|
||||
current->meanAnomaly = std::stof(parts[1]);
|
||||
}
|
||||
}
|
||||
|
||||
if (current.has_value()) {
|
||||
result.push_back(*current);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<Parameters> readSbdbFile(std::filesystem::path file) {
|
||||
constexpr int NDataFields = 9;
|
||||
constexpr std::string_view ExpectedHeader = "full_name,epoch_cal,e,a,i,om,w,ma,per";
|
||||
|
||||
ghoul_assert(std::filesystem::is_regular_file(file), "File must exist");
|
||||
|
||||
std::ifstream f;
|
||||
f.open(file);
|
||||
|
||||
std::string line;
|
||||
std::getline(f, line);
|
||||
if (line != ExpectedHeader) {
|
||||
throw ghoul::RuntimeError(fmt::format(
|
||||
"Expected JPL SBDB file to start with '{}' but found '{}' instead",
|
||||
ExpectedHeader, line
|
||||
));
|
||||
}
|
||||
|
||||
std::vector<Parameters> result;
|
||||
while (std::getline(f, line)) {
|
||||
constexpr double AuToKm = 1.496e8;
|
||||
|
||||
std::vector<std::string> parts = ghoul::tokenizeString(line, ',');
|
||||
if (parts.size() != NDataFields) {
|
||||
throw ghoul::RuntimeError(fmt::format(
|
||||
"Malformed line {}, expected 8 data fields, got {}", line, parts.size()
|
||||
));
|
||||
}
|
||||
Parameters p;
|
||||
|
||||
ghoul::trimWhitespace(parts[0]);
|
||||
p.name = parts[0];
|
||||
|
||||
p.epoch = epochFromYMDdSubstring(parts[1]);
|
||||
p.eccentricity = std::stod(parts[2]);
|
||||
p.semiMajorAxis = std::stod(parts[3]) * AuToKm;
|
||||
|
||||
auto importAngleValue = [](const std::string& angle) {
|
||||
if (angle.empty()) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double output = std::stod(angle);
|
||||
output = std::fmod(output, 360.0);
|
||||
if (output < 0.0) {
|
||||
output += 360.0;
|
||||
}
|
||||
return output;
|
||||
};
|
||||
|
||||
p.inclination = importAngleValue(parts[4]);
|
||||
p.ascendingNode = importAngleValue(parts[5]);
|
||||
p.argumentOfPeriapsis = importAngleValue(parts[6]);
|
||||
p.meanAnomaly = importAngleValue(parts[7]);
|
||||
p.period =
|
||||
std::stod(parts[8]) * std::chrono::seconds(std::chrono::hours(24)).count();
|
||||
|
||||
result.push_back(std::move(p));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void saveCache(const std::vector<Parameters>& params, std::filesystem::path file) {
|
||||
std::ofstream stream(file, std::ofstream::binary);
|
||||
|
||||
stream.write(reinterpret_cast<const char*>(&CurrentCacheVersion), sizeof(int8_t));
|
||||
|
||||
uint32_t size = static_cast<uint32_t>(params.size());
|
||||
stream.write(reinterpret_cast<const char*>(&size), sizeof(uint32_t));
|
||||
for (const Parameters& param : params) {
|
||||
uint32_t nameLength = static_cast<uint32_t>(param.name.size());
|
||||
stream.write(reinterpret_cast<const char*>(&nameLength), sizeof(uint32_t));
|
||||
stream.write(param.name.data(), nameLength * sizeof(char));
|
||||
|
||||
uint32_t idLength = static_cast<uint32_t>(param.id.size());
|
||||
stream.write(reinterpret_cast<const char*>(&idLength), sizeof(uint32_t));
|
||||
stream.write(param.id.data(), idLength * sizeof(char));
|
||||
|
||||
stream.write(reinterpret_cast<const char*>(¶m.inclination), sizeof(double));
|
||||
stream.write(reinterpret_cast<const char*>(¶m.semiMajorAxis), sizeof(double));
|
||||
stream.write(reinterpret_cast<const char*>(¶m.ascendingNode), sizeof(double));
|
||||
stream.write(reinterpret_cast<const char*>(¶m.eccentricity), sizeof(double));
|
||||
stream.write(
|
||||
reinterpret_cast<const char*>(¶m.argumentOfPeriapsis),
|
||||
sizeof(double)
|
||||
);
|
||||
stream.write(reinterpret_cast<const char*>(¶m.meanAnomaly), sizeof(double));
|
||||
stream.write(reinterpret_cast<const char*>(¶m.epoch), sizeof(double));
|
||||
stream.write(reinterpret_cast<const char*>(¶m.period), sizeof(double));
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<std::vector<Parameters>> loadCache(std::filesystem::path file) {
|
||||
std::ifstream stream(file, std::ifstream::binary);
|
||||
|
||||
int8_t version = 0;
|
||||
stream.read(reinterpret_cast<char*>(&version), sizeof(int8_t));
|
||||
if (version != CurrentCacheVersion) {
|
||||
LINFO("The format of the cached file has changed");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
uint32_t size = 0;
|
||||
stream.read(reinterpret_cast<char*>(&size), sizeof(uint32_t));
|
||||
std::vector<Parameters> res;
|
||||
res.reserve(size);
|
||||
for (uint32_t i = 0; i < size; i++) {
|
||||
Parameters param;
|
||||
|
||||
uint32_t nameLength = 0;
|
||||
stream.read(reinterpret_cast<char*>(&nameLength), sizeof(uint32_t));
|
||||
param.name.resize(nameLength);
|
||||
stream.read(param.name.data(), nameLength * sizeof(char));
|
||||
|
||||
uint32_t idLength = 0;
|
||||
stream.read(reinterpret_cast<char*>(&idLength), sizeof(uint32_t));
|
||||
param.id.resize(idLength);
|
||||
stream.read(param.id.data(), idLength * sizeof(char));
|
||||
|
||||
stream.read(reinterpret_cast<char*>(¶m.inclination), sizeof(double));
|
||||
stream.read(reinterpret_cast<char*>(¶m.semiMajorAxis), sizeof(double));
|
||||
stream.read(reinterpret_cast<char*>(¶m.ascendingNode), sizeof(double));
|
||||
stream.read(reinterpret_cast<char*>(¶m.eccentricity), sizeof(double));
|
||||
stream.read(reinterpret_cast<char*>(¶m.argumentOfPeriapsis), sizeof(double));
|
||||
stream.read(reinterpret_cast<char*>(¶m.meanAnomaly), sizeof(double));
|
||||
stream.read(reinterpret_cast<char*>(¶m.epoch), sizeof(double));
|
||||
stream.read(reinterpret_cast<char*>(¶m.period), sizeof(double));
|
||||
|
||||
res.push_back(std::move(param));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<Parameters> readFile(std::filesystem::path file, Format format) {
|
||||
std::filesystem::path cachedFile = FileSys.cacheManager()->cachedFilename(file);
|
||||
if (std::filesystem::is_regular_file(cachedFile)) {
|
||||
LINFO(fmt::format(
|
||||
"Cached file {} used for Kepler file {}", cachedFile, file
|
||||
));
|
||||
|
||||
std::optional<std::vector<Parameters>> res = loadCache(cachedFile);
|
||||
if (res.has_value()) {
|
||||
return *res;
|
||||
}
|
||||
|
||||
// If there is no value in the optional, the cached loading failed
|
||||
}
|
||||
|
||||
std::vector<Parameters> res;
|
||||
switch (format) {
|
||||
case Format::TLE:
|
||||
res = readTleFile(file);
|
||||
break;
|
||||
case Format::OMM:
|
||||
res = readOmmFile(file);
|
||||
break;
|
||||
case Format::SBDB:
|
||||
res = readSbdbFile(file);
|
||||
break;
|
||||
default:
|
||||
throw ghoul::MissingCaseException();
|
||||
}
|
||||
|
||||
LINFO(fmt::format("Saving cache {} for Kepler file {}", cachedFile, file));
|
||||
saveCache(res, cachedFile);
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace openspace::kepler
|
||||
110
modules/space/kepler.h
Normal file
110
modules/space/kepler.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __OPENSPACE_MODULE_SPACE___KEPLER___H__
|
||||
#define __OPENSPACE_MODULE_SPACE___KEPLER___H__
|
||||
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace openspace::kepler {
|
||||
|
||||
struct Parameters {
|
||||
// Some human-readable name for the object represented by this kepler parameter set
|
||||
std::string name;
|
||||
|
||||
// Some form of unique identifier for the object represented by this data
|
||||
std::string id;
|
||||
|
||||
double inclination = 0.0;
|
||||
double semiMajorAxis = 0.0;
|
||||
double ascendingNode = 0.0;
|
||||
double eccentricity = 0.0;
|
||||
double argumentOfPeriapsis = 0.0;
|
||||
double meanAnomaly = 0.0;
|
||||
double epoch = 0.0;
|
||||
double period = 0.0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Reads the object information from the provided \p file and returns them as individual
|
||||
* values.
|
||||
*
|
||||
* \param file The file to the TLE file. This file must be a valid file
|
||||
* \return Information about all of the contained objects in the \p file
|
||||
*
|
||||
* \pre \p file must be a file and must exist
|
||||
* \throw ghoul::RuntimeError If the provided \p file is not a valid TLE file
|
||||
*/
|
||||
std::vector<Parameters> readTleFile(std::filesystem::path file);
|
||||
|
||||
/**
|
||||
* Reads the object information from the provided \p file and returns them as individual
|
||||
* values.
|
||||
*
|
||||
* \param file The file to the OMM file. This file must be a valid file
|
||||
* \return Information about all of the contained objects in the \p file
|
||||
*
|
||||
* \pre \p file must be a file and must exist
|
||||
* \throw ghoul::RuntimeError If the provided \p file is not a valid OMM file
|
||||
*/
|
||||
std::vector<Parameters> readOmmFile(std::filesystem::path file);
|
||||
|
||||
/**
|
||||
* Reads the object information from a CSV file following JPL's Small Body Database
|
||||
* format, which provides the Epoch, eccentricity, semi-major axis (in AU), inclination,
|
||||
* ascending node, argument of periapsis, mean anomaly, and period in that order.
|
||||
*
|
||||
* \param file The CSV file containing the information about the objects
|
||||
* \return Information about all of the contained objects in the \p file
|
||||
*
|
||||
* \pre \p file must be a file and must exist
|
||||
* \throw ghoul::RuntimeError If the provided \p is not a valid JPL SBDB CSV format
|
||||
*/
|
||||
std::vector<Parameters> readSbdbFile(std::filesystem::path file);
|
||||
|
||||
/**
|
||||
* The different formats that the #readFile function is capable of loading
|
||||
*/
|
||||
enum class Format {
|
||||
TLE,
|
||||
OMM,
|
||||
SBDB
|
||||
};
|
||||
/**
|
||||
* Reads the object information from the provided file.
|
||||
*
|
||||
* \param file The file containing the information about the objects
|
||||
* \param format The format of the provided \p file
|
||||
* \return Information about all of the contained objects in the \p file
|
||||
*
|
||||
* \pre \p file must be a file and must exist
|
||||
* \throw ghoul::RuntimeError If the provided \p is not in the provided file
|
||||
*/
|
||||
std::vector<Parameters> readFile(std::filesystem::path file, Format format);
|
||||
|
||||
} // namespace openspace::kepler
|
||||
|
||||
#endif // __OPENSPACE_MODULE_SPACE___KEPLER___H__
|
||||
@@ -25,7 +25,6 @@
|
||||
#include <modules/space/rendering/renderableorbitalkepler.h>
|
||||
|
||||
#include <modules/space/translation/keplertranslation.h>
|
||||
#include <modules/space/translation/tletranslation.h>
|
||||
#include <modules/space/spacemodule.h>
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
@@ -42,130 +41,10 @@
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <math.h>
|
||||
#include <random>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
constexpr std::array<int, 36> LeapYears = {
|
||||
1956, 1960, 1964, 1968, 1972, 1976, 1980, 1984, 1988, 1992, 1996,
|
||||
2000, 2004, 2008, 2012, 2016, 2020, 2024, 2028, 2032, 2036, 2040,
|
||||
2044, 2048, 2052, 2056
|
||||
};
|
||||
constexpr std::array<int, 12> DaysOfMonths = {
|
||||
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
|
||||
};
|
||||
|
||||
// Find the position of the current year in the vector; its position in
|
||||
// the vector gives the number of leap seconds
|
||||
struct LeapSecond {
|
||||
int year;
|
||||
int dayOfYear;
|
||||
bool operator<(const LeapSecond& rhs) const {
|
||||
return std::tie(year, dayOfYear) < std::tie(rhs.year, rhs.dayOfYear);
|
||||
}
|
||||
};
|
||||
|
||||
constexpr LeapSecond LeapEpoch = { 2000, 1 };
|
||||
|
||||
// List taken from: https://www.ietf.org/timezones/data/leap-seconds.list
|
||||
constexpr std::array<LeapSecond, 28> LeapSeconds = {
|
||||
LeapSecond{ 1972, 1 },
|
||||
LeapSecond{ 1972, 183 },
|
||||
LeapSecond{ 1973, 1 },
|
||||
LeapSecond{ 1974, 1 },
|
||||
LeapSecond{ 1975, 1 },
|
||||
LeapSecond{ 1976, 1 },
|
||||
LeapSecond{ 1977, 1 },
|
||||
LeapSecond{ 1978, 1 },
|
||||
LeapSecond{ 1979, 1 },
|
||||
LeapSecond{ 1980, 1 },
|
||||
LeapSecond{ 1981, 182 },
|
||||
LeapSecond{ 1982, 182 },
|
||||
LeapSecond{ 1983, 182 },
|
||||
LeapSecond{ 1985, 182 },
|
||||
LeapSecond{ 1988, 1 },
|
||||
LeapSecond{ 1990, 1 },
|
||||
LeapSecond{ 1991, 1 },
|
||||
LeapSecond{ 1992, 183 },
|
||||
LeapSecond{ 1993, 182 },
|
||||
LeapSecond{ 1994, 182 },
|
||||
LeapSecond{ 1996, 1 },
|
||||
LeapSecond{ 1997, 182 },
|
||||
LeapSecond{ 1999, 1 },
|
||||
LeapSecond{ 2006, 1 },
|
||||
LeapSecond{ 2009, 1 },
|
||||
LeapSecond{ 2012, 183 },
|
||||
LeapSecond{ 2015, 182 },
|
||||
LeapSecond{ 2017, 1 }
|
||||
};
|
||||
|
||||
// Count the number of full days since the beginning of 2000 to the beginning of
|
||||
// the parameter 'year'
|
||||
int countDays(int year) {
|
||||
// Find the position of the current year in the vector, the difference
|
||||
// between its position and the position of 2000 (for J2000) gives the
|
||||
// number of leap years
|
||||
constexpr int Epoch = 2000;
|
||||
constexpr int DaysRegularYear = 365;
|
||||
constexpr int DaysLeapYear = 366;
|
||||
|
||||
if (year == Epoch) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get the position of the most recent leap year
|
||||
const auto lb = std::lower_bound(LeapYears.begin(), LeapYears.end(), year);
|
||||
|
||||
// Get the position of the epoch
|
||||
const auto y2000 = std::find(LeapYears.begin(), LeapYears.end(), Epoch);
|
||||
|
||||
// The distance between the two iterators gives us the number of leap years
|
||||
const int nLeapYears = static_cast<int>(std::abs(std::distance(y2000, lb)));
|
||||
|
||||
const int nYears = std::abs(year - Epoch);
|
||||
const int nRegularYears = nYears - nLeapYears;
|
||||
|
||||
// Get the total number of days as the sum of leap years + non leap years
|
||||
const int result = nRegularYears * DaysRegularYear + nLeapYears * DaysLeapYear;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns the number of leap seconds that lie between the {year, dayOfYear}
|
||||
// time point and { 2000, 1 }
|
||||
int countLeapSeconds(int year, int dayOfYear) {
|
||||
// Get the position of the last leap second before the desired date
|
||||
LeapSecond date{ year, dayOfYear };
|
||||
const auto it = std::lower_bound(LeapSeconds.begin(), LeapSeconds.end(), date);
|
||||
|
||||
// Get the position of the Epoch
|
||||
const auto y2000 = std::lower_bound(
|
||||
LeapSeconds.begin(),
|
||||
LeapSeconds.end(),
|
||||
LeapEpoch
|
||||
);
|
||||
|
||||
// The distance between the two iterators gives us the number of leap years
|
||||
const int nLeapSeconds = static_cast<int>(std::abs(std::distance(y2000, it)));
|
||||
return nLeapSeconds;
|
||||
}
|
||||
|
||||
int daysIntoGivenYear(int year, int month, int dayOfMonth) {
|
||||
//month and dayCount are zero-based.
|
||||
month -= 1;
|
||||
int dayCount = dayOfMonth - 1;
|
||||
const int February = 1;
|
||||
const bool isInLeapYear =
|
||||
std::find(LeapYears.begin(), LeapYears.end(), year)
|
||||
!= LeapYears.end();
|
||||
|
||||
for (int m = 0; m < month; ++m) {
|
||||
dayCount += DaysOfMonths[m];
|
||||
if (m == February && isInLeapYear) {
|
||||
dayCount += 1;
|
||||
}
|
||||
}
|
||||
return dayCount;
|
||||
}
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo PathInfo = {
|
||||
"Path",
|
||||
"Path",
|
||||
@@ -213,10 +92,30 @@ namespace {
|
||||
"Contiguous Size of Render Block",
|
||||
"Number of objects to render sequentially from StartRenderIdx"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo ContiguousModeInfo = {
|
||||
"ContiguousMode",
|
||||
"Contiguous Mode",
|
||||
"If enabled, then the contiguous set of objects starting from StartRenderIdx "
|
||||
"of size RenderSize will be rendered. If disabled, then the number of objects "
|
||||
"defined by UpperLimit will rendered from an evenly dispersed sample of the "
|
||||
"full length of the data file."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(RenderableOrbitalKepler)]] Parameters {
|
||||
// [[codegen::verbatim(PathInfo.description)]]
|
||||
std::string path;
|
||||
std::filesystem::path path;
|
||||
|
||||
enum class [[codegen::map(openspace::kepler::Format)]] Format {
|
||||
// A NORAD-style Two-Line element
|
||||
TLE,
|
||||
// Orbit Mean-Elements Message in the KVN notation
|
||||
OMM,
|
||||
// JPL's Small Bodies Database
|
||||
SBDB
|
||||
};
|
||||
// The file format that is contained in the file
|
||||
Format format;
|
||||
|
||||
// [[codegen::verbatim(SegmentQualityInfo.description)]]
|
||||
int segmentQuality;
|
||||
@@ -235,6 +134,9 @@ namespace {
|
||||
|
||||
// [[codegen::verbatim(RenderSizeInfo.description)]]
|
||||
std::optional<int> renderSize;
|
||||
|
||||
// [[codegen::verbatim(ContiguousModeInfo.description)]]
|
||||
std::optional<bool> contiguousMode;
|
||||
};
|
||||
#include "renderableorbitalkepler_codegen.cpp"
|
||||
} // namespace
|
||||
@@ -245,140 +147,20 @@ documentation::Documentation RenderableOrbitalKepler::Documentation() {
|
||||
return codegen::doc<Parameters>("space_renderableorbitalkepler");
|
||||
}
|
||||
|
||||
double RenderableOrbitalKepler::calculateSemiMajorAxis(double meanMotion) const {
|
||||
constexpr double GravitationalConstant = 6.6740831e-11;
|
||||
constexpr double MassEarth = 5.9721986e24;
|
||||
constexpr double muEarth = GravitationalConstant * MassEarth;
|
||||
|
||||
// Use Kepler's 3rd law to calculate semimajor axis
|
||||
// a^3 / P^2 = mu / (2pi)^2
|
||||
// <=> a = ((mu * P^2) / (2pi^2))^(1/3)
|
||||
// with a = semimajor axis
|
||||
// P = period in seconds
|
||||
// mu = G*M_earth
|
||||
const double period =
|
||||
std::chrono::seconds(std::chrono::hours(24)).count() / meanMotion;
|
||||
|
||||
constexpr double pisq = glm::pi<double>() * glm::pi<double>();
|
||||
const double semiMajorAxis = pow((muEarth * period*period) / (4 * pisq), 1.0 / 3.0);
|
||||
|
||||
// We need the semi major axis in km instead of m
|
||||
return semiMajorAxis / 1000.0;
|
||||
}
|
||||
|
||||
double RenderableOrbitalKepler::epochFromSubstring(const std::string& epochString) const {
|
||||
// The epochString is in the form:
|
||||
// YYDDD.DDDDDDDD
|
||||
// With YY being the last two years of the launch epoch, the first DDD the day
|
||||
// of the year and the remaning a fractional part of the day
|
||||
|
||||
// The main overview of this function:
|
||||
// 1. Reconstruct the full year from the YY part
|
||||
// 2. Calculate the number of days since the beginning of the year
|
||||
// 3. Convert the number of days to a number of seconds
|
||||
// 4. Get the number of leap seconds since January 1st, 2000 and remove them
|
||||
// 5. Adjust for the fact the epoch starts on 1st Januaray at 12:00:00, not
|
||||
// midnight
|
||||
|
||||
// According to https://celestrak.com/columns/v04n03/
|
||||
// Apparently, US Space Command sees no need to change the two-line element
|
||||
// set format yet since no artificial earth satellites existed prior to 1957.
|
||||
// By their reasoning, two-digit years from 57-99 correspond to 1957-1999 and
|
||||
// those from 00-56 correspond to 2000-2056. We'll see each other again in 057!
|
||||
|
||||
// 1. Get the full year
|
||||
std::string yearPrefix =
|
||||
std::atoi(epochString.substr(0, 2).c_str()) > 57 ? "19" : "20";
|
||||
const int year = std::atoi((yearPrefix + epochString.substr(0, 2)).c_str());
|
||||
const int daysSince2000 = countDays(year);
|
||||
|
||||
// 2.
|
||||
double daysInYear = std::atof(epochString.substr(2).c_str());
|
||||
|
||||
// 3
|
||||
using namespace std::chrono;
|
||||
const int SecondsPerDay = static_cast<int>(seconds(hours(24)).count());
|
||||
//Need to subtract 1 from daysInYear since it is not a zero-based count
|
||||
const double nSecondsSince2000 = (daysSince2000 + daysInYear - 1) * SecondsPerDay;
|
||||
|
||||
// 4
|
||||
// We need to remove additional leap seconds past 2000 and add them prior to
|
||||
// 2000 to sync up the time zones
|
||||
const double nLeapSecondsOffset = -countLeapSeconds(
|
||||
year,
|
||||
static_cast<int>(std::floor(daysInYear))
|
||||
);
|
||||
|
||||
// 5
|
||||
const double nSecondsEpochOffset = static_cast<double>(seconds(hours(12)).count());
|
||||
|
||||
// Combine all of the values
|
||||
const double epoch = nSecondsSince2000 + nLeapSecondsOffset - nSecondsEpochOffset;
|
||||
return epoch;
|
||||
}
|
||||
|
||||
double RenderableOrbitalKepler::epochFromYMDdSubstring(const std::string& epochString) {
|
||||
// The epochString is in the form:
|
||||
// YYYYMMDD.ddddddd
|
||||
// With YYYY as the year, MM the month (1 - 12), DD the day of month (1-31),
|
||||
// and dddd the fraction of that day.
|
||||
|
||||
// The main overview of this function:
|
||||
// 1. Read the year value
|
||||
// 2. Calculate the number of days since the beginning of the year
|
||||
// 3. Convert the number of days to a number of seconds
|
||||
// 4. Get the number of leap seconds since January 1st, 2000 and remove them
|
||||
// 5. Adjust for the fact the epoch starts on 1st January at 12:00:00, not
|
||||
// midnight
|
||||
|
||||
// 1
|
||||
int year = std::atoi(epochString.substr(0, 4).c_str());
|
||||
const int daysSince2000 = countDays(year);
|
||||
|
||||
// 2.
|
||||
int monthNum = std::atoi(epochString.substr(4, 2).c_str());
|
||||
int dayOfMonthNum = std::atoi(epochString.substr(6, 2).c_str());
|
||||
int wholeDaysInto = daysIntoGivenYear(year, monthNum, dayOfMonthNum);
|
||||
double fractionOfDay = std::atof(epochString.substr(9, 7).c_str());
|
||||
double daysInYear = static_cast<double>(wholeDaysInto) + fractionOfDay;
|
||||
|
||||
// 3
|
||||
using namespace std::chrono;
|
||||
const int SecondsPerDay = static_cast<int>(seconds(hours(24)).count());
|
||||
//Need to subtract 1 from daysInYear since it is not a zero-based count
|
||||
const double nSecondsSince2000 = (daysSince2000 + daysInYear - 1) * SecondsPerDay;
|
||||
|
||||
// 4
|
||||
// We need to remove additional leap seconds past 2000 and add them prior to
|
||||
// 2000 to sync up the time zones
|
||||
const double nLeapSecondsOffset = -countLeapSeconds(
|
||||
year,
|
||||
static_cast<int>(std::floor(daysInYear))
|
||||
);
|
||||
|
||||
// 5
|
||||
const double nSecondsEpochOffset = static_cast<double>(seconds(hours(12)).count());
|
||||
|
||||
// Combine all of the values
|
||||
const double epoch = nSecondsSince2000 + nLeapSecondsOffset - nSecondsEpochOffset;
|
||||
return epoch;
|
||||
}
|
||||
|
||||
RenderableOrbitalKepler::RenderableOrbitalKepler(const ghoul::Dictionary& dict)
|
||||
: Renderable(dict)
|
||||
, _segmentQuality(SegmentQualityInfo, 2, 1, 10)
|
||||
, _startRenderIdx(StartRenderIdxInfo, 0, 0, 1)
|
||||
, _sizeRender(RenderSizeInfo, 1, 1, 2)
|
||||
, _path(PathInfo)
|
||||
, _contiguousMode(ContiguousModeInfo, false)
|
||||
{
|
||||
_reinitializeTrailBuffers = std::function<void()>([this] { initializeGL(); });
|
||||
|
||||
const Parameters p = codegen::bake<Parameters>(dict);
|
||||
|
||||
addProperty(_opacity);
|
||||
|
||||
_segmentQuality = static_cast<unsigned int>(p.segmentQuality);
|
||||
_segmentQuality.onChange(_reinitializeTrailBuffers);
|
||||
_segmentQuality.onChange([this]() { initializeGL(); });
|
||||
addProperty(_segmentQuality);
|
||||
|
||||
_appearance.lineColor = p.color;
|
||||
@@ -386,13 +168,37 @@ RenderableOrbitalKepler::RenderableOrbitalKepler(const ghoul::Dictionary& dict)
|
||||
_appearance.lineWidth = p.lineWidth.value_or(2.f);
|
||||
addPropertySubOwner(_appearance);
|
||||
|
||||
_path = p.path;
|
||||
_path.onChange(_reinitializeTrailBuffers);
|
||||
_path = p.path.string();
|
||||
_path.onChange([this]() { initializeGL(); });
|
||||
addProperty(_path);
|
||||
|
||||
_format = codegen::map<kepler::Format>(p.format);
|
||||
|
||||
_startRenderIdx = p.startRenderIdx.value_or(0);
|
||||
_startRenderIdx.onChange([this]() {
|
||||
if (_contiguousMode) {
|
||||
if ((_numObjects - _startRenderIdx) < _sizeRender) {
|
||||
_sizeRender = static_cast<unsigned int>(_numObjects - _startRenderIdx);
|
||||
}
|
||||
_updateDataBuffersAtNextRender = true;
|
||||
}
|
||||
});
|
||||
addProperty(_startRenderIdx);
|
||||
|
||||
_sizeRender = p.renderSize.value_or(0u);
|
||||
_sizeRender.onChange([this]() {
|
||||
if (_contiguousMode) {
|
||||
if (_sizeRender > (_numObjects - _startRenderIdx)) {
|
||||
_startRenderIdx = static_cast<unsigned int>(_numObjects - _sizeRender);
|
||||
}
|
||||
}
|
||||
_updateDataBuffersAtNextRender = true;
|
||||
});
|
||||
addProperty(_sizeRender);
|
||||
|
||||
_contiguousMode = p.contiguousMode.value_or(false);
|
||||
_contiguousMode.onChange([this]() { _updateDataBuffersAtNextRender = true; });
|
||||
addProperty(_contiguousMode);
|
||||
}
|
||||
|
||||
void RenderableOrbitalKepler::initializeGL() {
|
||||
@@ -420,14 +226,6 @@ void RenderableOrbitalKepler::initializeGL() {
|
||||
_uniformCache.opacity = _programObject->uniformLocation("opacity");
|
||||
|
||||
updateBuffers();
|
||||
|
||||
double maxSemiMajorAxis = 0.0;
|
||||
for (const KeplerParameters& kp : _data) {
|
||||
if (kp.semiMajorAxis > maxSemiMajorAxis) {
|
||||
maxSemiMajorAxis = kp.semiMajorAxis;
|
||||
}
|
||||
}
|
||||
setBoundingSphere(maxSemiMajorAxis * 1000);
|
||||
}
|
||||
|
||||
void RenderableOrbitalKepler::deinitializeGL() {
|
||||
@@ -447,14 +245,16 @@ bool RenderableOrbitalKepler::isReady() const {
|
||||
return _programObject != nullptr;
|
||||
}
|
||||
|
||||
void RenderableOrbitalKepler::render(const RenderData& data, RendererTasks&) {
|
||||
if (_data.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
void RenderableOrbitalKepler::update(const UpdateData&) {
|
||||
if (_updateDataBuffersAtNextRender) {
|
||||
_updateDataBuffersAtNextRender = false;
|
||||
initializeGL();
|
||||
updateBuffers();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderableOrbitalKepler::render(const RenderData& data, RendererTasks&) {
|
||||
if (_vertexBufferData.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_programObject->activate();
|
||||
@@ -472,9 +272,7 @@ void RenderableOrbitalKepler::render(const RenderData& data, RendererTasks&) {
|
||||
);
|
||||
|
||||
// Because we want the property to work similar to the planet trails
|
||||
const float fade = static_cast<float>(
|
||||
pow(_appearance.lineFade.maxValue() - _appearance.lineFade, 2.0)
|
||||
);
|
||||
const float fade = pow(_appearance.lineFade.maxValue() - _appearance.lineFade, 2.f);
|
||||
|
||||
_programObject->setUniform(_uniformCache.projection, data.camera.projectionMatrix());
|
||||
_programObject->setUniform(_uniformCache.color, _appearance.lineColor);
|
||||
@@ -482,7 +280,7 @@ void RenderableOrbitalKepler::render(const RenderData& data, RendererTasks&) {
|
||||
|
||||
glLineWidth(_appearance.lineWidth);
|
||||
|
||||
const size_t nrOrbits = _data.size();
|
||||
const size_t nrOrbits = _segmentSize.size();
|
||||
gl::GLint vertices = 0;
|
||||
|
||||
//glDepthMask(false);
|
||||
@@ -499,21 +297,83 @@ void RenderableOrbitalKepler::render(const RenderData& data, RendererTasks&) {
|
||||
}
|
||||
|
||||
void RenderableOrbitalKepler::updateBuffers() {
|
||||
readDataFile(_path);
|
||||
std::vector<kepler::Parameters> parameters = kepler::readFile(
|
||||
_path.value(),
|
||||
_format
|
||||
);
|
||||
|
||||
_numObjects = parameters.size();
|
||||
|
||||
if (_startRenderIdx < 0 || _startRenderIdx >= _numObjects) {
|
||||
throw ghoul::RuntimeError(fmt::format(
|
||||
"Start index {} out of range [0, {}]", _startRenderIdx, _numObjects
|
||||
));
|
||||
}
|
||||
|
||||
long long endElement = _startRenderIdx + _sizeRender - 1;
|
||||
endElement = (endElement >= _numObjects) ? _numObjects - 1 : endElement;
|
||||
if (endElement < 0 || endElement >= _numObjects) {
|
||||
throw ghoul::RuntimeError(fmt::format(
|
||||
"End index {} out of range [0, {}]", endElement, _numObjects
|
||||
));
|
||||
}
|
||||
|
||||
_startRenderIdx.setMaxValue(static_cast<unsigned int>(_numObjects - 1));
|
||||
_sizeRender.setMaxValue(static_cast<unsigned int>(_numObjects));
|
||||
if (_sizeRender == 0u) {
|
||||
_sizeRender = static_cast<unsigned int>(_numObjects);
|
||||
}
|
||||
|
||||
if (_contiguousMode) {
|
||||
if (_startRenderIdx >= parameters.size() ||
|
||||
(_startRenderIdx + _sizeRender) >= parameters.size())
|
||||
{
|
||||
throw ghoul::RuntimeError(fmt::format(
|
||||
"Tried to load {} objects but only {} are available",
|
||||
_startRenderIdx + _sizeRender, parameters.size()
|
||||
));
|
||||
}
|
||||
|
||||
// Extract subset that starts at _startRenderIdx and contains _sizeRender obejcts
|
||||
parameters = std::vector<kepler::Parameters>(
|
||||
parameters.begin() + _startRenderIdx,
|
||||
parameters.begin() + _startRenderIdx + _sizeRender
|
||||
);
|
||||
}
|
||||
else {
|
||||
// First shuffle the whole array
|
||||
std::default_random_engine rng;
|
||||
std::shuffle(parameters.begin(), parameters.end(), rng);
|
||||
|
||||
// Then take the first _sizeRender values
|
||||
parameters = std::vector<kepler::Parameters>(
|
||||
parameters.begin(),
|
||||
parameters.begin() + _sizeRender
|
||||
);
|
||||
}
|
||||
|
||||
_segmentSize.clear();
|
||||
for (const kepler::Parameters& p : parameters) {
|
||||
const double scale = static_cast<double>(_segmentQuality) * 10.0;
|
||||
_segmentSize.push_back(
|
||||
static_cast<size_t>(scale + (scale / pow(1 - p.eccentricity, 1.2)))
|
||||
);
|
||||
}
|
||||
|
||||
size_t nVerticesTotal = 0;
|
||||
|
||||
int numOrbits = static_cast<int>(_data.size());
|
||||
int numOrbits = static_cast<int>(parameters.size());
|
||||
for (int i = 0; i < numOrbits; ++i) {
|
||||
nVerticesTotal += _segmentSize[i] + 1;
|
||||
}
|
||||
_vertexBufferData.resize(nVerticesTotal);
|
||||
|
||||
size_t vertexBufIdx = 0;
|
||||
KeplerTranslation keplerTranslator;
|
||||
for (int orbitIdx = 0; orbitIdx < numOrbits; ++orbitIdx) {
|
||||
const KeplerParameters& orbit = _data[orbitIdx];
|
||||
const kepler::Parameters& orbit = parameters[orbitIdx];
|
||||
|
||||
_keplerTranslator.setKeplerElements(
|
||||
keplerTranslator.setKeplerElements(
|
||||
orbit.eccentricity,
|
||||
orbit.semiMajorAxis,
|
||||
orbit.inclination,
|
||||
@@ -526,9 +386,9 @@ void RenderableOrbitalKepler::updateBuffers() {
|
||||
|
||||
for (size_t j = 0 ; j < (_segmentSize[orbitIdx] + 1); ++j) {
|
||||
double timeOffset = orbit.period *
|
||||
static_cast<double>(j)/ static_cast<double>(_segmentSize[orbitIdx]);
|
||||
static_cast<double>(j) / static_cast<double>(_segmentSize[orbitIdx]);
|
||||
|
||||
glm::dvec3 position = _keplerTranslator.position({
|
||||
glm::dvec3 position = keplerTranslator.position({
|
||||
{},
|
||||
Time(timeOffset + orbit.epoch),
|
||||
Time(0.0)
|
||||
@@ -556,7 +416,7 @@ void RenderableOrbitalKepler::updateBuffers() {
|
||||
);
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(TrailVBOLayout), nullptr);
|
||||
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(TrailVBOLayout), nullptr);
|
||||
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(
|
||||
@@ -569,6 +429,14 @@ void RenderableOrbitalKepler::updateBuffers() {
|
||||
);
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
||||
double maxSemiMajorAxis = 0.0;
|
||||
for (const kepler::Parameters& kp : parameters) {
|
||||
if (kp.semiMajorAxis > maxSemiMajorAxis) {
|
||||
maxSemiMajorAxis = kp.semiMajorAxis;
|
||||
}
|
||||
}
|
||||
setBoundingSphere(maxSemiMajorAxis * 1000);
|
||||
}
|
||||
|
||||
} // namespace opensapce
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <openspace/rendering/renderable.h>
|
||||
|
||||
#include <modules/base/rendering/renderabletrail.h>
|
||||
#include <modules/space/kepler.h>
|
||||
#include <modules/space/translation/keplertranslation.h>
|
||||
#include <openspace/properties/stringproperty.h>
|
||||
#include <openspace/properties/scalar/uintproperty.h>
|
||||
@@ -47,65 +48,21 @@ public:
|
||||
void deinitializeGL() override;
|
||||
|
||||
bool isReady() const override;
|
||||
void update(const UpdateData& data) override;
|
||||
void render(const RenderData& data, RendererTasks& rendererTask) override;
|
||||
|
||||
/**
|
||||
* Reads the provided data file and calls the KeplerTranslation::setKeplerElments
|
||||
* method with the correct values. If \p filename is a valid data file but contains
|
||||
* disallowed values (see KeplerTranslation::setKeplerElements), a
|
||||
* KeplerTranslation::RangeError is thrown.
|
||||
*
|
||||
* \param filename The path to the file that contains the data file.
|
||||
*
|
||||
* \throw ghoul::RuntimeError if the data file does not exist or there is a
|
||||
* problem with its format.
|
||||
* \pre The \p filename must exist
|
||||
*/
|
||||
virtual void readDataFile(const std::string& filename) = 0;
|
||||
|
||||
protected:
|
||||
static documentation::Documentation Documentation();
|
||||
|
||||
double calculateSemiMajorAxis(double meanMotion) const;
|
||||
double epochFromSubstring(const std::string& epochString) const;
|
||||
double epochFromYMDdSubstring(const std::string& epochString);
|
||||
private:
|
||||
void updateBuffers();
|
||||
|
||||
std::function<void()> _reinitializeTrailBuffers;
|
||||
std::function<void()> _updateStartRenderIdxSelect;
|
||||
std::function<void()> _updateRenderSizeSelect;
|
||||
|
||||
struct KeplerParameters {
|
||||
double inclination = 0.0;
|
||||
double semiMajorAxis = 0.0;
|
||||
double ascendingNode = 0.0;
|
||||
double eccentricity = 0.0;
|
||||
double argumentOfPeriapsis = 0.0;
|
||||
double meanAnomaly = 0.0;
|
||||
double meanMotion = 0.0;
|
||||
double epoch = 0.0;
|
||||
double period = 0.0;
|
||||
};
|
||||
|
||||
bool _updateDataBuffersAtNextRender = false;
|
||||
std::streamoff _numObjects;
|
||||
bool _isFileReadinitialized = false;
|
||||
inline static constexpr double convertAuToKm = 1.496e8;
|
||||
inline static constexpr double convertDaysToSecs = 86400.0;
|
||||
std::vector<KeplerParameters> _data;
|
||||
std::streamoff _numObjects;
|
||||
std::vector<size_t> _segmentSize;
|
||||
properties::UIntProperty _segmentQuality;
|
||||
properties::UIntProperty _startRenderIdx;
|
||||
properties::UIntProperty _sizeRender;
|
||||
properties::Property::OnChangeHandle _startRenderIdxCallbackHandle;
|
||||
properties::Property::OnChangeHandle _sizeRenderCallbackHandle;
|
||||
|
||||
private:
|
||||
struct Vertex {
|
||||
glm::vec3 position = glm::vec3(0.f);
|
||||
glm::vec3 color = glm::vec3(0.f);
|
||||
glm::vec2 texcoord = glm::vec2(0.f);
|
||||
};
|
||||
|
||||
/// The layout of the VBOs
|
||||
struct TrailVBOLayout {
|
||||
@@ -117,20 +74,17 @@ private:
|
||||
double period = 0.0;
|
||||
};
|
||||
|
||||
KeplerTranslation _keplerTranslator;
|
||||
|
||||
/// The backend storage for the vertex buffer object containing all points for this
|
||||
/// trail.
|
||||
/// The backend storage for the vertex buffer object containing all points
|
||||
std::vector<TrailVBOLayout> _vertexBufferData;
|
||||
|
||||
GLuint _vertexArray;
|
||||
GLuint _vertexBuffer;
|
||||
|
||||
|
||||
ghoul::opengl::ProgramObject* _programObject;
|
||||
properties::StringProperty _path;
|
||||
properties::BoolProperty _contiguousMode;
|
||||
kepler::Format _format;
|
||||
RenderableTrail::Appearance _appearance;
|
||||
glm::vec3 _position = glm::vec3(0.f);
|
||||
|
||||
UniformCache(modelView, projection, lineFade, inGameTime, color, opacity,
|
||||
numberOfSegments) _uniformCache;
|
||||
|
||||
@@ -1,253 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* 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 <modules/space/rendering/renderablesatellites.h>
|
||||
|
||||
#include <modules/space/translation/keplertranslation.h>
|
||||
#include <modules/space/translation/tletranslation.h>
|
||||
#include <modules/space/spacemodule.h>
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/documentation/verifier.h>
|
||||
#include <openspace/util/time.h>
|
||||
#include <openspace/util/updatestructures.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/filesystem/file.h>
|
||||
#include <ghoul/misc/csvreader.h>
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <chrono>
|
||||
#include <math.h>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
constexpr std::string_view _loggerCat = "Satellites";
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo SegmentsInfo = {
|
||||
"Segments",
|
||||
"Segments",
|
||||
"The number of segments to use for each orbit ellipse"
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(RenderableSatellites)]] Parameters {
|
||||
// [[codegen::verbatim(SegmentsInfo.description)]]
|
||||
double segments;
|
||||
};
|
||||
#include "renderablesatellites_codegen.cpp"
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation RenderableSatellites::Documentation() {
|
||||
return codegen::doc<Parameters>(
|
||||
"space_renderablesatellites",
|
||||
RenderableOrbitalKepler::Documentation()
|
||||
);
|
||||
}
|
||||
|
||||
RenderableSatellites::RenderableSatellites(const ghoul::Dictionary& dictionary)
|
||||
: RenderableOrbitalKepler(dictionary)
|
||||
{
|
||||
// Commented out right now as its not super clear how it works with inheritance. We'd
|
||||
// probably want a codegen::check function that only does the checking without
|
||||
// actually creating a Parameter objects
|
||||
// codegen::bake<Parameters>(dictionary);
|
||||
addProperty(_startRenderIdx);
|
||||
addProperty(_sizeRender);
|
||||
|
||||
_updateStartRenderIdxSelect = [this]() {
|
||||
if ((_numObjects - _startRenderIdx) < _sizeRender) {
|
||||
_sizeRender = static_cast<unsigned int>(_numObjects - _startRenderIdx);
|
||||
}
|
||||
updateBuffers();
|
||||
};
|
||||
_updateRenderSizeSelect = [this]() {
|
||||
if (_sizeRender > (_numObjects - _startRenderIdx)) {
|
||||
_startRenderIdx = static_cast<unsigned int>(_numObjects - _sizeRender);
|
||||
}
|
||||
updateBuffers();
|
||||
};
|
||||
_startRenderIdxCallbackHandle = _startRenderIdx.onChange(_updateStartRenderIdxSelect);
|
||||
_sizeRenderCallbackHandle = _sizeRender.onChange(_updateRenderSizeSelect);
|
||||
}
|
||||
|
||||
void RenderableSatellites::readDataFile(const std::string& filename) {
|
||||
if (!std::filesystem::is_regular_file(filename)) {
|
||||
throw ghoul::RuntimeError(fmt::format(
|
||||
"Satellite TLE file {} does not exist", filename
|
||||
));
|
||||
}
|
||||
_data.clear();
|
||||
_segmentSize.clear();
|
||||
|
||||
std::ifstream file;
|
||||
file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||
file.open(filename);
|
||||
|
||||
std::streamoff numberOfLines = std::count(
|
||||
std::istreambuf_iterator<char>(file),
|
||||
std::istreambuf_iterator<char>(),
|
||||
'\n'
|
||||
);
|
||||
file.seekg(std::ios_base::beg); // reset iterator to beginning of file
|
||||
|
||||
_numObjects = numberOfLines / nLineEntriesPerSatellite;
|
||||
|
||||
if (!_isFileReadinitialized) {
|
||||
_isFileReadinitialized = true;
|
||||
initializeFileReading();
|
||||
}
|
||||
|
||||
std::string line = "-";
|
||||
std::string name;
|
||||
long long endElement = _startRenderIdx + _sizeRender - 1;
|
||||
endElement = (endElement >= _numObjects) ? _numObjects - 1 : endElement;
|
||||
//Burn lines if not starting at first element
|
||||
for (unsigned int k = 0; k < _startRenderIdx; ++k) {
|
||||
skipSingleEntryInFile(file);
|
||||
}
|
||||
for (std::streamoff i = _startRenderIdx; i <= endElement; i++) {
|
||||
//Read title line
|
||||
std::getline(file, name);
|
||||
KeplerParameters keplerElements;
|
||||
|
||||
std::getline(file, line);
|
||||
if (line[0] == '1') {
|
||||
// First line
|
||||
// Field Columns Content
|
||||
// 1 01-01 Line number
|
||||
// 2 03-07 Satellite number
|
||||
// 3 08-08 Classification (U = Unclassified)
|
||||
// 4 10-11 International Designator (Last two digits of launch year)
|
||||
// 5 12-14 International Designator (Launch number of the year)
|
||||
// 6 15-17 International Designator(piece of the launch) A
|
||||
name += " " + line.substr(2, 15);
|
||||
if (_startRenderIdx == i && _sizeRender == 1) {
|
||||
LINFO(fmt::format(
|
||||
"Set render block to start at object {}",
|
||||
name
|
||||
));
|
||||
}
|
||||
// 7 19-20 Epoch Year(last two digits of year)
|
||||
// 8 21-32 Epoch(day of the year and fractional portion of the day)
|
||||
// 9 34-43 First Time Derivative of the Mean Motion divided by two
|
||||
// 10 45-52 Second Time Derivative of Mean Motion divided by six
|
||||
// 11 54-61 BSTAR drag term(decimal point assumed)[10] - 11606 - 4
|
||||
// 12 63-63 The "Ephemeris type"
|
||||
// 13 65-68 Element set number.Incremented when a new TLE is generated
|
||||
// 14 69-69 Checksum (modulo 10)
|
||||
keplerElements.epoch = epochFromSubstring(line.substr(18, 14));
|
||||
}
|
||||
else {
|
||||
throw ghoul::RuntimeError(fmt::format(
|
||||
"File {} entry {} does not have '1' header", filename, i + 1
|
||||
));
|
||||
}
|
||||
|
||||
std::getline(file, line);
|
||||
if (line[0] == '2') {
|
||||
// Second line
|
||||
// Field Columns Content
|
||||
// 1 01-01 Line number
|
||||
// 2 03-07 Satellite number
|
||||
// 3 09-16 Inclination (degrees)
|
||||
// 4 18-25 Right ascension of the ascending node (degrees)
|
||||
// 5 27-33 Eccentricity (decimal point assumed)
|
||||
// 6 35-42 Argument of perigee (degrees)
|
||||
// 7 44-51 Mean Anomaly (degrees)
|
||||
// 8 53-63 Mean Motion (revolutions per day)
|
||||
// 9 64-68 Revolution number at epoch (revolutions)
|
||||
// 10 69-69 Checksum (modulo 10)
|
||||
|
||||
std::stringstream stream;
|
||||
stream.exceptions(std::ios::failbit);
|
||||
|
||||
// Get inclination
|
||||
stream.str(line.substr(8, 8));
|
||||
stream >> keplerElements.inclination;
|
||||
stream.clear();
|
||||
|
||||
// Get Right ascension of the ascending node
|
||||
stream.str(line.substr(17, 8));
|
||||
stream >> keplerElements.ascendingNode;
|
||||
stream.clear();
|
||||
|
||||
// Get Eccentricity
|
||||
stream.str("0." + line.substr(26, 7));
|
||||
stream >> keplerElements.eccentricity;
|
||||
stream.clear();
|
||||
|
||||
// Get argument of periapsis
|
||||
stream.str(line.substr(34, 8));
|
||||
stream >> keplerElements.argumentOfPeriapsis;
|
||||
stream.clear();
|
||||
|
||||
// Get mean anomaly
|
||||
stream.str(line.substr(43, 8));
|
||||
stream >> keplerElements.meanAnomaly;
|
||||
stream.clear();
|
||||
|
||||
// Get mean motion
|
||||
stream.str(line.substr(52, 11));
|
||||
stream >> keplerElements.meanMotion;
|
||||
}
|
||||
else {
|
||||
throw ghoul::RuntimeError(fmt::format(
|
||||
"File {} entry {} does not have '2' header", filename, i + 1
|
||||
));
|
||||
}
|
||||
|
||||
// Calculate the semi major axis based on the mean motion using kepler's laws
|
||||
keplerElements.semiMajorAxis = calculateSemiMajorAxis(keplerElements.meanMotion);
|
||||
|
||||
using namespace std::chrono;
|
||||
double period = seconds(hours(24)).count() / keplerElements.meanMotion;
|
||||
keplerElements.period = period;
|
||||
|
||||
_data.push_back(keplerElements);
|
||||
_segmentSize.push_back(_segmentQuality * 16);
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
void RenderableSatellites::initializeFileReading() {
|
||||
_startRenderIdx.setMaxValue(static_cast<unsigned int>(_numObjects - 1));
|
||||
_sizeRender.setMaxValue(static_cast<unsigned int>(_numObjects));
|
||||
if (_sizeRender == 0u) {
|
||||
_sizeRender = static_cast<unsigned int>(_numObjects);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderableSatellites::skipSingleEntryInFile(std::ifstream& file) {
|
||||
std::string line;
|
||||
for (unsigned int i = 0; i < nLineEntriesPerSatellite; i++) {
|
||||
std::getline(file, line);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,424 +0,0 @@
|
||||
/****************************************************************************************
|
||||
* *
|
||||
* 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 <modules/space/rendering/renderablesmallbody.h>
|
||||
|
||||
#include <modules/space/rendering/renderablesatellites.h>
|
||||
#include <modules/space/translation/keplertranslation.h>
|
||||
#include <modules/space/translation/tletranslation.h>
|
||||
#include <modules/space/spacemodule.h>
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/documentation/verifier.h>
|
||||
#include <openspace/util/time.h>
|
||||
#include <openspace/util/updatestructures.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/filesystem/file.h>
|
||||
#include <ghoul/misc/csvreader.h>
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <chrono>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <math.h>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
constexpr std::string_view _loggerCat = "SmallSolarSystemBody";
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo ContiguousModeInfo = {
|
||||
"ContiguousMode",
|
||||
"Contiguous Mode",
|
||||
"If enabled, then the contiguous set of objects starting from StartRenderIdx "
|
||||
"of size RenderSize will be rendered. If disabled, then the number of objects "
|
||||
"defined by UpperLimit will rendered from an evenly dispersed sample of the "
|
||||
"full length of the data file"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo UpperLimitInfo = {
|
||||
"UpperLimit",
|
||||
"Upper Limit",
|
||||
"Upper limit on the number of objects for this renderable, regardless of "
|
||||
"how many objects are contained in the data file. Produces an evenly-distributed"
|
||||
"sample from the data file"
|
||||
};
|
||||
|
||||
double importAngleValue(const std::string& angle) {
|
||||
if (angle.empty()) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double output = std::stod(angle);
|
||||
output = std::fmod(output, 360.0);
|
||||
if (output < 0.0) {
|
||||
output += 360.0;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
std::string& formatObjectName(std::string& name) {
|
||||
const std::string trimChars = "\t\n\v\f\r\" ";
|
||||
name.erase(0, name.find_first_not_of(trimChars));
|
||||
name.erase(name.find_last_not_of(trimChars) + 1);
|
||||
return name;
|
||||
}
|
||||
|
||||
struct [[codegen::Dictionary(RenderableSmallBody)]] Parameters {
|
||||
// [[codegen::verbatim(ContiguousModeInfo.description)]]
|
||||
std::optional<bool> contiguousMode;
|
||||
|
||||
// [[codegen::verbatim(UpperLimitInfo.description)]]
|
||||
std::optional<int> upperLimit;
|
||||
};
|
||||
#include "renderablesmallbody_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation RenderableSmallBody::Documentation() {
|
||||
return codegen::doc<Parameters>(
|
||||
"space_renderablesmallbody",
|
||||
RenderableOrbitalKepler::Documentation()
|
||||
);
|
||||
}
|
||||
|
||||
RenderableSmallBody::RenderableSmallBody(const ghoul::Dictionary& dictionary)
|
||||
: RenderableOrbitalKepler(dictionary)
|
||||
, _contiguousMode(ContiguousModeInfo, false)
|
||||
, _upperLimit(UpperLimitInfo, 1000, 1, 1000000)
|
||||
{
|
||||
codegen::bake<Parameters>(dictionary);
|
||||
|
||||
addProperty(_startRenderIdx);
|
||||
addProperty(_sizeRender);
|
||||
addProperty(_contiguousMode);
|
||||
addProperty(_upperLimit);
|
||||
|
||||
if (dictionary.hasValue<double>(UpperLimitInfo.identifier)) {
|
||||
_upperLimit = static_cast<unsigned int>(
|
||||
dictionary.value<double>(UpperLimitInfo.identifier));
|
||||
}
|
||||
else {
|
||||
_upperLimit = 0u;
|
||||
}
|
||||
|
||||
if (dictionary.hasValue<bool>(ContiguousModeInfo.identifier)) {
|
||||
_contiguousMode = dictionary.value<bool>(ContiguousModeInfo.identifier);
|
||||
}
|
||||
else {
|
||||
_contiguousMode = false;
|
||||
}
|
||||
|
||||
_updateStartRenderIdxSelect = std::function<void()>([this] {
|
||||
if (_contiguousMode) {
|
||||
if ((_numObjects - _startRenderIdx) < _sizeRender) {
|
||||
_sizeRender = static_cast<unsigned int>(_numObjects - _startRenderIdx);
|
||||
}
|
||||
_updateDataBuffersAtNextRender = true;
|
||||
}
|
||||
});
|
||||
_updateRenderSizeSelect = std::function<void()>([this] {
|
||||
if (_contiguousMode) {
|
||||
if (_sizeRender > (_numObjects - _startRenderIdx)) {
|
||||
_startRenderIdx = static_cast<unsigned int>(_numObjects - _sizeRender);
|
||||
}
|
||||
_updateDataBuffersAtNextRender = true;
|
||||
}
|
||||
});
|
||||
_updateRenderUpperLimitSelect = std::function<void()>([this] {
|
||||
if (!_contiguousMode) {
|
||||
_updateDataBuffersAtNextRender = true;
|
||||
}
|
||||
});
|
||||
_updateContiguousModeSelect = std::function<void()>([this] {
|
||||
_updateDataBuffersAtNextRender = true;
|
||||
});
|
||||
|
||||
_startRenderIdxCallbackHandle = _startRenderIdx.onChange(_updateStartRenderIdxSelect);
|
||||
_sizeRenderCallbackHandle = _sizeRender.onChange(_updateRenderSizeSelect);
|
||||
_upperLimitCallbackHandle = _upperLimit.onChange(_updateRenderUpperLimitSelect);
|
||||
_contiguousModeCallbackhandle =
|
||||
_contiguousMode.onChange(_updateContiguousModeSelect);
|
||||
}
|
||||
|
||||
void RenderableSmallBody::readDataFile(const std::string& filename) {
|
||||
if (!std::filesystem::is_regular_file(filename)) {
|
||||
throw ghoul::RuntimeError(fmt::format(
|
||||
"JPL SBDB file {} does not exist", filename
|
||||
));
|
||||
}
|
||||
|
||||
std::ifstream file;
|
||||
file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||
file.open(filename);
|
||||
|
||||
std::streamoff numberOfLines = std::count(
|
||||
std::istreambuf_iterator<char>(file),
|
||||
std::istreambuf_iterator<char>(),
|
||||
'\n'
|
||||
);
|
||||
file.seekg(std::ios_base::beg); // reset iterator to beginning of file
|
||||
_data.clear();
|
||||
_sbNames.clear();
|
||||
_segmentSize.clear();
|
||||
|
||||
std::string line;
|
||||
unsigned int csvLine = 0;
|
||||
int fieldCount = 0;
|
||||
const std::string expectedHeaderLine = "full_name,epoch_cal,e,a,i,om,w,ma,per";
|
||||
|
||||
try {
|
||||
std::getline(file, line); // get rid of first line (header)
|
||||
numberOfLines -= 1;
|
||||
if (_numObjects != numberOfLines) {
|
||||
_isFileReadinitialized = false;
|
||||
}
|
||||
_numObjects = numberOfLines;
|
||||
|
||||
float lineSkipFraction = 1.0;
|
||||
if (!_isFileReadinitialized) {
|
||||
_isFileReadinitialized = true;
|
||||
initializeFileReading();
|
||||
}
|
||||
|
||||
unsigned int startElement = 0;
|
||||
unsigned int endElement;
|
||||
if (_contiguousMode) {
|
||||
lineSkipFraction = 1.0;
|
||||
startElement = _startRenderIdx;
|
||||
endElement = _startRenderIdx + _sizeRender - 1;
|
||||
}
|
||||
else {
|
||||
lineSkipFraction = static_cast<float>(_upperLimit)
|
||||
/ static_cast<float>(_numObjects);
|
||||
endElement = static_cast<unsigned int>(_numObjects - 1);
|
||||
}
|
||||
|
||||
if (line.compare(expectedHeaderLine) != 0) {
|
||||
LERROR(fmt::format(
|
||||
"File {} does not have the appropriate JPL SBDB header at line 1",
|
||||
filename
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int sequentialLineErrors = 0;
|
||||
endElement =
|
||||
(endElement >= _numObjects) ?
|
||||
static_cast<unsigned int>(_numObjects - 1) :
|
||||
endElement;
|
||||
// Burn lines if not starting at first element
|
||||
for (unsigned int k = 0; k < startElement; ++k) {
|
||||
skipSingleLineInFile(file);
|
||||
}
|
||||
bool firstDataLine = true;
|
||||
int lastLineCount = -1;
|
||||
for (csvLine = startElement + 1;
|
||||
csvLine <= endElement + 1;
|
||||
csvLine++, sequentialLineErrors++)
|
||||
{
|
||||
float currLineFraction = static_cast<float>(csvLine - 1) * lineSkipFraction;
|
||||
int currLineCount = static_cast<int>(currLineFraction);
|
||||
if (currLineCount > lastLineCount) {
|
||||
try {
|
||||
readOrbitalParamsFromThisLine(firstDataLine, fieldCount, csvLine,
|
||||
file);
|
||||
sequentialLineErrors = 0;
|
||||
}
|
||||
catch (std::invalid_argument&) {
|
||||
constexpr std::string_view errMsg = "Unable to convert field {} to "
|
||||
"double value (invalid_argument exception). Ignoring line {}/{} "
|
||||
"of {}";
|
||||
LINFO(fmt::format(
|
||||
errMsg,
|
||||
fieldCount, csvLine + 1, numberOfLines, filename
|
||||
));
|
||||
}
|
||||
catch (std::out_of_range&) {
|
||||
constexpr std::string_view errMsg = "Unable to convert field {} to "
|
||||
"double value (out_of_range exception). Ignoring line {}/{} of "
|
||||
"{}";
|
||||
LINFO(fmt::format(
|
||||
errMsg,
|
||||
fieldCount, csvLine + 1, numberOfLines, filename
|
||||
));
|
||||
}
|
||||
catch (std::ios_base::failure&) {
|
||||
throw;
|
||||
}
|
||||
|
||||
if (sequentialLineErrors == 4) {
|
||||
_data.clear();
|
||||
_sbNames.clear();
|
||||
LERROR(fmt::format(
|
||||
"Abandoning data file {} (too many sequential line errors)",
|
||||
filename
|
||||
));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
skipSingleLineInFile(file);
|
||||
}
|
||||
lastLineCount = currLineCount;
|
||||
firstDataLine = false;
|
||||
}
|
||||
}
|
||||
catch (const std::ios_base::failure&) {
|
||||
LERROR(fmt::format(
|
||||
"File read exception (ios_base::failure) while trying to read field {} at "
|
||||
"line {}/{} of {}",
|
||||
fieldCount, csvLine + 1, numberOfLines, filename
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
void RenderableSmallBody::initializeFileReading() {
|
||||
_startRenderIdx.setMaxValue(static_cast<unsigned int>(_numObjects - 1));
|
||||
_sizeRender.setMaxValue(static_cast<unsigned int>(_numObjects));
|
||||
if (_sizeRender == 0u) {
|
||||
_sizeRender = static_cast<unsigned int>(_numObjects);
|
||||
}
|
||||
|
||||
_upperLimit.setMaxValue(static_cast<unsigned int>(_numObjects));
|
||||
if (_upperLimit == 0u) {
|
||||
_upperLimit = static_cast<unsigned int>(_numObjects);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderableSmallBody::skipSingleLineInFile(std::ifstream& file) {
|
||||
std::string line;
|
||||
std::getline(file, line);
|
||||
}
|
||||
|
||||
void RenderableSmallBody::readOrbitalParamsFromThisLine(bool firstDataLine,
|
||||
int& fieldCount,
|
||||
unsigned int& csvLine,
|
||||
std::ifstream& file)
|
||||
{
|
||||
const int numDataFields = 8;
|
||||
std::string name;
|
||||
std::string field;
|
||||
KeplerParameters keplerElements;
|
||||
|
||||
//If there was a read/conversion error in the previous line, then read the remainder
|
||||
// of that line and throw it out first before proceeding with the next line.
|
||||
if (fieldCount != (numDataFields + 1) && !firstDataLine) {
|
||||
std::getline(file, field);
|
||||
}
|
||||
fieldCount = 0;
|
||||
|
||||
// Object designator string
|
||||
std::getline(file, name, ',');
|
||||
if (_startRenderIdx > 0 && _startRenderIdx == (csvLine - 1) && _sizeRender == 1) {
|
||||
formatObjectName(name);
|
||||
LINFO(fmt::format("Set render block to start at object {}", name));
|
||||
}
|
||||
fieldCount++;
|
||||
|
||||
// Epoch
|
||||
if (!std::getline(file, field, ',')) {
|
||||
throw std::invalid_argument(
|
||||
"Unable to read epoch from line" + std::to_string(csvLine + 1)
|
||||
);
|
||||
}
|
||||
keplerElements.epoch = epochFromYMDdSubstring(field);
|
||||
fieldCount++;
|
||||
|
||||
// Eccentricity (unit-less)
|
||||
if (!std::getline(file, field, ',')) {
|
||||
throw std::invalid_argument(
|
||||
"Unable to read eccentricity from line" + std::to_string(csvLine + 1)
|
||||
);
|
||||
}
|
||||
keplerElements.eccentricity = std::stod(field);
|
||||
fieldCount++;
|
||||
|
||||
// Semi-major axis (astronomical units - au)
|
||||
if (!std::getline(file, field, ',')) {
|
||||
throw std::invalid_argument(
|
||||
"Unable to read semi-major axis from line" + std::to_string(csvLine + 1)
|
||||
);
|
||||
}
|
||||
keplerElements.semiMajorAxis = std::stod(field);
|
||||
keplerElements.semiMajorAxis *= convertAuToKm;
|
||||
fieldCount++;
|
||||
|
||||
// Inclination (degrees)
|
||||
if (!std::getline(file, field, ',')) {
|
||||
throw std::invalid_argument(
|
||||
"Unable to read inclination from line" + std::to_string(csvLine + 1)
|
||||
);
|
||||
}
|
||||
keplerElements.inclination = importAngleValue(field);
|
||||
fieldCount++;
|
||||
|
||||
// Longitude of ascending node (degrees)
|
||||
if (!std::getline(file, field, ',')) {
|
||||
throw std::invalid_argument(
|
||||
"Unable to read ascending node from line" + std::to_string(csvLine + 1)
|
||||
);
|
||||
}
|
||||
keplerElements.ascendingNode = importAngleValue(field);
|
||||
fieldCount++;
|
||||
|
||||
// Argument of Periapsis (degrees)
|
||||
if (!std::getline(file, field, ',')) {
|
||||
throw std::invalid_argument(
|
||||
"Unable to read arg of periapsis from line" + std::to_string(csvLine + 1)
|
||||
);
|
||||
}
|
||||
keplerElements.argumentOfPeriapsis = importAngleValue(field);
|
||||
fieldCount++;
|
||||
|
||||
// Mean Anomaly (degrees)
|
||||
if (!std::getline(file, field, ',')) {
|
||||
throw std::invalid_argument(
|
||||
"Unable to read mean anomaly from line" + std::to_string(csvLine + 1)
|
||||
);
|
||||
}
|
||||
keplerElements.meanAnomaly = importAngleValue(field);
|
||||
fieldCount++;
|
||||
|
||||
// Period (days)
|
||||
if (!std::getline(file, field)) {
|
||||
throw std::invalid_argument(
|
||||
"Unable to read period from line" + std::to_string(csvLine + 1)
|
||||
);
|
||||
}
|
||||
keplerElements.period = std::stod(field);
|
||||
keplerElements.period *= convertDaysToSecs;
|
||||
fieldCount++;
|
||||
|
||||
_data.push_back(keplerElements);
|
||||
_sbNames.push_back(name);
|
||||
const double scale = static_cast<double>(_segmentQuality) * 10.0;
|
||||
_segmentSize.push_back(
|
||||
static_cast<size_t>(scale + (scale / pow(1 - keplerElements.eccentricity, 1.2)))
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
@@ -27,14 +27,13 @@
|
||||
#include <modules/space/rendering/renderableconstellationbounds.h>
|
||||
#include <modules/space/rendering/renderablefluxnodes.h>
|
||||
#include <modules/space/rendering/renderablehabitablezone.h>
|
||||
#include <modules/space/rendering/renderableorbitalkepler.h>
|
||||
#include <modules/space/rendering/renderablerings.h>
|
||||
#include <modules/space/rendering/renderablesatellites.h>
|
||||
#include <modules/space/rendering/renderablesmallbody.h>
|
||||
#include <modules/space/rendering/renderablestars.h>
|
||||
#include <modules/space/rendering/renderabletravelspeed.h>
|
||||
#include <modules/space/translation/keplertranslation.h>
|
||||
#include <modules/space/translation/spicetranslation.h>
|
||||
#include <modules/space/translation/tletranslation.h>
|
||||
#include <modules/space/translation/gptranslation.h>
|
||||
#include <modules/space/translation/horizonstranslation.h>
|
||||
#include <modules/space/rotation/spicerotation.h>
|
||||
#include <openspace/documentation/documentation.h>
|
||||
@@ -83,8 +82,7 @@ void SpaceModule::internalInitialize(const ghoul::Dictionary& dictionary) {
|
||||
fRenderable->registerClass<RenderableFluxNodes>("RenderableFluxNodes");
|
||||
fRenderable->registerClass<RenderableHabitableZone>("RenderableHabitableZone");
|
||||
fRenderable->registerClass<RenderableRings>("RenderableRings");
|
||||
fRenderable->registerClass<RenderableSatellites>("RenderableSatellites");
|
||||
fRenderable->registerClass<RenderableSmallBody>("RenderableSmallBody");
|
||||
fRenderable->registerClass<RenderableOrbitalKepler>("RenderableOrbitalKepler");
|
||||
fRenderable->registerClass<RenderableStars>("RenderableStars");
|
||||
fRenderable->registerClass<RenderableTravelSpeed>("RenderableTravelSpeed");
|
||||
|
||||
@@ -94,7 +92,7 @@ void SpaceModule::internalInitialize(const ghoul::Dictionary& dictionary) {
|
||||
|
||||
fTranslation->registerClass<KeplerTranslation>("KeplerTranslation");
|
||||
fTranslation->registerClass<SpiceTranslation>("SpiceTranslation");
|
||||
fTranslation->registerClass<TLETranslation>("TLETranslation");
|
||||
fTranslation->registerClass<GPTranslation>("GPTranslation");
|
||||
fTranslation->registerClass<HorizonsTranslation>("HorizonsTranslation");
|
||||
|
||||
ghoul::TemplateFactory<Rotation>* fRotation =
|
||||
@@ -120,13 +118,12 @@ std::vector<documentation::Documentation> SpaceModule::documentations() const {
|
||||
RenderableFluxNodes::Documentation(),
|
||||
RenderableHabitableZone::Documentation(),
|
||||
RenderableRings::Documentation(),
|
||||
RenderableSatellites::Documentation(),
|
||||
RenderableSmallBody::Documentation(),
|
||||
RenderableOrbitalKepler::Documentation(),
|
||||
RenderableStars::Documentation(),
|
||||
RenderableTravelSpeed::Documentation(),
|
||||
SpiceRotation::Documentation(),
|
||||
SpiceTranslation::Documentation(),
|
||||
TLETranslation::Documentation()
|
||||
GPTranslation::Documentation()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -135,7 +132,8 @@ scripting::LuaLibrary SpaceModule::luaLibrary() const {
|
||||
"space",
|
||||
{
|
||||
codegen::lua::ConvertFromRaDec,
|
||||
codegen::lua::ConvertToRaDec
|
||||
codegen::lua::ConvertToRaDec,
|
||||
codegen::lua::ReadKeplerFile
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include "kepler.h"
|
||||
|
||||
namespace {
|
||||
|
||||
/**
|
||||
@@ -77,6 +79,43 @@ namespace {
|
||||
return { raDecPair.first, raDecPair.second, deg.z };
|
||||
}
|
||||
|
||||
[[codegen::luawrap]]
|
||||
std::vector<ghoul::Dictionary> readKeplerFile(std::filesystem::path p, std::string type)
|
||||
{
|
||||
openspace::kepler::Format f;
|
||||
if (type == "TLE") {
|
||||
f = openspace::kepler::Format::TLE;
|
||||
}
|
||||
else if (type == "OMM") {
|
||||
f = openspace::kepler::Format::OMM;
|
||||
}
|
||||
else if (type == "SBDB") {
|
||||
f = openspace::kepler::Format::SBDB;
|
||||
}
|
||||
else {
|
||||
throw ghoul::lua::LuaError(fmt::format("Unsupported format '{}'", type));
|
||||
}
|
||||
|
||||
std::vector<openspace::kepler::Parameters> params = openspace::kepler::readFile(p, f);
|
||||
std::vector<ghoul::Dictionary> res;
|
||||
res.reserve(params.size());
|
||||
for (const openspace::kepler::Parameters& param : params) {
|
||||
ghoul::Dictionary d;
|
||||
d.setValue("Name", param.name);
|
||||
d.setValue("ID", param.id);
|
||||
d.setValue("inclination", param.inclination);
|
||||
d.setValue("SemiMajorAxis", param.semiMajorAxis);
|
||||
d.setValue("AscendingNode", param.ascendingNode);
|
||||
d.setValue("Eccentricity", param.eccentricity);
|
||||
d.setValue("ArgumentOfPeriapsis", param.argumentOfPeriapsis);
|
||||
d.setValue("MeanAnomaly", param.meanAnomaly);
|
||||
d.setValue("Epoch", param.epoch);
|
||||
d.setValue("Period", param.period);
|
||||
res.push_back(d);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#include "spacemodule_lua_codegen.cpp"
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include <openspace/util/task.h>
|
||||
#include <openspace/util/time.h>
|
||||
|
||||
#include <modules/space/rendering/renderablesatellites.h>
|
||||
#include <modules/space/rendering/renderableorbitalkepler.h>
|
||||
#include <modules/space/translation/keplertranslation.h>
|
||||
|
||||
|
||||
@@ -50,8 +50,6 @@ public:
|
||||
|
||||
std::string _gridType;
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
std::string _rawVolumeOutputPath;
|
||||
std::string _dictionaryOutputPath;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/****************************************************************************************
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
@@ -22,50 +22,71 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __OPENSPACE_MODULE_SPACE___RENDERABLESMALLBODY___H__
|
||||
#define __OPENSPACE_MODULE_SPACE___RENDERABLESMALLBODY___H__
|
||||
#include <modules/space/translation/gptranslation.h>
|
||||
|
||||
#include <modules/space/rendering/renderableorbitalkepler.h>
|
||||
#include <openspace/rendering/renderable.h>
|
||||
#include <modules/space/kepler.h>
|
||||
#include <openspace/documentation/verifier.h>
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
|
||||
#include <modules/base/rendering/renderabletrail.h>
|
||||
#include <modules/space/translation/keplertranslation.h>
|
||||
#include <openspace/properties/stringproperty.h>
|
||||
#include <openspace/properties/scalar/uintproperty.h>
|
||||
#include <ghoul/glm.h>
|
||||
#include <ghoul/misc/objectmanager.h>
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
namespace {
|
||||
struct [[codegen::Dictionary(GPTranslation)]] Parameters {
|
||||
// Specifies the filename of the general pertubation file
|
||||
std::filesystem::path file;
|
||||
|
||||
enum class [[codegen::map(openspace::kepler::Format)]] Format {
|
||||
// A NORAD-style Two-Line element
|
||||
TLE,
|
||||
// Orbit Mean-Elements Message in the KVN notation
|
||||
OMM,
|
||||
// JPL's Small Bodies Database
|
||||
SBDB
|
||||
};
|
||||
// The file format that is contained in the file
|
||||
Format format;
|
||||
|
||||
// Specifies the element within the file that should be used in case the file
|
||||
// provides multiple general pertubation elements. Defaults to 1.
|
||||
std::optional<int> element [[codegen::greater(0)]];
|
||||
};
|
||||
#include "gptranslation_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
namespace documentation { struct Documentation; }
|
||||
documentation::Documentation GPTranslation::Documentation() {
|
||||
return codegen::doc<Parameters>("space_transform_gp");
|
||||
}
|
||||
|
||||
class RenderableSmallBody : public RenderableOrbitalKepler {
|
||||
public:
|
||||
RenderableSmallBody(const ghoul::Dictionary& dictionary);
|
||||
static documentation::Documentation Documentation();
|
||||
GPTranslation::GPTranslation(const ghoul::Dictionary& dictionary) {
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
if (!std::filesystem::is_regular_file(p.file)) {
|
||||
throw ghoul::RuntimeError("The provided TLE file must exist");
|
||||
}
|
||||
|
||||
private:
|
||||
void readOrbitalParamsFromThisLine(bool firstDataLine, int& fieldCount,
|
||||
unsigned int& csvLine, std::ifstream& file);
|
||||
virtual void readDataFile(const std::string& filename) override;
|
||||
void initializeFileReading();
|
||||
void skipSingleLineInFile(std::ifstream& file);
|
||||
int element = p.element.value_or(1);
|
||||
|
||||
std::vector<std::string> _sbNames;
|
||||
std::function<void()> _updateContiguousModeSelect;
|
||||
std::function<void()> _updateRenderUpperLimitSelect;
|
||||
std::vector<kepler::Parameters> parameters = kepler::readFile(
|
||||
p.file,
|
||||
codegen::map<kepler::Format>(p.format)
|
||||
);
|
||||
if (parameters.size() < element) {
|
||||
throw ghoul::RuntimeError(fmt::format(
|
||||
"Requested element {} but only {} are available", element, parameters.size()
|
||||
));
|
||||
}
|
||||
|
||||
/// The index array that is potentially used in the draw call. If this is empty, no
|
||||
/// element draw call is used.
|
||||
std::vector<unsigned int> _indexBufferData;
|
||||
properties::BoolProperty _contiguousMode;
|
||||
properties::UIntProperty _upperLimit;
|
||||
properties::Property::OnChangeHandle _contiguousModeCallbackhandle;
|
||||
properties::Property::OnChangeHandle _upperLimitCallbackHandle;
|
||||
};
|
||||
kepler::Parameters param = parameters[element - 1];
|
||||
setKeplerElements(
|
||||
param.eccentricity,
|
||||
param.semiMajorAxis,
|
||||
param.inclination,
|
||||
param.ascendingNode,
|
||||
param.argumentOfPeriapsis,
|
||||
param.meanAnomaly,
|
||||
param.period,
|
||||
param.epoch
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __OPENSPACE_MODULE_SPACE___RENDERABLESMALLBODY___H__
|
||||
|
||||
@@ -22,37 +22,38 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __OPENSPACE_MODULE_SPACE___RENDERABLESATELLITES___H__
|
||||
#define __OPENSPACE_MODULE_SPACE___RENDERABLESATELLITES___H__
|
||||
#ifndef __OPENSPACE_MODULE_SPACE___GPTRANSLATION___H__
|
||||
#define __OPENSPACE_MODULE_SPACE___GPTRANSLATION___H__
|
||||
|
||||
#include <modules/space/rendering/renderableorbitalkepler.h>
|
||||
#include <openspace/rendering/renderable.h>
|
||||
|
||||
#include <modules/base/rendering/renderabletrail.h>
|
||||
#include <modules/space/translation/keplertranslation.h>
|
||||
#include <openspace/properties/stringproperty.h>
|
||||
#include <openspace/properties/scalar/uintproperty.h>
|
||||
#include <ghoul/glm.h>
|
||||
#include <ghoul/misc/objectmanager.h>
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
namespace documentation { struct Documentation; }
|
||||
|
||||
class RenderableSatellites : public RenderableOrbitalKepler {
|
||||
/**
|
||||
* A specialization of the KeplerTranslation that utilizes general pertubation file
|
||||
* formats to extracts the Keplerian elements
|
||||
*/
|
||||
class GPTranslation : public KeplerTranslation {
|
||||
public:
|
||||
RenderableSatellites(const ghoul::Dictionary& dictionary);
|
||||
virtual void readDataFile(const std::string& filename) override;
|
||||
static documentation::Documentation Documentation();
|
||||
void initializeFileReading();
|
||||
/**
|
||||
* Constructor for the GPTranslation class. The \p dictionary must contain a key for
|
||||
* the file that contains the general pertubation information as well as the file
|
||||
* format that is to be used.
|
||||
*
|
||||
* \param The ghoul::Dictionary that contains the information for this TLETranslation
|
||||
*/
|
||||
explicit GPTranslation(const ghoul::Dictionary& dictionary);
|
||||
|
||||
private:
|
||||
void skipSingleEntryInFile(std::ifstream& file);
|
||||
const unsigned int nLineEntriesPerSatellite = 3;
|
||||
/**
|
||||
* Method returning the openspace::Documentation that describes the ghoul::Dictionary
|
||||
* that can be passed to the constructor.
|
||||
*
|
||||
* \return The openspace::Documentation that describes the ghoul::Dicitonary that can
|
||||
* be passed to the constructor
|
||||
*/
|
||||
static documentation::Documentation Documentation();
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __OPENSPACE_MODULE_SPACE___RENDERABLESATELLITES___H__
|
||||
|
||||
#endif // __OPENSPACE_MODULE_SPACE___GPTRANSLATION___H__
|
||||
@@ -71,7 +71,7 @@ public:
|
||||
glm::dvec3 position(const UpdateData& data) const override;
|
||||
|
||||
/**
|
||||
* Method returning the openspace::Documentation that describes the ghoul::Dictinoary
|
||||
* Method returning the openspace::Documentation that describes the ghoul::Dictionary
|
||||
* that can be passed to the constructor.
|
||||
*
|
||||
* \return The openspace::Documentation that describes the ghoul::Dicitonary that can
|
||||
|
||||
@@ -1,364 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* 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 <modules/space/translation/tletranslation.h>
|
||||
|
||||
#include <openspace/documentation/verifier.h>
|
||||
#include <ghoul/filesystem/file.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <chrono>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
// The list of leap years only goes until 2056 as we need to touch this file then
|
||||
// again anyway ;)
|
||||
const std::vector<int> LeapYears = {
|
||||
1956, 1960, 1964, 1968, 1972, 1976, 1980, 1984, 1988, 1992, 1996,
|
||||
2000, 2004, 2008, 2012, 2016, 2020, 2024, 2028, 2032, 2036, 2040,
|
||||
2044, 2048, 2052, 2056
|
||||
};
|
||||
|
||||
// Count the number of full days since the beginning of 2000 to the beginning of
|
||||
// the parameter 'year'
|
||||
int countDays(int year) {
|
||||
// Find the position of the current year in the vector, the difference
|
||||
// between its position and the position of 2000 (for J2000) gives the
|
||||
// number of leap years
|
||||
constexpr int Epoch = 2000;
|
||||
constexpr int DaysRegularYear = 365;
|
||||
constexpr int DaysLeapYear = 366;
|
||||
|
||||
if (year == Epoch) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get the position of the most recent leap year
|
||||
const auto lb = std::lower_bound(LeapYears.begin(), LeapYears.end(), year);
|
||||
|
||||
// Get the position of the epoch
|
||||
const auto y2000 = std::find(LeapYears.begin(), LeapYears.end(), Epoch);
|
||||
|
||||
// The distance between the two iterators gives us the number of leap years
|
||||
const int nLeapYears = static_cast<int>(std::abs(std::distance(y2000, lb)));
|
||||
|
||||
const int nYears = std::abs(year - Epoch);
|
||||
const int nRegularYears = nYears - nLeapYears;
|
||||
|
||||
// Get the total number of days as the sum of leap years + non leap years
|
||||
const int result = nRegularYears * DaysRegularYear + nLeapYears * DaysLeapYear;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns the number of leap seconds that lie between the {year, dayOfYear}
|
||||
// time point and { 2000, 1 }
|
||||
int countLeapSeconds(int year, int dayOfYear) {
|
||||
// Find the position of the current year in the vector; its position in
|
||||
// the vector gives the number of leap seconds
|
||||
struct LeapSecond {
|
||||
int year;
|
||||
int dayOfYear;
|
||||
bool operator<(const LeapSecond& rhs) const {
|
||||
return std::tie(year, dayOfYear) < std::tie(rhs.year, rhs.dayOfYear);
|
||||
}
|
||||
};
|
||||
|
||||
const LeapSecond Epoch = { 2000, 1 };
|
||||
|
||||
// List taken from: https://www.ietf.org/timezones/data/leap-seconds.list
|
||||
static const std::vector<LeapSecond> LeapSeconds = {
|
||||
{ 1972, 1 },
|
||||
{ 1972, 183 },
|
||||
{ 1973, 1 },
|
||||
{ 1974, 1 },
|
||||
{ 1975, 1 },
|
||||
{ 1976, 1 },
|
||||
{ 1977, 1 },
|
||||
{ 1978, 1 },
|
||||
{ 1979, 1 },
|
||||
{ 1980, 1 },
|
||||
{ 1981, 182 },
|
||||
{ 1982, 182 },
|
||||
{ 1983, 182 },
|
||||
{ 1985, 182 },
|
||||
{ 1988, 1 },
|
||||
{ 1990, 1 },
|
||||
{ 1991, 1 },
|
||||
{ 1992, 183 },
|
||||
{ 1993, 182 },
|
||||
{ 1994, 182 },
|
||||
{ 1996, 1 },
|
||||
{ 1997, 182 },
|
||||
{ 1999, 1 },
|
||||
{ 2006, 1 },
|
||||
{ 2009, 1 },
|
||||
{ 2012, 183 },
|
||||
{ 2015, 182 },
|
||||
{ 2017, 1 }
|
||||
};
|
||||
|
||||
// Get the position of the last leap second before the desired date
|
||||
LeapSecond date { year, dayOfYear };
|
||||
const auto it = std::lower_bound(LeapSeconds.begin(), LeapSeconds.end(), date);
|
||||
|
||||
// Get the position of the Epoch
|
||||
const auto y2000 = std::lower_bound(
|
||||
LeapSeconds.begin(),
|
||||
LeapSeconds.end(),
|
||||
Epoch
|
||||
);
|
||||
|
||||
// The distance between the two iterators gives us the number of leap years
|
||||
const int nLeapSeconds = static_cast<int>(std::abs(std::distance(y2000, it)));
|
||||
return nLeapSeconds;
|
||||
}
|
||||
|
||||
double epochFromSubstring(const std::string& epochString) {
|
||||
// The epochString is in the form:
|
||||
// YYDDD.DDDDDDDD
|
||||
// With YY being the last two years of the launch epoch, the first DDD the day
|
||||
// of the year and the remaning a fractional part of the day
|
||||
|
||||
// The main overview of this function:
|
||||
// 1. Reconstruct the full year from the YY part
|
||||
// 2. Calculate the number of days since the beginning of the year
|
||||
// 3. Convert the number of days to a number of seconds
|
||||
// 4. Get the number of leap seconds since January 1st, 2000 and remove them
|
||||
// 5. Adjust for the fact the epoch starts on 1st Januaray at 12:00:00, not
|
||||
// midnight
|
||||
|
||||
// According to https://celestrak.com/columns/v04n03/
|
||||
// Apparently, US Space Command sees no need to change the two-line element
|
||||
// set format yet since no artificial earth satellites existed prior to 1957.
|
||||
// By their reasoning, two-digit years from 57-99 correspond to 1957-1999 and
|
||||
// those from 00-56 correspond to 2000-2056. We'll see each other again in 2057!
|
||||
|
||||
// 1. Get the full year
|
||||
std::string yearPrefix = [y = epochString.substr(0, 2)](){
|
||||
int year = std::atoi(y.c_str());
|
||||
return year >= 57 ? "19" : "20";
|
||||
}();
|
||||
const int year = std::atoi((yearPrefix + epochString.substr(0, 2)).c_str());
|
||||
const int daysSince2000 = countDays(year);
|
||||
|
||||
// 2.
|
||||
double daysInYear = std::atof(epochString.substr(2).c_str());
|
||||
|
||||
// 3
|
||||
using namespace std::chrono;
|
||||
const int SecondsPerDay = static_cast<int>(seconds(hours(24)).count());
|
||||
//Need to subtract 1 from daysInYear since it is not a zero-based count
|
||||
const double nSecondsSince2000 = (daysSince2000 + daysInYear - 1) * SecondsPerDay;
|
||||
|
||||
// 4
|
||||
// We need to remove additionbal leap seconds past 2000 and add them prior to
|
||||
// 2000 to sync up the time zones
|
||||
const double nLeapSecondsOffset = -countLeapSeconds(
|
||||
year,
|
||||
static_cast<int>(std::floor(daysInYear))
|
||||
);
|
||||
|
||||
// 5
|
||||
const double nSecondsEpochOffset = static_cast<double>(
|
||||
seconds(hours(12)).count()
|
||||
);
|
||||
|
||||
// Combine all of the values
|
||||
const double epoch = nSecondsSince2000 + nLeapSecondsOffset - nSecondsEpochOffset;
|
||||
return epoch;
|
||||
}
|
||||
|
||||
double calculateSemiMajorAxis(double meanMotion) {
|
||||
constexpr double GravitationalConstant = 6.6740831e-11;
|
||||
constexpr double MassEarth = 5.9721986e24;
|
||||
constexpr double muEarth = GravitationalConstant * MassEarth;
|
||||
|
||||
// Use Kepler's 3rd law to calculate semimajor axis
|
||||
// a^3 / P^2 = mu / (2pi)^2
|
||||
// <=> a = ((mu * P^2) / (2pi^2))^(1/3)
|
||||
// with a = semimajor axis
|
||||
// P = period in seconds
|
||||
// mu = G*M_earth
|
||||
double period = std::chrono::seconds(std::chrono::hours(24)).count() / meanMotion;
|
||||
|
||||
constexpr double pisq = glm::pi<double>() * glm::pi<double>();
|
||||
double semiMajorAxis = pow((muEarth * period*period) / (4 * pisq), 1.0 / 3.0);
|
||||
|
||||
// We need the semi major axis in km instead of m
|
||||
return semiMajorAxis / 1000.0;
|
||||
}
|
||||
|
||||
struct [[codegen::Dictionary(TLETranslation)]] Parameters {
|
||||
// Specifies the filename of the Two-Line-Element file
|
||||
std::string file;
|
||||
|
||||
// Specifies the line number within the file where the group of 3 TLE lines begins
|
||||
// (1-based). Defaults to 1
|
||||
std::optional<int> lineNumber [[codegen::greater(0)]];
|
||||
};
|
||||
#include "tletranslation_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation TLETranslation::Documentation() {
|
||||
return codegen::doc<Parameters>("space_transform_tle");
|
||||
}
|
||||
|
||||
TLETranslation::TLETranslation(const ghoul::Dictionary& dictionary) {
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
|
||||
int lineNum = p.lineNumber.value_or(1);
|
||||
readTLEFile(p.file, lineNum);
|
||||
}
|
||||
|
||||
void TLETranslation::readTLEFile(const std::string& filename, int lineNum) {
|
||||
ghoul_assert(std::filesystem::is_regular_file(filename), "The filename must exist");
|
||||
|
||||
std::ifstream file;
|
||||
file.exceptions(std::ofstream::failbit | std::ofstream::badbit);
|
||||
file.open(filename);
|
||||
|
||||
// All of the Kepler element information
|
||||
struct {
|
||||
double inclination = 0.0;
|
||||
double semiMajorAxis = 0.0;
|
||||
double ascendingNode = 0.0;
|
||||
double eccentricity = 0.0;
|
||||
double argumentOfPeriapsis = 0.0;
|
||||
double meanAnomaly = 0.0;
|
||||
double meanMotion = 0.0;
|
||||
double epoch = 0.0;
|
||||
} keplerElements;
|
||||
|
||||
std::string line;
|
||||
// Loop through and throw out lines until getting to the linNum of interest
|
||||
for (int i = 1; i < lineNum; ++i) {
|
||||
std::getline(file, line);
|
||||
}
|
||||
std::getline(file, line); // Throw out the TLE title line (1st)
|
||||
|
||||
std::getline(file, line); // Get line 1 of TLE format
|
||||
if (line[0] == '1') {
|
||||
// First line
|
||||
// Field Columns Content
|
||||
// 1 01-01 Line number
|
||||
// 2 03-07 Satellite number
|
||||
// 3 08-08 Classification (U = Unclassified)
|
||||
// 4 10-11 International Designator (Last two digits of launch year)
|
||||
// 5 12-14 International Designator (Launch number of the year)
|
||||
// 6 15-17 International Designator(piece of the launch) A
|
||||
// 7 19-20 Epoch Year(last two digits of year)
|
||||
// 8 21-32 Epoch(day of the year and fractional portion of the day)
|
||||
// 9 34-43 First Time Derivative of the Mean Motion divided by two
|
||||
// 10 45-52 Second Time Derivative of Mean Motion divided by six
|
||||
// 11 54-61 BSTAR drag term(decimal point assumed)[10] - 11606 - 4
|
||||
// 12 63-63 The "Ephemeris type"
|
||||
// 13 65-68 Element set number.Incremented when a new TLE is generated
|
||||
// 14 69-69 Checksum (modulo 10)
|
||||
keplerElements.epoch = epochFromSubstring(line.substr(18, 14));
|
||||
}
|
||||
else {
|
||||
throw ghoul::RuntimeError(fmt::format(
|
||||
"File {} @ line {} does not have '1' header", filename, lineNum + 1
|
||||
));
|
||||
}
|
||||
|
||||
std::getline(file, line); // Get line 2 of TLE format
|
||||
if (line[0] == '2') {
|
||||
// Second line
|
||||
// Field Columns Content
|
||||
// 1 01-01 Line number
|
||||
// 2 03-07 Satellite number
|
||||
// 3 09-16 Inclination (degrees)
|
||||
// 4 18-25 Right ascension of the ascending node (degrees)
|
||||
// 5 27-33 Eccentricity (decimal point assumed)
|
||||
// 6 35-42 Argument of perigee (degrees)
|
||||
// 7 44-51 Mean Anomaly (degrees)
|
||||
// 8 53-63 Mean Motion (revolutions per day)
|
||||
// 9 64-68 Revolution number at epoch (revolutions)
|
||||
// 10 69-69 Checksum (modulo 10)
|
||||
|
||||
std::stringstream stream;
|
||||
stream.exceptions(std::ios::failbit);
|
||||
|
||||
// Get inclination
|
||||
stream.str(line.substr(8, 8));
|
||||
stream >> keplerElements.inclination;
|
||||
stream.clear();
|
||||
|
||||
// Get Right ascension of the ascending node
|
||||
stream.str(line.substr(17, 8));
|
||||
stream >> keplerElements.ascendingNode;
|
||||
stream.clear();
|
||||
|
||||
// Get Eccentricity
|
||||
stream.str("0." + line.substr(26, 7));
|
||||
stream >> keplerElements.eccentricity;
|
||||
stream.clear();
|
||||
|
||||
// Get argument of periapsis
|
||||
stream.str(line.substr(34, 8));
|
||||
stream >> keplerElements.argumentOfPeriapsis;
|
||||
stream.clear();
|
||||
|
||||
// Get mean anomaly
|
||||
stream.str(line.substr(43, 8));
|
||||
stream >> keplerElements.meanAnomaly;
|
||||
stream.clear();
|
||||
|
||||
// Get mean motion
|
||||
stream.str(line.substr(52, 11));
|
||||
stream >> keplerElements.meanMotion;
|
||||
}
|
||||
else {
|
||||
throw ghoul::RuntimeError(fmt::format(
|
||||
"File {} @ line {} does not have '2' header", filename, lineNum + 2
|
||||
));
|
||||
}
|
||||
file.close();
|
||||
|
||||
// Calculate the semi major axis based on the mean motion using kepler's laws
|
||||
keplerElements.semiMajorAxis = calculateSemiMajorAxis(keplerElements.meanMotion);
|
||||
|
||||
// Converting the mean motion (revolutions per day) to period (seconds per revolution)
|
||||
using namespace std::chrono;
|
||||
double period = seconds(hours(24)).count() / keplerElements.meanMotion;
|
||||
|
||||
setKeplerElements(
|
||||
keplerElements.eccentricity,
|
||||
keplerElements.semiMajorAxis,
|
||||
keplerElements.inclination,
|
||||
keplerElements.ascendingNode,
|
||||
keplerElements.argumentOfPeriapsis,
|
||||
keplerElements.meanAnomaly,
|
||||
period,
|
||||
keplerElements.epoch
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
@@ -1,83 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __OPENSPACE_MODULE_SPACE___TLETRANSLATION___H__
|
||||
#define __OPENSPACE_MODULE_SPACE___TLETRANSLATION___H__
|
||||
|
||||
#include <modules/space/translation/keplertranslation.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
/**
|
||||
* A specialization of the KeplerTranslation that extracts the Keplerian elements from a
|
||||
* two-line element as described by the US Space Command
|
||||
* https://celestrak.com/columns/v04n03
|
||||
* The ghoul::Dictionary passed to the constructor must contain the pointer to a file that
|
||||
* will be read.
|
||||
*/
|
||||
class TLETranslation : public KeplerTranslation {
|
||||
public:
|
||||
struct FileFormatError : public ghoul::RuntimeError {
|
||||
explicit FileFormatError(std::string offense);
|
||||
std::string offense;
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor for the TLETranslation class. The \p dictionary must contain a key for
|
||||
* the file that contains the TLE information. The ghoul::Dictionary will be tested
|
||||
* against the openspace::Documentation returned by Documentation.
|
||||
* \param The ghoul::Dictionary that contains the information for this TLETranslation
|
||||
(*/
|
||||
TLETranslation(const ghoul::Dictionary& dictionary = ghoul::Dictionary());
|
||||
|
||||
/**
|
||||
* Method returning the openspace::Documentation that describes the ghoul::Dictinoary
|
||||
* that can be passed to the constructor.
|
||||
* \return The openspace::Documentation that describes the ghoul::Dicitonary that can
|
||||
* be passed to the constructor
|
||||
*/
|
||||
static documentation::Documentation Documentation();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Reads the provided TLE file and calles the KeplerTranslation::setKeplerElments
|
||||
* method with the correct values. If \p filename is a valid TLE file but contains
|
||||
* disallowed values (see KeplerTranslation::setKeplerElements), a
|
||||
* KeplerTranslation::RangeError is thrown.
|
||||
*
|
||||
* \param filename The path to the file that contains the TLE file.
|
||||
* \param lineNum The line number in the file where the set of 3 TLE lines starts
|
||||
*
|
||||
* \throw std::system_error if the TLE file is malformed (does not contain at least
|
||||
* two lines that start with \c 1 and \c 2.
|
||||
* \throw KeplerTranslation::RangeError If the Keplerian elements are outside of
|
||||
* the valid range supported by Kepler::setKeplerElements
|
||||
* \pre The \p filename must exist
|
||||
*/
|
||||
void readTLEFile(const std::string& filename, int lineNum);
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __OPENSPACE_MODULE_SPACE___TLETRANSLATION___H__
|
||||
@@ -875,14 +875,14 @@ void SessionRecording::saveScriptKeyframeToTimeline(std::string script) {
|
||||
bool SessionRecording::doesStartWithSubstring(const std::string& s,
|
||||
const std::string& matchSubstr)
|
||||
{
|
||||
return (s.substr(0, matchSubstr.length()).compare(matchSubstr) == 0);
|
||||
return s.substr(0, matchSubstr.length()) == matchSubstr;
|
||||
}
|
||||
|
||||
void SessionRecording::saveScriptKeyframeToPropertiesBaseline(std::string script) {
|
||||
Timestamps times
|
||||
= generateCurrentTimestamp3(global::windowDelegate->applicationTime());
|
||||
size_t indexIntoScriptKeyframesFromMainTimeline
|
||||
= _keyframesSavePropertiesBaseline_scripts.size();
|
||||
Timestamps times =
|
||||
generateCurrentTimestamp3(global::windowDelegate->applicationTime());
|
||||
size_t indexIntoScriptKeyframesFromMainTimeline =
|
||||
_keyframesSavePropertiesBaseline_scripts.size();
|
||||
_keyframesSavePropertiesBaseline_scripts.push_back(std::move(script));
|
||||
addKeyframeToTimeline(
|
||||
_keyframesSavePropertiesBaseline_timeline,
|
||||
@@ -2327,7 +2327,7 @@ std::string SessionRecording::convertFile(std::string filename, int depth) {
|
||||
// correct version of the file to be converted, then call getLegacy() to recurse
|
||||
// to the next level down in the legacy subclasses until we get the right
|
||||
// version, then proceed with conversion from there.
|
||||
if (fileVersion.compare(fileFormatVersion()) != 0) {
|
||||
if (fileVersion != fileFormatVersion()) {
|
||||
//conversionInStream.seekg(conversionInStream.beg);
|
||||
newFilename = getLegacyConversionResult(filename, depth + 1);
|
||||
removeTrailingPathSlashes(newFilename);
|
||||
|
||||
Reference in New Issue
Block a user