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
9887e978
Commit
9887e978
authored
Jun 21, 2022
by
Luc Maisonobe
Committed by
Maxime Journot
Aug 01, 2022
Browse files
Fixed date offsets just before whole seconds.
Fixes
#935
Fixes
#939
parent
e1e1bbe7
Changes
8
Hide whitespace changes
Inline
Side-by-side
src/main/java/org/orekit/propagation/events/EventState.java
View file @
9887e978
...
...
@@ -16,6 +16,8 @@
*/
package
org.orekit.propagation.events
;
import
java.util.function.DoubleFunction
;
import
org.hipparchus.analysis.UnivariateFunction
;
import
org.hipparchus.analysis.solvers.BracketedUnivariateSolver
;
import
org.hipparchus.analysis.solvers.BracketedUnivariateSolver.Interval
;
...
...
@@ -327,31 +329,29 @@ public class EventState<T extends EventDetector> {
final
AbsoluteDate
fT0
=
loopT
;
final
double
tbDouble
=
tb
.
durationFrom
(
fT0
);
final
double
middle
=
0.5
*
tbDouble
;
final
UnivariateFunction
f
=
dt
->
{
final
DoubleFunction
<
AbsoluteDate
>
date
=
dt
->
{
// use either fT0 or tb as the base time for shifts
// in order to ensure we reproduce exactly those times
// using only one reference time like fT0 would imply
// to use ft0.shiftedBy(tbDouble), which may be different
// from tb due to numerical noise (see issue 921)
final
AbsoluteDate
t
;
if
(
forward
==
dt
<=
middle
)
{
// use start of interval as reference
t
=
fT0
.
shiftedBy
(
dt
);
return
fT0
.
shiftedBy
(
dt
);
}
else
{
// use end of interval as reference
t
=
tb
.
shiftedBy
(
dt
-
tbDouble
);
return
tb
.
shiftedBy
(
dt
-
tbDouble
);
}
return
g
(
interpolator
.
getInterpolatedState
(
t
));
};
// tb as a double for use in f
final
UnivariateFunction
f
=
dt
->
g
(
interpolator
.
getInterpolatedState
(
date
.
apply
(
dt
)));
if
(
forward
)
{
try
{
final
Interval
interval
=
solver
.
solveInterval
(
maxIterationCount
,
f
,
0
,
tbDouble
);
beforeRootT
=
fT0
.
shiftedB
y
(
interval
.
getLeftAbscissa
());
beforeRootT
=
date
.
appl
y
(
interval
.
getLeftAbscissa
());
beforeRootG
=
interval
.
getLeftValue
();
afterRootT
=
fT0
.
shiftedB
y
(
interval
.
getRightAbscissa
());
afterRootG
=
interval
.
getRightValue
();
afterRootT
=
date
.
appl
y
(
interval
.
getRightAbscissa
());
afterRootG
=
interval
.
getRightValue
();
// CHECKSTYLE: stop IllegalCatch check
}
catch
(
RuntimeException
e
)
{
// CHECKSTYLE: resume IllegalCatch check
...
...
@@ -362,10 +362,10 @@ public class EventState<T extends EventDetector> {
try
{
final
Interval
interval
=
solver
.
solveInterval
(
maxIterationCount
,
f
,
tbDouble
,
0
);
beforeRootT
=
fT0
.
shiftedB
y
(
interval
.
getRightAbscissa
());
beforeRootT
=
date
.
appl
y
(
interval
.
getRightAbscissa
());
beforeRootG
=
interval
.
getRightValue
();
afterRootT
=
fT0
.
shiftedB
y
(
interval
.
getLeftAbscissa
());
afterRootG
=
interval
.
getLeftValue
();
afterRootT
=
date
.
appl
y
(
interval
.
getLeftAbscissa
());
afterRootG
=
interval
.
getLeftValue
();
// CHECKSTYLE: stop IllegalCatch check
}
catch
(
RuntimeException
e
)
{
// CHECKSTYLE: resume IllegalCatch check
...
...
src/main/java/org/orekit/propagation/events/FieldEventState.java
View file @
9887e978
...
...
@@ -16,8 +16,10 @@
*/
package
org.orekit.propagation.events
;
import
org.hipparchus.Field
;
import
java.util.function.DoubleFunction
;
import
org.hipparchus.CalculusFieldElement
;
import
org.hipparchus.Field
;
import
org.hipparchus.analysis.UnivariateFunction
;
import
org.hipparchus.analysis.solvers.BracketedUnivariateSolver
;
import
org.hipparchus.analysis.solvers.BracketedUnivariateSolver.Interval
;
...
...
@@ -331,19 +333,31 @@ public class FieldEventState<D extends FieldEventDetector<T>, T extends Calculus
// both non-zero, the usual case, use a root finder.
// time zero for evaluating the function f. Needs to be final
final
FieldAbsoluteDate
<
T
>
fT0
=
loopT
;
final
UnivariateFunction
f
=
dt
->
{
return
g
(
interpolator
.
getInterpolatedState
(
fT0
.
shiftedBy
(
dt
))).
getReal
();
final
double
tbDouble
=
tb
.
durationFrom
(
fT0
).
getReal
();
final
double
middle
=
0.5
*
tbDouble
;
final
DoubleFunction
<
FieldAbsoluteDate
<
T
>>
date
=
dt
->
{
// use either fT0 or tb as the base time for shifts
// in order to ensure we reproduce exactly those times
// using only one reference time like fT0 would imply
// to use ft0.shiftedBy(tbDouble), which may be different
// from tb due to numerical noise (see issue 921)
if
(
forward
==
dt
<=
middle
)
{
// use start of interval as reference
return
fT0
.
shiftedBy
(
dt
);
}
else
{
// use end of interval as reference
return
tb
.
shiftedBy
(
dt
-
tbDouble
);
}
};
// tb as a double for use in f
final
T
tbDouble
=
tb
.
durationFrom
(
fT0
);
final
UnivariateFunction
f
=
dt
->
g
(
interpolator
.
getInterpolatedState
(
date
.
apply
(
dt
))).
getReal
();
if
(
forward
)
{
try
{
final
Interval
interval
=
solver
.
solveInterval
(
maxIterationCount
,
f
,
0
,
tbDouble
.
getReal
()
);
beforeRootT
=
fT0
.
shiftedB
y
(
interval
.
getLeftAbscissa
());
solver
.
solveInterval
(
maxIterationCount
,
f
,
0
,
tbDouble
);
beforeRootT
=
date
.
appl
y
(
interval
.
getLeftAbscissa
());
beforeRootG
=
zero
.
add
(
interval
.
getLeftValue
());
afterRootT
=
fT0
.
shiftedB
y
(
interval
.
getRightAbscissa
());
afterRootG
=
zero
.
add
(
interval
.
getRightValue
());
afterRootT
=
date
.
appl
y
(
interval
.
getRightAbscissa
());
afterRootG
=
zero
.
add
(
interval
.
getRightValue
());
// CHECKSTYLE: stop IllegalCatch check
}
catch
(
RuntimeException
e
)
{
// CHECKSTYLE: resume IllegalCatch check
...
...
@@ -353,11 +367,11 @@ public class FieldEventState<D extends FieldEventDetector<T>, T extends Calculus
}
else
{
try
{
final
Interval
interval
=
solver
.
solveInterval
(
maxIterationCount
,
f
,
tbDouble
.
getReal
()
,
0
);
beforeRootT
=
fT0
.
shiftedB
y
(
interval
.
getRightAbscissa
());
solver
.
solveInterval
(
maxIterationCount
,
f
,
tbDouble
,
0
);
beforeRootT
=
date
.
appl
y
(
interval
.
getRightAbscissa
());
beforeRootG
=
zero
.
add
(
interval
.
getRightValue
());
afterRootT
=
fT0
.
shiftedB
y
(
interval
.
getLeftAbscissa
());
afterRootG
=
zero
.
add
(
interval
.
getLeftValue
());
afterRootT
=
date
.
appl
y
(
interval
.
getLeftAbscissa
());
afterRootG
=
zero
.
add
(
interval
.
getLeftValue
());
// CHECKSTYLE: stop IllegalCatch check
}
catch
(
RuntimeException
e
)
{
// CHECKSTYLE: resume IllegalCatch check
...
...
src/main/java/org/orekit/time/AbsoluteDate.java
View file @
9887e978
...
...
@@ -314,10 +314,21 @@ public class AbsoluteDate
// Use 2Sum for high precision.
final
SumAndResidual
sumAndResidual
=
MathUtils
.
twoSum
(
seconds
,
tsOffset
);
final
long
dl
=
(
long
)
FastMath
.
floor
(
sumAndResidual
.
getSum
());
final
double
regularOffset
=
(
sumAndResidual
.
getSum
()
-
dl
)
+
sumAndResidual
.
getResidual
();
offset
=
(
sumAndResidual
.
getSum
()
-
dl
)
+
sumAndResidual
.
getResidual
();
epoch
=
60
l
*
((
date
.
getJ2000Day
()
*
24
l
+
time
.
getHour
())
*
60
l
+
time
.
getMinute
()
-
time
.
getMinutesFromUTC
()
-
720
l
)
+
dl
;
if
(
regularOffset
>=
0
)
{
// regular case, the offset is between 0.0 and 1.0
offset
=
regularOffset
;
epoch
=
60
l
*
((
date
.
getJ2000Day
()
*
24
l
+
time
.
getHour
())
*
60
l
+
time
.
getMinute
()
-
time
.
getMinutesFromUTC
()
-
720
l
)
+
dl
;
}
else
{
// very rare case, the offset is just before a whole second
// we will loose some bits of accuracy when adding 1 second
// but this will ensure the offset remains in the [0.0; 1.0] interval
offset
=
1.0
+
regularOffset
;
epoch
=
60
l
*
((
date
.
getJ2000Day
()
*
24
l
+
time
.
getHour
())
*
60
l
+
time
.
getMinute
()
-
time
.
getMinutesFromUTC
()
-
720
l
)
+
dl
-
1
;
}
}
...
...
@@ -429,8 +440,18 @@ public class AbsoluteDate
epoch
=
(
sumAndResidual
.
getSum
()
<
0
)
?
Long
.
MIN_VALUE
:
Long
.
MAX_VALUE
;
}
else
{
final
long
dl
=
(
long
)
FastMath
.
floor
(
sumAndResidual
.
getSum
());
offset
=
(
sumAndResidual
.
getSum
()
-
dl
)
+
sumAndResidual
.
getResidual
();
epoch
=
since
.
epoch
+
dl
;
final
double
regularOffset
=
(
sumAndResidual
.
getSum
()
-
dl
)
+
sumAndResidual
.
getResidual
();
if
(
regularOffset
>=
0
)
{
// regular case, the offset is between 0.0 and 1.0
offset
=
regularOffset
;
epoch
=
since
.
epoch
+
dl
;
}
else
{
// very rare case, the offset is just before a whole second
// we will loose some bits of accuracy when adding 1 second
// but this will ensure the offset remains in the [0.0; 1.0] interval
offset
=
1.0
+
regularOffset
;
epoch
=
since
.
epoch
+
dl
-
1
;
}
}
}
...
...
src/main/java/org/orekit/time/FieldAbsoluteDate.java
View file @
9887e978
...
...
@@ -161,8 +161,18 @@ public class FieldAbsoluteDate<T extends CalculusFieldElement<T>>
epoch
=
(
sumAndResidual
.
getSum
().
getReal
()
<
0
)
?
Long
.
MIN_VALUE
:
Long
.
MAX_VALUE
;
}
else
{
final
long
dl
=
(
long
)
FastMath
.
floor
(
sumAndResidual
.
getSum
().
getReal
());
offset
=
sumAndResidual
.
getSum
().
subtract
(
dl
).
add
(
sumAndResidual
.
getResidual
());
epoch
=
since
.
epoch
+
dl
;
final
T
regularOffset
=
sumAndResidual
.
getSum
().
subtract
(
dl
).
add
(
sumAndResidual
.
getResidual
());
if
(
regularOffset
.
getReal
()
>=
0
)
{
// regular case, the offset is between 0.0 and 1.0
offset
=
regularOffset
;
epoch
=
since
.
epoch
+
dl
;
}
else
{
// very rare case, the offset is just before a whole second
// we will loose some bits of accuracy when adding 1 second
// but this will ensure the offset remains in the [0.0; 1.0] interval
offset
=
regularOffset
.
add
(
1.0
);
epoch
=
since
.
epoch
+
dl
-
1
;
}
}
}
...
...
@@ -208,11 +218,20 @@ public class FieldAbsoluteDate<T extends CalculusFieldElement<T>>
// Use 2Sum for high precision.
final
SumAndResidual
sumAndResidual
=
MathUtils
.
twoSum
(
seconds
,
tsOffset
);
final
long
dl
=
(
long
)
FastMath
.
floor
(
sumAndResidual
.
getSum
());
offset
=
field
.
getZero
().
add
((
sumAndResidual
.
getSum
()
-
dl
)
+
sumAndResidual
.
getResidual
());
epoch
=
60
l
*
((
date
.
getJ2000Day
()
*
24
l
+
time
.
getHour
())
*
60
l
+
time
.
getMinute
()
-
time
.
getMinutesFromUTC
()
-
720
l
)
+
dl
;
final
T
regularOffset
=
field
.
getZero
().
add
((
sumAndResidual
.
getSum
()
-
dl
)
+
sumAndResidual
.
getResidual
());
if
(
regularOffset
.
getReal
()
>=
0
)
{
// regular case, the offset is between 0.0 and 1.0
offset
=
regularOffset
;
epoch
=
60
l
*
((
date
.
getJ2000Day
()
*
24
l
+
time
.
getHour
())
*
60
l
+
time
.
getMinute
()
-
time
.
getMinutesFromUTC
()
-
720
l
)
+
dl
;
}
else
{
// very rare case, the offset is just before a whole second
// we will loose some bits of accuracy when adding 1 second
// but this will ensure the offset remains in the [0.0; 1.0] interval
offset
=
regularOffset
.
add
(
1.0
);
epoch
=
60
l
*
((
date
.
getJ2000Day
()
*
24
l
+
time
.
getHour
())
*
60
l
+
time
.
getMinute
()
-
time
.
getMinutesFromUTC
()
-
720
l
)
+
dl
-
1
;
}
this
.
field
=
field
;
}
...
...
@@ -366,11 +385,21 @@ public class FieldAbsoluteDate<T extends CalculusFieldElement<T>>
final
FieldSumAndResidual
<
T
>
sumAndResidual
=
MathUtils
.
twoSum
(
field
.
getZero
().
add
(
tA
),
tB
);
if
(
Double
.
isInfinite
(
sumAndResidual
.
getSum
().
getReal
()))
{
this
.
offset
=
sumAndResidual
.
getSum
();
this
.
epoch
=
(
sumAndResidual
.
getSum
().
getReal
()
<
0
)
?
Long
.
MIN_VALUE
:
Long
.
MAX_VALUE
;
this
.
epoch
=
(
sumAndResidual
.
getSum
().
getReal
()
<
0
)
?
Long
.
MIN_VALUE
:
Long
.
MAX_VALUE
;
}
else
{
final
long
dl
=
(
long
)
FastMath
.
floor
(
sumAndResidual
.
getSum
().
getReal
());
this
.
offset
=
sumAndResidual
.
getSum
().
subtract
(
dl
).
add
(
sumAndResidual
.
getResidual
());
this
.
epoch
=
epoch
+
dl
;
final
T
regularOffset
=
sumAndResidual
.
getSum
().
subtract
(
dl
).
add
(
sumAndResidual
.
getResidual
());
if
(
regularOffset
.
getReal
()
>=
0
)
{
// regular case, the offset is between 0.0 and 1.0
this
.
offset
=
regularOffset
;
this
.
epoch
=
epoch
+
dl
;
}
else
{
// very rare case, the offset is just before a whole second
// we will loose some bits of accuracy when adding 1 second
// but this will ensure the offset remains in the [0.0; 1.0) interval
this
.
offset
=
regularOffset
.
add
(
1.0
);
this
.
epoch
=
epoch
+
dl
-
1
;
}
}
}
...
...
src/test/java/org/orekit/propagation/events/DateDetectorTest.java
View file @
9887e978
...
...
@@ -16,6 +16,10 @@
*/
package
org.orekit.propagation.events
;
import
java.time.Instant
;
import
java.time.LocalDateTime
;
import
java.time.ZoneId
;
import
org.hipparchus.geometry.euclidean.threed.Vector3D
;
import
org.hipparchus.ode.events.Action
;
import
org.hipparchus.ode.nonstiff.AdaptiveStepsizeIntegrator
;
...
...
@@ -30,9 +34,13 @@ import org.orekit.frames.FramesFactory;
import
org.orekit.orbits.EquinoctialOrbit
;
import
org.orekit.orbits.Orbit
;
import
org.orekit.orbits.OrbitType
;
import
org.orekit.propagation.Propagator
;
import
org.orekit.propagation.SpacecraftState
;
import
org.orekit.propagation.analytical.tle.TLE
;
import
org.orekit.propagation.analytical.tle.TLEPropagator
;
import
org.orekit.propagation.events.handlers.ContinueOnEvent
;
import
org.orekit.propagation.events.handlers.EventHandler
;
import
org.orekit.propagation.events.handlers.StopOnEvent
;
import
org.orekit.propagation.integration.AdditionalDerivativesProvider
;
import
org.orekit.propagation.integration.CombinedDerivatives
;
import
org.orekit.propagation.numerical.NumericalPropagator
;
...
...
@@ -178,6 +186,49 @@ public class DateDetectorTest {
Assert
.
assertEquals
(
dt
,
finalState
.
getDate
().
durationFrom
(
iniDate
),
threshold
);
}
@Test
public
void
testIssue935
()
{
// startTime, endTime
long
start
=
1570802400000L
;
long
end
=
1570838399000L
;
// Build propagator
TLE
tle
=
new
TLE
(
"1 43197U 18015F 19284.07336221 .00000533 00000-0 24811-4 0 9998"
,
"2 43197 97.4059 50.1428 0017543 265.5429 181.0400 15.24136761 93779"
);
Propagator
propagator
=
TLEPropagator
.
selectExtrapolator
(
tle
);
// Max check to seconds
int
maxCheck
=
(
int
)
((
end
-
start
)
/
2000
);
DateDetector
dateDetector
=
new
DateDetector
(
maxCheck
,
1.0
e
-
6
,
getAbsoluteDateFromTimestamp
(
start
)).
withHandler
(
new
StopOnEvent
<>());
dateDetector
.
addEventDate
(
getAbsoluteDateFromTimestamp
(
end
));
// Add event detectors to orbit
propagator
.
addEventDetector
(
dateDetector
);
// Propagate
final
AbsoluteDate
startDate
=
getAbsoluteDateFromTimestamp
(
start
);
final
AbsoluteDate
endDate
=
getAbsoluteDateFromTimestamp
(
end
);
SpacecraftState
lastState
=
propagator
.
propagate
(
startDate
,
endDate
.
shiftedBy
(
1
));
Assert
.
assertEquals
(
0.0
,
lastState
.
getDate
().
durationFrom
(
endDate
),
1.0
e
-
15
);
}
public
static
AbsoluteDate
getAbsoluteDateFromTimestamp
(
final
long
timestamp
)
{
LocalDateTime
utcDate
=
LocalDateTime
.
ofInstant
(
Instant
.
ofEpochMilli
(
timestamp
),
ZoneId
.
of
(
"UTC"
));
int
year
=
utcDate
.
getYear
();
int
month
=
utcDate
.
getMonthValue
();
int
day
=
utcDate
.
getDayOfMonth
();
int
hour
=
utcDate
.
getHour
();
int
minute
=
utcDate
.
getMinute
();
double
second
=
utcDate
.
getSecond
();
double
millis
=
utcDate
.
getNano
()
/
1
e9
;
return
new
AbsoluteDate
(
year
,
month
,
day
,
hour
,
minute
,
second
,
TimeScalesFactory
.
getUTC
()).
shiftedBy
(
millis
);
}
@Before
public
void
setUp
()
{
try
{
...
...
src/test/java/org/orekit/propagation/events/FieldDateDetectorTest.java
View file @
9887e978
...
...
@@ -17,6 +17,9 @@
package
org.orekit.propagation.events
;
import
java.lang.reflect.Array
;
import
java.time.Instant
;
import
java.time.LocalDateTime
;
import
java.time.ZoneId
;
import
org.hipparchus.CalculusFieldElement
;
import
org.hipparchus.Field
;
...
...
@@ -34,9 +37,13 @@ import org.orekit.frames.FramesFactory;
import
org.orekit.orbits.FieldEquinoctialOrbit
;
import
org.orekit.orbits.FieldOrbit
;
import
org.orekit.orbits.OrbitType
;
import
org.orekit.propagation.FieldPropagator
;
import
org.orekit.propagation.FieldSpacecraftState
;
import
org.orekit.propagation.analytical.tle.FieldTLE
;
import
org.orekit.propagation.analytical.tle.FieldTLEPropagator
;
import
org.orekit.propagation.events.handlers.FieldContinueOnEvent
;
import
org.orekit.propagation.events.handlers.FieldEventHandler
;
import
org.orekit.propagation.events.handlers.FieldStopOnEvent
;
import
org.orekit.propagation.integration.FieldAdditionalDerivativesProvider
;
import
org.orekit.propagation.numerical.FieldNumericalPropagator
;
import
org.orekit.propagation.sampling.FieldOrekitStepInterpolator
;
...
...
@@ -59,23 +66,32 @@ public class FieldDateDetectorTest {
public
void
testSimpleTimer
()
{
doTestSimpleTimer
(
Decimal64Field
.
getInstance
());
}
@Test
public
void
testEmbeddedTimer
()
{
doTestEmbeddedTimer
(
Decimal64Field
.
getInstance
());
}
@Test
public
void
testAutoEmbeddedTimer
()
{
doTestAutoEmbeddedTimer
(
Decimal64Field
.
getInstance
());
}
@Test
(
expected
=
IllegalArgumentException
.
class
)
public
void
testExceptionTimer
()
{
doTestExceptionTimer
(
Decimal64Field
.
getInstance
());
}
@Test
public
void
testGenericHandler
()
{
doTestGenericHandler
(
Decimal64Field
.
getInstance
());
}
@Test
public
void
testIssue935
()
{
doTestIssue935
(
Decimal64Field
.
getInstance
());
}
private
<
T
extends
CalculusFieldElement
<
T
>>
void
doTestSimpleTimer
(
final
Field
<
T
>
field
)
{
T
zero
=
field
.
getZero
();
final
FieldVector3D
<
T
>
position
=
new
FieldVector3D
<>(
zero
.
add
(-
6142438.668
),
zero
.
add
(
3492467.560
),
zero
.
add
(
-
25767.25680
));
...
...
@@ -301,6 +317,51 @@ public class FieldDateDetectorTest {
Assert
.
assertEquals
(
dt
,
finalState
.
getDate
().
durationFrom
(
iniDate
).
getReal
(),
threshold
);
}
private
<
T
extends
CalculusFieldElement
<
T
>>
void
doTestIssue935
(
Field
<
T
>
field
)
{
// startTime, endTime
long
start
=
1570802400000L
;
long
end
=
1570838399000L
;
// Build propagator
FieldTLE
<
T
>
tle
=
new
FieldTLE
<>(
field
,
"1 43197U 18015F 19284.07336221 .00000533 00000-0 24811-4 0 9998"
,
"2 43197 97.4059 50.1428 0017543 265.5429 181.0400 15.24136761 93779"
);
FieldPropagator
<
T
>
propagator
=
FieldTLEPropagator
.
selectExtrapolator
(
tle
,
tle
.
getParameters
(
field
));
// Max check to seconds
int
maxCheck
=
(
int
)
((
end
-
start
)
/
2000
);
FieldDateDetector
<
T
>
dateDetector
=
new
FieldDateDetector
<>(
field
.
getZero
().
newInstance
(
maxCheck
),
field
.
getZero
().
newInstance
(
1.0
e
-
6
),
getAbsoluteDateFromTimestamp
(
field
,
start
)).
withHandler
(
new
FieldStopOnEvent
<>());
dateDetector
.
addEventDate
(
getAbsoluteDateFromTimestamp
(
field
,
end
));
// Add event detectors to orbit
propagator
.
addEventDetector
(
dateDetector
);
// Propagate
final
FieldAbsoluteDate
<
T
>
startDate
=
getAbsoluteDateFromTimestamp
(
field
,
start
);
final
FieldAbsoluteDate
<
T
>
endDate
=
getAbsoluteDateFromTimestamp
(
field
,
end
);
FieldSpacecraftState
<
T
>
lastState
=
propagator
.
propagate
(
startDate
,
endDate
.
shiftedBy
(
1
));
Assert
.
assertEquals
(
0.0
,
lastState
.
getDate
().
durationFrom
(
endDate
).
getReal
(),
1.0
e
-
15
);
}
public
static
<
T
extends
CalculusFieldElement
<
T
>>
FieldAbsoluteDate
<
T
>
getAbsoluteDateFromTimestamp
(
final
Field
<
T
>
field
,
final
long
timestamp
)
{
LocalDateTime
utcDate
=
LocalDateTime
.
ofInstant
(
Instant
.
ofEpochMilli
(
timestamp
),
ZoneId
.
of
(
"UTC"
));
int
year
=
utcDate
.
getYear
();
int
month
=
utcDate
.
getMonthValue
();
int
day
=
utcDate
.
getDayOfMonth
();
int
hour
=
utcDate
.
getHour
();
int
minute
=
utcDate
.
getMinute
();
double
second
=
utcDate
.
getSecond
();
double
millis
=
utcDate
.
getNano
()
/
1
e9
;
return
new
FieldAbsoluteDate
<>(
field
,
year
,
month
,
day
,
hour
,
minute
,
second
,
TimeScalesFactory
.
getUTC
()).
shiftedBy
(
millis
);
}
private
<
T
extends
CalculusFieldElement
<
T
>>
FieldTimeStamped
<
T
>[]
toArray
(
final
FieldAbsoluteDate
<
T
>
date
)
{
@SuppressWarnings
(
"unchecked"
)
final
FieldTimeStamped
<
T
>[]
array
=
(
FieldTimeStamped
<
T
>[])
Array
.
newInstance
(
FieldTimeStamped
.
class
,
1
);
...
...
src/test/java/org/orekit/time/AbsoluteDateTest.java
View file @
9887e978
...
...
@@ -18,6 +18,7 @@ package org.orekit.time;
import
java.io.IOException
;
import
java.lang.reflect.Field
;
import
java.sql.Timestamp
;
import
java.text.DecimalFormat
;
import
java.text.DecimalFormatSymbols
;
...
...
@@ -1373,6 +1374,45 @@ public class AbsoluteDateTest {
CoreMatchers
.
is
(
"(-9223372036854775779 + 3.0E300) seconds past epoch"
));
}
@Test
public
void
testNegativeOffsetConstructor
()
{
try
{
AbsoluteDate
date
=
new
AbsoluteDate
(
2019
,
10
,
11
,
20
,
40
,
FastMath
.
scalb
(
6629298651489277.0
,
-
55
),
TimeScalesFactory
.
getTT
());
AbsoluteDate
after
=
date
.
shiftedBy
(
Precision
.
EPSILON
);
Field
epochField
=
AbsoluteDate
.
class
.
getDeclaredField
(
"epoch"
);
epochField
.
setAccessible
(
true
);
Field
offsetField
=
AbsoluteDate
.
class
.
getDeclaredField
(
"offset"
);
offsetField
.
setAccessible
(
true
);
Assert
.
assertEquals
(
624098367L
,
epochField
.
getLong
(
date
));
Assert
.
assertEquals
(
FastMath
.
nextAfter
(
1.0
,
Double
.
NEGATIVE_INFINITY
),
offsetField
.
getDouble
(
date
),
1.0
e
-
20
);
Assert
.
assertEquals
(
Precision
.
EPSILON
,
after
.
durationFrom
(
date
),
1.0
e
-
20
);
}
catch
(
NoSuchFieldException
|
IllegalArgumentException
|
IllegalAccessException
e
)
{
Assert
.
fail
(
e
.
getLocalizedMessage
());
}
}
@Test
public
void
testNegativeOffsetShift
()
{
try
{
AbsoluteDate
reference
=
new
AbsoluteDate
(
2019
,
10
,
11
,
20
,
40
,
1.6667019180022178
E
-
7
,
TimeScalesFactory
.
getTAI
());
double
dt
=
FastMath
.
scalb
(
6596520010750484.0
,
-
39
);
AbsoluteDate
shifted
=
reference
.
shiftedBy
(
dt
);
AbsoluteDate
after
=
shifted
.
shiftedBy
(
Precision
.
EPSILON
);
Field
epochField
=
AbsoluteDate
.
class
.
getDeclaredField
(
"epoch"
);
epochField
.
setAccessible
(
true
);
Field
offsetField
=
AbsoluteDate
.
class
.
getDeclaredField
(
"offset"
);
offsetField
.
setAccessible
(
true
);
Assert
.
assertEquals
(
624110398L
,
epochField
.
getLong
(
shifted
));
Assert
.
assertEquals
(
1.0
-
1.69267
e
-
13
,
offsetField
.
getDouble
(
shifted
),
1.0
e
-
15
);
Assert
.
assertEquals
(
Precision
.
EPSILON
,
after
.
durationFrom
(
shifted
),
1.0
e
-
20
);
}
catch
(
NoSuchFieldException
|
IllegalArgumentException
|
IllegalAccessException
e
)
{
Assert
.
fail
(
e
.
getLocalizedMessage
());
}
}
@Before
public
void
setUp
()
{
Utils
.
setDataRoot
(
"regular-data"
);
...
...
src/test/java/org/orekit/time/FieldAbsoluteDateTest.java
View file @
9887e978
...
...
@@ -287,6 +287,16 @@ public class FieldAbsoluteDateTest {
doTestGetComponentsIssue681and676
(
Decimal64Field
.
getInstance
());
}
@Test
public
void
testNegativeOffsetConstructor
()
{
doTestNegativeOffsetConstructor
(
Decimal64Field
.
getInstance
());
}
@Test
public
void
testNegativeOffsetShift
()
{
doTestNegativeOffsetShift
(
Decimal64Field
.
getInstance
());
}
private
<
T
extends
CalculusFieldElement
<
T
>>
void
doTestStandardEpoch
(
final
Field
<
T
>
field
)
{
TimeScale
tai
=
TimeScalesFactory
.
getTAI
();
...
...
@@ -1200,6 +1210,46 @@ public class FieldAbsoluteDateTest {
MatcherAssert
.
assertThat
(
difference
,
CoreMatchers
.
is
(
Double
.
NaN
));
}
@SuppressWarnings
(
"unchecked"
)
private
<
T
extends
CalculusFieldElement
<
T
>>
void
doTestNegativeOffsetConstructor
(
final
Field
<
T
>
field
)
{
try
{
FieldAbsoluteDate
<
T
>
date
=
new
FieldAbsoluteDate
<>(
field
,
2019
,
10
,
11
,
20
,
40
,
FastMath
.
scalb
(
6629298651489277.0
,
-
55
),
TimeScalesFactory
.
getTT
());
FieldAbsoluteDate
<
T
>
after
=
date
.
shiftedBy
(
Precision
.
EPSILON
);
java
.
lang
.
reflect
.
Field
epochField
=
FieldAbsoluteDate
.
class
.
getDeclaredField
(
"epoch"
);
epochField
.
setAccessible
(
true
);
java
.
lang
.
reflect
.
Field
offsetField
=
FieldAbsoluteDate
.
class
.
getDeclaredField
(
"offset"
);
offsetField
.
setAccessible
(
true
);
Assert
.
assertEquals
(
624098367L
,
epochField
.
getLong
(
date
));
Assert
.
assertEquals
(
FastMath
.
nextAfter
(
1.0
,
Double
.
NEGATIVE_INFINITY
),
((
T
)
offsetField
.
get
(
date
)).
getReal
(),
1.0
e
-
20
);
Assert
.
assertEquals
(
Precision
.
EPSILON
,
after
.
durationFrom
(
date
).
getReal
(),
1.0
e
-
20
);
}
catch
(
NoSuchFieldException
|
IllegalArgumentException
|
IllegalAccessException
e
)
{
Assert
.
fail
(
e
.
getLocalizedMessage
());
}
}
@SuppressWarnings
(
"unchecked"
)
private
<
T
extends
CalculusFieldElement
<
T
>>
void
doTestNegativeOffsetShift
(
final
Field
<
T
>
field
)
{
try
{
FieldAbsoluteDate
<
T
>
reference
=
new
FieldAbsoluteDate
<>(
field
,
2019
,
10
,
11
,
20
,
40
,
1.6667019180022178
E
-
7
,
TimeScalesFactory
.
getTAI
());
T
dt
=
field
.
getZero
().
newInstance
(
FastMath
.
scalb
(
6596520010750484.0
,
-
39
));
FieldAbsoluteDate
<
T
>
shifted
=
reference
.
shiftedBy
(
dt
);
FieldAbsoluteDate
<
T
>
after
=
shifted
.
shiftedBy
(
Precision
.
EPSILON
);
java
.
lang
.
reflect
.
Field
epochField
=
FieldAbsoluteDate
.
class
.
getDeclaredField
(
"epoch"
);
epochField
.
setAccessible
(
true
);
java
.
lang
.
reflect
.
Field
offsetField
=
FieldAbsoluteDate
.
class
.
getDeclaredField
(
"offset"
);
offsetField
.
setAccessible
(
true
);
Assert
.
assertEquals
(
624110398L
,
epochField
.
getLong
(
shifted
));
Assert
.
assertEquals
(
1.0
-
1.69267
e
-
13
,
((
T
)
offsetField
.
get
(
shifted
)).
getReal
(),
1.0
e
-
15
);
Assert
.
assertEquals
(
Precision
.
EPSILON
,
after
.
durationFrom
(
shifted
).
getReal
(),
1.0
e
-
20
);
}
catch
(
NoSuchFieldException
|
IllegalArgumentException
|
IllegalAccessException
e
)
{
Assert
.
fail
(
e
.
getLocalizedMessage
());
}
}
private
<
T
extends
CalculusFieldElement
<
T
>>
void
check
(
FieldAbsoluteDate
<
T
>
date
,
int
year
,
int
month
,
int
day
,
int
hour
,
int
minute
,
double
second
,
double
roundTripUlps
,
final
int
secondUlps
,
final
double
absTol
)
{
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment