org.orekit.utils.OccultationEngine Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of orekit Show documentation
Show all versions of orekit Show documentation
OREKIT (ORbits Extrapolation KIT) is a low level space dynamics library.
It provides basic elements (orbits, dates, attitude, frames ...) and
various algorithms to handle them (conversions, analytical and numerical
propagation, pointing ...).
/* Copyright 2002-2024 Luc Maisonobe
* Licensed to CS GROUP (CS) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* CS licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.orekit.utils;
import org.hipparchus.CalculusFieldElement;
import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.hipparchus.util.FastMath;
import org.orekit.bodies.OneAxisEllipsoid;
import org.orekit.propagation.FieldSpacecraftState;
import org.orekit.propagation.SpacecraftState;
/** Computation engine for occultation events.
* @author Luc Maisonobe
* @since 12.0
*/
public class OccultationEngine {
/** Occulting body. */
private final OneAxisEllipsoid occulting;
/** Occulted body. */
private final ExtendedPVCoordinatesProvider occulted;
/** Occulted body radius (m). */
private final double occultedRadius;
/** Build a new occultation engine.
* @param occulted the body to be occulted
* @param occultedRadius the radius of the body to be occulted (m)
* @param occulting the occulting body
*/
public OccultationEngine(final ExtendedPVCoordinatesProvider occulted, final double occultedRadius,
final OneAxisEllipsoid occulting) {
this.occulted = occulted;
this.occultedRadius = FastMath.abs(occultedRadius);
this.occulting = occulting;
}
/** Getter for the occulting body.
* @return the occulting body
*/
public OneAxisEllipsoid getOcculting() {
return occulting;
}
/** Getter for the occulted body.
* @return the occulted body
*/
public ExtendedPVCoordinatesProvider getOcculted() {
return occulted;
}
/** Getter for the occultedRadius.
* @return the occultedRadius
*/
public double getOccultedRadius() {
return occultedRadius;
}
/** Compute the occultation angles as seen from a spacecraft.
* @param state the current state information: date, kinematics, attitude
* @return occultation angles
*/
public OccultationAngles angles(final SpacecraftState state) {
final Vector3D psat = state.getPosition(occulting.getBodyFrame());
final Vector3D pted = occulted.getPosition(state.getDate(), occulting.getBodyFrame());
final Vector3D plimb = occulting.pointOnLimb(psat, pted);
final Vector3D ps = psat.subtract(pted);
final Vector3D pi = psat.subtract(plimb);
final double angle = Vector3D.angle(ps, psat);
final double rs = FastMath.asin(occultedRadius / ps.getNorm());
final double ro = Vector3D.angle(pi, psat);
if (Double.isNaN(rs)) {
// we are inside the occulted body…
// set up dummy values consistent with full lighting (assuming occulted is the Sun)
return new OccultationAngles(FastMath.PI, 0.0, 0.0);
} else {
// regular case, we can compute limit angles as seen from spacecraft
return new OccultationAngles(angle, ro, rs);
}
}
/** Compute the occultation angles as seen from a spacecraft.
* @param state the current state information: date, kinematics, attitude
* @param the type of the field elements
* @return occultation angles
*/
public > FieldOccultationAngles angles(final FieldSpacecraftState state) {
final FieldVector3D psat = state.getPosition(occulting.getBodyFrame());
final FieldVector3D pted = occulted.getPosition(state.getDate(), occulting.getBodyFrame());
final FieldVector3D plimb = occulting.pointOnLimb(psat, pted);
final FieldVector3D ps = psat.subtract(pted);
final FieldVector3D pi = psat.subtract(plimb);
final T angle = FieldVector3D.angle(ps, psat);
final T rs = FastMath.asin(ps.getNorm().reciprocal().multiply(occultedRadius));
final T ro = FieldVector3D.angle(pi, psat);
if (rs.isNaN()) {
// we are inside the occulted body…
// set up dummy values consistent with full lighting (assuming occulted is the Sun)
final T zero = rs.getField().getZero();
return new FieldOccultationAngles<>(zero.newInstance(FastMath.PI), zero, zero);
} else {
// regular case, we can compute limit angles as seen from spacecraft
return new FieldOccultationAngles<>(angle, ro, rs);
}
}
/** Container for occultation angles.
* @since 12.0
*/
public static class OccultationAngles {
/** Apparent separation between occulting and occulted directions. */
private final double separation;
/** Limb radius in occulting/occulted plane. */
private final double limbRadius;
/** Apparent radius of occulted body. */
private final double occultedApparentRadius;
/** Simple constructor.
* @param separation apparent separation between occulting and occulted directions (rad)
* @param limbRadius limb radius in occulting/occulted plane (rad)
* @param occultedApparentRadius apparent radius of occulted body (rad)
*/
OccultationAngles(final double separation, final double limbRadius, final double occultedApparentRadius) {
this.separation = separation;
this.limbRadius = limbRadius;
this.occultedApparentRadius = occultedApparentRadius;
}
/** Get apparent separation between occulting and occulted directions.
* @return apparent separation between occulting and occulted directions (rad)
*/
public double getSeparation() {
return separation;
}
/** Get limb radius in occulting/occulted plane.
* @return limb radius in occulting/occulted plane (rad)
*/
public double getLimbRadius() {
return limbRadius;
}
/** Get apparent radius of occulted body.
* @return apparent radius of occulted body (rad)
*/
public double getOccultedApparentRadius() {
return occultedApparentRadius;
}
}
/** Container for occultation angles.
* @param the type of the field elements
* @since 12.0
*/
public static class FieldOccultationAngles> {
/** Apparent separation between occulting and occulted directions. */
private final T separation;
/** Limb radius in occulting/occulted plane. */
private final T limbRadius;
/** Apparent radius of occulted body. */
private final T occultedApparentRadius;
/** Simple constructor.
* @param separation apparent separation between occulting and occulted directions (rad)
* @param limbRadius limb radius in occulting/occulted plane (rad)
* @param occultedApparentRadius apparent radius of occulted body (rad)
*/
FieldOccultationAngles(final T separation, final T limbRadius, final T occultedApparentRadius) {
this.separation = separation;
this.limbRadius = limbRadius;
this.occultedApparentRadius = occultedApparentRadius;
}
/** Get apparent separation between occulting and occulted directions.
* @return apparent separation between occulting and occulted directions (rad)
*/
public T getSeparation() {
return separation;
}
/** Get limb radius in occulting/occulted plane.
* @return limb radius in occulting/occulted plane (rad)
*/
public T getLimbRadius() {
return limbRadius;
}
/** Get apparent radius of occulted body.
* @return apparent radius of occulted body (rad)
*/
public T getOccultedApparentRadius() {
return occultedApparentRadius;
}
}
}