Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
Orekit
Orekit tutorials
Commits
f635e660
Commit
f635e660
authored
Nov 03, 2020
by
Luc Maisonobe
1
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added tutorial for impulsive maneuvers.
parent
d912fb2a
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
317 additions
and
0 deletions
+317
-0
src/changes/changes.xml
src/changes/changes.xml
+6
-0
src/main/java/org/orekit/tutorials/maneuvers/ImpulseAtNode.java
...in/java/org/orekit/tutorials/maneuvers/ImpulseAtNode.java
+158
-0
src/site/markdown/tutorials/maneuvers.md
src/site/markdown/tutorials/maneuvers.md
+152
-0
src/site/site.xml
src/site/site.xml
+1
-0
No files found.
src/changes/changes.xml
View file @
f635e660
...
...
@@ -20,6 +20,12 @@
<title>
Orekit Tutorials Changes
</title>
</properties>
<body>
<release
version=
"10.3"
date=
"TBC"
description=
"TBC."
>
<action
dev=
"luc"
type=
"add"
issue=
"7"
>
Added tutorial for impulsive maneuvers.
</action>
</release>
<release
version=
"10.2"
date=
"2020-07-16"
description=
"Version 10.2 is the second release of the Orekit Tutorials.
The version number is 10.2 to follow Orekit version number.
...
...
src/main/java/org/orekit/tutorials/maneuvers/ImpulseAtNode.java
0 → 100644
View file @
f635e660
/* Copyright 2002-2020 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.tutorials.maneuvers
;
import
java.io.File
;
import
java.util.Locale
;
import
org.hipparchus.geometry.euclidean.threed.Vector3D
;
import
org.hipparchus.util.FastMath
;
import
org.orekit.attitudes.AttitudeProvider
;
import
org.orekit.attitudes.LofOffset
;
import
org.orekit.data.DataContext
;
import
org.orekit.data.DataProvidersManager
;
import
org.orekit.data.DirectoryCrawler
;
import
org.orekit.errors.OrekitException
;
import
org.orekit.forces.maneuvers.ImpulseManeuver
;
import
org.orekit.frames.Frame
;
import
org.orekit.frames.FramesFactory
;
import
org.orekit.frames.LOFType
;
import
org.orekit.orbits.KeplerianOrbit
;
import
org.orekit.orbits.Orbit
;
import
org.orekit.orbits.PositionAngle
;
import
org.orekit.propagation.analytical.KeplerianPropagator
;
import
org.orekit.propagation.events.EnablingPredicate
;
import
org.orekit.propagation.events.EventDetector
;
import
org.orekit.propagation.events.EventEnablingPredicateFilter
;
import
org.orekit.propagation.events.NodeDetector
;
import
org.orekit.propagation.events.handlers.StopOnIncreasing
;
import
org.orekit.time.AbsoluteDate
;
import
org.orekit.time.DateComponents
;
import
org.orekit.time.TimeComponents
;
import
org.orekit.time.TimeScalesFactory
;
import
org.orekit.utils.Constants
;
/**
* Orekit tutorial for simple impulsive maneuver.
*
* <p>This tutorial shows a basic usage for performing
* an impulsive inclination maneuver at node.</p>
* @author Luc Maisonobe
*/
public
class
ImpulseAtNode
{
/** Private constructor for utility class. */
private
ImpulseAtNode
()
{
// empty
}
/**
* Program entry point.
* @param args program arguments (unused here)
*/
public
static
void
main
(
final
String
[]
args
)
{
try
{
// configure Orekit
final
File
home
=
new
File
(
System
.
getProperty
(
"user.home"
));
final
File
orekitData
=
new
File
(
home
,
"orekit-data"
);
if
(!
orekitData
.
exists
())
{
System
.
err
.
format
(
Locale
.
US
,
"Failed to find %s folder%n"
,
orekitData
.
getAbsolutePath
());
System
.
err
.
format
(
Locale
.
US
,
"You need to download %s from %s, unzip it in %s and rename it 'orekit-data' for this tutorial to work%n"
,
"orekit-data-master.zip"
,
"https://gitlab.orekit.org/orekit/orekit-data/-/archive/master/orekit-data-master.zip"
,
home
.
getAbsolutePath
());
System
.
exit
(
1
);
}
final
DataProvidersManager
manager
=
DataContext
.
getDefault
().
getDataProvidersManager
();
manager
.
addProvider
(
new
DirectoryCrawler
(
orekitData
));
// set up an initial orbit, with 50 degrees inclination
final
Frame
eme2000
=
FramesFactory
.
getEME2000
();
final
Orbit
initialOrbit
=
new
KeplerianOrbit
(
8000000.0
,
0.01
,
FastMath
.
toRadians
(
50.0
),
// ← this is initial inclination
FastMath
.
toRadians
(
140.0
),
FastMath
.
toRadians
(
12.0
),
FastMath
.
toRadians
(-
60.0
),
PositionAngle
.
MEAN
,
eme2000
,
new
AbsoluteDate
(
new
DateComponents
(
2008
,
6
,
23
),
new
TimeComponents
(
14
,
0
,
0
),
TimeScalesFactory
.
getUTC
()),
Constants
.
EIGEN5C_EARTH_MU
);
// the maneuver will be defined in spacecraft frame
// we need to ensure the Z axis is aligned with orbital momentum
// so we select an attitude aligned with LVLH Local Orbital frame
final
AttitudeProvider
attitudeProvider
=
new
LofOffset
(
eme2000
,
LOFType
.
LVLH
);
// we want to perform a series of 3 inclination reduction maneuvers,
// as they modify only inclination, they must occur at node
// but not all nodes are suitable, we want ascending nodes, with a ΔV along -Z
// the maneuvers are triggered when Action.STOP events occur (and are filtered out)
final
NodeDetector
ascendingNodeStopper
=
new
NodeDetector
(
FramesFactory
.
getEME2000
()).
withMaxCheck
(
300.0
).
withThreshold
(
1.0
e
-
6
).
withHandler
(
new
StopOnIncreasing
<>());
// we allow only maneuvers on the first 3 orbits
final
AbsoluteDate
lastAllowedDate
=
initialOrbit
.
getDate
().
shiftedBy
(
3
*
initialOrbit
.
getKeplerianPeriod
());
final
EnablingPredicate
<
EventDetector
>
predicate
=
(
state
,
detector
,
g
)
->
state
.
getDate
().
isBefore
(
lastAllowedDate
);
final
EventDetector
trigger
=
new
EventEnablingPredicateFilter
<>(
ascendingNodeStopper
,
predicate
);
// create the maneuver, using ascending node detector as a trigger
final
ImpulseManeuver
<
EventDetector
>
maneuver
=
new
ImpulseManeuver
<>(
trigger
,
new
Vector3D
(
0.0
,
0.0
,
-
122.25
),
// ← 122.25 m/s along -Z
350.0
);
// wrap-up everything in a propagator
// note that ImpulseManeuver is a event detector, not a force model!
// this allows it to be used for all propagators, including analytical ones
// like the Keplerian propagator used here
final
KeplerianPropagator
propagator
=
new
KeplerianPropagator
(
initialOrbit
,
attitudeProvider
);
propagator
.
addEventDetector
(
maneuver
);
// progress monitoring: we should see inclination remain constant as we
// cross descending nodes (i.e. switch from Northern to Southern
// hemisphere), and change as we cross the first three ascending nodes
propagator
.
setMasterMode
(
900.0
,
(
state
,
isLast
)
->
{
final
Vector3D
pos
=
state
.
getPVCoordinates
(
eme2000
).
getPosition
();
System
.
out
.
format
(
Locale
.
US
,
"%s %s hemisphere inclination = %5.3f%n"
,
state
.
getDate
(),
pos
.
getZ
()
>
0
?
"Northern"
:
"Southern"
,
FastMath
.
toDegrees
(
state
.
getOrbit
().
getI
()));
});
// run simulation
propagator
.
propagate
(
initialOrbit
.
getDate
().
shiftedBy
(
5
*
initialOrbit
.
getKeplerianPeriod
()));
System
.
exit
(
0
);
}
catch
(
OrekitException
e
)
{
System
.
err
.
println
(
e
.
getLocalizedMessage
());
System
.
exit
(
1
);
}
}
}
src/site/markdown/tutorials/maneuvers.md
0 → 100644
View file @
f635e660
<!--- Copyright 2002-2020 CS GROUP
Licensed 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.
-->
# Maneuvers
The next tutorials detail some elementary usages of the maneuvers,
ranging from simple impulsive maneuvers (which can be used in
many propagators, including analytical ones) to continuous thrust
maneuvers (which can only be used with integration-based propagators).
## Impulsive maneuvers
Impulsive maneuvers are very simple discrete changes to the velocity
of a spacecraft. They are mainly used in two cases:
-
for station-keeping, as they remain realistic models given the small
size of the required maneuvers
-
for initialization of optimization or search algorithm that will
internally use more realistic models for large maneuvers
This tutorial shows how to implement a series of maneuvers to change
progressively the inclination of an orbit.
In this case, the calling application coordinates all the tasks, the propagator just propagates.
Let's set up an initial state as:
final Frame eme2000 = FramesFactory.getEME2000();
final Orbit initialOrbit =
new KeplerianOrbit(8000000.0, 0.01,
FastMath.toRadians(50.0), // ← this is initial inclination
FastMath.toRadians(140.0),
FastMath.toRadians(12.0),
FastMath.toRadians(-60.0), PositionAngle.MEAN,
eme2000,
new AbsoluteDate(new DateComponents(2008, 6, 23),
new TimeComponents(14, 0, 0),
TimeScalesFactory.getUTC()),
Constants.EIGEN5C_EARTH_MU);
The maneuver will be defined in spacecraft frame. We need to ensure the Z axis is
aligned with orbital momentum, so we select an attitude aligned with LVLH
Local Orbital frame
final AttitudeProvider attitudeProvider = new LofOffset(eme2000, LOFType.LVLH);
We want to perform a series of 3 inclination reduction maneuvers. As they modify
only inclination, they must occur at node, but not all nodes are suitable, we want
ascending nodes, with a ΔV along -Z. The maneuvers are triggered when
`Action.STOP`
events occur (and are filtered out)
final NodeDetector ascendingNodeStopper =
new NodeDetector(FramesFactory.getEME2000()).
withMaxCheck(300.0).
withThreshold(1.0e-6).
withHandler(new StopOnIncreasing<>());
We allow only maneuvers on the first 3 orbits
final AbsoluteDate lastAllowedDate =
initialOrbit.getDate().shiftedBy(3 * initialOrbit.getKeplerianPeriod());
final EnablingPredicate<EventDetector> predicate =
(state, detector, g) -> state.getDate().isBefore(lastAllowedDate);
final EventDetector trigger =
new EventEnablingPredicateFilter<>(ascendingNodeStopper, predicate);
Create the maneuver, using ascending node detector as a trigger
final ImpulseManeuver<EventDetector> maneuver =
new ImpulseManeuver<>(trigger,
new Vector3D(0.0, 0.0, -122.25), // ← 122.25 m/s along -Z
350.0);
Wrap-up everything in a propagator. Note that ImpulseManeuver is a event detector,
not a force model! This allows it to be used for all propagators, including
analytical ones like the Keplerian propagator used here
final KeplerianPropagator propagator = new KeplerianPropagator(initialOrbit, attitudeProvider);
propagator.addEventDetector(maneuver);
Progress monitoring
propagator.setMasterMode(900.0, (state, isLast) -> {
final Vector3D pos = state.getPVCoordinates(eme2000).getPosition();
System.out.format(Locale.US, "%s %s hemisphere inclination = %5.3f%n",
state.getDate(),
pos.getZ() > 0 ? "Northern" : "Southern",
FastMath.toDegrees(state.getOrbit().getI()));
});
Run simulation
propagator.propagate(initialOrbit.getDate().shiftedBy(5 * initialOrbit.getKeplerianPeriod()));
The printed result is shown below. We see that inclination remains constant as
we cross descending nodes (i.e. switch from Northern to Southern hemisphere),
and changes as we cross the first three ascending nodes
2008-06-23T14:00:00.000 Northern hemisphere inclination = 50.000
2008-06-23T14:15:00.000 Northern hemisphere inclination = 50.000
2008-06-23T14:30:00.000 Northern hemisphere inclination = 50.000
2008-06-23T14:45:00.000 Southern hemisphere inclination = 50.000
2008-06-23T15:00:00.000 Southern hemisphere inclination = 50.000
2008-06-23T15:15:00.000 Southern hemisphere inclination = 50.000
2008-06-23T15:30:00.000 Southern hemisphere inclination = 50.000
2008-06-23T15:45:00.000 Northern hemisphere inclination = 49.000
2008-06-23T16:00:00.000 Northern hemisphere inclination = 49.000
2008-06-23T16:15:00.000 Northern hemisphere inclination = 49.000
2008-06-23T16:30:00.000 Northern hemisphere inclination = 49.000
2008-06-23T16:45:00.000 Southern hemisphere inclination = 49.000
2008-06-23T17:00:00.000 Southern hemisphere inclination = 49.000
2008-06-23T17:15:00.000 Southern hemisphere inclination = 49.000
2008-06-23T17:30:00.000 Southern hemisphere inclination = 49.000
2008-06-23T17:45:00.000 Northern hemisphere inclination = 48.001
2008-06-23T18:00:00.000 Northern hemisphere inclination = 48.001
2008-06-23T18:15:00.000 Northern hemisphere inclination = 48.001
2008-06-23T18:30:00.000 Northern hemisphere inclination = 48.001
2008-06-23T18:45:00.000 Southern hemisphere inclination = 48.001
2008-06-23T19:00:00.000 Southern hemisphere inclination = 48.001
2008-06-23T19:15:00.000 Southern hemisphere inclination = 48.001
2008-06-23T19:30:00.000 Southern hemisphere inclination = 48.001
2008-06-23T19:45:00.000 Northern hemisphere inclination = 47.001
2008-06-23T20:00:00.000 Northern hemisphere inclination = 47.001
2008-06-23T20:15:00.000 Northern hemisphere inclination = 47.001
2008-06-23T20:30:00.000 Southern hemisphere inclination = 47.001
2008-06-23T20:45:00.000 Southern hemisphere inclination = 47.001
2008-06-23T21:00:00.000 Southern hemisphere inclination = 47.001
2008-06-23T21:15:00.000 Southern hemisphere inclination = 47.001
2008-06-23T21:30:00.000 Northern hemisphere inclination = 47.001
2008-06-23T21:45:00.000 Northern hemisphere inclination = 47.001
2008-06-23T22:00:00.000 Northern hemisphere inclination = 47.001
2008-06-23T22:15:00.000 Northern hemisphere inclination = 47.001
2008-06-23T22:30:00.000 Southern hemisphere inclination = 47.001
2008-06-23T22:45:00.000 Southern hemisphere inclination = 47.001
2008-06-23T23:00:00.000 Southern hemisphere inclination = 47.001
2008-06-23T23:15:00.000 Southern hemisphere inclination = 47.001
2008-06-23T23:30:00.000 Northern hemisphere inclination = 47.001
2008-06-23T23:45:00.000 Northern hemisphere inclination = 47.001
The complete code for this example can be found in the source tree of the tutorials,
in file
`src/main/java/org/orekit/tutorials/maneuvers/ImpulseAtNode.java`
.
src/site/site.xml
View file @
f635e660
...
...
@@ -39,6 +39,7 @@
<item
name=
"Frames"
href=
"/tutorials/frames.html"
/>
<item
name=
"Propagation"
href=
"/tutorials/propagation.html"
/>
<item
name=
"Propagation in non-inertial frame"
href=
"/tutorials/propagation-in-non-inertial-frame.html"
/>
<item
name=
"Maneuvers"
href=
"/tutorials/maneuvers.html"
/>
<item
name=
"Time"
href=
"/tutorials/time.html"
/>
<item
name=
"Geomagnetic field"
href=
"/tutorials/geomagnetic-field.html"
/>
<item
name=
"Integration in other languages"
href=
"/tutorials/integration-in-other-languages.html"
/>
...
...
Luc Maisonobe
@luc
mentioned in commit
08baf57d
·
Nov 04, 2020
mentioned in commit
08baf57d
mentioned in commit 08baf57d044b2d089c77635d2f975ef37614f03d
Toggle commit list
Write
Preview
Markdown
is supported
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