Dynamic Attitude Tracking


My team and I are trying to simulate two satellites pointing at each other through their orbits using the python wrapper, any ideas on how to get stared?


Hi @jemeza

First, welcome to the Orekit forum !

To answer your question, I don’t think Orekit has an attitude model able to simulate two satellites pointing at each other.
Orekit has many attitude laws (i.e. Celestial body pointing, ground pointing, predefined attitude table, etc.) but not for what you want. Indeed, to common point between that attitude laws in Orekit is that the target is considered as fixed during the propagation time.

Therefore, you will have to implement your own attitude law. I am very far to be an expert of Python. However, if you want to add a new attitude model, you have to implement AttitudeProvider interface.

Another problem is that the getAttitude() methods only uses the dynamic coordinates of the propagated spacecraft. In other words, this methods cannot access the coordinates of the pointed spacecraft. Therefore, to access the coordinates of the pointed satellite, I think you have to initialize them at the construction of the attitude model. For instance, by using a List<TimeStampedPVCoordinates>. The pointed satellite ephemeris can be easily computed using an analytical orbit propagator (TLEPropagator or KeplerianPropagator for instance).

Finally, for attitude computation, you can look at the already attitude models developed in Orekit to help you.

Kind regards,

There is a workaround: you can use CelestialBodyPointed, but there is a subtle trick in the setup. At construction, CelestialBodyPointed needs a PVCoordinatesProvider to point to the body (which in your case would not be a CelestialBody but a regular spacecraft. Any Propagator is also a PVCoordinatesProvider so you may be tempted to do that (don’t do that, read further on):

  Propagator p1 = new SomePropagatorYouWant(...config for spacecraft 1...);
  Propagator p2 = new SomePropagatorYouWant(...config for spacecraft 2...);
  AttitudeProvider doesntWork1 = new CelestialBodyPointed(eme2000,
  AttitudeProvider doesntWork2 = new CelestialBodyPointed(eme2000,
  p1.propagate(someDate); // <-- this will blow up with stack overflow due to infinite recursion

As explained in the comment in the snippet above, this setting would cause infinite recursion because propagator 1 calls its attitude provider, which calls propagator 2, which calls its own attitude provider, which calls propagator 1, which…

As in fact we only need a PVCoordinatesProvider for building the CelestialBodyPointed instances, we don’t really use the full state created by the Propagator we embed into it. So the idea to break the infinite recursion is to use different propagators embedded in the CelestialBodyPointed, and to have these propagators not manage the attitude (or rather just let them use their default basic attitude law) since the attitude part will in fact be ignored: the CelestialBodyPointed just need to know where to look, it see its target as a point and don’t need to know how the body centered at this point is oriented.

In order to avoid lengthy computations, I would highly recommend to use analytical propagators to be embedded within the CelestialBodyPointed instances, using numerical propagators would introduce big performance bottleneck. If you need your pointing to be accurate with many perturbations taken into account, then I would recommend doing this in several steps:

  1. set up numerical propagators without computing attitude
  2. configure the propagators in ephemeris generation mode
  3. run the propagators
  4. extract the ephemeris, which is a Propagator and therefore also a PVCoordinatesProvider
  5. set up attitude provider to CelestialBodyPointed with ephemeris2 being used for propagator1
    and ephemeris1 used for propagator2
  6. reset initial state of both propagators back to start
  7. run the propagators again, this time they will have a representative attitude

If you really want highly accurate computation and your force model includes surface forces like solar radiation pressure or drag with a BoxAndSolarArraySpacecraft, then you may need to run the previous steps twice, but I doubt this will change much the results. It would change things if surface force were so large that wrong orientation of spacecraft 1 would imply wrong forces and wrong trajectory, and therefore would imply wrong orientation of spacecraft 2. Such a loop would converge rather quickly. Suppose for example that wrong orientation in spacecraft 1 introduce a 10 meters position error during one iteration and the other spacecraft is very close, say 1 kilometer away only. Then the attitude error of the other spacecraft would be about 0.6°. Changing an attitude by 0.6° changes the surface forces very slightly so the next propagation for the second spacecraft would probably be much more accurate than 10 meters. You could do some experiments, but I am pretty sure you won’t really need to loop.

1 Like

Hey @bcazabonne and @luc ,

Thank you so much for the help–I’m on the team with jemeza, and we’ve been trying to impliment the CelestialBodyPointed solution. Before this, we were trying to use TargetPointing by simply putting in the coordinate point of the second satellite and the same of the earth and then updating the law with every point, but the CelestialBodyPointed solution seems much better.

Question about your CelestialBodyPointed method: we definitely won’t be needing the numerical propagators for this project at the initial phase, but I’m getting an error when I simply define the law any both of these ways:

law = CelestialBodyPointed(p1) or law = CelestialBodyPointed(pv)

where pv is a PVCoordinate.

Might you be able to show how/what would be put into the constructor of the law to avoid the recursion? If it’s possible to adapt the script with the overflow error it would be incredibly helpful–we’re working on a Jupyter notebook tutorial for this, so we’d love to share it once we figure this out.

Thank you so much for the help!

Thank you for your feedback, we were able get it working!