Hi all, I am progressing with my version of GNSS pseudo-range and carrier-phase simulator, but I found an obstacle dealing with the ambiguity for carrier phase. In particular I implemented the following class as ambiguity handler
class AmbiguityHandlerDetector(PythonEventHandler):
"""
A custom Python implementation of EventDetector to handle
AmbiguityCache invalidation upon link loss.
"""
def __init__(self, cache: AmbiguityCache, emitter_id: str, receiver_id: str, wavelength: float):
# Call the super constructor using the specific Orekit signature you need
# e.g., ElevationDetector(double minElevation, TopocentricFrame f)
super(AmbiguityHandlerDetector, self).__init__()
# Store Python references to the required objects
self.ambiguity_cache = cache
self.emitter_id = emitter_id
self.receiver_id = receiver_id
self.wavelength = float(wavelength)
def init(self, initial_state: SpacecraftState, target, detector: EventDetector):
pass
# We must explicitly define the eventOccurred method signature that matches
# the Java interface, including type hints if possible for clarity.
# This overrides the default handler logic.
def eventOccurred(self, s: SpacecraftState, detector: EventDetector, increasing: bool):
"""
Handles the event occurrence logic when elevation crosses the threshold (0 == event).
"""
event_date = s.getDate()
# Retrieve the driver (which might be new due to the previous invalidate)
new_driver = self.ambiguity_cache.getAmbiguity(
self.emitter_id,
self.receiver_id,
self.wavelength
)
driver = AmbiguityDriver.cast_(new_driver)
if driver is None:
print("Error: AmbiguityDriver not found in cache!")
return EventHandler.Action.CONTINUE
if increasing:
# Link Starts visibility
print(f"Python Detector: Link Start detected at: {event_date}")
# Set a new random integer value for the *true* simulation ambiguity for this pass
new_true_ambiguity = 1.0
# Use the eventDate to set the value within the correct span
driver.setValue[float, AbsoluteDate](float(new_true_ambiguity), event_date)
driver.setSelected(True) # Ensure it's marked for estimation later
else:
# Link Ends visibility (Elevation falling)
print(f"Python Detector: Link End (Invalidating ambiguity) detected at: {event_date}")
# CRUCIAL STEP: Invalidate the cache at the exact time the event occurs.
driver.addSpanAtDate[AbsoluteDate](event_date)
"""self.ambiguity_cache.invalidate(
self.emitter_id,
self.receiver_id,
self.wavelength,
event_date
)"""
# Continue propagation
return EventHandler.Action.CONTINUE
def resetState(self, detector: EventDetector, old_state: SpacecraftState):
return old_state
def finish(self, s: SpacecraftState, detector: EventDetector):
pass
and I used in my simulator as follows
# create detector for inter-satellite visibility (Earth occlusion)
visib_inter_sat = InterSatDirectViewDetector(EAR_SHAPE, sp3_prop)
# create detector for angular separation visibility (angular separation of FOV_HA radians between GNSS and s/c):
# - in general for this detector propagation stops at the end of the visibility,
# - ContinueOnEvent() resumes the propagation after it
visib_ang = AngularSeparationDetector(ConstantPVCoordinatesProvider(Vector3D.ZERO, sp3_prop.getFrame()),
sp3_prop, settings.obs_gen_settings.fov_ha*math.pi/180.0).withHandler(ContinueOnEvent())
visib_metric = BooleanDetector.andCombine([visib_inter_sat,
BooleanDetector.notCombine(visib_ang)])
ambiguity_cache = AmbiguityCache()
handler = AmbiguityHandlerDetector(ambiguity_cache, gnss_satellite.getName(), satellite.getName(), WAVELENGTH)
final_detector = visib_metric.withHandler(handler)
carrier_phase = get_carrier_phase_builder(settings.obs_gen_settings, satellite, gnss_satellite, WAVELENGTH, ambiguity_cache)
generator.addScheduler(EventBasedScheduler(carrier_phase,
FixedStepSelector(settings.obs_pro_settings.tstep_out*3600.0, t_scale),
sat_prop,
final_detector,
SignSemantic.FEASIBLE_MEASUREMENT_WHEN_POSITIVE))
This is just a part of a general loop where the similutaro is computing the observables between a LEO and a set GNSS satellites taken from SP3 ephemeris files. I do not understand why I keep receiving the following runtime error
Python Detector: Link Start detected at: 2022-10-21T20:19:20.114389524007492576Z
Traceback (most recent call last):
File "/home/bracalicioci/miniforge3/envs/ob-astra/bin/gnss-sim", line 7, in <module>
sys.exit(run())
~~~^^
File "/home/bracalicioci/gitlab/spacedys/ob-astra/py-sim/src/ob_astra_sim/gnss_sim.py", line 273, in run
main(sys.argv[1:])
~~~~^^^^^^^^^^^^^^
File "/home/bracalicioci/gitlab/spacedys/ob-astra/py-sim/src/ob_astra_sim/gnss_sim.py", line 233, in main
generator.generate(t0, t1)
~~~~~~~~~~~~~~~~~~^^^^^^^^
orekit.JavaError: <super: <class 'JavaError'>, <JavaError object>>
Java stacktrace:
org.orekit.errors.OrekitException: java.lang.RuntimeException: TypeError
at org.orekit.propagation.PropagatorsParallelizer$PropagatorMonitoring.manageException(PropagatorsParallelizer.java:474)
at org.orekit.propagation.PropagatorsParallelizer$PropagatorMonitoring.retrieveNextParameters(PropagatorsParallelizer.java:456)
at org.orekit.propagation.PropagatorsParallelizer.propagate(PropagatorsParallelizer.java:209)
at org.orekit.estimation.measurements.generation.Generator.generate(Generator.java:157)
Caused by: java.lang.RuntimeException: TypeError
at org.orekit.propagation.events.handlers.PythonEventHandler.eventOccurred(Native Method)
at org.orekit.estimation.measurements.generation.EventBasedScheduler$FeasibilityModifier.lambda$getHandler$0(EventBasedScheduler.java:189)
at org.orekit.propagation.integration.AbstractIntegratedPropagator$AdaptedEventDetector$1.eventOccurred(AbstractIntegratedPropagator.java:1020)
at org.hipparchus.ode.events.DetectorBasedEventState.doEvent(DetectorBasedEventState.java:507)
at org.hipparchus.ode.AbstractIntegrator.acceptStep(AbstractIntegrator.java:369)
at org.hipparchus.ode.nonstiff.EmbeddedRungeKuttaIntegrator.integrate(EmbeddedRungeKuttaIntegrator.java:268)
at org.orekit.propagation.integration.AbstractIntegratedPropagator.integrateDynamics(AbstractIntegratedPropagator.java:543)
at org.orekit.propagation.integration.AbstractIntegratedPropagator.propagate(AbstractIntegratedPropagator.java:474)
at org.orekit.propagation.PropagatorsParallelizer$PropagatorMonitoring.lambda$new$0(PropagatorsParallelizer.java:417)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:750)
I don’t know if this is related to JCC wrapper or if I am doing something nasty with the Ambiguity handler. Do you have any ideas? Do you see another way to implement this? Thank you in advance.