Dear Luc,
thank you for your reply. I have implemented your comments, I wanted to know if from code side everything seems fine or if I am incorrectly propagating the orbits / obtaining the relative positions.
Note that I am using the same “propagationType” for the propagator definition and the tolerances, but does it matter if I choose keplerian or cartesian?
Furthermore, by choosing (60,60) for the gravity model, does this mean I am including harmonics parameters up to J60?
# Initial date
year = 2026
month = 1
day = 1
hour = 12
minute = 0
seconds = 00.000
duration = 5650. # Propagation duration [s]
step_time = 0.4 # Propagation step-time [s]
#Orbital parameters (keplerian)
a = 6890. * 1000 # Orbit semi-major axis [m]
e = 0.001 # Orbit eccentricity [-]
i = radians(97.4) # Orbit inclination [rad]
omega = radians(90.0) # Orbit perigee argument [rad]
raan = radians(50.0) # Orbit RAAN [rad]
true_anomaly = radians(90.0) # Spacecraft true anomaly [rad]
at_separation = 200 # Spacecraft along-track separation [m]
### here funciton to compute delta-true anomaly based on along track separation - skipped for easier reading ###
utc = TimeScalesFactory.getUTC()
epochDate = AbsoluteDate(year, month, day, hour, minute, seconds, utc) # Propagation start-time [s]
# Initial orbit definition, spacecraft behind in the formation
initialOrbit = KeplerianOrbit(a, e, i, omega, raan, true_anomaly,
PositionAngle.TRUE,
inertialFrame, epochDate, Constants.EIGEN5C_EARTH_MU)
# Initial orbit definition, first spacecraft of the formation
initialOrbit2 = KeplerianOrbit(a, e, i, omega, raan, true_anomaly+dtheta,
PositionAngle.TRUE,
inertialFrame, epochDate, Constants.EIGEN5C_EARTH_MU)
satellite_mass = 20.
# Numerical propagator definition
# Step size
minStep = 0.001
maxStep = 10.
initStep = 0.4
positionTolerance = 1E-3
propagationType = OrbitType.CARTESIAN
tolerances = NumericalPropagator.tolerances(positionTolerance, initialOrbit, propagationType)
# Spacecraft behind - numerical propagator
integrator = DormandPrince853Integrator(minStep, maxStep, orekit.JArray('double').cast_(tolerances[0]), orekit.JArray('double').cast_(tolerances[1]))
integrator.setInitialStepSize((initStep))
numericalPropagator = NumericalPropagator(integrator)
numericalPropagator.setOrbitType(propagationType)
itrf = FramesFactory.getITRF(IERSConventions.IERS_2010, True) # International Terrestrial Reference Frame, earth fixed
earth = OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
Constants.WGS84_EARTH_FLATTENING,
itrf)
gravityProvider = GravityFieldFactory.getNormalizedProvider(60, 60)
numericalPropagator.addForceModel(HolmesFeatherstoneAttractionModel(earth.getBodyFrame(), gravityProvider))
numericalPropagator.setInitialState(SpacecraftState(initialOrbit, satellite_mass))
# First spacecraft in the formation - numerical propagator
tolerances2 = NumericalPropagator.tolerances(positionTolerance, initialOrbit2, propagationType)
integrator2 = DormandPrince853Integrator(minStep, maxStep, orekit.JArray('double').cast_(tolerances2[0]), orekit.JArray('double').cast_(tolerances2[1]))
integrator2.setInitialStepSize((initStep))
numericalPropagator2 = NumericalPropagator(integrator2)
numericalPropagator2.setOrbitType(propagationType)
numericalPropagator2.addForceModel(HolmesFeatherstoneAttractionModel(earth.getBodyFrame(), gravityProvider))
numericalPropagator2.setInitialState(SpacecraftState(initialOrbit2, satellite_mass))
# Drag
crossSection_drag = 0.1
dragCoeff = 2.2
strenghtLevel = MarshallSolarActivityFutureEstimation.StrengthLevel.AVERAGE
supportedNames = MarshallSolarActivityFutureEstimation.DEFAULT_SUPPORTED_NAMES
inputParameters_Drag = MarshallSolarActivityFutureEstimation(supportedNames, strenghtLevel)
atmosphere = NRLMSISE00(inputParameters_Drag, sun, earth)
spacecraftDrag = IsotropicDrag(crossSection_drag, dragCoeff)
drag = DragForce(atmosphere, spacecraftDrag)
numericalPropagator.addForceModel(drag)
numericalPropagator2.addForceModel(drag)
# SRP
crossSection_SRP = 0.1
reflectivityCoeff = 1.3
spacecraftSRP = IsotropicRadiationSingleCoefficient(crossSection_SRP, reflectivityCoeff)
solarRadiationPressure = SolarRadiationPressure(sun, R_e, spacecraftSRP)
numericalPropagator.addForceModel(solarRadiationPressure)
numericalPropagator2.addForceModel(solarRadiationPressure)
#Moon and Sun perturbations
moon = CelestialBodyFactory.getMoon()
sun = CelestialBodyFactory.getSun()
moon_3dbodyattraction = ThirdBodyAttraction(moon)
numericalPropagator.addForceModel(moon_3dbodyattraction)
numericalPropagator2.addForceModel(moon_3dbodyattraction)
sun_3dbodyattraction = ThirdBodyAttraction(sun)
numericalPropagator.addForceModel(sun_3dbodyattraction)
numericalPropagator2.addForceModel(sun_3dbodyattraction)
# Start propagations
initialDate = epochDate
t = [initialDate.shiftedBy(float(dt)) for dt in np.arange(0, duration, step_time)]
# Propagated orbits
spacecraft1 = [numericalPropagator.propagate(tt) for tt in t]
spacecraft2 = [numericalPropagator2.propagate(tt) for tt in t]
# Behind spacecraft coordinates
pv = [x.getPVCoordinates() for x in spacecraft1]
p = [tpv.getPosition() for tpv in pv]
v1 = [tpv.getVelocity() for tpv in pv]
# LVLH of behind spacecraft
lvlh = [LofOffset(sc1.getFrame(), LOFType.LVLH_CCSDS) for sc1 in spacecraft1]
# Conversion function
converted_sc1 = [SpacecraftState(placeholder1.getOrbit(),
placeholder2.getAttitude(placeholder1.getOrbit(), placeholder1.getDate(), placeholder1.getFrame())) for placeholder1, placeholder2in zip(spacecraft1, lvlh)]
# Positions of spacecraft 2 (first) with respect to LVLH of spacecraft 1 (behind)
pv2t = [a.toTransform().transformPVCoordinates(y.getPVCoordinates(x.getFrame())) for a,y,x in zip(converted_sc1, spacecraft2, spacecraft1)]