pymgp.crstrans.xyz2neu#
- pymgp.crstrans.xyz2neu(xyz, ref, origin='ref', mode='plh', unit='rad', rotmatrix=False)[source]#
Convert Cartesian XYZ coordinates to local coordinates (North,East,Up).
- Parameters:
- xyzarray_like with shape (…,3)
Cartesian XYZ coordinates. The origin is either in the center of the Earth or at the position given by the second argument ref.
- refarray_like with shape (…,3) or (…,2)
Reference position(s) on the ellipsoid. The type of coordinates are specified by mode. ref can be a vector with a single coordinate triplet/doublet or have a similar shape to xyz. The North, East, Up coordinates for the(se) point(s) are (0, 0, 0). In case ref is a single coordinate triplet/doublet then the same reference points is used for all the points in xyz.
- origin{‘ref’, ‘ecef’}, default=’ref’
Origin of the coordinates in xyz. If origin=’ref’ then the XYZ coordinates in xyz are with respect to the point(s) given in ref. The other possibility is coordinates in the ECEF reference frame with the origin at the center of the Earth.
- mode{‘plh’, ‘xyz’,’normal’}, default = ‘plh’
Coordinate type for ref. Possible values are:
‘plh’ : ref contains the geographic latitude and longitude with the unit specified by unit. A third coordinate with the height is optional.
‘xyz’ : ref contains cartesian XYZ coordinates in the ECEF of a point (close) to the ellipsoid. The normal vector is computed for a point on the ellipsoid above or below ref.
‘normal’ : ref contains a normal vector with Cartesian coordinates. It does not necessarily have to be a unit vector (the function returns the unit vector). This options only works when the origin of the xyz coordinates is ref (origin=’ref’).
- unit{‘rad’, ‘deg’}, default = ‘rad’
Units for latitude and longitude, only useful in case mode=’plh’ option is used.
- rotmatrixbool, default=False
Output the rotation matrix(es) as an optional output argument. The rotation matrix can be used for instance to convert the covariance matrix (when available and needed).
- Returns:
- neundarray with shape (…,3) similar to xyz
Local North, East, Up coordinates neu with respect to the point(s) in ref.
- Rndarray with shape (…,3,3), optional
Rotation matrix(es), with
neu = dxyz @ R
. In case ref is a vector R is a 3-by-3 matrix , in case ref is a multidimensional array, R has one more dimension than ref with shape (…,3,3). The rotation matrix can be used for instance to convert the covariance matrix (when available and needed). The rotation matrix is the “transpose” of the rotation matrix of xyz2neu (but the same as ellrotmatrix).
See also
Notes
The rotation matrix differs from the Matlab version in the sense that it is the transpose. This is intentional because of differences between Python and Matlab array storage, broadcasting rules, and matrix multiplication. Possible methods are:
neu = dxyz @ R neu = np.matmul(dxyz, R) neu = np.einsum('...j,...ji',dxyz,R)
The third method using Einstein summation is the most general. The first two methods only work for dxyz.shape (:,3) or (3,), and with R.shape(3,3), but fail with higher dimensions. The rotation matrix also differs between the inverse functions xyz2neu and neu2xyz who return transposed versions to each other so that the above mathematics remain the same.
To convert covariance matrices we recommend to use the function covtransform.
Examples
Create some test data
>>> ref = [ 52*np.pi/180, 4*np.pi/180 ] >>> refxyz = plh2xyz([52, 4, 0],unit='deg') >>> dxyz = [1, 1, 1] >>> xyz = refxyz + np.array(dxyz)
The following examples all have the same ouput
>>> neu = xyz2neu(dxyz, ref) >>> neu = xyz2neu(dxyz, [52, 4], unit='deg') >>> neu = xyz2neu(dxyz, refxyz, mode='xyz') >>> neu = xyz2neu(xyz , refxyz, mode='xyz', origin='ecef') >>> neu = xyz2neu(xyz, [52, 4, 0], origin='ecef', unit='deg') >>> print(neu) [-0.22539858 0.92780758 1.44511888]
You can use only latitude and longitude in ref, but not in ECEF mode where ref MUST have three coordinates
>>> neu = xyz2neu(dxyz, [52, 4], unit='deg') # ok >>> neu = xyz2neu(xyz, [52 , 4], unit='deg', origin='ecef') # fails Traceback (most recent call last): ... AssertionError: Reference coordinate vector ref must have three coordinates when used in combination with origin='ecef'.
Examples with multi dimensional coordinate input xyz. The second parameter ref can either be a row vector or have the same shape as the first input xyz. The number of dimensions is not restricted to two.
>>> dxyz = [[ 1, 1, 1],[ 2, 2, 2],[ 3, 0, 0],[ 0, 4, 1]] >>> neu = xyz2neu(dxyz, ref) # ref is a single coordinate doublet >>> print(neu) [[-0.22539858 0.92780758 1.44511888] [-0.45079715 1.85561515 2.89023776] [-2.3582736 -0.20926942 1.84248526] [ 0.39578607 3.9902562 0.95979625]] >>> neu1 = xyz2neu(dxyz, [ref ,ref, ref, ref]) # matching shapes (ref can be different for each point) >>> neu2 = xyz2neu(dxyz, [ refxyz ,refxyz, refxyz, refxyz], mode='xyz') >>> print( np.max(np.abs(neu1-neu)) < 1e-8, np.max(np.abs(neu2-neu)) < 1e-8) True True
Example with additional rotation matrix output
>>> neu, R = xyz2neu(dxyz, ref, rotmatrix=True) # Rotation matrix output >>> print(R) [[-0.7860912 -0.06975647 0.61416175] [-0.05496885 0.99756405 0.04294637] [ 0.61566148 0. 0.78801075]] >>> print(np.all(neu - np.array(dxyz) @ R < 1e-14)) True
The following two examples do not give the same results because the up-direction is different (geodetic versus astronomic)
>>> xyz2neu([1, 1, 1], refxyz, mode='xyz') # same result as neu = xyz2neu(dxyz,ref) array([-0.22539858, 0.92780758, 1.44511888]) >>> xyz2neu([1, 1, 1], refxyz, mode='normal') array([-0.2206844 , 0.92780758, 1.44584629])