CPF.addSatelliteCoordinate(CPFCoordinate coord) method writes null as satelliteId in ephemeris
From forum post: https://forum.orekit.org/t/writing-cpf-access-to-cpfheader-inside-cpf-class/1381
I am trying to write a ILRS CPF file containing position data generated via orbit determination.
My code is the following:
from org.orekit.files.ilrs import CPFHeader
cpf_header = CPFHeader()
cpf_header.setSource(ephemeris_source)
cpf_header.setStep(step_time)
cpf_header.setEndEpoch(date_end_cpf)
cpf_header.setIlrsSatelliteId(cospar_id)
cpf_header.setName(target_name)
cpf_header.setNoradId(str(norad_id))
cpf_header.setProductionEpoch(production_epoch)
cpf_header.setProductionHour(production_hour)
cpf_header.setSequenceNumber(ephemeris_sequence)
cpf_header.setSic(sic)
cpf_header.setStartEpoch(ephemeris_start_date)
cpf_header_v1 = cpf_header
cpf_header_v1.setVersion(1)
from org.orekit.files.ilrs import CPFWriter
cpf_writer_v1 = CPFWriter(cpf_header_v1, utc)
from org.orekit.files.ilrs import CPF
cpf = CPF()
# Add data to CPF file
date_current = ephemeris_start_date
leap = 0
while date_current.compareTo(date_end_cpf) <= 0:
pv_itrf = bounded_propagator.getPVCoordinates(date_current, itrf)
coord = CPF.CPFCoordinate(date_current, pv_itrf.getPosition(), pv_itrf.getVelocity(), leap)
cpf.addSatelliteCoordinate(coord)
date_current = date_current.shiftedBy(dt_cpf)
from java.io import StringWriter
string_writer_v1 = StringWriter()
cpf_writer_v1.write(string_writer_v1, cpf)
It fails with the following:
JavaError Traceback (most recent call last) in 11 from java.io import StringWriter 12 string_writer_v1 = StringWriter() ---> 13 cpf_writer_v1.write(string_writer_v1, cpf)
JavaError: <super: <class 'JavaError'>, > Java stacktrace: java.lang.NullPointerException at org.orekit.files.ilrs.CPFWriter.write(CPFWriter.java:83)
I tried with both Orekit 10.3 and 11.0 with no difference (apart from minor syntax changes I had to apply).
It seems to come from the Map get
at CPFWriter.java
:82 which returns a null pointer.
This is due to the satellite ID in the ephemeris map being null:
cpf.getSatellites()
returns:
<Map: {null=org.orekit.files.ilrs.CPF$CPFEphemeris@153cffb8}>
Because at CPF.java
:81, ephemeris.getId()
returns null
. In turn, this comes from CPF.java:190
: header.getIlrsSatelliteId()
returns null
.
I realized that the header
member of cpf
is an empty CPFHeader
object created in the CPF
constructor, and not the cpf_header_v1
variable that was defined above. Looking at CPF.java
:69, it makes sense as there's no way to pass the CPFHeader
object to the CPF
object (only the CPFWriter
gets the CPFHeader
object as an argument of its constructor).
In the Java unit tests it appears that the CPFWriter
class is never tested to write (non-null) CPF files from scratch. Instead, existing files are loaded, written to another file and then both files are compared for consistency, which explains that this missing header issue doesn't occur.
A suggestion from @bryan to fix this is the following:
- Deprecate the
addSatelliteCoordinate(CPFCoordinate coord)
method - Have a constructor
CPFEphemeris(String id)
. The previous one must also be deprecated. - Replace the deprecated method at 1. by
addSatelliteCoordinate(String id, CPFCoordinate coord)
. It can be also useful to have the following signature:addSatelliteCoordinates(String id, List<CPFCoordinate> coord)