ootk
Version:
Orbital Object Toolkit including Multiple Propagators, Initial Orbit Determination, and Maneuver Calculations.
76 lines • 3.27 kB
JavaScript
/**
* @author @thkruz Theodore Kruczek
* @license AGPL-3.0-or-later
* @copyright (c) 2025 Kruczek Labs LLC
*
* Orbital Object ToolKit is free software: you can redistribute it and/or modify it under the
* terms of the GNU Affero General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* Orbital Object ToolKit is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with
* Orbital Object ToolKit. If not, see <http://www.gnu.org/licenses/>.
*/
import { DEG2RAD, Earth, halfPi, J2000, } from '../main.js';
import { ForceModel } from './../force/ForceModel.js';
import { RungeKutta89Propagator } from './../propagator/RungeKutta89Propagator.js';
/**
* Gibbs 3-position inital orbit determination.
*/
export class GibbsIOD {
mu;
constructor(mu = Earth.mu) {
this.mu = mu;
// Nothing to do here.
}
/** Abort solve if position plane exceeds this value. */
static coplanarThreshold_ = (5.0 * DEG2RAD);
/**
* Attempt to create a state estimate from three inertial position vectors.
*
* Throws an error if the positions are not coplanar.
* @param r1 Position vector 1.
* @param r2 Position vector 2.
* @param r3 Position vector 3.
* @param t2 Time of position 2.
* @param t3 Time of position 3.
* @returns State estimate at time t2.
*/
solve(r1, r2, r3, t2, t3) {
const num = r1.normalize().dot(r2.normalize().cross(r3.normalize()));
const alpha = halfPi - Math.acos(num);
if (Math.abs(alpha) > GibbsIOD.coplanarThreshold_) {
throw new Error('Orbits are not coplanar.');
}
const r1m = r1.magnitude();
const r2m = r2.magnitude();
const r3m = r3.magnitude();
const d = r1.cross(r2).add(r2.cross(r3).add(r3.cross(r1)));
const n = r2.cross(r3).scale(r1m).add(r3.cross(r1).scale(r2m)).add(r1.cross(r2).scale(r3m));
const b = d.cross(r2);
const s = r1.scale(r2m - r3m).add(r2.scale(r3m - r1m).add(r3.scale(r1m - r2m)));
const nm = n.magnitude();
const dm = d.magnitude();
const vm = Math.sqrt(this.mu / (nm * dm));
const vlEci = b.scale((vm / r2m)).add(s.scale(vm));
const pv = new J2000(t2, r2, vlEci);
const forceModel = new ForceModel().setGravity(this.mu);
const orbit = new RungeKutta89Propagator(pv, forceModel);
const pv2 = new J2000(t2, r2, vlEci.negate());
const orbit2 = new RungeKutta89Propagator(pv2, forceModel);
const estP3 = orbit.propagate(t3).position;
const dist = estP3.subtract(r3).magnitude();
const estP3b = orbit2.propagate(t3).position;
const dist2 = estP3b.subtract(r3).magnitude();
if (dist <= dist2) {
orbit.reset();
return orbit.propagate(t2);
}
orbit2.reset();
return orbit2.propagate(t2);
}
}
//# sourceMappingURL=GibbsIOD.js.map