classless solar system data objects
- contain physical characteristics of solar system objects
class AnimatedSpaceObject
- any kind of objects that is in space
- has attributes:
- object3d: its three.js object3d added to the scene
- initAnimation(newDate) for initialization
- animate(msecTimestamp) for animation
class PlanetArtist:
- handles artistic aspect of planet itself (sphere, color, etc...)
idea:
- separate orbital positions components of:
- plane the orbiter is on relative to orbital system and...
- path orbiter is following on that plane (circular, ecliptic, other...) -> allows for better separation of circular/elliptic and tilted/not tilted -> how to do it?
- Orbit abstract class, with children CircularOrbit and EllipticOrbit: defines x,y position relative to center
- OrbitPlane class: basically an object3d, that may or may not be tilted (actually) idea bis:
- get rid of Orbiter classes and rename PlanetArtist Planet:
- Orbit and Planet take an object3d in constructor + their required metadata
- Both modify only the object3d data relevant to their role (Orbit: x,z positions; Planet: sphere & appearance)
Todolist:
- DONE 1) create elliptic orbit with constant orbital speed, sun center-centered
- DONE 2) sun in 1 of the 2 focal point
- DONE 3) ellipse correctly oriented
- DONE 4) tilted elliptic orbits
- DONE 5) orbital speed is keplerian speed
- DONE 6) create KeplerOrbit object
- DONE 7) add meanAnomaly
- DONE 8) OrbitalSystem
- DONE 9) better separation of animation&position calculation
- position calculation (from given date or interval) in a set of functions?
- adding "listeners" (=?orbiters) called as part of animation?
- shared position Vector3D?
- not having intermediary object3ds? but only a global shared position vector?
- challenges with computeState() approach:
- Orbit/spaceObject do not only compute positions, but also rotations and scale
- why do we need a "plane" object3d for KeplerOrbits? -> because rotations are in object3d's local world: rotating them fucks their x/y positioning
- we want children object3ds to have proper rotations/orientation as well as positions (typically: CircularOrbit rotates instead of setting position) -> DONE a) set a initDate and currentTimestamp property for Orbits -> initTimestamp from data!! -> DONE FOR ELLIPTIC b) currently: initAnimation() is never used -> sets currentTimestamp & updates positions according to it -> DONE c) create Orbit's "mobile" object3d -> computeState() computes the mobile new position, by default by making a kopy with an option to updates its properties' instead -> animate() calls computeState() with mobile update -> DONE d) computeState(): -> using a Date or an interval from currentTimestamp -> doesn't update any state variable -> DONE e) animate() and initAnimation() use computeState()
- DONE 10) .computeState() improvement:
- re-separate computeStateAtDate from computeState?
-> it is weird to mix dates & interval in same function
-> what does computeState() needs to compute Orbit?
- intervalTimestamp, posOnOrbit (=x&y), and THAT'S ALL! -> makes sense to do only this computation in computeState() -> returns posOnOrbit and vector3
- DONE a) new architecture:
- computeState() takes a posOnOrbit and interval timeStamp -> computes all from it
- animate calls computeState for new pos & then updates state
- re-separate computeStateAtDate from computeState?
-> it is weird to mix dates & interval in same function
-> what does computeState() needs to compute Orbit?
-
- A single file per Orbit in Orbit.js: Orbit, CircularOrbit, EllipticOrbit, KeplerOrbit, Planes
-
- Orbit getPoint(), getPoints(), getPointAt(), getPointsAt(), , getPointAtDate()
general:
- X) set date/speed using variable UI modifiers
- X) light source: sun
- X) planet imaged texture
- X) open wikipedia widget on click descriptive solar system
- X) CircularOrbit.computeState()
- X) OrbitArtist class:
- disappearing&static orbits
- DONE distance to ecliptic markers
- different shades depending on above/below on ecliptic
- Orbit.showPath() takes an OrbitArtist argument (default to the simplest static orbit)
- X) Fix Orbit and Artist weaknesses:
- fromOrbiterData() center Argument
discussion:
- separation is desirable for:
- compute positions without any three.js overhead
- separation not desirable for:
- on the three.js side, it doesn't make sense to separate: the tiltedOrbitalPlane of a KeplerOrbit is essential to the proper positioning of a planetArtist (orientation of planet rotational tilt/etc...)
current:
- object3ds (both orbit&artist) are all clumsily gathered in the planet's data object literal -> no proper separation!
- proposal: -> the OrbitalSystem creates an object that gathers the object's data, artist & orbit -> simply put everything in that object
A gravitationally affected body needs properties:
- mass
- position
- speed A gravitational system needs:
- a list of bodies
- ...what else?
Needs:
- good optimization:
- avoid duplication
- efficient code (call-stack)
- precision:
- resists to different animation step deltaT interval
- separation of visual&computational part
Proposition:
- NewtonianBody class -> mass, position, speed, acceleration, force properties -> only a data-repository for computations!
- GravitationalSystem -> bodies property: list of NB -> reimplements computeState(), computeStateAtDate() -> computes positions/speeds/accelerations/forces only, no three.js!
- AnimatedNewtonianBody class extends ASOG -> takes a NB property -> unifies ANB.object3d.position = NB.position -> reimplements initAnimation(), animate()
- AnimatedGravitationalSystem class extends ASOG -> bodies property=children = list of ANB -> creates a GS from the ANBs' NBs -> reimplements initAnimation(), animate() -> calling GS.computeState() / GS.computeStateAtDate()
Computational/Precision optimization:
- add cache: CachingGraviationalSystem -> has a dict of dates -> NB -> has a caching step arguments -> caches at every caching step -> computes in between caching steps
- precision next order derivations:
- compute instantaneous acceleration -> add acceleration to speed, and speed to position using smaller deltaTs
DEBUGGING
- earth revolves around sun in a matter of days -> probably handling time/forces computation wrong somewhere
distance:
- AU, astronomical unit = avg earth-sun distance = 1.495978707×10^11 m -> within solar system measurement
- parsecm = 3.08567758149137×10^16 m = 648000/pi AU -> astronomy/astrophysics measurement unit
time:
- J2000 12h on 1 January 2000
orbit:
- periapsis: closest point in orbit to primary body (peri=close) (periphelion = periapsis when primary=sun)
- apoapsis: furthest point in orbit to primary body (ap=far) (aphelion = apoapsis when primary=sun)
- Argument of periapsis (- semi-major-axis: half of segment going through peri- and a-phelion)
- mean anomaly: fraction of elliptical orbit elapsed since last periapsis at given time -> useful to determine orbital starting point!
- orbital eccentricity: determines shape of ellipse
- inclination
position
mass
https://github.com/orbitalindex/awesome-space#astronomy-apis
best introduction to Keplerian orbits: https://en.wikipedia.org/wiki/Orbital_elements
website dowing the same: http://planetoweb.net/app/
stylish orbital simulator: https://github.com/TheHappyKoala/Harmony-of-the-Spheres
Planetary satellites: https://ssd.jpl.nasa.gov/?sat_elem#legend
JPL Horizon API (hard to use) https://ssd.jpl.nasa.gov/horizons.cgi
nasa spice: https://naif.jpl.nasa.gov/naif/
Astroquery, python package for querying astronomical datasets: https://astroquery.readthedocs.io/en/latest/
other web service: https://minorplanetcenter.net//web_service
for earth satellites: http://celestrak.com/NORAD/elements/
Incredible planet visualiser, with terrain pictures and exagerable height maps: http://planetmaker.wthr.us/#
http://podgorskiy.com/KeplerOrbits/KeplerOrbits.html
- DONE switch to ts
- fix NewtonianBody GravitationalSystem
- Animation bug when leaving window
- divergence from KeplerOrbit
- DONE improve software architecture
- more flexible time handling
- DONE clear separation of computation and artistry
following https://www.typescriptlang.org/docs/handbook/migrating-from-javascript.html
core:
- Animated initAnimation() animate() <- MOST IMPORTANTE used by global animate() doing the animation!
- AnimatedSpaceObject (ASO) extends Animated object3d
- AnimatedSpaceObjectsGroup (ASOG) extends AnimatedSpaceObject
- mobile (=this.object3d? why?)
- children: ASO[]
descriptive:
- AbstractOrbit (AO) extends ASOG data: initDate currentSimulTimestamp pathObject3d UNUSED computeState() <- MOST IMPORTANTE computeStateAtDate()
- CircularOrbit computeState() <- not implemented -> uses simple constant speed across circle, very
- EllipticOrbit lastAnimateTimestamp currentPosOnOrbit _initPosOnOrbit -> nothing to ordinary, pretty fine
- core/
- minimal
- data/
- descriptive/
- AbstractOrbit
- CircularOrbit
- EllipticOrbit
- KeplerOrbit and System
- OrbitArtist
- newtonian/
- GravitationalSystem
- NewtonianBody
proposition:
- new artist/ folder with artistry stuff
- DONE clear separation of computation and artistry
- DONE clear folder structure
- metadata flowing freely between parts
Orbits
- remove the AnimatedSpaceObjectsGroup (ASOG) inheritance and animate() method
- removes currentPosition and currentTimestamp properties
- computes position, orientation (and velocity, optional)
- NONO is a "XxxSpaceObjectsGroup" and can compute positions for multiple objects, i.e. the earth orbit computes position, orientation and velocity for the earth and its moon
- only return raw position and orientation in the global frame of reference
- can use THREE objects, but by default those are not added to the THREE scene
- are stateless: no currentTimestamp, etc SpaceCache:
- Orbits can take advantage of caching
- Caching by timestamp OrbitalSystem
- has a list of SpaceObjects
- computes states for all SpaceObjects
- is responsible for optimizations of computations DescriptiveOrbitalSystem child class of OS
Artists:
-
take a position and rotation to draw stuff in global reference frame
-
SpaceCache:
- param: a buffer size
Map<timestamp, {position, rotation, velocity, ...other}>- once bufferSize reached, removes random cache entry -> pitfall: coordinate random cache deletion across caches
Question:
- does the orbitCache have a orbit property...
- or the orbit have a cache property?
- or the XxSpaceCache be a child class of XxOrbit
orbitCache.orbit:
- interacts with the cache directly
- harder access to orbit.data
SELECTED pro orbit.cache:
- MAIN REASON any orbit does need a initialPosition anyway
- easier access to orbit.data stuff
- ?less clean code-wise? (an orbit doesn't actually need a cache -> yes it does!)
XxSpaceCache child class of XxOrbit:
- neat access to orbit.data and cache
- XxSpaceCache and YySpaceCache don't have a common parent class -> use SpaceCache interface
- how to not rewrite code for each of them -> Mixin pattern https://www.typescriptlang.org/docs/handbook/mixins.html
Question:
- How to organize objects which orbit objects that orbit other objects? (orbiters2)
- How to organize objects efficiently for 1) computation and 2) artistry and drawing
goals:
- being able to efficiently compute global position for orbiters2
- being able to efficiently compute&cache "local" position for orbiters2
- no code duplication
- easy transition from descriptive/kepler orbits to newtonian orbits
- what about re-creating the hierarchy in the THREE.js artistry part?
Propositions: a) AbstractOrbit has a "parent" property, which references the parent orbit, with getGlobalState() method b) "OrbitalSystem" class keeps a flat list of all the orbits/objects it has. Each AO object has a system property (ref to OS), a parent property (string to AO id), and a getGlobalState() method c) "OrbitalSystem" class keeps a flat list of all the orbits/objects it has. Each AO object has a parent property (string to AO id). OS takes care of composing each object's globalState() from AO.getState() d) CompositeOrbit class has a "parent" and "orbit" property and computes the global getState()
Proposition a) AO parent ref + getGlobalState():
- each AO is able to compute its globalState
- easy to pass an AO to a NewtonianOrbit and get Initial State
- ref mumbo-jumbo
- footgun with AO.getGlobalState/getState()
- less tight control on optimization: might re-compute parents' state multiple times
Proposition b) OS AO flatlist + AO.getGlobalState()
- each AO is able to compute its globalState
- easy to pass an AO to a NewtonianOrbit and get Initial State
- footgun with AO.getGlobalState/getState()
Proposition c) OS AO flatlist + OS.getGlobalState()
- no footgun between getState() getGlobalState()
- OS is responsible for optimization of computations
- AO unaware of its globalState()
Proposition d) CompositeOrbit class
- NewtonianOrbit non-compatible
- too focused on hierarchized orbits
Decision:
- hard to choose between c) and b)
- will go for c):
- in b) AO must go through OS -> so as well skip this step and go directly to OS computing everything -> leaves freedom for the OS to use Three.group or single globally positionned Three.object3d
Computation and artistry
- Computation: DescriptiveOrbitalSystem
- takes OrbiterData[] and fromData: (data)=> Orbit
- Artistry:
- <Hierarchical/Descriptive>OrbitalSystemArtist -> child class of DescriptiveOrbitalSystem
- HierarchicalOrbitArtist -> Takes all the old object3d/group artistry properties/quirks of the old Orbits -> orbit property -> builds a hierarchical tree of Orbit&children -> draws them in hierarchical order -> avoids "world" position/rotation computations
- DONE create OrbitCache
- DONE refactor ASOG
- DONE think of and write up new way of hierarchyzing orbits&objects
- DONE rewrite artistry
- DONE rewrite NewtonianBody as a stateless with cache object
- DONE rewrite GravitationalSystem using the new NewtonianBody
Ideas:
- allow for better visualisation of state/vector properties
- be able to see a state's properties by clicking (velocity, etc)
- create a mock solar system where parameters are known -> errors will be easily identified
- compare velocity values from GS to KOS
- ?compute GS values at KOS places?
steps:
- DONE show each step with a sphere
- click on a sphere
- shows vectors
- shows velocity/Acc/force values in a html elment
- ?shows comparable value from KOS
AnimatedSpaceObject (ASO) renamed to Artist AnimatedSpaceObjectsGroup (ASO) renamed to ArtistsGroup
needs:
- keeps track of currently selected feature
- allows hover/click interaction
- different places to show stuff?
Proposition:
- EventListener3D class to listen events
- id property
- .onClick() & .onHover() methods
- singleton global EventManager3D object
- addEventListener(click/hover, EventListener3D) method
- listens to hover/click events
- triggers EventListener3D methods
- Artists
- have "eventListeners" array with ids of eventListener, addEventListener(elId) -> each EventListener3D is responsible to add itself to the proper artists
- Selector?
- object with "selected", "clicked" attribute
- select/unselect method
onClick/onHover() arguments signature:
- three.intersection
- artist
- whatelse?
currently:
- compute forces
- compute acc
- update velocity
- update position
with initialStates:
- wrongly adds the initial acc to the initial velocity!!