I’ve been building playing with a sequential UKF and generating synthetic angle only measurement for sample data. The filter seems to work great which gives me confidence that the measurements are being generated correctly. I wanted to produce the initial guess via IOD and the results have been absolutely horrible, even for long arcs.
Here is how I create measurements
def simluate_orbit_measurements( # type: ignore
reference_orbit: Orbit,
topo_frame: TopocentricFrame,
t0: AbsoluteDate,
tf: AbsoluteDate,
step: float = 1.0,
az_cov: float = 0.001,
el_cov: float = 0.001,
small: float = 0.00001,
sigma_az: float = 0.001,
sigma_el: float = 0.001,
):
"""
Create simulated measurements.
Args:
reference_orbit (Orbit): reference orbit
topo_frame (TopocentricFrame): topo frame of the observer
t0 (AbsoluteDate): meas period start time
tf (AbsoluteDate): meas period end time
step (float): measurement time step
az_cov (float): process noise covariance matrix index [0, 0].
Azimuth and elevation are being treated as
independent variable for simplicity’s sake so
az_cov and el_cov are used to populate a
diagonal matrix
el_cov (float): process noise covariance matrix index [1, 1].
small (float): Diagonal elements threshold under which column
are considered to be dependent on previous ones
and are discarded. This is straight from
Orekit definition
sigma_az (float):
sigma_el (float):
Returns
-------
Set[AngularAzEl]
"""
# create propagator for reference orbit
prop_kep = KeplerianPropagator(reference_orbit, EARTH_MU)
# create ground station that's measuring the simulated measurements
ground_station: GroundStation = GroundStation(topo_frame)
# create measurement generator
meas_gen = Generator() # type: ignore
obs_sat = meas_gen.addPropagator(prop_kep)
subscriber = GatheringSubscriber() # type: ignore
subscriber.init(t0, tf)
meas_gen.addSubscriber(subscriber)
# this adds noise to the measurements
vec_gen = CorrelatedRandomVectorGenerator(
DiagonalMatrix([az_cov, el_cov]),
small,
GaussianRandomGenerator(RandomDataGenerator()),
)
# give equal weights to az and el hence [1.0, 1.0] magic numbers. No need to make
# this function infinitely configurable
azel_builder = AngularAzElBuilder(
vec_gen, ground_station, [sigma_az, sigma_el], [1.0, 1.0], obs_sat
)
# generate measurements only when visible, that way we don't get atmospheric
# corrections erroring out or some other unforeseen behavior
elevation_detector = ElevationDetector(topo_frame)
event_scheduler = EventBasedScheduler(
azel_builder,
FixedStepSelector(step, UTC),
prop_kep,
elevation_detector,
SignSemantic.FEASIBLE_MEASUREMENT_WHEN_POSITIVE,
)
meas_gen.addScheduler(event_scheduler)
meas_gen.generate(t0, tf)
measurements = subscriber.getGeneratedMeasurements()
return measurements
This generates about 2000 measurements from which I pick three and try Gauss, Laplace, and Gooding IODs. I won’t go into my implementation of how I call these IOD methods because I’ve run them with other data and had great results (great for angles iod at least) so I want to point the finger to either an ill conditioned scenario or something to do with how I generated the measurements. The pass is rather low, with peak elevation angle < 40 deg
These are the results I get with 3 measurements that cover 400 seconds of separation
Reference Orbit:
Keplerian parameters: {a: 2.6871E7; e: 0.1; i: 55.0; pa: 0.0; raan: -20.0; v: 180.0;}
Gauss IOD
Keplerian parameters: {a: 4.237043009921982E7; e: 0.8878027310562274; i: 105.71985914321517; pa: 136.77671702324247; raan: -18.417826165868302; v: -68.4322943654454;}
Laplace IOD
Keplerian parameters: {a: 5.568142916102404E7; e: 0.9156744453115059; i: 105.49433163980962; pa: 137.15157457590072; raan: -18.964216651890524; v: -69.15886823807563;}
Gooding IOD
Keplerian parameters: {a: 3511316.136873923; e: 0.9998490378536055; i: 39.65962372833863; pa: 303.40046926246333; raan: 45.5261157625205; v: -179.99955679702893;}
I know eccentricities are tough with angles only but I have gotten much better results in the past with real data. Even the orbit plane is pretty bad here.
Is there anything that immediately jumps out to you?
Thank you in advance.