Commit 92d0a6b2 authored by Bryan Cazabonne's avatar Bryan Cazabonne

Merge branch 'develop' into tropo

parents f1aacd44 df70fbfc
' Copyright 2002-2018 CS Systèmes d'Information
' Licensed to CS Systèmes d'Information (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.
@startuml
skinparam svek true
skinparam ClassBackgroundColor #F3EFEB/CCC9C5
skinparam ClassArrowColor #691616
skinparam ClassBorderColor #691616
skinparam NoteBackgroundColor #F3EFEB
skinparam NoteBorderColor #691616
skinparam NoteFontColor #691616
skinparam ClassFontSize 11
skinparam PackageFontSize 12
package org.hipparchus #ECEBD8 {
interface RandomVectorGenerator
}
package org.orekit #ECEBD8 {
package propagation.events #DDEBD8 {
interface EventsDetector
note top
ground visibility,
ground at night,
sunlit satellite,
inter sat direct view,
boolean combination...
end note
}
package estimation.measurements #DDEBD8 {
package generation #CEEBD8 {
interface "MeasurementBuilder<T>" as MeasurementBuilder_T_ {
+addModifier(estimationModifier)
+T build(spacecraftStates)
}
class "...MeasurementBuilder" as XXXMeasurementBuilder
note right
one for each
measurement type
end note
class Generator {
+int addPropagator(Propagator)
+Propagator getPropagator(index)
+addScheduler(Scheduler)
+SortedSet<ObservedMeasurements> generate(startDate, endDate)
}
enum SignSemantic {
+FEASIBLE_MEASUREMENT_WHEN_POSITIVE
+FEASIBLE_MEASUREMENT_WHEN_NEGATIVE
}
class "EventBasedScheduler<T>" as EventBasedScheduler_T_
class "ContinuousScheduler<T>" as ContinuousScheduler_T_
interface "Scheduler<T>" as Scheduler_T_ {
+SortedSet<T> generate(interpolators)
}
XXXMeasurementBuilder ..|> MeasurementBuilder_T_
MeasurementBuilder_T_ "1" <--* Scheduler_T_
XXXMeasurementBuilder -up-> RandomVectorGenerator
SignSemantic "1" <--* EventBasedScheduler_T_
Scheduler_T_ <|.left. EventBasedScheduler_T_
ContinuousScheduler_T_ .right.|> Scheduler_T_
Scheduler_T_ "*" <--* Generator
EventBasedScheduler_T_ *-right-> "1" EventsDetector
}
interface "EstimationModifier<T>" as EstimationModifier_T_
interface "ObservedMeasurement<T>" as ObservedMeasurement_T_
class "...Measurement" as XXXMeasurement
note bottom
this box represents any
measurement type
(range, range-rate, ...)
end note
EstimationModifier_T_ "*" <-left-* ObservedMeasurement_T_
ObservedMeasurement_T_ <|.. XXXMeasurement
XXXMeasurementBuilder --> XXXMeasurement
EstimationModifier_T_ "*" <--* XXXMeasurementBuilder
}
package propagation #DDEBD8 {
interface Propagator
class PropagatorsParallelizer {
propagate()
}
Generator --> PropagatorsParallelizer
Generator *--> "*" Propagator
Propagator <-left- PropagatorsParallelizer
}
package time #DDEBD8 {
class FixedStepSelector
class BurstSelector
interface DatesSelector {
+selectDates(interval)
}
FixedStepSelector --|> DatesSelector
BurstSelector --|> DatesSelector
Scheduler_T_ *--> "1" DatesSelector
}
}
package mission.specific #C4D2C5 {
class "CustomScheduler<T>" as CustomScheduler_T_ #D5E0D5/E2EBE2
Scheduler_T_ <|.up. CustomScheduler_T_
}
@enduml
......@@ -84,12 +84,15 @@ class JPLCelestialBody implements CelestialBody {
* @param iauPole IAU pole implementation
* @param definingFrameAlignedWithICRF frame in which celestial body coordinates are defined,
* this frame <strong>must</strong> be aligned with ICRF
* @param inertialFrameName name to use for inertial frame (if null a default name will be built)
* @param bodyOrientedFrameName name to use for body-oriented frame (if null a default name will be built)
*/
JPLCelestialBody(final String name, final String supportedNames,
final JPLEphemeridesLoader.EphemerisType generateType,
final JPLEphemeridesLoader.RawPVProvider rawPVProvider,
final double gm, final double scale,
final IAUPole iauPole, final Frame definingFrameAlignedWithICRF) {
final IAUPole iauPole, final Frame definingFrameAlignedWithICRF,
final String inertialFrameName, final String bodyOrientedFrameName) {
this.name = name;
this.gm = gm;
this.scale = scale;
......@@ -97,8 +100,8 @@ class JPLCelestialBody implements CelestialBody {
this.generateType = generateType;
this.rawPVProvider = rawPVProvider;
this.iauPole = iauPole;
this.inertialFrame = new InertiallyOriented(definingFrameAlignedWithICRF);
this.bodyFrame = new BodyOriented();
this.inertialFrame = new InertiallyOriented(definingFrameAlignedWithICRF, inertialFrameName);
this.bodyFrame = new BodyOriented(bodyOrientedFrameName);
}
/** {@inheritDoc} */
......@@ -179,8 +182,9 @@ class JPLCelestialBody implements CelestialBody {
/** Simple constructor.
* @param definingFrame frame in which celestial body coordinates are defined
* @param frameName name to use (if null a default name will be built)
*/
InertiallyOriented(final Frame definingFrame) {
InertiallyOriented(final Frame definingFrame, final String frameName) {
super(definingFrame, new TransformProvider() {
/** Serializable UID. */
......@@ -245,7 +249,7 @@ class JPLCelestialBody implements CelestialBody {
}
}, name + INERTIAL_FRAME_SUFFIX, true);
}, frameName == null ? name + INERTIAL_FRAME_SUFFIX : frameName, true);
}
/** Replace the instance with a data transfer object for serialization.
......@@ -271,8 +275,9 @@ class JPLCelestialBody implements CelestialBody {
private static final String BODY_FRAME_SUFFIX = "/rotating";
/** Simple constructor.
* @param frameName name to use (if null a default name will be built)
*/
BodyOriented() {
BodyOriented(final String frameName) {
super(inertialFrame, new TransformProvider() {
/** Serializable UID. */
......@@ -299,7 +304,7 @@ class JPLCelestialBody implements CelestialBody {
new FieldVector3D<>(w1.subtract(w0).divide(dt), Vector3D.PLUS_K));
}
}, name + BODY_FRAME_SUFFIX, false);
}, frameName == null ? name + BODY_FRAME_SUFFIX : frameName, false);
}
/** Replace the instance with a data transfer object for serialization.
......
......@@ -39,6 +39,7 @@ import org.orekit.errors.OrekitMessages;
import org.orekit.errors.TimeStampedCacheException;
import org.orekit.frames.Frame;
import org.orekit.frames.FramesFactory;
import org.orekit.frames.Predefined;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.DateComponents;
import org.orekit.time.FieldAbsoluteDate;
......@@ -279,6 +280,8 @@ public class JPLEphemeridesLoader implements CelestialBodyLoader {
final double scale;
final Frame definingFrameAlignedWithICRF;
final RawPVProvider rawPVProvider;
String inertialFrameName = null;
String bodyOrientedFrameName = null;
switch (generateType) {
case SOLAR_SYSTEM_BARYCENTER : {
scale = -1.0;
......@@ -288,6 +291,8 @@ public class JPLEphemeridesLoader implements CelestialBodyLoader {
parentLoader.loadCelestialBody(CelestialBodyFactory.EARTH_MOON);
definingFrameAlignedWithICRF = parentBody.getInertiallyOrientedFrame();
rawPVProvider = new EphemerisRawPVProvider();
inertialFrameName = Predefined.ICRF.getName();
bodyOrientedFrameName = null;
break;
}
case EARTH_MOON :
......@@ -318,7 +323,8 @@ public class JPLEphemeridesLoader implements CelestialBodyLoader {
// build the celestial body
return new JPLCelestialBody(name, supportedNames, generateType, rawPVProvider,
gm, scale, iauPole, definingFrameAlignedWithICRF);
gm, scale, iauPole, definingFrameAlignedWithICRF,
inertialFrameName, bodyOrientedFrameName);
}
......
......@@ -139,17 +139,28 @@ public class OneAxisEllipsoid extends Ellipsoid implements BodyShape {
return bodyFrame;
}
/** {@inheritDoc} */
public GeodeticPoint getIntersectionPoint(final Line line, final Vector3D close,
final Frame frame, final AbsoluteDate date) {
/** Get the intersection point of a line with the surface of the body.
* <p>A line may have several intersection points with a closed
* surface (we consider the one point case as a degenerated two
* points case). The close parameter is used to select which of
* these points should be returned. The selected point is the one
* that is closest to the close point.</p>
* @param line test line (may intersect the body or not)
* @param close point used for intersections selection
* @param frame frame in which line is expressed
* @param date date of the line in given frame
* @return intersection point at altitude zero or null if the line does
* not intersect the surface
* @since 9.3
*/
public Vector3D getCartesianIntersectionPoint(final Line line, final Vector3D close,
final Frame frame, final AbsoluteDate date) {
// transform line and close to body frame
final Transform frameToBodyFrame = frame.getTransformTo(bodyFrame, date);
final Line lineInBodyFrame = frameToBodyFrame.transformLine(line);
final Vector3D closeInBodyFrame = frameToBodyFrame.transformPosition(close);
final double closeAbscissa = lineInBodyFrame.getAbscissa(closeInBodyFrame);
// compute some miscellaneous variables outside of the loop
// compute some miscellaneous variables
final Vector3D point = lineInBodyFrame.getOrigin();
final double x = point.getX();
final double y = point.getY();
......@@ -178,9 +189,22 @@ public class OneAxisEllipsoid extends Ellipsoid implements BodyShape {
final double k2 = c / (a * k1);
// select the right point
final Vector3D closeInBodyFrame = frameToBodyFrame.transformPosition(close);
final double closeAbscissa = lineInBodyFrame.getAbscissa(closeInBodyFrame);
final double k =
(FastMath.abs(k1 - closeAbscissa) < FastMath.abs(k2 - closeAbscissa)) ? k1 : k2;
final Vector3D intersection = lineInBodyFrame.pointAt(k);
return lineInBodyFrame.pointAt(k);
}
/** {@inheritDoc} */
public GeodeticPoint getIntersectionPoint(final Line line, final Vector3D close,
final Frame frame, final AbsoluteDate date) {
final Vector3D intersection = getCartesianIntersectionPoint(line, close, frame, date);
if (intersection == null) {
return null;
}
final double ix = intersection.getX();
final double iy = intersection.getY();
final double iz = intersection.getZ();
......@@ -192,18 +216,16 @@ public class OneAxisEllipsoid extends Ellipsoid implements BodyShape {
}
/** {@inheritDoc} */
public <T extends RealFieldElement<T>> FieldGeodeticPoint<T> getIntersectionPoint(final FieldLine<T> line,
final FieldVector3D<T> close,
final Frame frame,
final FieldAbsoluteDate<T> date) {
public <T extends RealFieldElement<T>> FieldVector3D<T> getCartesianIntersectionPoint(final FieldLine<T> line,
final FieldVector3D<T> close,
final Frame frame,
final FieldAbsoluteDate<T> date) {
// transform line and close to body frame
final FieldTransform<T> frameToBodyFrame = frame.getTransformTo(bodyFrame, date);
final FieldLine<T> lineInBodyFrame = frameToBodyFrame.transformLine(line);
final FieldVector3D<T> closeInBodyFrame = frameToBodyFrame.transformPosition(close);
final T closeAbscissa = lineInBodyFrame.getAbscissa(closeInBodyFrame);
// compute some miscellaneous variables outside of the loop
// compute some miscellaneous variables
final FieldVector3D<T> point = lineInBodyFrame.getOrigin();
final T x = point.getX();
final T y = point.getY();
......@@ -232,9 +254,23 @@ public class OneAxisEllipsoid extends Ellipsoid implements BodyShape {
final T k2 = c.divide(a.multiply(k1));
// select the right point
final FieldVector3D<T> closeInBodyFrame = frameToBodyFrame.transformPosition(close);
final T closeAbscissa = lineInBodyFrame.getAbscissa(closeInBodyFrame);
final T k = (FastMath.abs(k1.getReal() - closeAbscissa.getReal()) < FastMath.abs(k2.getReal() - closeAbscissa.getReal())) ?
k1 : k2;
final FieldVector3D<T> intersection = lineInBodyFrame.pointAt(k);
return lineInBodyFrame.pointAt(k);
}
/** {@inheritDoc} */
public <T extends RealFieldElement<T>> FieldGeodeticPoint<T> getIntersectionPoint(final FieldLine<T> line,
final FieldVector3D<T> close,
final Frame frame,
final FieldAbsoluteDate<T> date) {
final FieldVector3D<T> intersection = getCartesianIntersectionPoint(line, close, frame, date);
if (intersection == null) {
return null;
}
final T ix = intersection.getX();
final T iy = intersection.getY();
final T iz = intersection.getZ();
......
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
/* Copyright 2002-2018 CS Systèmes d'Information
* Licensed to CS Systèmes d'Information (CS) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
......
......@@ -19,9 +19,9 @@ package org.orekit.estimation.measurements;
import org.orekit.time.TimeStamped;
/** Base interface for comparing measurements regardless of thei type.
/** Base interface for comparing measurements regardless of their type.
* @author Luc Maisonobe
* @since 9.2
* @since 9.2
*/
public interface ComparableMeasurement extends TimeStamped, Comparable<ComparableMeasurement> {
......
/* Copyright 2002-2018 CS Systèmes d'Information
* Licensed to CS Systèmes d'Information (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.estimation.measurements.generation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.hipparchus.random.CorrelatedRandomVectorGenerator;
import org.orekit.estimation.measurements.EstimatedMeasurement;
import org.orekit.estimation.measurements.EstimationModifier;
import org.orekit.estimation.measurements.ObservedMeasurement;
import org.orekit.time.AbsoluteDate;
/** Base class for {@link MeasurementBuilder measurements builders}.
* @param <T> the type of the measurement
* @author Luc Maisonobe
* @since 9.3
*/
public abstract class AbstractMeasurementBuilder<T extends ObservedMeasurement<T>> implements MeasurementBuilder<T> {
/** Noise source (may be null). */
private final CorrelatedRandomVectorGenerator noiseSource;
/** Modifiers that apply to the measurement.*/
private final List<EstimationModifier<T>> modifiers;
/** Theoretical standard deviation. */
private final double[] sigma;
/** Base weight. */
private final double[] baseWeight;
/** Indices of the propagators related to this measurement. */
private final int[] propagatorsIndices;
/** Start of the measurements time span. */
private AbsoluteDate spanStart;
/** End of the measurements time span. */
private AbsoluteDate spanEnd;
/** Simple constructor.
* @param noiseSource noise source, may be null for generating perfect measurements
* @param sigma theoretical standard deviation
* @param baseWeight base weight
* @param propagatorsIndices indices of the propagators related to this measurement
*/
protected AbstractMeasurementBuilder(final CorrelatedRandomVectorGenerator noiseSource,
final double sigma, final double baseWeight,
final int... propagatorsIndices) {
this(noiseSource,
new double[] {
sigma
}, new double[] {
baseWeight
}, propagatorsIndices);
}
/** Simple constructor.
* @param noiseSource noise source, may be null for generating perfect measurements
* @param sigma theoretical standard deviation
* @param baseWeight base weight
* @param propagatorsIndices indices of the propagators related to this measurement
*/
protected AbstractMeasurementBuilder(final CorrelatedRandomVectorGenerator noiseSource,
final double[] sigma, final double[] baseWeight,
final int... propagatorsIndices) {
this.noiseSource = noiseSource;
this.modifiers = new ArrayList<>();
this.sigma = sigma.clone();
this.baseWeight = baseWeight.clone();
this.propagatorsIndices = propagatorsIndices.clone();
}
/** {@inheritDoc}
* <p>
* This implementation stores the time span of the measurements generation.
* </p>
*/
@Override
public void init(final AbsoluteDate start, final AbsoluteDate end) {
spanStart = start;
spanEnd = end;
}
/** {@inheritDoc} */
@Override
public void addModifier(final EstimationModifier<T> modifier) {
modifiers.add(modifier);
}
/** {@inheritDoc} */
@Override
public List<EstimationModifier<T>> getModifiers() {
return Collections.unmodifiableList(modifiers);
}
/** Get the start of the measurements time span.
* @return start of the measurements time span
*/
protected AbsoluteDate getStart() {
return spanStart;
}
/** Get the end of the measurements time span.
* @return end of the measurements time span
*/
protected AbsoluteDate getEnd() {
return spanEnd;
}
/** Generate a noise vector.
* @return noise vector (null if we generate perfect measurements)
*/
protected double[] getNoise() {
return noiseSource == null ? null : noiseSource.nextVector();
}
/** Get the theoretical standard deviation.
* <p>
* The theoretical standard deviation is a theoretical value
* used for normalizing the residuals. It acts as a weighting
* factor to mix appropriately measurements with different units
* and different accuracy. The value has the same dimension as
* the measurement itself (i.e. when a residual is divided by
* this value, it becomes dimensionless).
* </p>
* @return expected standard deviation
* @see #getBaseWeight()
*/
protected double[] getTheoreticalStandardDeviation() {
return sigma.clone();
}
/** Get the base weight associated with the measurement
* <p>
* The base weight is used on residuals already normalized thanks to
* {@link #getTheoreticalStandardDeviation()} to increase or
* decrease relative effect of some measurements with respect to
* other measurements. It is a dimensionless value, typically between
* 0 and 1 (but it can really have any non-negative value).
* </p>
* @return base weight
* @see #getTheoreticalStandardDeviation()
* @see EstimatedMeasurement#getCurrentWeight()
*/
protected double[] getBaseWeight() {
return baseWeight.clone();
}
/** Get the indices of the {@link org.orekit.propagation.Propagator propagators}
* related to this measurement.
* <p>
* The propagators are indexed starting from 0 and ordered according to
* the order of the {@link org.orekit.propagation.conversion.PropagatorBuilder
* propagators builders} in the orbit determination engine used.
* </p>
* @return indices of the {@link org.orekit.propagation.Propagator propagators}
* related to this measurement
* @since 9.0
*/
protected int[] getPropagatorsIndices() {
return propagatorsIndices.clone();
}
}
/* Copyright 2002-2018 CS Systèmes d'Information
* Licensed to CS Systèmes d'Information (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.estimation.measurements.generation;
import org.orekit.estimation.measurements.ObservedMeasurement;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.DatesSelector;
/** Base implementation of {@link Scheduler} managing {@link DatesSelector dates selection}.
* @param <T> the type of the measurement
* @author Luc Maisonobe
* @since 9.3
*/
public abstract class AbstractScheduler<T extends ObservedMeasurement<T>> implements Scheduler<T> {
/** Builder for individual measurements. */
private final MeasurementBuilder<T> builder;
/** Selector for dates. */
private final DatesSelector selector;
/** Simple constructor.
* @param builder builder for individual measurements
* @param selector selector for dates
*/
protected AbstractScheduler(final MeasurementBuilder<T> builder,
final DatesSelector selector) {
this.builder = builder;
this.selector = selector;
}
/** {@inheritDoc}
* <p>
* This implementation initialize the measurement builder.
* </p>
*/
@Override
public void init(final AbsoluteDate start, final AbsoluteDate end) {
builder.init(start, end);
}
/** Get the measurements builder.
* @return measurements builder
*/
public MeasurementBuilder<T> getBuilder() {
return builder;
}
/** Get the dates selector.
* @return dates selector
*/
public DatesSelector getSelector() {
return selector;
}
}
/* Copyright 2002-2018 CS Systèmes d'Information
* Licensed to CS Systèmes d'Information (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.estimation.measurements.generation;
import org.hipparchus.random.CorrelatedRandomVectorGenerator;
import org.orekit.estimation.measurements.AngularAzEl;