That was exactly my thought as well!
So my code is a bit of a mess but I’ll try to walk you through it!
This function is to generate the reference trajectory:
def getReference(x0 = None, t0 = None, integrationTime = None,
write = True, file_name='reference_trajectory.txt',
file_dir='data_files', from_file = False):
"""
Generate reference orbit
Paremeters:
- x0: initial state np.array([px, py, pz, vx, vy, vz])
- t0: initial time (datetime)
- dt: time step for state interpolation (s)
- mass: spacecraft mass (kg)
- write: write to file (boolean)
- file_name: name of file
- file_dir: directory where the file will be stored
Returns:
- array with time, px, py, pz, vx, vy, vz
"""
if from_file:
data = read2file(file_name, file_directory=file_dir)
t, px, py, pz, vx, vy, vz = data[0], data[1], data[2], data[3], data[4], data[5], data[6]
else:
px0, py0, pz0, vx0, vy0, vz0 = x0
pos = Vector3D(float(px0), float(py0), float(pz0))
vel = Vector3D(float(vx0), float(vy0), float(vz0))
t0_absolute = datetime_to_absolutedate(t0)
tpv0 = TimeStampedPVCoordinates(t0_absolute, pos, vel)
initialOrbit = CartesianOrbit(tpv0, frames['eci'], EARTH_MU)
initialSpacecraftState = SpacecraftState(initialOrbit, satellite['mass'])
if propagatorSettings['integration_method'] == 'DOPRI':
integrator = getDORPIIntegrator(initialOrbit)
elif propagatorSettings['integration_method'] == 'RK4':
integrator = getRK4Integrator()
# Here I select which force model I want to use
if propagatorSettings['propagation_method'] == 'Kepler':
propagator = getKeplerPropagator(integrator, initialSpacecraftState)
elif propagatorSettings['propagation_method'] == 'J2':
propagator = getJ2Propagator(integrator, initialSpacecraftState)
elif propagatorSettings['propagation_method'] == 'Advanced':
propagator = getAdvancedPropagator(integrator, initialSpacecraftState)
time_array = [t0_absolute.shiftedBy(float(dt)) for dt in np.arange(0, integrationTime, observationSettings['update_time'])]
state = [propagator.propagate(tt) for tt in time_array]
numSteps = len(state)
px = np.zeros(numSteps)
py = np.zeros(numSteps)
pz = np.zeros(numSteps)
vx = np.zeros(numSteps)
vy = np.zeros(numSteps)
vz = np.zeros(numSteps)
t = []
for i in range(numSteps):
px[i] = float(state[i].getPVCoordinates().getPosition().x)
py[i] = float(state[i].getPVCoordinates().getPosition().y)
pz[i] = float(state[i].getPVCoordinates().getPosition().z)
vx[i] = float(state[i].getPVCoordinates().getVelocity().x)
vy[i] = float(state[i].getPVCoordinates().getVelocity().y)
vz[i] = float(state[i].getPVCoordinates().getVelocity().z)
t.append(absolutedate_to_datetime(time_array[i]))
if write:
write2file(t, px, py, pz, vx, vy, vz,file_name=file_name,file_directory=file_dir)
return np.array([t, px, py, pz, vx, vy, vz]).T
I have three different force models:
def getKeplerPropagator(integrator, initialSpacecraftState):
propagator = NumericalPropagator(integrator)
propagator.setOrbitType(OrbitType.CARTESIAN)
propagator.setInitialState(initialSpacecraftState)
propagator.addForceModel(NewtonianAttraction(EARTH_MU))
return propagator
def getAdvancedPropagator(integrator, initialSpacecraftState):
propagator = NumericalPropagator(integrator)
propagator.setOrbitType(OrbitType.CARTESIAN)
propagator.setInitialState(initialSpacecraftState)
isotropic_drag = IsotropicDrag(satellite['A'], satellite['CD'])
drag = DragForce(environment['atmosphere'], isotropic_drag)
gravityProvider = GravityFieldFactory.getNormalizedProvider(10,10)
radiation = IsotropicRadiationClassicalConvention(satellite['A'], satellite['abs_coef'], satellite['CR'])
srp = SolarRadiationPressure(environment['sun'], environment['earth'], radiation)
# Add forces to propagator
propagator.addForceModel(HolmesFeatherstoneAttractionModel(frames['ecef'], gravityProvider))
propagator.addForceModel(ThirdBodyAttraction(environment['moon']))
propagator.addForceModel(ThirdBodyAttraction(environment['sun']))
propagator.addForceModel(ThirdBodyAttraction(environment['mars']))
propagator.addForceModel(ThirdBodyAttraction(environment['jupiter']))
propagator.addForceModel(ThirdBodyAttraction(environment['saturn']))
propagator.addForceModel(drag)
propagator.addForceModel(srp)
return propagator
def getJ2Propagator(integrator, initialSpacecraftState):
propagator = NumericalPropagator(integrator)
propagator.setOrbitType(OrbitType.CARTESIAN)
propagator.setInitialState(initialSpacecraftState)
gravityProvider = GravityFieldFactory.getNormalizedProvider(2,0)
# Add forces to propagator
propagator.addForceModel(HolmesFeatherstoneAttractionModel(frames['ecef'], gravityProvider))
return propagator
For the measurement builder I have something similar to this:
def getTheoreticalMeasurements(x0 = None, t0 = None, integrationTime = None,
write = True, file_name='theoretical_radar_measurements.txt',
file_dir='data_files', from_file = False):
if from_file:
data = read2file(file_name, file_directory= file_dir)
t, r, a, e, rr = data[0], data[1], data[2], data[3], data[4]
else:
px0, py0, pz0, vx0, vy0, vz0 = x0
pos = Vector3D(float(px0), float(py0), float(pz0))
vel = Vector3D(float(vx0), float(vy0), float(vz0))
t0_absolute = datetime_to_absolutedate(t0)
te_absolute = t0_absolute.shiftedBy(integrationTime)
tpv0 = TimeStampedPVCoordinates(t0_absolute, pos, vel)
initialOrbit = CartesianOrbit(tpv0, frames['eci'], EARTH_MU)
integrator = getDOPRIBuilder()
propagator_ = getKeplerPropagatorBuilder(integrator, initialOrbit)
if propagatorSettings['integration_method'] == 'DOPRI':
integrator = getDOPRIBuilder()
elif propagatorSettings['integration_method'] == 'RK4':
integrator = getRK4Builder()
# Again, here I select which dynamics model to use
if propagatorSettings['propagation_method'] == 'Kepler':
propagator = getKeplerPropagatorBuilder(integrator, initialOrbit)
elif propagatorSettings['propagation_method'] == 'J2':
propagator = getJ2PropagatorBuilder(integrator, initialOrbit)
elif propagatorSettings['propagation_method'] == 'Advanced':
propagator = getAdvancedPropagatorBuilder(integrator, initialOrbit)
propagator = propagator_.buildPropagator(propagator_.getSelectedNormalizedParameters())
time_array = [t0_absolute.shiftedBy(float(dt)) for dt in np.arange(0, integrationTime, observationSettings['update_time'])]
# Generate range measurements
rangeBuilder = RangeBuilder(
observationSettings['noise_source'],
observationSettings['ground_station'],
observationSettings['two_way'],
observationSettings['std'],
observationSettings['base_weight'],
observationSettings['satellite']
)
dataSelectorRange = FixedStepSelector(observationSettings['update_time'],UTC)
rangeScheduler = ContinuousScheduler(rangeBuilder, dataSelectorRange)
rangeSubscriber = GatheringSubscriber()
rangeGenerator = Generator()
rangeGenerator.addPropagator(propagator)
rangeGenerator.addSubscriber(rangeSubscriber)
rangeGenerator.addScheduler(rangeScheduler)
rangeGenerator.generate(t0_absolute, te_absolute)
rangeMeasurements = rangeSubscriber.getGeneratedMeasurements()
rangeArray = rangeMeasurements.toArray()
numMeas = len(rangeArray)
r = np.zeros(numMeas)
t = []
for i in range(numMeas):
t.append(absolutedate_to_datetime(time_array[i]))
r[i] = Range.cast_(rangeArray[i]).getObservedValue()[0]
# Generate angular measuremetns (azimuth and elevation)
AzElBuilder = AngularAzElBuilder(
observationSettings['noise_source'],
observationSettings['ground_station'],
[observationSettings['std'], observationSettings['std']],
[observationSettings['base_weight'], observationSettings['base_weight']],
observationSettings['satellite']
)
dataSelectorAzEl = FixedStepSelector(observationSettings['update_time'], UTC)
AzElScheduler = ContinuousScheduler(AzElBuilder, dataSelectorAzEl)
AzElSubscriber = GatheringSubscriber()
AzElGenerator = Generator()
AzElGenerator.addPropagator(propagator)
AzElGenerator.addSubscriber(AzElSubscriber)
AzElGenerator.addScheduler(AzElScheduler)
AzElGenerator.generate(t0_absolute, te_absolute)
AzElMeasurements = AzElSubscriber.getGeneratedMeasurements()
AzElArray = AzElMeasurements.toArray()
a = np.zeros(numMeas)
e = np.zeros(numMeas)
for i in range(numMeas):
a[i] = AngularAzEl.cast_(AzElArray[i]).getObservedValue()[0]
e[i] = AngularAzEl.cast_(AzElArray[i]).getObservedValue()[1]
# Generate range rate measurements
rangerateBuilder = RangeRateBuilder(
observationSettings['noise_source'],
observationSettings['ground_station'],
observationSettings['two_way'],
observationSettings['std'],
observationSettings['base_weight'],
observationSettings['satellite']
)
dataSelectorRangeRate = FixedStepSelector(observationSettings['update_time'], UTC)
rangerateScheduler = ContinuousScheduler(rangerateBuilder, dataSelectorRangeRate)
rangerateSubscriber = GatheringSubscriber()
rangerateGenerator = Generator()
rangerateGenerator.addPropagator(propagator)
rangerateGenerator.addSubscriber(rangerateSubscriber)
rangerateGenerator.addScheduler(rangerateScheduler)
rangerateGenerator.generate(t0_absolute, te_absolute)
rangerateMeasurements = rangerateSubscriber.getGeneratedMeasurements()
rangerateArray = rangerateMeasurements.toArray()
rr = np.zeros(numMeas)
for i in range(numMeas):
rr[i] = RangeRate.cast_(rangerateArray[i]).getObservedValue()[0]
if write:
write2file(t, r, a, e, rr, file_name = file_name, file_directory=file_dir)
return np.array([t, r, a, e, rr]).T
With the following, similar, dynamics models:
def getKeplerPropagatorBuilder(integrator, initialOrbit):
propagatorBuilder = NumericalPropagatorBuilder(initialOrbit, integrator, PositionAngleType.TRUE, 1.0)
propagatorBuilder.addForceModel(NewtonianAttraction(EARTH_MU))
return propagatorBuilder
def getAdvancedPropagatorBuilder(integrator, initialOrbit):
propagatorBuilder = NumericalPropagatorBuilder(initialOrbit, integrator, PositionAngleType.TRUE, 1.0)
isotropic_drag = IsotropicDrag(satellite['A'], satellite['CD'])
drag = DragForce(environment['atmosphere'], isotropic_drag)
gravityProvider = GravityFieldFactory.getNormalizedProvider(10,10)
radiation = IsotropicRadiationClassicalConvention(satellite['A'], satellite['abs_coef'], satellite['CR'])
srp = SolarRadiationPressure(environment['sun'], environment['earth'], radiation)
# Add forces to propagator
propagatorBuilder.addForceModel(HolmesFeatherstoneAttractionModel(frames['ecef'], gravityProvider))
propagatorBuilder.addForceModel(ThirdBodyAttraction(environment['moon']))
propagatorBuilder.addForceModel(ThirdBodyAttraction(environment['sun']))
propagatorBuilder.addForceModel(ThirdBodyAttraction(environment['mars']))
propagatorBuilder.addForceModel(ThirdBodyAttraction(environment['jupiter']))
propagatorBuilder.addForceModel(ThirdBodyAttraction(environment['saturn']))
propagatorBuilder.addForceModel(drag)
propagatorBuilder.addForceModel(srp)
return propagatorBuilder
def getJ2PropagatorBuilder(integrator, initialOrbit):
propagatorBuilder = NumericalPropagatorBuilder(initialOrbit, integrator, PositionAngleType.TRUE, 1.0)
gravityProvider = GravityFieldFactory.getNormalizedProvider(2,0)
# Add forces to propagator
propagatorBuilder.addForceModel(HolmesFeatherstoneAttractionModel(frames['ecef'], gravityProvider))
return propagatorBuilder
I think these are the most important snippets of the code, but I uploaded the code below:
main.py (153.5 KB)
Thanks for responding!