GPS SVs orbits definition

Hi all,

This is my first post in this forum. I’m very new to Java and Orekit, so forgive my “newbie” questions or doubts. :slight_smile: I have a simple GNSS simulator, and currently the GPS SVs orbits are defined manually, i.e. I manually import the GPS SVs keplerian parameters (taken from the almanacs) and I use these parameters to define the GPS initial orbits (as KeplerianOrbit). After that, these orbits are propagated through the method shiftedBy(double time). In the last few days, I’ve noticed some problems with the initial position of the GPS SVs. I’ve read on the internet that the keplerian parameters in the almanacs are not expressed in EME2000, but in WGS84 frame. Could you confirm me that, please? If that is true, I am making a mistake in the orbits definition: in fact, when I use the constructor

KeplerianOrbit (double a, double e, double i, double pa, double raan, double anomaly, PositionAngle type, Frame frame, AbsoluteDate date, double mu)

I pass the frame EME2000 as argument. If I pass an ITRF, I get an IllegalArgumentException because the frame is not a pseudo-inertial frame. Is there a way to create a KeplerianOrbit using an ITRF as frame? I’ve read that it is possible to properly import a GPS almanac and propagate the GPS SVs orbits through the classes YUMAParser, GPSAlmanac and GPSPropagator, but I’d like to use a quicker (even if less accurate) method to solve this problem.

Would any of you be able to help me out?

Thank you very much.

D.

Hi @DM93,

Welcome to the Orekit forum! I hope you enjoy your experience with Orekit :slight_smile:

Yes, it’s true. You can’t use directly the data contained in the almanac to initialize a KeplerianOrbit object. It’s the same behavior with Two Line Elements (TLE): You can’t initialize a KeplerianOrbit using directly the elements contained in the TLE.

The good (and only) solution is:

  1. Depending the almanac type, read the almanac using the SEMParser or YUMAParser class of Orekit. You can find an example on how reading an almanac in the DOPComputation tutorial of Orekit. You can also find examples in the SEMParser test class or the YUMAParser test class.

  2. Access the almanac of your satellite. An example below where almanac is obtained from the previous step (i.e. final List<GPSAlmanac> almanacs = reader.getAlmanacs();).

     GPSAlmanac myAlmanac;
     for (GPSAlmanac almanac: almanacs) {
         if (almanac.getPRN() == theWantedPRN) {
             myAlmanac = almanac;
         }
     }
    

Please not that a better solution could be to add a method getAlmanac(final int prn) in the parsing class.

  1. Now you have a GPSAlmanac object ready to be used to access the orbit of the satellite. For this step, you have to use GPSPropagator class.

final GPSPropagator propagator = new GPSPropagator.Builder(myAlmanac).build();

Now you can access the orbit of the satellite using the propagate() method of the propagator object. By default, the orbit given by the propagate() method is in EME2000 frame.

Please note that for the new Orekit version (i.e. 11.0), the GPSPropagator class has been replaced by a GNSSPropagator class. The idea is to have a common class for all GNSS satellites. A tutorial has been recently added for helping users with GNSS propagation. So, I think it should help you.

Best regards,
Bryan

1 Like

Hi @bcazabonne,

Thank you a lot for your help and your clear explanation. :slight_smile: At the moment, I can easily import the GPS almanacs and define the GPS SVs initial positions, so thank you. Is there a similar way to import the Galileo almanacs and to define the Galileo SVs initial positions as well? In your previous post, you talked about Orekit version 11.0 and class GNSSPropagator, but this new version is not available yet.

Thank you in advance for your help.

Kind regards,

D.

Hi,

We don’t have a GalileoAlmanacParser class in Orekit. So you have to initialize the almanac yourself using setter methods in GalileoAlmanac class. Another possibility is to use navigation files provided by IGS. For its version 11.0 Orekit will be able to read these files for any GNSS constellation.

For you example and for the current Orekit version (i.e. 10.3), you have to use a GalileoPropagator to get Galileo initial positions.

