Commit 1384536e authored by Luc Maisonobe's avatar Luc Maisonobe

Merge branch 'issue-494' into develop

Conflicts:
	src/site/xdoc/changes.xml
parents 30043ab0 d9fcecbc
' 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
......@@ -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();
......
......@@ -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;
import org.orekit.estimation.measurements.EstimationModifier;
import org.orekit.estimation.measurements.GroundStation;
import org.orekit.propagation.SpacecraftState;
import org.orekit.time.AbsoluteDate;
import org.orekit.utils.ParameterDriver;
/** Builder for {@link AngularAzEl} measurements.
* @author Luc Maisonobe
* @since 9.3
*/
public class AngularAzElBuilder extends AbstractMeasurementBuilder<AngularAzEl> {
/** Ground station from which measurement is performed. */
private final GroundStation station;
/** Simple constructor.
* @param noiseSource noise source, may be null for generating perfect measurements
* @param station ground station from which measurement is performed
* @param sigma theoretical standard deviation
* @param baseWeight base weight
* @param propagatorIndex index of the propagator related to this measurement
*/
public AngularAzElBuilder(final CorrelatedRandomVectorGenerator noiseSource,
final GroundStation station,
final double[] sigma, final double[] baseWeight,
final int propagatorIndex) {
super(noiseSource, sigma, baseWeight, propagatorIndex);
this.station = station;
}
/** {@inheritDoc} */
@Override
public AngularAzEl build(final SpacecraftState[] states) {
final int propagatorIndex = getPropagatorsIndices()[0];
final double[] sigma = getTheoreticalStandardDeviation();
final double[] baseWeight = getBaseWeight();
final SpacecraftState state = states[propagatorIndex];
// create a dummy measurement
final AngularAzEl dummy = new AngularAzEl(station, state.getDate(),
new double[] {
0.0, 0.0
}, sigma, baseWeight, propagatorIndex);
for (final EstimationModifier<AngularAzEl> modifier : getModifiers()) {
dummy.addModifier(modifier);
}
// set a reference date for parameters missing one
for (final ParameterDriver driver : dummy.getParametersDrivers()) {
if (driver.getReferenceDate() == null) {
final AbsoluteDate start = getStart();
final AbsoluteDate end = getEnd();
driver.setReferenceDate(start.durationFrom(end) <= 0 ? start : end);
}
}
// estimate the perfect value of the measurement
final double[] angular = dummy.estimate(0, 0, states).getEstimatedValue();
// add the noise
final double[] noise = getNoise();
if (noise != null) {
angular[0] += noise[0];
angular[1] += noise[1];
}
// generate measurement
final AngularAzEl measurement = new AngularAzEl(station, state.getDate(), angular,
sigma, baseWeight, propagatorIndex);
for (final EstimationModifier<AngularAzEl> modifier : getModifiers()) {
measurement.addModifier(modifier);
}
return measurement;
}
}
/* 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.AngularRaDec;
import org.orekit.estimation.measurements.EstimationModifier;
import org.orekit.estimation.measurements.GroundStation;
import org.orekit.frames.Frame;
import org.orekit.propagation.SpacecraftState;
import org.orekit.time.AbsoluteDate;
import org.orekit.utils.ParameterDriver;
/** Builder for {@link AngularRaDec} measurements.
* @author Luc Maisonobe
* @since 9.3
*/
public class AngularRaDecBuilder extends AbstractMeasurementBuilder<AngularRaDec> {
/** Ground station from which measurement is performed. */
private final GroundStation station;
/** Reference frame in which the right ascension - declination angles are given. */
private final Frame referenceFrame;
/** Simple constructor.
* @param noiseSource noise source, may be null for generating perfect measurements
* @param station ground station from which measurement is performed
* @param referenceFrame Reference frame in which the right ascension - declination angles are given
* @param sigma theoretical standard deviation
* @param baseWeight base weight
* @param propagatorIndex index of the propagator related to this measurement
*/
public AngularRaDecBuilder(final CorrelatedRandomVectorGenerator noiseSource,
final GroundStation station, final Frame referenceFrame,
final double[] sigma, final double[] baseWeight,
final int propagatorIndex) {
super(noiseSource, sigma, baseWeight, propagatorIndex);
this.station = station;
this.referenceFrame = referenceFrame;
}
/** {@inheritDoc} */
@Override
public AngularRaDec build(final SpacecraftState[] states) {