mirror of
https://github.com/christiaangoossens/Planetary-Orbit-Simulator
synced 2025-07-03 18:10:47 +00:00
Changed the nodes algoritms and fixed the argument of periapsis calculation
This commit is contained in:
@ -35,15 +35,18 @@ public class Main {
|
||||
//Object moon = new Object("The Moon", 734.9E20, AU.convertToMeter(new Vector3d(1.002390058141768E+00,-1.318677081380600E-01,-1.051759034600983E-04)), AU.convertToMetersPerSecond(new Vector3d(2.294349896503608E-03,1.752303034437222E-02,-5.522655228080146E-05)));
|
||||
|
||||
// 1 januari startdag
|
||||
Object sun = new Object("Sun", 1.988544E30, AU.convertToMeter(new Vector3d(3.737881713150281E-03,1.402397586692506E-03,-1.612700291840256E-04)), AU.convertToMetersPerSecond(new Vector3d(8.619338996535534E-07,6.895607793642275E-06,-2.794074909231784E-08)));
|
||||
Object earth = new Object("Earth", 5.97219E24, AU.convertToMeter(new Vector3d(-1.630229002588497E-01,9.704723344534316E-01,-1.955367328932975E-04)), AU.convertToMetersPerSecond(new Vector3d(-1.723383356491747E-02,-2.969134550063944E-03,-4.433758674928828E-07)));
|
||||
Object sun = new Object("Sun", 1.988544E30, AU.convertToMeter(new Vector3d(3.737881713150281E-03,1.402397586692506E-03,-1.612700291840256E-04)), AU.convertToMetersPerSecond(new Vector3d(8.619338996535534E-07,6.895607793642275E-06,-2.794074909231784E-08)));
|
||||
Object earth = new Object("Earth", 5.97219E24, AU.convertToMeter(new Vector3d(-1.630229002588497E-01,9.704723344534316E-01,-1.955367328932975E-04)), AU.convertToMetersPerSecond(new Vector3d(-1.723383356491747E-02,-2.969134550063944E-03,-4.433758674928828E-07)));
|
||||
Object moon = new Object("The Moon", 734.9E20, AU.convertToMeter(new Vector3d(-1.657103868749121E-01,9.706382026425473E-01,-1.879812512691582E-04)), AU.convertToMetersPerSecond(new Vector3d(-1.728100931961937E-02,-3.525371122447976E-03,4.909148618073602E-05)));
|
||||
Object jupiter = new Object("Jupiter", 1898.13E24, AU.convertToMeter(new Vector3d(-5.172279968303672E+00,1.591564562098799E+00,1.090553487095606E-01)), AU.convertToMetersPerSecond(new Vector3d(-2.306423668033420E-03,-6.856869314900905E-03,8.012916249248967E-05)));
|
||||
Object saturn = new Object("Saturn", 5.68319E26, AU.convertToMeter(new Vector3d(-3.710637850378867E+00,-9.289569433157130E+00,3.091990731378936E-01)), AU.convertToMetersPerSecond(new Vector3d(4.874750391005278E-03,-2.086615906689840E-03,-1.574898601194673E-04)));
|
||||
Object venus = new Object("Venus", 48.685E23, AU.convertToMeter(new Vector3d(-7.130901319004951E-01,-5.719763212192740E-02,4.040076577877051E-02)), AU.convertToMetersPerSecond(new Vector3d(1.525993024372452E-03,-2.024175581604569E-02,-3.656582385749146E-04)));
|
||||
|
||||
/**
|
||||
* Object listing
|
||||
*/
|
||||
|
||||
Object[] objects = {sun, earth, moon};
|
||||
Object[] objects = {sun, earth, moon, jupiter, saturn};
|
||||
|
||||
|
||||
/**
|
||||
|
@ -64,7 +64,7 @@ public class Simulator {
|
||||
/**
|
||||
* Do the processing on the objects
|
||||
*/
|
||||
processor.process(objects);
|
||||
processor.process(objects, t + 1);
|
||||
|
||||
/**
|
||||
* The round has ended
|
||||
|
@ -5,8 +5,8 @@ public class SimulatorConfig {
|
||||
* Time settings
|
||||
*/
|
||||
|
||||
public static int rounds = 526100 * 35 * 60; // Amount of rounds to run the simulator for
|
||||
public static double time = 1; // Time steps in seconds
|
||||
public static int rounds = 526100 * 10; // Amount of rounds to run the simulator for
|
||||
public static double time = 60; // Time steps in seconds
|
||||
|
||||
/**
|
||||
* Object settings
|
||||
@ -19,8 +19,8 @@ public class SimulatorConfig {
|
||||
* Ascending & descending node detection
|
||||
*/
|
||||
|
||||
public static double z = -22439680.6; // Reference z height for the used system in meters
|
||||
public static double zThreshold = 100; // Threshold value to specify the maximum value (in meters) the z difference can be to be considered close to the reference plane (To eliminate all bending points that are to far away from the z-axis to count as nodes)
|
||||
//public static double z = -22439680.6; // Reference z height for the used system in meters
|
||||
//public static double zThreshold = 1000; // Threshold value to specify the maximum value (in meters) the z difference can be to be considered close to the reference plane (To eliminate all bending points that are to far away from the z-axis to count as nodes)
|
||||
|
||||
/**
|
||||
* Output preferences
|
||||
@ -28,6 +28,6 @@ public class SimulatorConfig {
|
||||
|
||||
public static String outputUnit = "AU"; // Preferred output unit preference (AU => AU/day, m => m/s)
|
||||
public static int outputNumbers = 0; // Preferred way of outputting numbers: (0 => comma for decimals, dot in large numbers OR 1 => comma for large numbers, dot with decimals)
|
||||
public static int skipLines = 2629743; // Set the skipLines integer to skip lines (for example: every 5th line is written) in the output file (for smaller files), if this is set to 1, it has no effect and all lines will be written.
|
||||
public static int skipLines = 1440; // Set the skipLines integer to skip lines (for example: every 5th line is written) in the output file (for smaller files), if this is set to 1, it has no effect and all lines will be written.
|
||||
public static boolean skipUnnecessary = true; // Skip the unnecessary objects in the export
|
||||
}
|
||||
|
@ -9,6 +9,11 @@ public class AOP {
|
||||
public static double calculate(Vector3d ascendingNode, Vector3d perihelion, Vector3d aphelion) {
|
||||
Vector3d eccentricity = new Vector3d(0,0,0);
|
||||
eccentricity.sub(perihelion, aphelion);
|
||||
return ascendingNode.angle(eccentricity);
|
||||
|
||||
if (perihelion.getY() > ascendingNode.getY()) {
|
||||
return ascendingNode.angle(eccentricity);
|
||||
} else {
|
||||
return (2 * Math.PI) - ascendingNode.angle(eccentricity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +50,10 @@ public class AU {
|
||||
return output;
|
||||
}
|
||||
|
||||
public static double convertFromMeter(double input) {
|
||||
return input * 6.6845871E-12;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts m/s to AU/day for data collection
|
||||
* @param input Vector3d with values in m/s
|
||||
|
@ -1,10 +1,9 @@
|
||||
package com.verictas.pos.simulator.processor;
|
||||
|
||||
import com.verictas.pos.simulator.Object;
|
||||
import com.verictas.pos.simulator.SimulatorConfig;
|
||||
import com.verictas.pos.simulator.mathUtils.AU;
|
||||
|
||||
import javax.vecmath.Vector3d;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ObjectProcessor {
|
||||
public Vector3d aphelion;
|
||||
@ -22,9 +21,12 @@ public class ObjectProcessor {
|
||||
public Vector3d ascendingNode;
|
||||
public Vector3d descendingNode;
|
||||
|
||||
public double zAxisDistance = -1;
|
||||
public double pastzAxisDistance = -1;
|
||||
public Vector3d lastPos;
|
||||
public Vector3d absoluteMax;
|
||||
public Vector3d absoluteMin;
|
||||
|
||||
public double referenceZ;
|
||||
|
||||
public HashMap<Integer, Vector3d[]> history = new HashMap<>();
|
||||
|
||||
public void setStartingPosition(Vector3d position) {
|
||||
this.startingPosition = position;
|
||||
@ -38,6 +40,14 @@ public class ObjectProcessor {
|
||||
this.referenceObject = object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep an history of the object position and speed (for logging and further processing)
|
||||
*/
|
||||
|
||||
public void processHistory(int round) {
|
||||
this.history.put(round, new Vector3d[] {this.thisObject.position, this.thisObject.speed});
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the aphelion & perihelion
|
||||
*/
|
||||
@ -71,57 +81,67 @@ public class ObjectProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the ascending node
|
||||
* Get the absolute maximum and minimum positions (max z and min z)
|
||||
*/
|
||||
|
||||
public void calculateTops() {
|
||||
if (this.absoluteMax == null) {
|
||||
this.absoluteMax = this.thisObject.position;
|
||||
}
|
||||
|
||||
if (this.absoluteMin == null) {
|
||||
this.absoluteMin = this.thisObject.position;
|
||||
}
|
||||
|
||||
if (this.thisObject.position.getZ() > this.absoluteMax.getZ()) {
|
||||
this.absoluteMax = this.thisObject.position;
|
||||
}
|
||||
|
||||
if (this.thisObject.position.getZ() < this.absoluteMin.getZ()) {
|
||||
this.absoluteMin = this.thisObject.position;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Process the nodes
|
||||
*/
|
||||
|
||||
public void processNodes() {
|
||||
double zAxisDistance = Math.abs(this.thisObject.position.getZ() - SimulatorConfig.z);
|
||||
this.referenceZ = (this.absoluteMin.getZ() + this.absoluteMax.getZ()) / 2;
|
||||
|
||||
if (this.pastzAxisDistance == -1) {
|
||||
this.pastzAxisDistance = zAxisDistance;
|
||||
}
|
||||
// Loop through the entire history
|
||||
for (Map.Entry<Integer, Vector3d[]> entry : this.history.entrySet()) {
|
||||
Integer round = entry.getKey();
|
||||
Vector3d[] vectorArray = entry.getValue();
|
||||
|
||||
if (this.pastzAxisDistance != -1 && this.zAxisDistance == -1) {
|
||||
this.zAxisDistance = zAxisDistance;
|
||||
}
|
||||
|
||||
if (this.zAxisDistance != -1 && this.pastzAxisDistance != 1) {
|
||||
if ((this.pastzAxisDistance > this.zAxisDistance && zAxisDistance > this.zAxisDistance) && (this.zAxisDistance < SimulatorConfig.zThreshold)) {
|
||||
if (SimulatorConfig.outputUnit.equals("AU")) {
|
||||
System.out.println("INFO:: Found a node within the threshold at " + AU.convertFromMeter(this.lastPos) + " (in AU) for object " + this.thisObject.name + "!");
|
||||
} else {
|
||||
System.out.println("INFO:: Found a node within the threshold at " + this.lastPos + " (in m) for object " + this.thisObject.name + "!");
|
||||
}
|
||||
|
||||
if ((this.lastPos.getZ() - this.thisObject.position.getZ()) < 0) {
|
||||
if (SimulatorConfig.z < 0) {
|
||||
// The reference plane is in negative z, so you have gone up!
|
||||
this.ascendingNode = this.lastPos;
|
||||
System.out.println("INFO:: Detected node as: ASCENDING NODE!");
|
||||
if (this.history.get(round + 1) != null) {
|
||||
// There is a next key!
|
||||
if (vectorArray[0].getZ() < referenceZ && this.history.get(round + 1)[0].getZ() > referenceZ) {
|
||||
// This point is below the reference height and the next is above. This point is the ascending node (with positive z)
|
||||
if (referenceZ <= 0) {
|
||||
// Descending
|
||||
this.descendingNode = vectorArray[0];
|
||||
System.out.println("INFO:: Found a descending node at round " + round + " at position: " + vectorArray[0]);
|
||||
} else {
|
||||
// The reference plane is in positive z, so you have gone down!
|
||||
this.descendingNode = this.lastPos;
|
||||
System.out.println("INFO:: Detected node as: DESCENDING NODE!");
|
||||
// Ascending
|
||||
this.ascendingNode = vectorArray[0];
|
||||
System.out.println("INFO:: Found a ascending node at round " + round + " at position: " + vectorArray[0]);
|
||||
}
|
||||
} else {
|
||||
if (SimulatorConfig.z < 0) {
|
||||
// The reference plane is in negative z, so you have gone down!
|
||||
this.descendingNode = this.lastPos;
|
||||
System.out.println("INFO:: Detected node as: DESCENDING NODE!");
|
||||
} else if (vectorArray[0].getZ() > referenceZ && this.history.get(round + 1)[0].getZ() < referenceZ) {
|
||||
// This point is above the reference height and the next is below. This point is the descending node (with positive z)
|
||||
if (referenceZ <= 0) {
|
||||
// Ascending
|
||||
this.ascendingNode = vectorArray[0];
|
||||
System.out.println("INFO:: Found a ascending node at round " + round + " at position: " + vectorArray[0]);
|
||||
} else {
|
||||
// The reference plane is in positive z, so you have gone up!
|
||||
this.ascendingNode = this.lastPos;
|
||||
System.out.println("INFO:: Detected node as: ASCENDING NODE!");
|
||||
// Descending
|
||||
this.descendingNode = vectorArray[0];
|
||||
System.out.println("INFO:: Found a descending node at round " + round + " at position: " + vectorArray[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.pastzAxisDistance = this.zAxisDistance;
|
||||
this.zAxisDistance = zAxisDistance;
|
||||
}
|
||||
|
||||
this.lastPos = this.thisObject.position;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -178,7 +198,9 @@ public class ObjectProcessor {
|
||||
perihelion = null;
|
||||
ascendingNode = null;
|
||||
descendingNode = null;
|
||||
zAxisDistance = -1;
|
||||
lastPos = null;
|
||||
history = new HashMap<>();
|
||||
absoluteMax = null;
|
||||
absoluteMin = null;
|
||||
referenceZ = -1;
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ public class Processor {
|
||||
}
|
||||
}
|
||||
|
||||
public void process(Object[] objectArray) throws ProcessingException, WritingException {
|
||||
public void process(Object[] objectArray, int rounds) throws ProcessingException, WritingException {
|
||||
HashMap<String, Object> objects = objectArrayToHashMap(objectArray);
|
||||
|
||||
/**
|
||||
@ -48,54 +48,68 @@ public class Processor {
|
||||
|
||||
object.setObjectData(objects.get(objectName));
|
||||
object.setReferenceObjectData(objects.get(SimulatorConfig.sunName));
|
||||
object.processHistory(rounds);
|
||||
|
||||
// Check if the object has gone round last round
|
||||
|
||||
boolean round = object.processRoundCheck();
|
||||
if (round) {
|
||||
// Object has gone full circle last round!
|
||||
System.out.println("\n\n============== ROTATION DATA: " + objectName.toUpperCase() + " =============");
|
||||
System.out.println("Current position (AU): " + AU.convertFromMeter(objects.get(objectName).position));
|
||||
System.out.println("Current position (m): " + objects.get(objectName).position + "\n");
|
||||
// Process the nodes
|
||||
object.processNodes();
|
||||
|
||||
if (object.ascendingNode != null) {
|
||||
System.out.println("Ascending node (AU): " + AU.convertFromMeter(object.ascendingNode));
|
||||
System.out.println("Ascending node (m): " + object.ascendingNode + "\n");
|
||||
} else {
|
||||
if (object.descendingNode != null) {
|
||||
System.out.println("WARNING:: Ascending node not found. Because a descending node was found, you can assume the current position is the ascending node (or it is between the starting position and the current.\n");
|
||||
} else {
|
||||
System.out.println("WARNING:: Ascending node not found. Have you set the reference plane height correctly?\n");
|
||||
}
|
||||
}
|
||||
// ECHO:: Object has gone full circle last round!
|
||||
System.out.println("\n\n============== ROTATION DATA: " + objectName.toUpperCase() + ", ROUND " + (rounds - 1) + " =============");
|
||||
|
||||
if (SimulatorConfig.outputUnit == "AU") {
|
||||
System.out.println("Current position (AU): " + AU.convertFromMeter(objects.get(objectName).position) + "\n");
|
||||
System.out.println("Highest point (z-axis graph) (AU): " + AU.convertFromMeter(object.absoluteMax));
|
||||
System.out.println("Lowest point (z-axis graph) (AU): " + AU.convertFromMeter(object.absoluteMin));
|
||||
System.out.println("Calculated reference height (AU) : " + AU.convertFromMeter(object.referenceZ) + "\n");
|
||||
|
||||
if (object.descendingNode != null) {
|
||||
System.out.println("Descending node (AU): " + AU.convertFromMeter(object.descendingNode));
|
||||
System.out.println("Descending node (m): " + object.descendingNode + "\n");
|
||||
} else {
|
||||
if (object.ascendingNode != null) {
|
||||
System.out.println("WARNING:: Descending node not found. Because a ascending node was found, you can assume the current position is the descending node (or it is between the starting position and the current).\n");
|
||||
System.out.println("Ascending node (AU): " + AU.convertFromMeter(object.ascendingNode));
|
||||
} else {
|
||||
System.out.println("WARNING:: Descending node not found. Have you set the reference plane height correctly?\n");
|
||||
System.out.println("WARNING:: Ascending node not found.");
|
||||
}
|
||||
|
||||
if (object.descendingNode != null) {
|
||||
System.out.println("Descending node (AU): " + AU.convertFromMeter(object.descendingNode) + "\n");
|
||||
} else {
|
||||
System.out.println("WARNING:: Descending node not found.\n");
|
||||
}
|
||||
|
||||
System.out.println("Position during apastron (AU): " + AU.convertFromMeter(object.aphelion));
|
||||
System.out.println("Distance from (the) " + SimulatorConfig.sunName + " during apastron in km: " + object.aphelionDistance / 1000 + "\n");
|
||||
System.out.println("Position during periastron (AU): " + AU.convertFromMeter(object.perihelion));
|
||||
System.out.println("Distance from (the) " + SimulatorConfig.sunName + " during periastron in km: " + object.perihelionDistance / 1000 + "\n");
|
||||
} else {
|
||||
System.out.println("Current position (m): " + objects.get(objectName).position + "\n");
|
||||
System.out.println("Highest point (z-axis graph) (m): " + object.absoluteMax);
|
||||
System.out.println("Lowest point (z-axis graph) (m): " + object.absoluteMin);
|
||||
System.out.println("Calculated reference height (m) : " + object.referenceZ + "\n");
|
||||
|
||||
if (object.ascendingNode != null) {
|
||||
System.out.println("Ascending node (m): " + object.ascendingNode);
|
||||
} else {
|
||||
System.out.println("WARNING:: Ascending node not found.");
|
||||
}
|
||||
|
||||
if (object.descendingNode != null) {
|
||||
System.out.println("Descending node (m): " + object.descendingNode + "\n");
|
||||
} else {
|
||||
System.out.println("WARNING:: Descending node not found.\n");
|
||||
}
|
||||
|
||||
System.out.println("Position during apastron (m): " + object.aphelion);
|
||||
System.out.println("Distance from (the) " + SimulatorConfig.sunName + " during apastron in km: " + object.aphelionDistance / 1000 + "\n");
|
||||
System.out.println("Position during periastron (m): " + object.perihelion);
|
||||
System.out.println("Distance from (the) " + SimulatorConfig.sunName + " during periastron in km: " + object.perihelionDistance / 1000 + "\n");
|
||||
}
|
||||
|
||||
System.out.println("Position during apastron (AU): " + AU.convertFromMeter(object.aphelion));
|
||||
System.out.println("Position during apastron (m): " + object.aphelion);
|
||||
System.out.println("Distance from (the) " + SimulatorConfig.sunName + " during apastron in m: " + object.aphelionDistance + "\n");
|
||||
System.out.println("Position during periastron (AU): " + AU.convertFromMeter(object.perihelion));
|
||||
System.out.println("Position during periastron (m): " + object.perihelion);
|
||||
System.out.println("Distance from (the) " + SimulatorConfig.sunName + " during periastron in m: " + object.perihelionDistance + "\n");
|
||||
|
||||
if (object.ascendingNode != null) {
|
||||
System.out.println("Argument of periapsis (range: 0 - PI): " + AOP.calculate(object.ascendingNode, object.perihelion, object.aphelion) + " rad");
|
||||
System.out.println("Argument of periapsis: " + Math.toDegrees(AOP.calculate(object.ascendingNode, object.perihelion, object.aphelion)) + " degrees");
|
||||
System.out.println("Argument of periapsis (radians): " + AOP.calculate(object.ascendingNode, object.perihelion, object.aphelion));
|
||||
System.out.println("Argument of periapsis (degrees): " + Math.toDegrees(AOP.calculate(object.ascendingNode, object.perihelion, object.aphelion)));
|
||||
} else {
|
||||
if (object.descendingNode != null) {
|
||||
System.out.println("WARNING:: Ascending node not found. The argument is calculated with the current position as ascending node).\n");
|
||||
System.out.println("Argument of periapsis (range: 0 - PI): " + AOP.calculate(objects.get(objectName).position, object.perihelion, object.aphelion) + " rad");
|
||||
System.out.println("Argument of periapsis: " + Math.toDegrees(AOP.calculate(objects.get(objectName).position, object.perihelion, object.aphelion)) + " degrees");
|
||||
}
|
||||
System.out.println("ERROR:: Can't calculate the argument of periapsis because the ascending node is missing.");
|
||||
}
|
||||
|
||||
@ -109,7 +123,7 @@ public class Processor {
|
||||
|
||||
// Process values for this round
|
||||
object.processAphelionAndPerihelion();
|
||||
object.processNodes();
|
||||
object.calculateTops();
|
||||
|
||||
this.objects.put(objectName, object);
|
||||
}
|
||||
|
Reference in New Issue
Block a user