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.