CommonPhysicalProperties.java
/* Copyright 2002-2026 CS GROUP
* 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.files.ccsds.ndm;
import java.util.Arrays;
import java.util.Optional;
import org.hipparchus.complex.Quaternion;
import org.orekit.annotation.Nullable;
import org.orekit.files.ccsds.definitions.CcsdsFrameMapper;
import org.orekit.files.ccsds.definitions.FrameFacade;
import org.orekit.files.ccsds.ndm.cdm.AdditionalParameters;
import org.orekit.files.ccsds.ndm.odm.ocm.OrbitPhysicalProperties;
import org.orekit.files.ccsds.section.CommentsContainer;
import org.orekit.frames.Frame;
import org.orekit.time.AbsoluteDate;
/** Container for common physical properties for both {@link OrbitPhysicalProperties} and {@link AdditionalParameters}.
* <p>
* Beware that the Orekit getters and setters all rely on SI units. The parsers
* and writers take care of converting these SI units into CCSDS mandatory units.
* The {@link org.orekit.utils.units.Unit Unit} class provides useful
* {@link org.orekit.utils.units.Unit#fromSI(double) fromSi} and
* {@link org.orekit.utils.units.Unit#toSI(double) toSI} methods in case the callers
* already use CCSDS units instead of the API SI units. The general-purpose
* {@link org.orekit.utils.units.Unit Unit} class (without an 's') and the
* CCSDS-specific {@link org.orekit.files.ccsds.definitions.Units Units} class
* (with an 's') also provide some predefined units. These predefined units and the
* {@link org.orekit.utils.units.Unit#fromSI(double) fromSi} and
* {@link org.orekit.utils.units.Unit#toSI(double) toSI} conversion methods are indeed
* what the parsers and writers use for the conversions.
* </p>
* @author Maxime Journot
* @since 11.3
*/
public class CommonPhysicalProperties extends CommentsContainer {
/** For creating a {@link Frame}. */
private final CcsdsFrameMapper frameMapper;
/** Optimally Enclosing Box parent reference frame. */
private FrameFacade oebParentFrame;
/** Optimally Enclosing Box parent reference frame epoch. */
@Nullable
private AbsoluteDate oebParentFrameEpoch;
/** Quaternion defining Optimally Enclosing Box. */
@Nullable
private double[] oebQ;
/** Maximum physical dimension of Optimally Enclosing Box. */
@Nullable
private Double oebMax;
/** Intermediate physical dimension of Optimally Enclosing Box. */
@Nullable
private Double oebIntermediate;
/** Minimum physical dimension of Optimally Enclosing Box. */
@Nullable
private Double oebMin;
/** Cross-sectional area of Optimally Enclosing Box when viewed along the maximum OEB direction. */
@Nullable
private Double oebAreaAlongMax;
/** Cross-sectional area of Optimally Enclosing Box when viewed along the intermediate OEB direction. */
@Nullable
private Double oebAreaAlongIntermediate;
/** Cross-sectional area of Optimally Enclosing Box when viewed along the minimum OEB direction. */
@Nullable
private Double oebAreaAlongMin;
/** Typical (50th percentile) radar cross-section. */
@Nullable
private Double rcs;
/** Minimum radar cross-section. */
@Nullable
private Double minRcs;
/** Maximum radar cross-section. */
@Nullable
private Double maxRcs;
/** Typical (50th percentile) visual magnitude. */
@Nullable
private Double vmAbsolute;
/** Minimum apparent visual magnitude. */
@Nullable
private Double vmApparentMin;
/** Typical (50th percentile) apparent visual magnitude. */
@Nullable
private Double vmApparent;
/** Maximum apparent visual magnitude. */
@Nullable
private Double vmApparentMax;
/** Typical (50th percentile) coefficient of reflectivity. */
@Nullable
private Double reflectance;
/**
* Simple constructor.
*
* @param epochT0 T0 epoch from file metadata
* @param frameMapper for creating a {@link Frame}.
* @since 13.1.5
*/
public CommonPhysicalProperties(final AbsoluteDate epochT0, final CcsdsFrameMapper frameMapper) {
// 502.0-B-3 (page 6-23) says the default is RSW_ROTATING, but also says,
// "This keyword shall be provided if OEB_Q1,2,3,4 are specified".
// Which means it must be specified in the file any time it would be used,
// which leaves the default without any effect.
this.frameMapper = frameMapper;
oebParentFrame = new FrameFacade(null, null, null, null, null);
// 502.0-B-3 (page 6-23) says the default is EPOCH_TZERO from the OCM metadata.
oebParentFrameEpoch = epochT0;
}
/** Get the Optimally Enclosing Box parent reference frame.
* @return Optimally Enclosing Box parent reference frame
*/
public FrameFacade getOebParentFrame() {
return oebParentFrame;
}
/** Set the Optimally Enclosing Box parent reference frame.
* @param oebParentFrame Optimally Enclosing Box parent reference frame
*/
public void setOebParentFrame(final FrameFacade oebParentFrame) {
refuseFurtherComments();
this.oebParentFrame = oebParentFrame;
}
/** Get the Optimally Enclosing Box parent reference frame epoch.
* @return Optimally Enclosing Box parent reference frame epoch
*/
public Optional<AbsoluteDate> getOebParentFrameEpoch() {
return Optional.ofNullable(oebParentFrameEpoch);
}
/** Set the Optimally Enclosing Box parent reference frame epoch.
* @param oebParentFrameEpoch Optimally Enclosing Box parent reference frame epoch
*/
public void setOebParentFrameEpoch(final AbsoluteDate oebParentFrameEpoch) {
refuseFurtherComments();
this.oebParentFrameEpoch = oebParentFrameEpoch;
}
/**
* Get the mapping between a CCSDS frame and a {@link Frame}.
*
* @return the frame mapper.
* @since 13.1.5
*/
public CcsdsFrameMapper getFrameMapper() {
return frameMapper;
}
/**
* Get the frame OEB parent frame. Note that only the orientation of the
* returned frame is significant, the position of the returned frame is
* irrelevant and should be ignored.
*
* @return Orekit frame for this covariance history.
* @see #getOebParentFrame()
* @see #getOebParentFrameEpoch()
* @see #getFrameMapper()
* @since 13.1.5
*/
public Frame getOebParent() {
return getFrameMapper().buildCcsdsFrame(oebParentFrame, oebParentFrameEpoch);
}
/** Get the quaternion defining Optimally Enclosing Box.
* @return quaternion defining Optimally Enclosing Box
*/
public Optional<Quaternion> getOebQ() {
if (oebQ == null) {
return Optional.empty();
}
return Optional.of(new Quaternion(oebQ[0], oebQ[1], oebQ[2], oebQ[3]));
}
/** set the component of quaternion defining Optimally Enclosing Box.
* @param i index of the component
* @param qI component of quaternion defining Optimally Enclosing Box
*/
public void setOebQ(final int i, final double qI) {
refuseFurtherComments();
if (oebQ == null) {
oebQ = new double[4];
Arrays.fill(oebQ, Double.NaN);
}
oebQ[i] = qI;
}
/** Get the maximum physical dimension of the OEB.
* @return maximum physical dimension of the OEB.
*/
public Optional<Double> getOebMax() {
return Optional.ofNullable(oebMax);
}
/** Set the maximum physical dimension of the OEB.
* @param oebMax maximum physical dimension of the OEB.
*/
public void setOebMax(final double oebMax) {
refuseFurtherComments();
this.oebMax = oebMax;
}
/** Get the intermediate physical dimension of the OEB.
* @return intermediate physical dimension of the OEB.
*/
public Optional<Double> getOebIntermediate() {
return Optional.ofNullable(oebIntermediate);
}
/** Set the intermediate physical dimension of the OEB.
* @param oebIntermediate intermediate physical dimension of the OEB.
*/
public void setOebIntermediate(final double oebIntermediate) {
refuseFurtherComments();
this.oebIntermediate = oebIntermediate;
}
/** Get the minimum physical dimension of the OEB.
* @return dimensions the minimum physical dimension of the OEB.
*/
public Optional<Double> getOebMin() {
return Optional.ofNullable(oebMin);
}
/** Set the minimum physical dimension of the OEB.
* @param oebMin the minimum physical dimension of the OEB.
*/
public void setOebMin(final double oebMin) {
refuseFurtherComments();
this.oebMin = oebMin;
}
/** Get the cross-sectional area of Optimally Enclosing Box when viewed along the maximum OEB direction.
* @return cross-sectional area of Optimally Enclosing Box when viewed along the maximum OEB direction.
*/
public Optional<Double> getOebAreaAlongMax() {
return Optional.ofNullable(oebAreaAlongMax);
}
/** Set the cross-sectional area of Optimally Enclosing Box when viewed along the maximum OEB direction.
* @param oebAreaAlongMax cross-sectional area of Optimally Enclosing Box when viewed along the maximum OEB direction.
*/
public void setOebAreaAlongMax(final double oebAreaAlongMax) {
refuseFurtherComments();
this.oebAreaAlongMax = oebAreaAlongMax;
}
/** Get the cross-sectional area of Optimally Enclosing Box when viewed along the intermediate OEB direction.
* @return cross-sectional area of Optimally Enclosing Box when viewed along the intermediate OEB direction.
*/
public Optional<Double> getOebAreaAlongIntermediate() {
return Optional.ofNullable(oebAreaAlongIntermediate);
}
/** Set the cross-sectional area of Optimally Enclosing Box when viewed along the intermediate OEB direction.
* @param oebAreaAlongIntermediate cross-sectional area of Optimally Enclosing Box when viewed along the intermediate OEB direction.
*/
public void setOebAreaAlongIntermediate(final double oebAreaAlongIntermediate) {
refuseFurtherComments();
this.oebAreaAlongIntermediate = oebAreaAlongIntermediate;
}
/** Get the cross-sectional area of Optimally Enclosing Box when viewed along the minimum OEB direction.
* @return cross-sectional area of Optimally Enclosing Box when viewed along the minimum OEB direction.
*/
public Optional<Double> getOebAreaAlongMin() {
return Optional.ofNullable(oebAreaAlongMin);
}
/** Set the cross-sectional area of Optimally Enclosing Box when viewed along the minimum OEB direction.
* @param oebAreaAlongMin cross-sectional area of Optimally Enclosing Box when viewed along the minimum OEB direction.
*/
public void setOebAreaAlongMin(final double oebAreaAlongMin) {
refuseFurtherComments();
this.oebAreaAlongMin = oebAreaAlongMin;
}
/** Get the typical (50th percentile) radar cross-section.
* @return typical (50th percentile) radar cross-section
*/
public Optional<Double> getRcs() {
return Optional.ofNullable(rcs);
}
/** Set the typical (50th percentile) radar cross-section.
* @param rcs typical (50th percentile) radar cross-section
*/
public void setRcs(final double rcs) {
refuseFurtherComments();
this.rcs = rcs;
}
/** Get the minimum radar cross-section.
* @return minimum radar cross-section
*/
public Optional<Double> getMinRcs() {
return Optional.ofNullable(minRcs);
}
/** Set the minimum radar cross-section.
* @param minRcs minimum radar cross-section
*/
public void setMinRcs(final double minRcs) {
refuseFurtherComments();
this.minRcs = minRcs;
}
/** Get the maximum radar cross-section.
* @return maximum radar cross-section
*/
public Optional<Double> getMaxRcs() {
return Optional.ofNullable(maxRcs);
}
/** Set the maximum radar cross-section.
* @param maxRcs maximum radar cross-section
*/
public void setMaxRcs(final double maxRcs) {
refuseFurtherComments();
this.maxRcs = maxRcs;
}
/** Get the typical (50th percentile) visual magnitude.
* @return typical (50th percentile) visual magnitude
*/
public Optional<Double> getVmAbsolute() {
return Optional.ofNullable(vmAbsolute);
}
/** Set the typical (50th percentile) visual magnitude.
* @param vmAbsolute typical (50th percentile) visual magnitude
*/
public void setVmAbsolute(final double vmAbsolute) {
refuseFurtherComments();
this.vmAbsolute = vmAbsolute;
}
/** Get the minimum apparent visual magnitude.
* @return minimum apparent visual magnitude
*/
public Optional<Double> getVmApparentMin() {
return Optional.ofNullable(vmApparentMin);
}
/** Set the minimum apparent visual magnitude.
* @param vmApparentMin minimum apparent visual magnitude
*/
public void setVmApparentMin(final double vmApparentMin) {
refuseFurtherComments();
this.vmApparentMin = vmApparentMin;
}
/** Get the typical (50th percentile) apparent visual magnitude.
* @return typical (50th percentile) apparent visual magnitude
*/
public Optional<Double> getVmApparent() {
return Optional.ofNullable(vmApparent);
}
/** Set the typical (50th percentile) apparent visual magnitude.
* @param vmApparent typical (50th percentile) apparent visual magnitude
*/
public void setVmApparent(final double vmApparent) {
refuseFurtherComments();
this.vmApparent = vmApparent;
}
/** Get the maximum apparent visual magnitude.
* @return maximum apparent visual magnitude
*/
public Optional<Double> getVmApparentMax() {
return Optional.ofNullable(vmApparentMax);
}
/** Set the maximum apparent visual magnitude.
* @param vmApparentMax maximum apparent visual magnitude
*/
public void setVmApparentMax(final double vmApparentMax) {
refuseFurtherComments();
this.vmApparentMax = vmApparentMax;
}
/** Get the typical (50th percentile) coefficient of reflectance.
* @return typical (50th percentile) coefficient of reflectance
*/
public Optional<Double> getReflectance() {
return Optional.ofNullable(reflectance);
}
/** Set the typical (50th percentile) coefficient of reflectance.
* @param reflectance typical (50th percentile) coefficient of reflectance
*/
public void setReflectance(final double reflectance) {
refuseFurtherComments();
this.reflectance = reflectance;
}
}