Generate a new Frame from cartesian vectors

Hi All!
I searched a lot in the forum but I didn’t find anything that could help me with my problem.
My problem is the following: I have to express attitude coordinates from a given reference frame (e.g. GCRF) to a custom one defined by 3 vectors that I have expressed in ITRF. Now how can I generate a brand new Frame from 3 vetors expressed in a known reference frame? Do I have to use some kind of transformation?
Thanks in advance for the help

Hi @aeroanselm, welcome!

The way to do it depends on how your vectors are defined. If they do evolve with time, you will probably need to set up your own implementation of AttitudeProvider, which will recompute the vectors as needed. If you are only interested at one Attitude for a single date, then you can build this Attitude directly from a Rotation.

What are the semantics of your three vectors? Do they represent directly the satellite X, Y and Z axes? Are they known to represent a perfect orthonormal frame (i.e. can we just pick 2 vectors out of the 3 to build the frame?) or are they affected by some measurements errors and we need to find the closest perfect frame?

Hi @luc , thanks for the reply!
I will describe more in detail the problem to make you understand better the situation. I have an input ephemeris file (custom one not CCSDS) with data info about the orbit state and attitude state at prescribed epochs. What I have to do is to change the attitude data information expressd via quaternion in GCRF to euler angles in this new frame defined as Zero Doppler Reference Frame

  • x: spacecraft velocity vector
  • y: Rellip X x (Rellip: vector from platform to ground normal)
    -z: x X y

Obviously this new frame is moving with time and having the input data set I am able to compute the 3 unit vectors that generate the frame every time but then I have problem to express the attitude I have according to this new frame. I attach here a sample of code where I generate an example of orbit and attitude state and then extract the data to generate the new frame.

public class Example {
    public static void main(String[] args) {
        ReferenceEllipsoid referenceEllipsoid = ReferenceEllipsoid.getWgs84(FramesFactory.getEME2000());
        AbsolutePVCoordinates coordinates = Example.generateCoordinates();
        Attitude attitude = Example.generateAttitude();
        Vector3D groundProjection = referenceEllipsoid.projectToGround(coordinates.getPosition(), coordinates.getDate(),
                coordinates.getFrame());
        Vector3D Rellip = new Vector3D(
                groundProjection.getX() - coordinates.getPosition().getX(),
                groundProjection.getY() - coordinates.getPosition().getY(),
                groundProjection.getZ() - coordinates.getPosition().getZ());
        Vector3D zdrfX = coordinates.getVelocity().normalize();
        Vector3D zdrfY = Rellip.crossProduct(zdrfX);
        Vector3D zdrfZ = zdrfX.crossProduct(zdrfY);
    }

    public static AbsolutePVCoordinates generateCoordinates() {

        AbsoluteDate epoch = new AbsoluteDate(2023, 9, 1, 23, 54, 17.726, TimeScalesFactory.getUTC());

        // Vector3D position = new Vector3D(5549.730024780708, -3051.055950442332,
        // -2736.524960047117);
        // Vector3D velocity = new Vector3D(1.8737817080475325, -2.779282460590368,
        // 6.91152869462395);
        Vector3D position = new Vector3D(8000000.0, 0.0, 0.0);
        Vector3D velocity = new Vector3D(0.0, Math.sqrt(398600 / 8000), 0.0);
        TimeStampedPVCoordinates coordinates = new TimeStampedPVCoordinates(epoch, position, velocity);
        Frame itrf = FramesFactory.getITRF(IERSConventions.IERS_2010, false);
        return new AbsolutePVCoordinates(itrf, coordinates);
    }

    public static Attitude generateAttitude() {

        AbsoluteDate epoch = new AbsoluteDate(2023, 9, 1, 23, 54, 17.726, TimeScalesFactory.getUTC());
        Frame gcrf = FramesFactory.getGCRF();
        Rotation rotation = new Rotation(1, 0, 0, 0, false);
        return new Attitude(epoch, gcrf, rotation, Vector3D.ZERO, Vector3D.ZERO);
    }
}

Did you try using the NadirPointing attitude?
It seems close to what you need, except its Z axis is your Y axis

Unfortunately I can’t. I am forced to express the attitude according to the frame generated from the 3 vectors I described above

try this:

  public Attitude getAttitude(PVCoordinatesProvider pvProv, AbsoluteDate date, Frame frame) {
    Vector3D Rellip = ... your computation...
    Vector3D velocity = pvProv.getPVCoordinates(date, frame).getVelocity();
    Rotation r = new Rotation(Rellip, velocity, Vector3D.PLUS_J, Vector3D.PLUS_I);
    return new Attitude(date, frame, r, Vector3D.ZERO, Vector3D.ZERO);
  }

You can pass your AbsolutePVCoordinates as pvProv and the GCRF as frame.
Beware this does just compute the rotation, not the rotation rate nor the rotation acceleration, but if you need that, it is possible to add it.