SSO ground tracks not repeating

I am using a numerical propagator with a DormandPrince853 integrator and I am trying to achieve an SSO. However, despite inputting what I believe to be the correct Keplerian initial orbital parameters, the ground tracks of the orbit do not repeat when plotted over multiple days. These are my orbital parameters:

    // semi-maj axis
    double a =  7000000;
    // eccentricity
    double e = 0.001;
    // inclination
    double i = FastMath.toRadians(97.87375968733356);
    // Perigee argument
    double pa = 0;
    // Right ascension of ascending node
    double raan = FastMath.toRadians(100);
    // Anomaly
    double anom = 0;
    // Type of anomaly
    PositionAngleType type = PositionAngleType.TRUE;

I am modeling the J2 perturbation as such:

        int degree = 2;
        int order = 0;
        NormalizedSphericalHarmonicsProvider gravityProvider =
                GravityFieldFactory.getNormalizedProvider(degree, order);
        ForceModel j2eff = new HolmesFeatherstoneAttractionModel(frame, gravityProvider);

Without this ForceModel, the ground tracks of different days have a wider gap between them than with the model – Leading me to believe that the force model is indeed affecting the orbit in the right direction. Any help or advice at all would be appreciated!

Hi @mpic welcome

I suggest you look at the phasing tutorial that is devoted to compute SSO orbits with repeat cycle.

It can be tricky to find the input parameters due to the various perturbations. Using only J₂ is not sufficient. This tutorial starts fro a theoretical initial guess using analytical formulation (that take into account J₂ and J₃) and then uses numerical propagation and fitting until it reaches a stable orbit.

Thanks for the quick reply! I’ll take a look at it.

Hi @luc, Thanks again for the direction. I have been looking over the phasing tutorial but I’ve been having a hard time understanding the program. After the final orbit has been found, can this orbit not just be propagated numerically to find it’s ground track? I tried it out and I ended up with non-repeating ground tracks again. It would be greatly helpful to me If you could explain a little bit about the purpose of the printGridPoints() method and how it works. Thank you for the help so far and all that you do for the community!

Yes the orbit can be propagated, but it will be repeating only if propagated with the exact same force model that was used to build it, and on the same time range.
The reason is that all force models distort the orbit; the fitting performed by the program finds at the end some trade-off so that when all the forces are used together, the position with respect to Earth will be the same at both ends of the fitting period.

If one changes the force models, then the trajectory will be different from what was used during fitting and the endpoint will not match.

If one changes the start or end dates, then the force models will be slightly different (just think about the relative position of Sun, Moon, and Earth orientation), so the endpoints will also be different.

Note also that the orbit computed is mainly intended to be a reference orbit for station-keeping. It includes neither atmospheric drag nor maneuvers. These should be added later on with station-keeping. If you want an example of how the perturbations affect SSO orbits and how station-keeping can be used to compensate them, you can look at the paper I wrote a few years ago : Very Low Thrust Station-Keeping for Low Earth Orbiting Satellites. For the record, the initial orbits used in this paper were produced using the phasing tutorial. This paper also explains the purpose of the grid points, as well as how to improve them iteratively. Note however that this improvement requires a complete station-keeping simulator, and this is way more complex than the tutorial.

I see. That all makes a lot more sense now. Thank you for the help!

Hi @luc, Unfortunately I’m still having a bit of trouble. Despite using the same exact propagator and force model, the orbit does not repeat even for the first couple days, nor does it repeat up to the end date. I am using the code directly from the tutorial, so I’m not sure what the issue could be. I am plotting the ground-tracks by propagating in small increments and converting the satellite position to a geodetic point, then I am using Python to graph the coordinates. Is there some sort of error in the way that I am propagating the orbit? Thanks again for all the help.

Hi @mpic,
I had a similar issue in the past and I managed to trace it back to the fact that I was computing orbital elements for a repeating ground-track orbit that, by theory, are mean elements. Using these in a numerical propagator, which works using osculating elements, was causing the ground track not to repeat.

I don’t know whether the same is happening to you, but if that is the case I would suggest you to try and propagate the orbit using the DSST mean propagation, or using the DSSTPropagator.computeOsculatingState() method to obtain the corresponding osculating elements to be used in the numerical propagator.

Hi @a_gior, thanks for the reply. I’m not sure I fully understand the implementation of what you described. Like in the phasing tutorial, I am producing a stable orbit found through an analytical formula. I am then using this orbit directly to propagate the ground track. I tried using the computeOsculatingState() method to set the initial state of the propagator but I’m not sure if this is what you mean. Could you provide a little bit more detail about how you actually used the DSSTPropagator? Thank you again!

Fortunately, I’ve found the solution now. The problem had to do with the parameters inputted by the .yaml file. Thanks for all the help!