Hello @MaximeJ,
Unfortunately no luck figuring this out yet - I’ve been looking at using the master-mode which is probably more ‘orekit-ian’ anyway, but it would be good to understand this behavior in slave mode.
Here is a setup in python that shows the issue. If you toggle the ‘stepwise’ flag (True/False), this will walk the slave-mode propagator either through defined time steps up to final time t, OR input final time t as the single propagation time. The maneuvers only happen in the later case, when it’s set to False.
A side issue I’ve been scratching my head over is that the span duration must be 2.0 * the orbit period (T) or no maneuver happens. For example span = 1.0 or 1.8T no maneuver, and the trigger is mean anomaly, so anything >1.0T should always work. Maybe I’ll make another post for that though.
Thanks!
import orekit
from orekit.pyhelpers import setup_orekit_curdir
from org.orekit.attitudes import LofOffset
from org.orekit.utils import Constants, IERSConventions
from org.orekit.forces.maneuvers import ImpulseManeuver
from org.orekit.frames import FramesFactory, LOFType
from org.orekit.propagation import PropagationType, SpacecraftState
from org.orekit.propagation.conversion import DSSTPropagatorBuilder, DormandPrince853IntegratorBuilder
from org.orekit.propagation.events import PositionAngleDetector, EventDetector, EventEnablingPredicateFilter
from org.orekit.time import TimeScalesFactory, AbsoluteDate, UT1Scale, TimeScales
from org.orekit.orbits import KeplerianOrbit, PositionAngle, OrbitType
from org.hipparchus.geometry.euclidean.threed import Vector3D
import math
vm = orekit.initVM()
setup_orekit_curdir()
eme2000 = FramesFactory.getEME2000()
utc = TimeScalesFactory.getUTC()
mu = Constants.EIGEN5C_EARTH_MU
startDate = AbsoluteDate(2021, 1, 21, 12, 58, 59.00, utc)
initialOrbit2 = KeplerianOrbit(1000_000.0, # a
0.01, # e
math.radians(50.0), # inc
math.radians(140.0), # pa
math.radians(10.0), # raan
math.radians(10.0), # anomaly
PositionAngle.MEAN,
eme2000,
startDate,
mu
)
'''
Set sat attitude frame:
- VNC: Velocity - Normal - Co-normal frame (X axis aligned with velocity, Y axis aligned with orbital momentum)
'''
attitudeOverride = LofOffset(eme2000, LOFType.VNC)
sc_state2 = SpacecraftState(initialOrbit2)
# Propagator:
min_step = 1.0
max_step = 100.0
pos_err = 10.0
prop_builder = DSSTPropagatorBuilder(initialOrbit2,
DormandPrince853IntegratorBuilder(min_step, max_step, pos_err),
1.0, # position 'scaling factor'. Typically standard dev of pos err
PropagationType.MEAN, # type OF THE ORBIT used for prop
PropagationType.MEAN # type of elements used to define orbital state
)
propagator2 = prop_builder.buildPropagator(prop_builder.getSelectedNormalizedParameters())
# Create maneuver trigger on mean anomaly, specified below:
angle = math.radians(0.0)
trigger = PositionAngleDetector(OrbitType.KEPLERIAN, PositionAngle.TRUE, angle)
# Create maneuver with trigger (in-track, +ve dir)
dv_dir = Vector3D.PLUS_I.scalarMultiply(100.0)
maneuver = ImpulseManeuver(trigger,
attitudeOverride,
dv_dir, # delta-v dir, along x-axis (i,j,k)
500.0 # ISP - required but NOT used for impuslive. weird
)
# add maneuver to propagator
propagator2.addEventDetector(maneuver)
print(f"- Initial attributes:")
print(f"SMA, km: {round(initialOrbit2.getA(),3) / 1000.0 }")
print(f"RAAN: {round(math.degrees(initialOrbit2.getRightAscensionOfAscendingNode()),3)}")
print(f"Inc: {round(math.degrees(initialOrbit2.getI()),3)}")
# propagate
span_sec = 2.0 * initialOrbit2.getKeplerianPeriod()
step_sec = 100.0
# Now propagate one of two different ways, both using slave mode, but one with predefined steps, the other right
# to the end of time span:
stepwise = True # toggle this to see the difference
if stepwise: # propagate and print in defined steps
print(f"Mean_Anom(deg), SMA (km)")
for t in range(1, round(span_sec / step_sec)):
state = propagator2.propagate(startDate.shiftedBy(t*step_sec))
kep_orb = KeplerianOrbit(state.getOrbit())
SMA = round(kep_orb.getA(), 2)
mean_anom = round(math.degrees(kep_orb.getMeanAnomaly()), 3)
print(f"{mean_anom}: {SMA / 1000.0}")
else: # give the propagator the final end time
state = propagator2.propagate(startDate.shiftedBy(span_sec))
finalOrbit = state.getOrbit()
finalOrb_Kep = KeplerianOrbit(finalOrbit)
final_SMA = round(finalOrbit.getA() / 1000, 5)
final_RAAN = round(math.degrees(finalOrb_Kep.getRightAscensionOfAscendingNode()), 5)
final_inc = round(math.degrees(finalOrb_Kep.getI()), 5)
print(f"\n- Final attributes:")
print(f"SMA, km: {final_SMA}")
print(f"RAAN: {final_RAAN}")
print(f"Inc: {final_inc}")