Orekit 11.0 will probably be released for the mid of July. Meanwhile, you can use the development version of Orekit available in our Gitlab repository or in the Nexus repository manager

Hi @bcazabonne
Going through the forum, I found this old topic as I have a similar use case: initialize and orbit via keplerian elements, defined in ITRF.
I was thinking about this solution (too naive?)

  1. build the KeplerianOrbit with the ITRF keplerian parameters from the input
KeplerianOrbit (double a, double e, double i, double pa, double raan, double anomaly, PositionAngle type, Frame frame, AbsoluteDate date, double mu)

In this case the the frame can be set as EME2000 and as date, the date of the sample.

  1. From the obtained KeplerianOrbit, get TimeStampedPVCoordinates. So to obtain position and velocity vectors and build a simple PVCoordinates object, that is frameless (right?)
PVCoordinates pvCoordinates = new PVCoordinates(keplerianOrbit.getPVCoordinates().getPosition(),
      keplerianOrbit.getPVCoordinates().getVelocity());
  1. Consider position and velocity vectors as they were actually generated in ITRF frame (as they are frameless), and convert them to EME2000.
Frame eme2000 = FramesFactory.getEME2000();
Frame itrf = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
Transform toEme20000 = itrf.getTransformTo(eme2000, date);
TimeStampedPVCoordinates timePVCoordinatesJ2000 = toEme20000.transformPVCoordinates(
          new TimeStampedPVCoordinates(date, pvCoordinates.getPosition(),
              pvCoordinates.getVelocity()));
  1. Build up new orbit from the state vector, converted in EME2000.
KeplerianOrbit keplerianOrbitJ2000 = new KeplerianOrbit(timePVCoordinatesJ2000, eme2000, mu);

My main concern is about point 3, transforming to EME2000, but from where?

Not really convinced on this method but would be nice to have a second opinion!

PS: the algo can be thinner, just expanded for being more clear

Alberto

Hi @alberto-ferrero

My consern is about the first step. What is your provider for ITRF keplerian elements?
I don’t really like ithe action of nitializing an orbit with a frame which is not representative of the real frame.

Best regards,
Bryan

Hi Bryan
Yes you are right, the input Keplerian elements might not being coming from a real or compliant orbit.
My use case was simpler, I had an EME2000 Keplerian orbit, converted in ITRF using GMAT and wanted to implement the same in Orekit:

  • GMAT ITRF Keplerian → Cartesian EME2000
  • Orekit ITRF Keplerian (generated in GMAT indeed) → Cartesian EME2000

With the described steps, I do have same results GMAT-Orekit.

I think we could even look at the problem even from an higher prospective, would be ok to have a Keplerian → PV coordinates converter (like PVCoordinates pv = PVCoordinates.fromKeplerian(a, e, i, pa, raan, ...etc) , just a pure set of classical orbital mechanics equations.

I can see that is indeed already done inside the KeplerianOrbit class.

Just a suggestion :slight_smile:
Alberto

That’s cool if you have similar results.

I was also concern about the fact of having the same keplerian to cartesian transformation between intertial frame and non-inertial frame. In other words, I didn’t know that the equations used to convert keplerian elements to cartesian were the same between inertial and non inertial frames.

That’s interesting to have a method like that. That’s a cleaner solution compare to intializing a KeplerianOrbit with a wrong frame. However, I think it should be in AbsolutePVCoordinates class because it was initially designed to handle non inertial frames.

I would like to have the opinion of the other Orekit developers about this method :slight_smile:

Best regards,
Bryan

Hi,

I just wanted to ask a question, what does GMAT means by:

Because, in my opinion Keplerian elements have no meaning in a rotating frame like this.
Is it an ITRF frame considered fixed at the date of the elements ?
If so you could build your orbital elements with a classical KeplerianOrbit using the getFrozenFrame method from Frame.
It will freeze the frame at a given date and render it pseudo-inertial.