Generate CPF AZEL measurements from list of dates

Hi!
I have a list of dates for which I’m trying to generate altaz measurements based on CPF data from EDC. My first approach was something like this:

...
earth = OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS, 
                         Constants.WGS84_EARTH_FLATTENING, 
                         itrf)

station = GeodeticPoint(math.radians(lat), math.radians(lon), elevation)
topo = TopocentricFrame(earth, station, "topo")
alts = [ ]
azs = [ ]
distance = [ ]
times = list_of_dates
for t in times:
    absdate = datetime_to_absolutedate(t)
    state = prop.propagate(absdate)
    pvInit = state.getPVCoordinates()
    frame = state.getFrame()

    alt = np.degrees(topo.getElevation(pvInit.getPosition(), frame, absdate))
    az = np.degrees(topo.getAzimuth(pvInit.getPosition(), frame, absdate))
    distance = topo.getRange(pvInit.getPosition(), frame, absdate)

    alts.append(alt)
    azs.append(az)
    distances.append(distance)

And I think it works ok, but I read somewhere that I should use AngularAzElBuilder for that kind of things, so I tried but I have no idea how to create scheduler that would allow me to generate measurements for given dates:

err = 1e-5
altazError = [err, err]
altazWeight = [1.0, 1.0]
covariance = MatrixUtils.createRealDiagonalMatrix([err**2, err**2, err**2, err**2, err**2, err**2])
random_vector = CorrelatedRandomVectorGenerator(covariance, 1.0e-10, GaussianRandomGenerator(MersenneTwister()))
obs_sat   = ObservableSatellite(0)
generator = Generator()
generator.addPropagator(prop)
absdates = [datetime_to_absolutedate(t) for t in times]
azelBuilder = AngularAzElBuilder(random_vector, ground_station, altazError, altazWeight, obs_sat)

generator.addScheduler(???)

meas = generator.generate(absdates[0], absdates[-1])

Is this approach valid and/or better than the first one? And if it’s better how to approach this problem?

The measurements generation feature is depicted here. There are two existing schedulers provided by Orekit: ContinuousScheduler and EventBasedScheduler. The first one generates uninterrupted lists of measurements regardless of station and satellite relative position, so you may end up with measurements below the horizon. The second one generates measurements only when some conditions triggered by event detectors allow it. This is the most often used scheduler, and it is often configured with events detectors based on satellite visibility from the measurement receiver (ground station, other satellite…).

Yes, but my problem is that I don’t have any fixed step or continuous dates. To be honest, I’m working with observations of some LEO satellites (with available CPFs) that I need to verify. Timing of these observations does not follow any specific pattern.

As I mentioned, propagating the state to a chosen absolute date seems to work fine, but I’m not sure if that’s the correct approach.

The scheduler documentation for both ContinousScheduler and EventBasedScheduler mentions a “repetitive pattern,” which I don’t have. So, is there a way to use AngularAzElBuilder to generate AzEl measurements for a discrete set of dates?

Hi,

I guess you could still use a DateDetector with a bunch of dates.

Cheers,
Romain.

Thanks for the suggestion!
I realized that I never shared how I create my propagator — maybe there’s an error there:

DS = DataSource(path_to_cpf)
parser = CPFParser()
cpf = parser.parse(DS)
sat_eph = cpf.getSatellites().get(cpf.getHeader().getIlrsSatelliteId())
prop = sat_eph.getPropagator()

I tried something like this: first, I created my own date selector class to always return a list of my dates:

@JImplements(DatesSelector)
class myDateSelector():
    def __init__(self, dates):
        self.absdates = ArrayList()
        for t in dates:
            self.absdates.add(t)
    
    @JOverride
    def init(self, start, end):
        pass

    @JOverride
    def selectDates(self, s, e):
        return self.absdates

Then, I created a DateDetector with the same dates and used it to create an EventBasedScheduler:

absdates = [datetime_to_absolutedate(t) for t in times]
detector = DateDetector(0.1, absdates[0]).withHandler(ContinueOnEvent())
for t in absdates[1:]:
    detector.addEventDate(t)
date_selector = myDateSelector(absdates)
scheduler = EventBasedScheduler(azelBuilder, date_selector, prop, detector, SignSemantic.FEASIBLE_MEASUREMENT_WHEN_POSITIVE)
generator.addScheduler(scheduler)
meas = generator.generate(absdates[0], absdates[-1])

Unfortunately, this doesn’t work. There are no exceptions or warnings, but meas is always NoneType and empty. I’m not sure if the issue is related to SignSemantic — I’ve tried both POSITIVE and NEGATIVE, but it made no difference.

What am I doing wrong?

EDIT
So I discovered that you need a subscriber now to store measurements, so I added a subscriber:

subscriber = GatheringSubscriber()
generator.addSubscriber(subscriber)
generator.generate(absdates[0], absdates[-1])
 
for i in subscirber.getGeneratedMeasurements():
    print(np.rad2deg(i.getObservedMeasurement().getObservedValue()[0]))
    print(np.rad2deg(i.getObservedMeasurement().getObservedValue()[1]))
    print(i.getObservedMeasurement().getDate())

And it somewhat works, but I get many more generated measurements than initial dates, and the number of measurements is not constant, it is different with every time I run the script.