Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Orekit
Orekit
Commits
320158e9
Commit
320158e9
authored
Jun 02, 2022
by
Pascal Parraud
Browse files
Merge branch 'issue-922' into develop
parents
f8ef24ef
b57a85af
Changes
13
Hide whitespace changes
Inline
Side-by-side
src/main/java/org/orekit/estimation/measurements/BistaticRange.java
0 → 100644
View file @
320158e9
/* Copyright 2002-2022 Mark Rutten
* 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.
* Mark Rutten 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
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.Map
;
import
org.hipparchus.analysis.differentiation.Gradient
;
import
org.hipparchus.analysis.differentiation.GradientField
;
import
org.hipparchus.geometry.euclidean.threed.FieldVector3D
;
import
org.orekit.frames.FieldTransform
;
import
org.orekit.propagation.SpacecraftState
;
import
org.orekit.time.AbsoluteDate
;
import
org.orekit.time.FieldAbsoluteDate
;
import
org.orekit.utils.Constants
;
import
org.orekit.utils.ParameterDriver
;
import
org.orekit.utils.TimeStampedFieldPVCoordinates
;
import
org.orekit.utils.TimeStampedPVCoordinates
;
/**
* Class modeling a bistatic range measurement using
* an emitter ground station and a receiver ground station.
* <p>
* The measurement is considered to be a signal:
* <ul>
* <li>Emitted from the emitter ground station</li>
* <li>Reflected on the spacecraft</li>
* <li>Received on the receiver ground station</li>
* </ul>
* The date of the measurement corresponds to the reception on ground of the reflected signal.
* <p>
* The motion of the stations and the spacecraft during the signal flight time are taken into account.
* </p>
*
* @author Mark Rutten
* @since 11.2
*/
public
class
BistaticRange
extends
AbstractMeasurement
<
BistaticRange
>
{
/**
* Ground station from which transmission is made.
*/
private
final
GroundStation
emitter
;
/**
* Ground station from which measurement is performed.
*/
private
final
GroundStation
receiver
;
/**
* Simple constructor.
*
* @param emitter ground station from which transmission is performed
* @param receiver ground station from which measurement is performed
* @param date date of the measurement
* @param range observed value
* @param sigma theoretical standard deviation
* @param baseWeight base weight
* @param satellite satellite related to this measurement
* @since 11.2
*/
public
BistaticRange
(
final
GroundStation
emitter
,
final
GroundStation
receiver
,
final
AbsoluteDate
date
,
final
double
range
,
final
double
sigma
,
final
double
baseWeight
,
final
ObservableSatellite
satellite
)
{
super
(
date
,
range
,
sigma
,
baseWeight
,
Collections
.
singletonList
(
satellite
));
addParameterDriver
(
emitter
.
getClockOffsetDriver
());
addParameterDriver
(
emitter
.
getEastOffsetDriver
());
addParameterDriver
(
emitter
.
getNorthOffsetDriver
());
addParameterDriver
(
emitter
.
getZenithOffsetDriver
());
addParameterDriver
(
emitter
.
getPrimeMeridianOffsetDriver
());
addParameterDriver
(
emitter
.
getPrimeMeridianDriftDriver
());
addParameterDriver
(
emitter
.
getPolarOffsetXDriver
());
addParameterDriver
(
emitter
.
getPolarDriftXDriver
());
addParameterDriver
(
emitter
.
getPolarOffsetYDriver
());
addParameterDriver
(
emitter
.
getPolarDriftYDriver
());
addParameterDriver
(
receiver
.
getClockOffsetDriver
());
addParameterDriver
(
receiver
.
getEastOffsetDriver
());
addParameterDriver
(
receiver
.
getNorthOffsetDriver
());
addParameterDriver
(
receiver
.
getZenithOffsetDriver
());
addParameterDriver
(
receiver
.
getPrimeMeridianOffsetDriver
());
addParameterDriver
(
receiver
.
getPrimeMeridianDriftDriver
());
addParameterDriver
(
receiver
.
getPolarOffsetXDriver
());
addParameterDriver
(
receiver
.
getPolarDriftXDriver
());
addParameterDriver
(
receiver
.
getPolarOffsetYDriver
());
addParameterDriver
(
receiver
.
getPolarDriftYDriver
());
this
.
emitter
=
emitter
;
this
.
receiver
=
receiver
;
}
public
GroundStation
getEmitterStation
()
{
return
emitter
;
}
public
GroundStation
getReceiverStation
()
{
return
receiver
;
}
/**
* {@inheritDoc}
*/
@Override
protected
EstimatedMeasurement
<
BistaticRange
>
theoreticalEvaluation
(
final
int
iteration
,
final
int
evaluation
,
final
SpacecraftState
[]
states
)
{
final
SpacecraftState
state
=
states
[
0
];
// Range derivatives are computed with respect to spacecraft state in inertial frame
// and station parameters
// ----------------------
//
// Parameters:
// - 0..2 - Position of the spacecraft in inertial frame
// - 3..5 - Velocity of the spacecraft in inertial frame
// - 6..n - measurements parameters (clock offset, station offsets, pole, prime meridian, sat clock offset...)
int
nbParams
=
6
;
final
Map
<
String
,
Integer
>
indices
=
new
HashMap
<>();
for
(
ParameterDriver
driver
:
getParametersDrivers
())
{
if
(
driver
.
isSelected
())
{
indices
.
put
(
driver
.
getName
(),
nbParams
++);
}
}
final
FieldVector3D
<
Gradient
>
zero
=
FieldVector3D
.
getZero
(
GradientField
.
getField
(
nbParams
));
// Coordinates of the spacecraft expressed as a gradient
final
TimeStampedFieldPVCoordinates
<
Gradient
>
pvaDS
=
getCoordinates
(
state
,
0
,
nbParams
);
// transform between station and inertial frame, expressed as a gradient
// The components of station's position in offset frame are the 3 last derivative parameters
final
FieldTransform
<
Gradient
>
offsetToInertialRx
=
receiver
.
getOffsetToInertial
(
state
.
getFrame
(),
getDate
(),
nbParams
,
indices
);
final
FieldAbsoluteDate
<
Gradient
>
downlinkDateDS
=
offsetToInertialRx
.
getFieldDate
();
// Station position in inertial frame at end of the downlink leg
final
TimeStampedFieldPVCoordinates
<
Gradient
>
stationReceiver
=
offsetToInertialRx
.
transformPVCoordinates
(
new
TimeStampedFieldPVCoordinates
<>(
downlinkDateDS
,
zero
,
zero
,
zero
));
// Compute propagation times
// (if state has already been set up to pre-compensate propagation delay,
// we will have delta == tauD and transitState will be the same as state)
// Downlink delay
final
Gradient
tauD
=
signalTimeOfFlight
(
pvaDS
,
stationReceiver
.
getPosition
(),
downlinkDateDS
);
// Transit state & Transit state (re)computed with gradients
final
Gradient
delta
=
downlinkDateDS
.
durationFrom
(
state
.
getDate
());
final
Gradient
deltaMTauD
=
tauD
.
negate
().
add
(
delta
);
final
SpacecraftState
transitState
=
state
.
shiftedBy
(
deltaMTauD
.
getValue
());
final
TimeStampedFieldPVCoordinates
<
Gradient
>
transitStateDS
=
pvaDS
.
shiftedBy
(
deltaMTauD
);
// transform between secondary station topocentric frame (east-north-zenith) and inertial frame expressed as gradients
// The components of secondary station's position in offset frame are the 3 last derivative parameters
final
FieldAbsoluteDate
<
Gradient
>
transitDate
=
downlinkDateDS
.
shiftedBy
(
tauD
.
negate
());
final
FieldTransform
<
Gradient
>
offsetToInertialTxApprox
=
emitter
.
getOffsetToInertial
(
state
.
getFrame
(),
transitDate
,
nbParams
,
indices
);
// Secondary station PV in inertial frame at transit time
final
TimeStampedFieldPVCoordinates
<
Gradient
>
transmitApprox
=
offsetToInertialTxApprox
.
transformPVCoordinates
(
new
TimeStampedFieldPVCoordinates
<>(
transitDate
,
zero
,
zero
,
zero
));
// Uplink time of flight from secondary station to transit state of leg2
final
Gradient
tauU
=
signalTimeOfFlight
(
transmitApprox
,
transitStateDS
.
getPosition
(),
transitStateDS
.
getDate
());
// Total time of flight
final
Gradient
tauTotal
=
deltaMTauD
.
negate
().
add
(
tauU
);
// Absolute date of transmission
final
FieldAbsoluteDate
<
Gradient
>
transmitDateDS
=
downlinkDateDS
.
shiftedBy
(
tauTotal
);
final
FieldTransform
<
Gradient
>
transmitToInert
=
emitter
.
getOffsetToInertial
(
state
.
getFrame
(),
transmitDateDS
,
nbParams
,
indices
);
// Secondary station PV in inertial frame at rebound date on secondary station
final
TimeStampedFieldPVCoordinates
<
Gradient
>
stationTransmitter
=
transmitToInert
.
transformPVCoordinates
(
new
TimeStampedFieldPVCoordinates
<>(
transmitDateDS
,
zero
,
zero
,
zero
));
// Prepare the evaluation
final
EstimatedMeasurement
<
BistaticRange
>
estimated
=
new
EstimatedMeasurement
<>(
this
,
iteration
,
evaluation
,
new
SpacecraftState
[]
{
transitState
},
new
TimeStampedPVCoordinates
[]
{
stationReceiver
.
toTimeStampedPVCoordinates
(),
transitStateDS
.
toTimeStampedPVCoordinates
(),
stationTransmitter
.
toTimeStampedPVCoordinates
()
});
// Range value
final
Gradient
tau
=
tauD
.
add
(
tauU
);
final
Gradient
range
=
tau
.
multiply
(
Constants
.
SPEED_OF_LIGHT
);
estimated
.
setEstimatedValue
(
range
.
getValue
());
// Range partial derivatives with respect to state
final
double
[]
derivatives
=
range
.
getGradient
();
estimated
.
setStateDerivatives
(
0
,
Arrays
.
copyOfRange
(
derivatives
,
0
,
6
));
// set partial derivatives with respect to parameters
// (beware element at index 0 is the value, not a derivative)
for
(
final
ParameterDriver
driver
:
getParametersDrivers
())
{
final
Integer
index
=
indices
.
get
(
driver
.
getName
());
if
(
index
!=
null
)
{
estimated
.
setParameterDerivatives
(
driver
,
derivatives
[
index
]);
}
}
return
estimated
;
}
}
src/main/java/org/orekit/estimation/measurements/generation/BistaticRangeBuilder.java
0 → 100644
View file @
320158e9
/* Copyright 2002-2022 Mark Rutten
* 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.
* Mark Rutten 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.BistaticRange
;
import
org.orekit.estimation.measurements.EstimationModifier
;
import
org.orekit.estimation.measurements.GroundStation
;
import
org.orekit.estimation.measurements.ObservableSatellite
;
import
org.orekit.propagation.SpacecraftState
;
import
org.orekit.time.AbsoluteDate
;
import
org.orekit.utils.ParameterDriver
;
/** Builder for {@link BistaticRange} measurements.
* @author Pascal Parraud
* @author Mark Rutten
* @since 11.2
*/
public
class
BistaticRangeBuilder
extends
AbstractMeasurementBuilder
<
BistaticRange
>
{
/** Emitter ground station. */
private
final
GroundStation
emitter
;
/** Receiver ground station. */
private
final
GroundStation
receiver
;
/** Simple constructor.
* @param noiseSource noise source, may be null for generating perfect measurements
* @param emitter emitter ground station
* @param receiver receiver ground station, from which measurement is performed
* @param sigma theoretical standard deviation
* @param baseWeight base weight
* @param satellite satellite related to this builder
*/
public
BistaticRangeBuilder
(
final
CorrelatedRandomVectorGenerator
noiseSource
,
final
GroundStation
emitter
,
final
GroundStation
receiver
,
final
double
sigma
,
final
double
baseWeight
,
final
ObservableSatellite
satellite
)
{
super
(
noiseSource
,
sigma
,
baseWeight
,
satellite
);
this
.
emitter
=
emitter
;
this
.
receiver
=
receiver
;
}
/** {@inheritDoc} */
@Override
public
BistaticRange
build
(
final
SpacecraftState
[]
states
)
{
final
ObservableSatellite
satellite
=
getSatellites
()[
0
];
final
double
sigma
=
getTheoreticalStandardDeviation
()[
0
];
final
double
baseWeight
=
getBaseWeight
()[
0
];
final
SpacecraftState
[]
relevant
=
new
SpacecraftState
[]
{
states
[
satellite
.
getPropagatorIndex
()]
};
// create a dummy measurement
final
BistaticRange
dummy
=
new
BistaticRange
(
emitter
,
receiver
,
relevant
[
0
].
getDate
(),
Double
.
NaN
,
sigma
,
baseWeight
,
satellite
);
for
(
final
EstimationModifier
<
BistaticRange
>
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
double
range
=
dummy
.
estimate
(
0
,
0
,
relevant
).
getEstimatedValue
()[
0
];
// add the noise
final
double
[]
noise
=
getNoise
();
if
(
noise
!=
null
)
{
range
+=
noise
[
0
];
}
// generate measurement
final
BistaticRange
measurement
=
new
BistaticRange
(
emitter
,
receiver
,
relevant
[
0
].
getDate
(),
range
,
sigma
,
baseWeight
,
satellite
);
for
(
final
EstimationModifier
<
BistaticRange
>
modifier
:
getModifiers
())
{
measurement
.
addModifier
(
modifier
);
}
return
measurement
;
}
}
src/main/java/org/orekit/estimation/measurements/modifiers/BaseRangeIonosphericDelayModifier.java
0 → 100644
View file @
320158e9
/* Copyright 2002-2022 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.estimation.measurements.modifiers
;
import
java.util.List
;
import
org.hipparchus.CalculusFieldElement
;
import
org.orekit.estimation.measurements.GroundStation
;
import
org.orekit.frames.TopocentricFrame
;
import
org.orekit.models.earth.ionosphere.IonosphericModel
;
import
org.orekit.propagation.FieldSpacecraftState
;
import
org.orekit.propagation.SpacecraftState
;
import
org.orekit.utils.ParameterDriver
;
/** Base class modifying theoretical range measurement with ionospheric delay.
* The effect of ionospheric correction on the range is directly computed
* through the computation of the ionospheric delay.
*
* The ionospheric delay depends on the frequency of the signal (GNSS, VLBI, ...).
* For optical measurements (e.g. SLR), the ray is not affected by ionosphere charged particles.
* <p>
* Since 10.0, state derivatives and ionospheric parameters derivates are computed
* using automatic differentiation.
* </p>
* @author Joris Olympio
* @since 11.2
*/
public
abstract
class
BaseRangeIonosphericDelayModifier
{
/** Ionospheric delay model. */
private
final
IonosphericModel
ionoModel
;
/** Frequency [Hz]. */
private
final
double
frequency
;
/** Constructor.
*
* @param model Ionospheric delay model appropriate for the current range-rate measurement method.
* @param freq frequency of the signal in Hz
*/
protected
BaseRangeIonosphericDelayModifier
(
final
IonosphericModel
model
,
final
double
freq
)
{
this
.
ionoModel
=
model
;
this
.
frequency
=
freq
;
}
/** Get the ionospheric delay model.
* @return ionospheric delay model
*/
protected
IonosphericModel
getIonoModel
()
{
return
ionoModel
;
}
/** Compute the measurement error due to Ionosphere.
* @param station station
* @param state spacecraft state
* @return the measurement error due to Ionosphere
*/
protected
double
rangeErrorIonosphericModel
(
final
GroundStation
station
,
final
SpacecraftState
state
)
{
// Base frame associated with the station
final
TopocentricFrame
baseFrame
=
station
.
getBaseFrame
();
// delay in meters
final
double
delay
=
ionoModel
.
pathDelay
(
state
,
baseFrame
,
frequency
,
ionoModel
.
getParameters
());
return
delay
;
}
/** Compute the measurement error due to Ionosphere.
* @param <T> type of the elements
* @param station station
* @param state spacecraft state
* @param parameters ionospheric model parameters
* @return the measurement error due to Ionosphere
*/
protected
<
T
extends
CalculusFieldElement
<
T
>>
T
rangeErrorIonosphericModel
(
final
GroundStation
station
,
final
FieldSpacecraftState
<
T
>
state
,
final
T
[]
parameters
)
{
// Base frame associated with the station
final
TopocentricFrame
baseFrame
=
station
.
getBaseFrame
();
// delay in meters
final
T
delay
=
ionoModel
.
pathDelay
(
state
,
baseFrame
,
frequency
,
parameters
);
return
delay
;
}
/** Get the drivers for this modifier parameters.
* @return drivers for this modifier parameters
*/
public
List
<
ParameterDriver
>
getParametersDrivers
()
{
return
ionoModel
.
getParametersDrivers
();
}
}
src/main/java/org/orekit/estimation/measurements/modifiers/BaseRangeTroposphericDelayModifier.java
0 → 100644
View file @
320158e9
/* Copyright 2002-2022 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.estimation.measurements.modifiers
;
import
java.util.List
;
import
org.hipparchus.CalculusFieldElement
;
import
org.hipparchus.Field
;
import
org.hipparchus.geometry.euclidean.threed.FieldVector3D
;
import
org.hipparchus.geometry.euclidean.threed.Vector3D
;
import
org.orekit.estimation.measurements.GroundStation
;
import
org.orekit.models.earth.troposphere.DiscreteTroposphericModel
;
import
org.orekit.propagation.FieldSpacecraftState
;
import
org.orekit.propagation.SpacecraftState
;
import
org.orekit.utils.ParameterDriver
;
/** Base class modifying theoretical range measurements with tropospheric delay.
* The effect of tropospheric correction on the range is directly computed
* through the computation of the tropospheric delay.
*
* In general, for GNSS, VLBI, ... there is hardly any frequency dependence in the delay.
* For SLR techniques however, the frequency dependence is sensitive.
*
* @author Joris Olympio
* @since 11.2
*/
public
abstract
class
BaseRangeTroposphericDelayModifier
{
/** Tropospheric delay model. */
private
final
DiscreteTroposphericModel
tropoModel
;
/** Constructor.
*
* @param model Tropospheric delay model appropriate for the current range measurement method.
*/
protected
BaseRangeTroposphericDelayModifier
(
final
DiscreteTroposphericModel
model
)
{
tropoModel
=
model
;
}
/** Get the tropospheric delay model.
* @return tropospheric delay model
*/
protected
DiscreteTroposphericModel
getTropoModel
()
{
return
tropoModel
;
}
/** Compute the measurement error due to Troposphere.
* @param station station
* @param state spacecraft state
* @return the measurement error due to Troposphere
*/
public
double
rangeErrorTroposphericModel
(
final
GroundStation
station
,
final
SpacecraftState
state
)
{
// spacecraft position and elevation as seen from the ground station
final
Vector3D
position
=
state
.
getPVCoordinates
().
getPosition
();
final
double
elevation
=
station
.
getBaseFrame
().
getElevation
(
position
,
state
.
getFrame
(),
state
.
getDate
());
// only consider measures above the horizon
if
(
elevation
>
0
)
{
// tropospheric delay in meters
final
double
delay
=
tropoModel
.
pathDelay
(
elevation
,
station
.
getBaseFrame
().
getPoint
(),
tropoModel
.
getParameters
(),
state
.
getDate
());
return
delay
;
}
return
0
;
}
/** Compute the measurement error due to Troposphere.
* @param <T> type of the element
* @param station station
* @param state spacecraft state
* @param parameters tropospheric model parameters
* @return the measurement error due to Troposphere
*/
public
<
T
extends
CalculusFieldElement
<
T
>>
T
rangeErrorTroposphericModel
(
final
GroundStation
station
,
final
FieldSpacecraftState
<
T
>
state
,
final
T
[]
parameters
)
{
// Field
final
Field
<
T
>
field
=
state
.
getDate
().
getField
();
final
T
zero
=
field
.
getZero
();
// spacecraft position and elevation as seen from the ground station
final
FieldVector3D
<
T
>
position
=
state
.
getPVCoordinates
().
getPosition
();
final
T
elevation
=
station
.
getBaseFrame
().
getElevation
(
position
,
state
.
getFrame
(),
state
.
getDate
());
// only consider measures above the horizon
if
(
elevation
.
getReal
()
>
0
)
{
// tropospheric delay in meters
final
T
delay
=
tropoModel
.
pathDelay
(
elevation
,
station
.
getBaseFrame
().
getPoint
(
field
),
parameters
,
state
.
getDate
());
return
delay
;
}
return
zero
;
}
/** Get the drivers for this modifier parameters.
* @return drivers for this modifier parameters
*/
public
List
<
ParameterDriver
>
getParametersDrivers
()
{
return
tropoModel
.
getParametersDrivers
();
}
}
src/main/java/org/orekit/estimation/measurements/modifiers/BistaticRangeIonosphericDelayModifier.java
0 → 100644
View file @
320158e9
/* Copyright 2002-2022 Mark Rutten
* Licensed to CS GROUP (CS) under one or more