How to perform a change PVCoordinates change Frame?

Hi everybody !

I’m a new user of orekit and I have some troubles perfoming a conversion of my data…

I’d like to go from a TimestampedPVCoordinates object, defined in the ECEF Frame to obtain Azimuth and Elevation of this object seen from a GroundStation object (I used Topocentric & Body objects to define this GroundStation using the IRTF2014 model).

I explored Transform Class but I’m not sure to clearly understand the procedure to follow.

Thank you in advance !
AD

I tried the following solution, can you give me some feedback please ?

groundstation.getBaseFrame().getAzimuth(point.getPosition(), inertialFrame, point.getDate())

Thank you !

Hi @adelalla,

Using the GroundStation object, you can compute the elevation and azimuth of your object. Let station be your GroundStation object and coordinates be your TimestampedPVCoordinates object, the angles are computed using:

    // Elevation
    final double elevation = station.getBaseFrame().getElevation(coordinates.getPosition(),
                                                                 // frame in which your coordinates are defined,
                                                                 coordinates.getDate());

    // Azimuth
    final double azimuth = station.getBaseFrame().getAzimuth(coordinates.getPosition(),
                                                             // frame in which your coordinates are defined,
                                                              coordinates.getDate());

Please note that the angles are given in radians.

I see that you use inertialFrame name. However, you said that your coordinates are defined in ECEF frame which is not inertial. Is it normal?

1 Like

Hi @bcazabonne, thank you for your answer !

I noticed that your solution is the same than mine so I’m satisfied this that :wink:

About the inertialFrame, you’re right it’s a mistake of mine.
The variable inertialFrame in my code is the same than in all exemples :
inertialFrame = FrameFractory.getEME2000() so it’s not ECEF. I’m gonna correct that, thank you for the remark.

See you later,
AD

Hi @bcazabonne,

I’m still working on those topics and I have some trouble to perform the opposite opération, ie :
Azimuth, Elevation, Range, Date => Vector3D

The problem is that I have an inversion between X and Y componants of the Vector3D. I think that there is a difference in Frames between Orekit and Hipparchus.
To illustrate the problem, I make this simple code :

from math import radians
from org.orekit.bodies import GeodeticPoint, OneAxisEllipsoid
from org.orekit.estimation.measurements import GroundStation
from org.orekit.frames import FramesFactory, TopocentricFrame
from org.orekit.orbits import KeplerianOrbit, PositionAngle
from org.orekit.utils import Constants, IERSConventions
from org.orekit.time import AbsoluteDate, TimeScalesFactory
from org.hipparchus.geometry.euclidean.threed import Vector3D

# Set inertial Frame
inertial = FramesFactory.getEME2000()

# Set groundstation Frame
ecef = FramesFactory.getITRF(IERSConventions.IERS_2010, False)
body = OneAxisEllipsoid(Constants.IERS2010_EARTH_EQUATORIAL_RADIUS,
Constants.IERS2010_EARTH_FLATTENING, ecef)
geodeticPoint = GeodeticPoint(radians(-1.15), radians(45.), 0.)
groundstation = GroundStation(TopocentricFrame(body, geodeticPoint, ‘radar’))
gsframe = groundstation.getBaseFrame()

# Set TimestampedPVCoordinates
alt = 1000e3
a = 6378e3 + alt # semi major axis in meters
e = 0.001 # eccentricity
i = radians(90) # inclination
w = radians(0) # perigee argument
Omega = radians(-130) # right ascension of ascending node
m = 0. # mean anomaly
duree = 3600. * 1 * 1 # duree de la trajectoire en s
dt = 5. # pas temporel en s
initialDate = AbsoluteDate(2020, 1, 1, 10, 0, 0.0, TimeScalesFactory.getUTC())
finalDate = initialDate.shiftedBy(duree)
initialOrbit = KeplerianOrbit(a, e, i, w, Omega, m, PositionAngle.MEAN, inertial, initialDate, Constants.IERS2010_EARTH_MU)

# Get Vector3D in groundstation frame
pvcoordinates = initialOrbit.getPVCoordinates()
vectECEF = pvcoordinates.getPosition()
vectENU = inertial.getTransformTo(gsframe, initialDate).transformPosition(vectECEF)
print(vectENU, vectENU.getNorm())

az = gsframe.getAzimuth(vectECEF, inertial, initialDate)
el = gsframe.getElevation(vectECEF, inertial, initialDate)
dist = gsframe.getRange(vectECEF, inertial, initialDate)

newVectENU = Vector3D(dist, Vector3D(az, el))
print(newVectENU, newVectENU.getNorm())

And here is the result that I obtain :

{-6 694 945,61910018; 52 025,3761510483; -3 295 762,78818715} 7462376.018298159
{52 025,3761510504; -6 694 945,61910018; -3 295 762,78818715} 7462376.018298159

Do you know what’s going on ? Thank you in advance for your answer.
AD

This is not a problem between Orekit and Hipparchus but a problem of conventions between two different types of coordinates within Orekit.

The axes of a TopocentricFrame are defined as follows, as explained in the class javadoc:

  • X axis in the local horizontal plane (normal to zenith direction) and following the local parallel towards East
  • Y axis in the horizontal plane (normal to zenith direction) and following the local meridian towards North
  • Z axis towards Zenith direction

That is TopocentricFrame is really East-North-up, just as you assumed in your code. However, the azimuth is not defined with respect to East. As explained in the same class (TopocentricFrame) for the getAzimuth method, it is defined as:

  • The azimuth is the angle between the North direction at local point and the projection in local horizontal plane of the direction from local point to given point. Azimuth angles are counted clockwise, i.e positive towards the East.

So you should rather define your newVectENU as follows:

newVectENU = Vector3D(dist, Vector3D(0.5 * FastMath.PI - az, el));

Both conventions (ENU for the frame and azimuth counted from North) are classical ones, they may seem inconsistent, but this is how conventions go…