Added possibility to go to now, without program freezing, and improved lifecycle with already downloaded field lines

This commit is contained in:
Kollberg
2019-09-12 16:15:56 -04:00
parent 3a9fef1e60
commit b27399128c
10 changed files with 94 additions and 61 deletions
+38 -15
View File
@@ -6,11 +6,11 @@ local renderableHelper = asset.require('util/renderable_helper')
-- Specifying which other assets should be loaded in this scene
asset.require('spice/base')
assetHelper.requestAll(asset, 'scene/solarsystem/sun')
-- asset.require('scene/solarsystem/planets')
asset.require('scene/solarsystem/planets')
-- asset.require('scene/solarsystem/planets/mars/moons/phobos')
-- asset.require('scene/solarsystem/planets/mars/moons/deimos')
-- asset.require('scene/solarsystem/dwarf_planets/pluto/system')
-- assetHelper.requestAll(asset, 'scene/digitaluniverse')
assetHelper.requestAll(asset, 'scene/digitaluniverse')
-- Load default key bindings applicable to most scenes
asset.require('util/default_keybindings')
@@ -18,7 +18,7 @@ asset.require('util/default_dashboard')
-- asset.require('util/default_joystick')
-- DEBUG
asset.require('./testwsa/debugcoordaxes');
-- asset.require('./testwsa/debugcoordaxes');
asset.require('util/webgui')
@@ -38,14 +38,14 @@ asset.require('./testwsa/pfss_io')
-- Parker Solar Probe asset package
asset.require('scene/solarsystem/missions/parkersolarprobe/parker_solar_probe_trail')
--asset.require('./testwsa/psp_pfss_io')
--asset.require('./testwsa/psp_pfss_oi')
--asset.require('./testwsa/psp_scs_oi')
-- asset.require('./testwsa/psp_pfss_io')
-- asset.require('./testwsa/psp_pfss_oi')
-- asset.require('./testwsa/psp_scs_oi')
-- asset.require('./testwsa/psp_sub_satellite')
-- Sub-Earth track
asset.require('./testwsa/sub_earth')
-- asset.require('./testwsa/sub_earth')
local Keybindings = {
{
@@ -104,15 +104,15 @@ local Keybindings = {
},
{
Key = "x",
Command = "openspace.time.setTime('2021 APR 28 00:00:00.000')",
Documentation = "Jump to 1 September 2017",
Name = "Jump to 2017",
Command = "openspace.time.setTime('2018 NOV 1 00:00:00.000')",
Documentation = "Jump to 1 November 2018",
Name = "Jump to 1 November 2018",
GuiPath = "/Parker Solar Probe",
Local = false
},
{
Key = "b",
Command = renderableHelper.toggle('Scene.WSA_Fieldlines_Sun_Earth_Connection'),
Command = renderableHelper.toggle('Scene.WSA_Fieldlines_Sub_Earth_Track'),
Documentation = "Toggle ballerina skirt",
Name = "Toggle Sub Earth connection",
GuiPath = "/Parker Solar Probe",
@@ -144,13 +144,36 @@ local Keybindings = {
},
{
Key = "l",
Command = "openspace.setPropertyValue('Scene.WSA_Fieldlines_SCS_OI.Renderable.Masking.maskingQuantity', 1);" ..
"openspace.setPropertyValue('Scene.WSA_Fieldlines_SCS_OI.Renderable.maskingEnabled', not openspace.getPropertyValue('Scene.WSA_Fieldlines_SCS_OI.Renderable.maskingEnabled'))",
Documentation = "Toggle SCS out to in model",
Name = "Toggle SCS out to in model",
Command = "openspace.setPropertyValue('Scene.WSA_Fieldlines_SCS_OI.Renderable.Masking.maskingQuantity', 1)" ..
"openspace.setPropertyValue('Scene.WSA_Fieldlines_SCS_OI.Renderable.maskingEnabled', not openspace.getPropertyValue('Scene.WSA_Fieldlines_SCS_OI.Renderable.maskingEnabled'))" ..
"openspace.setPropertyValue('Scene.WSA_Fieldlines_PFSS_OI.Renderable.Masking.maskingQuantity', 1)" ..
"openspace.setPropertyValue('Scene.WSA_Fieldlines_PFSS_OI.Renderable.maskingEnabled', not openspace.getPropertyValue('Scene.WSA_Fieldlines_PFSS_OI.Renderable.maskingEnabled'));" ..
"openspace.setPropertyValue('Scene.PSP_WSA_Fieldlines_SCS_OI.Renderable.Masking.maskingQuantity', 1)" ..
"openspace.setPropertyValue('Scene.PSP_WSA_Fieldlines_SCS_OI.Renderable.maskingEnabled', not openspace.getPropertyValue('Scene.PSP_WSA_Fieldlines_SCS_OI.Renderable.maskingEnabled'))" ..
"openspace.setPropertyValue('Scene.PSP_WSA_Fieldlines_PFSS_OI.Renderable.Masking.maskingQuantity', 1)" ..
"openspace.setPropertyValue('Scene.PSP_WSA_Fieldlines_PFSS_OI.Renderable.maskingEnabled', not openspace.getPropertyValue('Scene.PSP_WSA_Fieldlines_PFSS_OI.Renderable.maskingEnabled'));",
Documentation = "Toggle current sheet in all out to in models",
Name = "Toggle current sheet in all out to in models",
GuiPath = "/Parker Solar Probe",
Local = false
},
{
Key = "h",
Command = "openspace.setPropertyValue('Scene.WSA_Fieldlines_Sub_Earth_Track.Renderable.Masking.maskingQuantity', 1)" ..
"openspace.setPropertyValue('Scene.WSA_Fieldlines_Sub_Earth_Track.Renderable.maskingEnabled', true);",
Documentation = "Show only one layer of sub earth track",
Name = "Toggle sub satellite layers",
GuiPath = "/Parker Solar Probe",
Local = false
},
{
Key = "Shift+g",
Command = "openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Anchor', 'Earth');" ..
"openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil)" ..
"openspace.globebrowsing.goToGeo(38.995412,-76.857665)",
Documentation = "Sets the focus of the camera on 'Goddard'",
Local = false
},
}
asset.onInitialize(function ()
-1
View File
@@ -7,7 +7,6 @@ local opennessColorTable = transferFunctions .. "/openness_spec.txt"
local sunRadius = 695508000
-- Fieldlies from json
local fieldlines = {
Identifier = "WSA_Fieldlines_PFSS_IO",
Parent = transforms.TransformGONG.Identifier, -- Use this for regular GONG (Main fieldline endpoints)
-1
View File
@@ -8,7 +8,6 @@ local currentSheetColorTable = transferFunctions .. "/currentsheet_spec.txt"
local sunRadius = 695508000
-- Fieldlies from json
local fieldlines = {
Identifier = "WSA_Fieldlines_SCS_OI",
Parent = transforms.TransformGONG.Identifier, -- Use this for regular GONG (Main fieldline endpoints)
+2 -2
View File
@@ -330,9 +330,9 @@ void RenderableSphere::initializeGL() {
loadTexture();
if(_texturePath.fullyQualifiedIdentifier() == "Scene.Sun.Renderable.Texture"){
/*if(_texturePath.fullyQualifiedIdentifier() == "Scene.Sun.Renderable.Texture"){
_sunTexMgr.loadWSATexture(_texture);
}
} */
}
void RenderableSphere::deinitializeGL() {
@@ -625,7 +625,7 @@ namespace openspace {
extractTriggerTimesFromFileNames();
FieldlinesState newState;
if (!newState.loadStateFromOsfls(_sourceFiles[0])) {
LERROR("The provided .osfls files seem to be corrupt!");
LERROR("The provided .osfls files seem to be corrupt: " + _sourceFiles[0]);
return false;
}
_states.push_back(newState);
@@ -156,21 +156,19 @@ namespace openspace{
// First it checks the time against the "bigger window" aka the long list of
// timesteps we know are available online. If it's outside that we're gonna need a new one
if (_webFieldlinesWindow.timeIsInTriggerTimesWebList(openspaceTime) && !_webFieldlinesWindow.expectedWindowIsOutOfBounds(openspaceTime)) {
if (_webFieldlinesWindow.timeIsInTriggerTimesWebList(openspaceTime) && !_webFieldlinesWindow.expectedWindowIsOutOfBounds(openspaceTime) || _webFieldlinesWindow.checkWorkerEdgeMode()){
// Check if in window
if (_webFieldlinesWindow.timeIsInWindow(openspaceTime)) {
if (_webFieldlinesWindow.edgeWindowReady() || _webFieldlinesWindow.timeIsInWindow(openspaceTime)) {
// Check if in the edge of the window, so we can start downloading a new one
if (_webFieldlinesWindow.timeIsInWindowMargin(openspaceTime, deltaTime)) {
if (!_webFieldlinesWindow.edgeWindowReady() && _webFieldlinesWindow.timeIsInWindowMargin(openspaceTime, deltaTime)) {
// get new window
_webFieldlinesWindow.newWindow(openspaceTime);
hasUpdated = false;
}
else {
// If it's in the middle of the window, we can just sit back and relax
// And let the worker work
// If it's in the middle of the window, we can just sit back and relax and let the worker work
_webFieldlinesWindow.executeDownloadWorker();
}
}
@@ -80,7 +80,6 @@ namespace openspace{
if (direction > 0){ // If time is moving forward
if(time >= _window.triggerTimes[_window.nTriggerTimes - threshold].first){
if(time > windowEnd()){
LERROR("Time is outside of window in margin-check-function. This shouldn't happen.");
return false;
}
return true;
@@ -90,7 +89,6 @@ namespace openspace{
else{ // If time is moving backwards
if(time <= _window.triggerTimes[threshold].first){
if(time < windowStart()){
LERROR("Time is outside of window in margin-check-function. This shouldn't happen.");
return false;
}
return true;
@@ -106,6 +104,7 @@ namespace openspace{
void WebFieldlinesWindow::executeDownloadWorker(){
_worker.downloadWindow(_window.triggerTimes);
_worker.updateRFSSourceFiles(*rfs_sourceFiles);
_edgeWindowReady = false;
}
void WebFieldlinesWindow::newWindow(double time){
@@ -115,23 +114,27 @@ namespace openspace{
});
const int index = static_cast<int>(std::distance(it, _triggerTimesWeb.rend())) - 1;
_window.triggerTimes.clear();
_window.nTriggerTimes = 0;
// This should be safe, because in the manager, it is checked wether the current position is within
// the boundaries with respect to back & forward width
for(int i = index - _window.backWidth; i <= index + _window.forwardWidth; i++){
if(i < 0) i = 0;
for(int i = std::max(index - _window.backWidth,0); i <= std::min(index + _window.forwardWidth, static_cast<int>(_triggerTimesWeb.size() -1)); i++){
_window.triggerTimes.push_back(std::make_pair(_triggerTimesWeb[i].first, _triggerTimesWeb[i].second));
_window.nTriggerTimes++;
}
if (_worker.edgeMode())
_edgeWindowReady = true;
_worker.newWindowToDownload();
}
bool WebFieldlinesWindow::timeIsInTriggerTimesWebList(double time){
// There are no files to compare with, just going to be false.
if(_nAvailableWeb == 0) return false;
// Most cases, we are currently in the middle of a bunch of datasets, if we are not, lets get some new ones.
if(time >= (_triggerTimesWeb.front().first) && time <= (_triggerTimesWeb.back().first))
return true;
else
@@ -139,7 +142,6 @@ namespace openspace{
}
void WebFieldlinesWindow::getNewTriggerTimesWebList(double time){
_worker.getRangeOfAvailableTriggerTimes(time, time, _triggerTimesWeb);
_nAvailableWeb = static_cast<int>(_triggerTimesWeb.size());
}
@@ -165,6 +167,14 @@ namespace openspace{
void WebFieldlinesWindow::rfsHasUpdated() {
_worker.flagUpdated();
}
bool WebFieldlinesWindow::checkWorkerEdgeMode(){
return _worker.edgeMode();
}
bool WebFieldlinesWindow::edgeWindowReady(){
return _edgeWindowReady;
}
// -------------------------- PRIVATE FUNCTIONS -----------------------------------//
// Returns first trigger of window
@@ -106,6 +106,13 @@ public:
// Calling the functioh in worker that renderable fieldlinessequence has updated.
void rfsHasUpdated();
// Returns true if big window is fetching files from the end or beginning of a data segment
// Returns false if not.
bool checkWorkerEdgeMode();
// Returns true if edge-window is ready
bool edgeWindowReady();
private:
// PRIVATE MEMBER VARIABLES
@@ -115,6 +122,7 @@ private:
// The worker that handles downloads
WebFieldlinesWorker _worker;
bool _edgeWindowReady = false;
// This is a long list of everything available online,
// they are tuples of 3; double is timetrigger, string is donwload key, int is index to where it is on disk
@@ -64,12 +64,8 @@ namespace openspace{
// PUBLIC FUNCTIONS
void WebFieldlinesWorker::getRangeOfAvailableTriggerTimes(double startTime, double endTime, std::vector<std::pair<double, std::string>> &_triggerTimesWeb){
if (global::timeManager.time().j2000Seconds() < acceptableToStartRequestingAgain.first || global::timeManager.time().j2000Seconds() > acceptableToStartRequestingAgain.second) {
_noEmptyResponses = true;
}
// We don't want to keep sending request, if we just get empty responses.
if (_noEmptyResponses) {
if (!_noMoreRequests) {
auto time = global::timeManager.time().ISO8601();
Time maxTime;
Time minTime;
@@ -97,14 +93,14 @@ namespace openspace{
});
auto res = json::parse(stringResult);
auto temp = std::move(_triggerTimesWeb);
_triggerTimesWeb.clear(); // Clear old big window
for (auto& elem : res[files]) {
timeList.push_back(elem["timestamp"]);
urlList.push_back(elem["url"]);
}
_triggerTimesWeb.clear(); // Clear old big window
// Just want to make sure there is no error in the parsing, so taking the smallest dimension, but should be the same
for (int i = 0; i < std::min(timeList.size(), urlList.size()); i++) {
_triggerTimesWeb.push_back(std::make_pair(triggerTimeString2Double(timeList[i]), urlList[i]));
@@ -112,11 +108,12 @@ namespace openspace{
std::sort(_triggerTimesWeb.begin(), _triggerTimesWeb.end()); // If by any chance it would not sort in properly
if (_triggerTimesWeb.size() == 0) // We got an empty response
if (_triggerTimesWeb.size() == 0 || std::equal(temp.begin(),temp.end(),_triggerTimesWeb.begin(), _triggerTimesWeb.end())) // We got an empty response or the same response twice, stahp it
_strikes++;
if (_strikes % 2 == 0){ // We have got 2 strikes, no more requests for you, Mr.Sir.
_noEmptyResponses = false;
_bigWindowHasData = (_triggerTimesWeb.size() > 0);
_noMoreRequests = true;
acceptableToStartRequestingAgain = std::make_pair(minTime.j2000Seconds(), maxTime.j2000Seconds());
}
}
@@ -134,22 +131,9 @@ namespace openspace{
bool oneUpdate = false;
bool fastDownload = global::timeManager.deltaTime() > 1800.0;
// May be interesting to keep something like this, if it will be possible to use a list of
// AsyncHttpFileDownloads
/*if (auto index = std::find_if(_downloadList.begin(), _downloadList.end(), [](auto element) {
return element.first->hasSucceeded();
}); index != _downloadList.end()) {
// There is a successful download
index->first->wait();
addToDownloadedList(index->second);
_downloadList.erase(index);
}
else { */
if (fastDownload) startingPoint = triggerTimes.size() - 1;
// Is there a download thread to be joined and added to the list?
if (_downloading && _downloading->hasSucceeded() && _newWindow) {
_downloading->wait();
addToDownloadedList(_latestDownload);
@@ -172,7 +156,6 @@ namespace openspace{
}
});
// Backwards
if (!downloaded) {
std::for_each(triggerTimes.rbegin(), triggerTimes.rend(), [this, &downloaded](auto it) {
@@ -185,7 +168,7 @@ namespace openspace{
}
}
if ((!downloaded && !_doneUpdating && _newWindow && _readyToDownload) || oneUpdate) {
if ((!downloaded && !_doneUpdating && _newWindow && _readyToDownload && _downloadedSomething) || oneUpdate && _downloadedSomething) {
// If reach this point, we now know that we have downloaded all the sets
_readyToUpdateSourceFiles = true;
if(!oneUpdate)
@@ -240,10 +223,19 @@ namespace openspace{
void WebFieldlinesWorker::newWindowToDownload(){
_newWindow = true;
_downloadedSomething = false;
}
bool WebFieldlinesWorker::edgeMode(){
if (global::timeManager.time().j2000Seconds() < acceptableToStartRequestingAgain.first || global::timeManager.time().j2000Seconds() > acceptableToStartRequestingAgain.second) {
_noMoreRequests = false;
_bigWindowHasData = false;
}
return _noMoreRequests && _bigWindowHasData;
}
std::string WebFieldlinesWorker::downloadOsfls(std::pair<double,std::string> downloadKey){
_downloadedSomething = true;
_latestDownload = downloadKey;
// YYYY-MM-DDTHH-MM-SS.sss.osfls - Might change
const int fileNameLength = 29;
@@ -64,12 +64,16 @@ public:
// Notifies the worker that a new window is ready
void newWindowToDownload();
// If the current window is on the edge of a datasets, but if there are some file in that window, it is still desired to download it.
bool edgeMode();
private:
// This list is the keep all the started downloads alive between frames, the second argument is a pair, used for identifying which download it is
std::vector<AsyncHttpFileDownload> _downloadList;
std::vector<std::pair<double,std::string>> _downloadListIdentifier;
// Asynchttpdownloader worker.
std::unique_ptr<AsyncHttpFileDownload> _downloading;
// Might need this l8r
@@ -91,10 +95,10 @@ private:
bool _readyToUpdateSourceFiles = false;
bool _doneUpdating = false;
bool _newWindow = false;
bool _readyToDownload = true;
bool _noEmptyResponses = true;
bool _noMoreRequests = false;
bool _bigWindowHasData = false;
bool _downloadedSomething = false;
unsigned int _strikes = 0;
std::pair<double, double> acceptableToStartRequestingAgain = std::make_pair(0.0, 0.0);