Some bug fixes

This commit is contained in:
Martin Asprusten 2026-04-06 13:14:11 +02:00
parent 9d435fb255
commit b176a4a412

View File

@ -192,13 +192,8 @@ export class LambertSolutions {
transferGoalTrueAnomaly -= 2 * Math.PI;
}
if (transferStartTrueAnomaly < 2 * Math.PI && transferGoalTrueAnomaly > 2 * Math.PI) {
transferStartTrueAnomaly -= 2 * Math.PI;
transferGoalTrueAnomaly -= 2 * Math.PI;
}
let closestPoint;
if (transferStartTrueAnomaly < 0 && transferGoalTrueAnomaly >= 0) {
if ((transferStartTrueAnomaly < 0 && transferGoalTrueAnomaly >= 0) || (transferStartTrueAnomaly < 2 * Math.PI && transferGoalTrueAnomaly >= 2 * Math.PI)) {
closestPoint = semiLatusRectum / (1 + eccentricity);
} else {
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);
}
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 variableTwo = initialGuessVaribaleTwo;
let bestValue = functionToMinimize(variableOne, variableTwo);
@ -649,6 +644,18 @@ export function perform2dGradientDescent(functionToMinimize: ((variableOne: numb
break;
}
if (variableOneBounds) {
if (variableOneUpdate < variableOneBounds[0] || variableOneUpdate > variableOneBounds[1]) {
break;
}
}
if (variableTwoBounds) {
if (variableTwoUpdate < variableTwoBounds[0] || variableTwoUpdate > variableTwoBounds[1]) {
break;
}
}
variableOne = variableOneUpdate;
variableTwo = variableTwoUpdate;
bestValue = bestValueImprovement;
@ -992,17 +999,26 @@ export function findCheapestIntercept(startingSituation: OrbitalCoordinates, tar
}
let extraStartOrbits = Math.floor(startOrbitMeanAnomaly / (2 * Math.PI));
let extraEndOrbits = Math.floor(endOrbitMeanAnomaly / (2 * Math.PI));
let startTrueAnomaly: number = 0;
let endTrueAnomaly: number = 0;
startOrbitMeanAnomaly = startOrbitMeanAnomaly % (2 * Math.PI);
endOrbitMeanAnomaly = endOrbitMeanAnomaly % (2 * Math.PI);
["start", "end"].forEach(orbit => {
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);
let [__, endTrueAnomaly] = getEccentricAndTrueAnomalyFromMeanAnomaly(endOrbitMeanAnomaly, targetSituation.orbit.eccentricity);
startTrueAnomaly += extraStartOrbits * 2 * Math.PI;
endTrueAnomaly += extraEndOrbits * 2 * Math.PI;
if (orbit == "start") {
startTrueAnomaly = trueAnomaly;
} else if (orbit == "end") {
endTrueAnomaly = trueAnomaly;
}
});
let targetTransferTime = endTime - startTime;
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;
}
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;
}
@ -1066,7 +1087,7 @@ export function findCheapestIntercept(startingSituation: OrbitalCoordinates, tar
return;
}
let result = perform2dGradientDescent(interceptFunction, foundStartTime, foundEndTime, 0, 30);
let result = perform2dGradientDescent(interceptFunction, foundStartTime, foundEndTime, 0, 30, [0, 1e99]);
if (result) {
let foundTransfer = getTransfer(result[0], result[1], backwards);
if (foundTransfer) {
@ -1463,22 +1484,30 @@ export function findOrbitThroughInterpolation(ownCoordinates: OrbitalCoordinates
}
const getAnglesFromPhaseAngles = (firstPhaseAngle: number, secondPhaseAngle: number) => {
let angleOne;
let angleTwo;
let cosAngleOne;
let cosAngleTwo;
if (Math.abs(interpolationParameters.firstPhaseAngle) < Math.PI / 2) {
angleOne = Math.acos(Math.tan(firstPhaseAngle) * firstDistanceAlongDirection / firstDistancePerpendicularToDirection);
cosAngleOne = Math.tan(firstPhaseAngle) * firstDistanceAlongDirection / firstDistancePerpendicularToDirection;
} 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) {
angleTwo = Math.acos(Math.tan(secondPhaseAngle) * secondDistanceAlongDirection / secondDistancePerpendicularToDirection);
cosAngleTwo = Math.tan(secondPhaseAngle) * secondDistanceAlongDirection / secondDistancePerpendicularToDirection;
} 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]];
@ -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
let ux = normalVector[0][0];