Some bug fixes
This commit is contained in:
parent
9d435fb255
commit
b176a4a412
@ -192,13 +192,8 @@ export class LambertSolutions {
|
|||||||
transferGoalTrueAnomaly -= 2 * Math.PI;
|
transferGoalTrueAnomaly -= 2 * Math.PI;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (transferStartTrueAnomaly < 2 * Math.PI && transferGoalTrueAnomaly > 2 * Math.PI) {
|
|
||||||
transferStartTrueAnomaly -= 2 * Math.PI;
|
|
||||||
transferGoalTrueAnomaly -= 2 * Math.PI;
|
|
||||||
}
|
|
||||||
|
|
||||||
let closestPoint;
|
let closestPoint;
|
||||||
if (transferStartTrueAnomaly < 0 && transferGoalTrueAnomaly >= 0) {
|
if ((transferStartTrueAnomaly < 0 && transferGoalTrueAnomaly >= 0) || (transferStartTrueAnomaly < 2 * Math.PI && transferGoalTrueAnomaly >= 2 * Math.PI)) {
|
||||||
closestPoint = semiLatusRectum / (1 + eccentricity);
|
closestPoint = semiLatusRectum / (1 + eccentricity);
|
||||||
} else {
|
} else {
|
||||||
closestPoint = Math.min(this.positionOneMagnitude, this.positionTwoMagnitude);
|
closestPoint = Math.min(this.positionOneMagnitude, this.positionTwoMagnitude);
|
||||||
@ -570,7 +565,7 @@ export function getOrbitalPeriod(semiMajor: number, body: Body) {
|
|||||||
return Math.sqrt(semiMajor**3 / body.gravitationalParameter);
|
return Math.sqrt(semiMajor**3 / body.gravitationalParameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function perform2dGradientDescent(functionToMinimize: ((variableOne: number, variableTwo: number) => number | null), initialGuessVariableOne: number, initialGuessVaribaleTwo: number, maxDifference?: number, maxTries?: number): [number, number] | null {
|
export function perform2dGradientDescent(functionToMinimize: ((variableOne: number, variableTwo: number) => number | null), initialGuessVariableOne: number, initialGuessVaribaleTwo: number, maxDifference?: number, maxTries?: number, variableOneBounds?: [number, number], variableTwoBounds?: [number, number]): [number, number] | null {
|
||||||
let variableOne = initialGuessVariableOne;
|
let variableOne = initialGuessVariableOne;
|
||||||
let variableTwo = initialGuessVaribaleTwo;
|
let variableTwo = initialGuessVaribaleTwo;
|
||||||
let bestValue = functionToMinimize(variableOne, variableTwo);
|
let bestValue = functionToMinimize(variableOne, variableTwo);
|
||||||
@ -649,6 +644,18 @@ export function perform2dGradientDescent(functionToMinimize: ((variableOne: numb
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (variableOneBounds) {
|
||||||
|
if (variableOneUpdate < variableOneBounds[0] || variableOneUpdate > variableOneBounds[1]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (variableTwoBounds) {
|
||||||
|
if (variableTwoUpdate < variableTwoBounds[0] || variableTwoUpdate > variableTwoBounds[1]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
variableOne = variableOneUpdate;
|
variableOne = variableOneUpdate;
|
||||||
variableTwo = variableTwoUpdate;
|
variableTwo = variableTwoUpdate;
|
||||||
bestValue = bestValueImprovement;
|
bestValue = bestValueImprovement;
|
||||||
@ -992,17 +999,26 @@ export function findCheapestIntercept(startingSituation: OrbitalCoordinates, tar
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let extraStartOrbits = Math.floor(startOrbitMeanAnomaly / (2 * Math.PI));
|
let startTrueAnomaly: number = 0;
|
||||||
let extraEndOrbits = Math.floor(endOrbitMeanAnomaly / (2 * Math.PI));
|
let endTrueAnomaly: number = 0;
|
||||||
|
|
||||||
startOrbitMeanAnomaly = startOrbitMeanAnomaly % (2 * Math.PI);
|
["start", "end"].forEach(orbit => {
|
||||||
endOrbitMeanAnomaly = endOrbitMeanAnomaly % (2 * Math.PI);
|
let meanAnomaly = orbit == "start" ? startOrbitMeanAnomaly : endOrbitMeanAnomaly;
|
||||||
|
let eccentricity = orbit == "start" ? startingSituation.orbit.eccentricity : targetSituation.orbit.eccentricity;
|
||||||
|
let extraOrbits = 0;
|
||||||
|
if (eccentricity < 1) {
|
||||||
|
extraOrbits = Math.floor(meanAnomaly / (2 * Math.PI));
|
||||||
|
meanAnomaly = meanAnomaly % (2 * Math.PI);
|
||||||
|
}
|
||||||
|
let [_, trueAnomaly] = getEccentricAndTrueAnomalyFromMeanAnomaly(meanAnomaly, eccentricity);
|
||||||
|
trueAnomaly += extraOrbits * 2 * Math.PI;
|
||||||
|
|
||||||
let [_, startTrueAnomaly] = getEccentricAndTrueAnomalyFromMeanAnomaly(startOrbitMeanAnomaly, startingSituation.orbit.eccentricity);
|
if (orbit == "start") {
|
||||||
let [__, endTrueAnomaly] = getEccentricAndTrueAnomalyFromMeanAnomaly(endOrbitMeanAnomaly, targetSituation.orbit.eccentricity);
|
startTrueAnomaly = trueAnomaly;
|
||||||
|
} else if (orbit == "end") {
|
||||||
startTrueAnomaly += extraStartOrbits * 2 * Math.PI;
|
endTrueAnomaly = trueAnomaly;
|
||||||
endTrueAnomaly += extraEndOrbits * 2 * Math.PI;
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let targetTransferTime = endTime - startTime;
|
let targetTransferTime = endTime - startTime;
|
||||||
let lambertSolutions = new LambertSolutions(startingSituation.orbit, startTrueAnomaly, targetSituation.orbit, endTrueAnomaly + extraTrueAnomaly, body, backwards);
|
let lambertSolutions = new LambertSolutions(startingSituation.orbit, startTrueAnomaly, targetSituation.orbit, endTrueAnomaly + extraTrueAnomaly, body, backwards);
|
||||||
@ -1024,7 +1040,12 @@ export function findCheapestIntercept(startingSituation: OrbitalCoordinates, tar
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (transfer.farthestPointDistance > body.sphereOfInfluence || transfer.closestPointDistance < body.closestSafeDistance) {
|
if (transfer.farthestPointDistance >= body.sphereOfInfluence || transfer.closestPointDistance <= body.closestSafeDistance) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sometimes, we get eccentric orbits that are impossible to do
|
||||||
|
if (transfer.transferOrbitTrueAnomalyAtManoeuvreOne < Math.PI && transfer.transferOrbitTrueanomalyAtManoeuvreTwo > Math.PI && transfer.transferOrbit.eccentricity - 1 >= 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1066,7 +1087,7 @@ export function findCheapestIntercept(startingSituation: OrbitalCoordinates, tar
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = perform2dGradientDescent(interceptFunction, foundStartTime, foundEndTime, 0, 30);
|
let result = perform2dGradientDescent(interceptFunction, foundStartTime, foundEndTime, 0, 30, [0, 1e99]);
|
||||||
if (result) {
|
if (result) {
|
||||||
let foundTransfer = getTransfer(result[0], result[1], backwards);
|
let foundTransfer = getTransfer(result[0], result[1], backwards);
|
||||||
if (foundTransfer) {
|
if (foundTransfer) {
|
||||||
@ -1463,22 +1484,30 @@ export function findOrbitThroughInterpolation(ownCoordinates: OrbitalCoordinates
|
|||||||
}
|
}
|
||||||
|
|
||||||
const getAnglesFromPhaseAngles = (firstPhaseAngle: number, secondPhaseAngle: number) => {
|
const getAnglesFromPhaseAngles = (firstPhaseAngle: number, secondPhaseAngle: number) => {
|
||||||
let angleOne;
|
let cosAngleOne;
|
||||||
let angleTwo;
|
let cosAngleTwo;
|
||||||
|
|
||||||
if (Math.abs(interpolationParameters.firstPhaseAngle) < Math.PI / 2) {
|
if (Math.abs(interpolationParameters.firstPhaseAngle) < Math.PI / 2) {
|
||||||
angleOne = Math.acos(Math.tan(firstPhaseAngle) * firstDistanceAlongDirection / firstDistancePerpendicularToDirection);
|
cosAngleOne = Math.tan(firstPhaseAngle) * firstDistanceAlongDirection / firstDistancePerpendicularToDirection;
|
||||||
} else {
|
} else {
|
||||||
angleOne = Math.acos(Math.tan(Math.PI - firstPhaseAngle) * -firstDistanceAlongDirection / firstDistancePerpendicularToDirection);
|
cosAngleOne = Math.tan(Math.PI - firstPhaseAngle) * -firstDistanceAlongDirection / firstDistancePerpendicularToDirection;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Math.abs(interpolationParameters.secondPhaseAngle) < Math.PI / 2) {
|
if (Math.abs(interpolationParameters.secondPhaseAngle) < Math.PI / 2) {
|
||||||
angleTwo = Math.acos(Math.tan(secondPhaseAngle) * secondDistanceAlongDirection / secondDistancePerpendicularToDirection);
|
cosAngleTwo = Math.tan(secondPhaseAngle) * secondDistanceAlongDirection / secondDistancePerpendicularToDirection;
|
||||||
} else {
|
} else {
|
||||||
angleTwo = Math.acos(Math.tan(Math.PI - secondPhaseAngle) * -secondDistanceAlongDirection / secondDistancePerpendicularToDirection);
|
cosAngleTwo = Math.tan(Math.PI - secondPhaseAngle) * -secondDistanceAlongDirection / secondDistancePerpendicularToDirection;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [angleOne, angleTwo];
|
if (Math.abs(cosAngleOne) > 1) {
|
||||||
|
cosAngleOne = 1 * Math.sign(cosAngleOne);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Math.abs(cosAngleTwo) > 1) {
|
||||||
|
cosAngleTwo = 1 * Math.sign(cosAngleTwo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [Math.acos(cosAngleOne), Math.acos(cosAngleTwo)];
|
||||||
}
|
}
|
||||||
|
|
||||||
let bestAngles = [[0], [0]];
|
let bestAngles = [[0], [0]];
|
||||||
@ -1519,7 +1548,7 @@ export function findOrbitThroughInterpolation(ownCoordinates: OrbitalCoordinates
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
let normalVector = normalizeVector(vectorCrossProduct(targetPositionTwo, targetPositionOne));
|
let normalVector = normalizeVector(vectorCrossProduct(targetPositionOne, targetPositionTwo));
|
||||||
|
|
||||||
// Rotate the position vector about this normal vector to get the direction of the periapsis
|
// Rotate the position vector about this normal vector to get the direction of the periapsis
|
||||||
let ux = normalVector[0][0];
|
let ux = normalVector[0][0];
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user