mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-06 03:29:44 -06:00
TimeFrame specification and status (#3553)
* Makes Translation/Scale/Rotation all able to have a TimeFrame, not just the SpiceRotation. Add read-only BoolProperty to the TimeFrame that indicates whether the current time is a in the timeframe --------- Co-authored-by: Emma Broman <emma.broman@liu.se>
This commit is contained in:
@@ -636,20 +636,20 @@ void RenderableOrbitalKepler::updateBuffers() {
|
||||
_vertexBufferData.resize(nVerticesTotal);
|
||||
|
||||
size_t vertexBufIdx = 0;
|
||||
KeplerTranslation keplerTranslator;
|
||||
for (int orbitIdx = 0; orbitIdx < numOrbits; ++orbitIdx) {
|
||||
const kepler::Parameters& orbit = parameters[orbitIdx];
|
||||
|
||||
keplerTranslator.setKeplerElements(
|
||||
orbit.eccentricity,
|
||||
orbit.semiMajorAxis,
|
||||
orbit.inclination,
|
||||
orbit.ascendingNode,
|
||||
orbit.argumentOfPeriapsis,
|
||||
orbit.meanAnomaly,
|
||||
orbit.period,
|
||||
orbit.epoch
|
||||
);
|
||||
ghoul::Dictionary d;
|
||||
d.setValue("Type", std::string("KeplerTranslation"));
|
||||
d.setValue("Eccentricity", orbit.eccentricity);
|
||||
d.setValue("SemiMajorAxis", orbit.semiMajorAxis);
|
||||
d.setValue("Inclination", orbit.inclination);
|
||||
d.setValue("AscendingNode", orbit.ascendingNode);
|
||||
d.setValue("ArgumentOfPeriapsis", orbit.argumentOfPeriapsis);
|
||||
d.setValue("MeanAnomaly", orbit.meanAnomaly);
|
||||
d.setValue("Period", orbit.period);
|
||||
d.setValue("Epoch", orbit.epoch);
|
||||
KeplerTranslation keplerTranslator = KeplerTranslation(d);
|
||||
|
||||
for (GLint j = 0 ; j < (_segmentSize[orbitIdx]); j++) {
|
||||
const double timeOffset = orbit.period *
|
||||
|
||||
@@ -48,13 +48,6 @@ namespace {
|
||||
openspace::properties::Property::Visibility::Developer
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo TimeFrameInfo = {
|
||||
"TimeFrame",
|
||||
"Time Frame",
|
||||
"The time frame in which the spice kernels are valid.",
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo FixedDateInfo = {
|
||||
"FixedDate",
|
||||
"Fixed Date",
|
||||
@@ -81,10 +74,6 @@ namespace {
|
||||
// specified, a reference frame of 'GALACTIC' is used instead
|
||||
std::optional<std::string> destinationFrame;
|
||||
|
||||
// [[codegen::verbatim(TimeFrameInfo.description)]]
|
||||
std::optional<ghoul::Dictionary> timeFrame
|
||||
[[codegen::reference("core_time_frame")]];
|
||||
|
||||
// [[codegen::verbatim(FixedDateInfo.description)]]
|
||||
std::optional<std::string> fixedDate
|
||||
[[codegen::annotation("A time to lock the rotation to")]];
|
||||
@@ -102,7 +91,8 @@ documentation::Documentation SpiceRotation::Documentation() {
|
||||
}
|
||||
|
||||
SpiceRotation::SpiceRotation(const ghoul::Dictionary& dictionary)
|
||||
: _sourceFrame(SourceInfo)
|
||||
: Rotation(dictionary)
|
||||
, _sourceFrame(SourceInfo)
|
||||
, _destinationFrame(DestinationInfo)
|
||||
, _fixedDate(FixedDateInfo)
|
||||
, _timeOffset(TimeOffsetInfo)
|
||||
@@ -126,11 +116,6 @@ SpiceRotation::SpiceRotation(const ghoul::Dictionary& dictionary)
|
||||
_timeOffset = p.timeOffset.value_or(_timeOffset);
|
||||
addProperty(_timeOffset);
|
||||
|
||||
if (p.timeFrame.has_value()) {
|
||||
_timeFrame = TimeFrame::createFromDictionary(*p.timeFrame);
|
||||
addPropertySubOwner(_timeFrame.get());
|
||||
}
|
||||
|
||||
addProperty(_sourceFrame);
|
||||
addProperty(_destinationFrame);
|
||||
|
||||
@@ -139,9 +124,6 @@ SpiceRotation::SpiceRotation(const ghoul::Dictionary& dictionary)
|
||||
}
|
||||
|
||||
glm::dmat3 SpiceRotation::matrix(const UpdateData& data) const {
|
||||
if (_timeFrame && !_timeFrame->isActive(data.time)) {
|
||||
return glm::dmat3(1.0);
|
||||
}
|
||||
return SpiceManager::ref().positionTransformMatrix(
|
||||
_sourceFrame,
|
||||
_destinationFrame,
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
|
||||
#include <openspace/properties/stringproperty.h>
|
||||
#include <openspace/properties/scalar/floatproperty.h>
|
||||
#include <openspace/scene/timeframe.h>
|
||||
#include <optional>
|
||||
|
||||
namespace openspace {
|
||||
@@ -40,7 +39,6 @@ class SpiceRotation : public Rotation {
|
||||
public:
|
||||
explicit SpiceRotation(const ghoul::Dictionary& dictionary);
|
||||
|
||||
const glm::dmat3& matrix() const;
|
||||
glm::dmat3 matrix(const UpdateData& data) const override;
|
||||
|
||||
static documentation::Documentation Documentation();
|
||||
@@ -51,7 +49,6 @@ private:
|
||||
properties::StringProperty _fixedDate;
|
||||
properties::FloatProperty _timeOffset;
|
||||
|
||||
ghoul::mm_unique_ptr<TimeFrame> _timeFrame;
|
||||
std::optional<double> _fixedEphemerisTime;
|
||||
};
|
||||
|
||||
|
||||
@@ -50,6 +50,43 @@ namespace {
|
||||
std::optional<int> element [[codegen::greater(0)]];
|
||||
};
|
||||
#include "gptranslation_codegen.cpp"
|
||||
|
||||
ghoul::Dictionary gpDictionaryToKepler(const ghoul::Dictionary& dictionary) {
|
||||
using namespace openspace;
|
||||
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
if (!std::filesystem::is_regular_file(p.file)) {
|
||||
throw ghoul::RuntimeError("The provided TLE file must exist");
|
||||
}
|
||||
|
||||
int element = p.element.value_or(1);
|
||||
|
||||
std::vector<kepler::Parameters> parameters = kepler::readFile(
|
||||
p.file,
|
||||
codegen::map<kepler::Format>(p.format)
|
||||
);
|
||||
|
||||
if (element > static_cast<int>(parameters.size())) {
|
||||
throw ghoul::RuntimeError(std::format(
|
||||
"Requested element {} but only {} are available", element, parameters.size()
|
||||
));
|
||||
}
|
||||
|
||||
const kepler::Parameters& param = parameters[element - 1];
|
||||
|
||||
// We copy the old dictionary to make sure we keep values intact that we don't
|
||||
// want to touch here (for example the 'Type')
|
||||
ghoul::Dictionary res = dictionary;
|
||||
res.setValue("Eccentricity", param.eccentricity);
|
||||
res.setValue("SemiMajorAxis", param.semiMajorAxis);
|
||||
res.setValue("Inclination", param.inclination);
|
||||
res.setValue("AscendingNode", param.ascendingNode);
|
||||
res.setValue("ArgumentOfPeriapsis", param.argumentOfPeriapsis);
|
||||
res.setValue("MeanAnomaly", param.meanAnomaly);
|
||||
res.setValue("Period", param.period);
|
||||
res.setValue("Epoch", param.epoch);
|
||||
return res;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
@@ -58,36 +95,8 @@ documentation::Documentation GPTranslation::Documentation() {
|
||||
return codegen::doc<Parameters>("space_translation_gp");
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
int element = p.element.value_or(1);
|
||||
|
||||
std::vector<kepler::Parameters> parameters = kepler::readFile(
|
||||
p.file,
|
||||
codegen::map<kepler::Format>(p.format)
|
||||
);
|
||||
|
||||
if (element > static_cast<int>(parameters.size())) {
|
||||
throw ghoul::RuntimeError(std::format(
|
||||
"Requested element {} but only {} are available", element, parameters.size()
|
||||
));
|
||||
}
|
||||
|
||||
const kepler::Parameters& param = parameters[element - 1];
|
||||
setKeplerElements(
|
||||
param.eccentricity,
|
||||
param.semiMajorAxis,
|
||||
param.inclination,
|
||||
param.ascendingNode,
|
||||
param.argumentOfPeriapsis,
|
||||
param.meanAnomaly,
|
||||
param.period,
|
||||
param.epoch
|
||||
);
|
||||
}
|
||||
GPTranslation::GPTranslation(const ghoul::Dictionary& dictionary)
|
||||
: KeplerTranslation(gpDictionaryToKepler(dictionary))
|
||||
{}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -66,19 +66,9 @@ documentation::Documentation HorizonsTranslation::Documentation() {
|
||||
return codegen::doc<Parameters>("base_transform_translation_horizons");
|
||||
}
|
||||
|
||||
HorizonsTranslation::HorizonsTranslation()
|
||||
: _horizonsFiles(HorizonsTextFileInfo)
|
||||
{
|
||||
_horizonsFiles.onChange([this](){
|
||||
requireUpdate();
|
||||
notifyObservers();
|
||||
loadData();
|
||||
});
|
||||
addProperty(_horizonsFiles);
|
||||
}
|
||||
|
||||
HorizonsTranslation::HorizonsTranslation(const ghoul::Dictionary& dictionary)
|
||||
: HorizonsTranslation()
|
||||
: Translation(dictionary)
|
||||
, _horizonsFiles(HorizonsTextFileInfo)
|
||||
{
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
@@ -99,6 +89,13 @@ HorizonsTranslation::HorizonsTranslation(const ghoul::Dictionary& dictionary)
|
||||
);
|
||||
_horizonsFiles = f;
|
||||
}
|
||||
|
||||
_horizonsFiles.onChange([this](){
|
||||
requireUpdate();
|
||||
notifyObservers();
|
||||
loadData();
|
||||
});
|
||||
addProperty(_horizonsFiles);
|
||||
}
|
||||
|
||||
glm::dvec3 HorizonsTranslation::position(const UpdateData& data) const {
|
||||
|
||||
@@ -69,7 +69,6 @@ namespace documentation { struct Documentation; }
|
||||
*/
|
||||
class HorizonsTranslation : public Translation {
|
||||
public:
|
||||
HorizonsTranslation();
|
||||
explicit HorizonsTranslation(const ghoul::Dictionary& dictionary);
|
||||
|
||||
glm::dvec3 position(const UpdateData& data) const override;
|
||||
|
||||
@@ -101,8 +101,8 @@ namespace {
|
||||
constexpr openspace::properties::Property::PropertyInfo EpochInfo = {
|
||||
"Epoch",
|
||||
"Epoch",
|
||||
"This value determines the epoch for which the initial location is defined in "
|
||||
"the form of YYYY MM DD HH:mm:ss.",
|
||||
"Specifies the epoch in which the first position of the Kepler arguments are "
|
||||
"provided. The epoch is specified in numbers of seconds past the J2000 epoch.",
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
@@ -132,8 +132,10 @@ namespace {
|
||||
// [[codegen::verbatim(MeanAnomalyAtEpochInfo.description)]]
|
||||
double meanAnomaly [[codegen::inrange(-360.0, 360.0)]];
|
||||
|
||||
// [[codegen::verbatim(EpochInfo.description)]]
|
||||
std::string epoch;
|
||||
// This value determines the epoch for which the initial location is defined in.
|
||||
// This is specified either in the form of a date (YYYY MM DD HH:mm:ss) or in the
|
||||
// number of seconds past the J2000 epoch.
|
||||
std::variant<std::string, double> epoch;
|
||||
|
||||
// [[codegen::verbatim(PeriodInfo.description)]]
|
||||
double period [[codegen::greater(0.0)]];
|
||||
@@ -152,8 +154,9 @@ documentation::Documentation KeplerTranslation::Documentation() {
|
||||
return codegen::doc<Parameters>("space_transform_kepler");
|
||||
}
|
||||
|
||||
KeplerTranslation::KeplerTranslation()
|
||||
: _eccentricity(EccentricityInfo, 0.0, 0.0, 1.0)
|
||||
KeplerTranslation::KeplerTranslation(const ghoul::Dictionary& dictionary)
|
||||
: Translation(dictionary)
|
||||
, _eccentricity(EccentricityInfo, 0.0, 0.0, 1.0)
|
||||
, _semiMajorAxis(SemiMajorAxisInfo, 0.0, 0.0, 1e6)
|
||||
, _inclination(InclinationInfo, 0.0, 0.0, 360.0)
|
||||
, _ascendingNode(AscendingNodeInfo, 0.0, 0.0, 360.0)
|
||||
@@ -162,6 +165,8 @@ KeplerTranslation::KeplerTranslation()
|
||||
, _epoch(EpochInfo, 0.0, 0.0, 1e9)
|
||||
, _period(PeriodInfo, 0.0, 0.0, 1e6)
|
||||
{
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
auto update = [this]() {
|
||||
_orbitPlaneDirty = true;
|
||||
requireUpdate();
|
||||
@@ -188,12 +193,11 @@ KeplerTranslation::KeplerTranslation()
|
||||
addProperty(_meanAnomalyAtEpoch);
|
||||
addProperty(_epoch);
|
||||
addProperty(_period);
|
||||
}
|
||||
|
||||
KeplerTranslation::KeplerTranslation(const ghoul::Dictionary& dictionary)
|
||||
: KeplerTranslation()
|
||||
{
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
const double epoch =
|
||||
std::holds_alternative<double>(p.epoch) ?
|
||||
std::get<double>(p.epoch) :
|
||||
SpiceManager::ref().ephemerisTimeFromDate(std::get<std::string>(p.epoch));
|
||||
|
||||
setKeplerElements(
|
||||
p.eccentricity,
|
||||
@@ -201,11 +205,11 @@ KeplerTranslation::KeplerTranslation(const ghoul::Dictionary& dictionary)
|
||||
p.inclination < 0.0 ? p.inclination + 360.0 : p.inclination,
|
||||
p.ascendingNode < 0.0 ? p.ascendingNode + 360.0 : p.ascendingNode,
|
||||
p.argumentOfPeriapsis < 0.0 ?
|
||||
p.argumentOfPeriapsis + 360.0 :
|
||||
p.argumentOfPeriapsis,
|
||||
p.argumentOfPeriapsis + 360.0 :
|
||||
p.argumentOfPeriapsis,
|
||||
p.meanAnomaly < 0.0 ? p.meanAnomaly + 360.0 : p.meanAnomaly,
|
||||
p.period,
|
||||
p.epoch
|
||||
epoch
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -121,11 +121,6 @@ public:
|
||||
double ascendingNode, double argumentOfPeriapsis, double meanAnomalyAtEpoch,
|
||||
double orbitalPeriod, double epoch);
|
||||
|
||||
/**
|
||||
* Default construct that initializes all the properties and member variables.
|
||||
*/
|
||||
KeplerTranslation();
|
||||
|
||||
/**
|
||||
* Recombutes the rotation matrix used in the update method.
|
||||
*/
|
||||
|
||||
@@ -111,7 +111,8 @@ documentation::Documentation SpiceTranslation::Documentation() {
|
||||
}
|
||||
|
||||
SpiceTranslation::SpiceTranslation(const ghoul::Dictionary& dictionary)
|
||||
: _target(TargetInfo)
|
||||
: Translation(dictionary)
|
||||
, _target(TargetInfo)
|
||||
, _observer(ObserverInfo)
|
||||
, _frame(FrameInfo, "GALACTIC")
|
||||
, _fixedDate(FixedDateInfo)
|
||||
|
||||
Reference in New Issue
Block a user