地上固定座標系 ECEF および ENU 座標系におけるカメラのポーズの変換

地球科学とナビゲーションの分野では、通常、地球を中心とした地球固定座標系 (ECEF、地球中心、地球固定) と北東の空の座標系 (ENU、イーストノースアップ) が使用されます。地球上の位置と態度。以下に示すように:

地球中心の地球固定座標 ecef および北東の空 ENU 座標系

斜め写真測量のプロセスでは、通常、これら 2 つの座標系の変換が含まれ、カメラの姿勢が回転されます。地球中心地球固定座標系 (ECEF) でのカメラの位置 Xecef_cam が既にわかっている場合は、とカメラの姿勢回転行列 R は、次の手順で北東の空の座標系 (ENU) に変換できます。

1. ENU 座標系でのカメラ位置の座標を計算します。

まず、カメラ位置が ECEF 座標系から ENU 座標系に変換されます。ENU 座標系は基準点を基準としたローカル座標系であるため、基準点の位置を指定する必要があります。基準点の位置は通常、地理座標の緯度と経度の高さで表されます。ECEF 座標 Xecef_ref を持つ参照点があるとします。次に、ENU 座標系におけるカメラ位置の座標 Xenu_cam は、次のように計算できます。dXecef = Xecef_cam - Xecef_ref

Xenu_cam = R_ref.T * dXecef

ここで、dXecef はカメラ位置と基準点の ECEF 座標の差、R_ref.Tは基準点の回転行列の転置、R_ref は基準点の緯度と経度を計算することで取得できます。具体的な形式は以下の通り

# 参考点的经纬度
lon = 114.676720
lat = 37.746420
alt = 0  # 参考点的海拔高度(单位:米)
rclat, rclng = np.radians(lat), np.radians(lon) 
rot_ECEF2ENUV = np.array([[-math.sin(rclng),                math.cos(rclng),                              0],
                              [-math.sin(rclat)*math.cos(rclng), -math.sin(rclat)*math.sin(rclng), math.cos(rclat)],
                              [math.cos(rclat)*math.cos(rclng),  math.cos(rclat)*math.sin(rclng),  math.sin(rclat)]])

2. ENU 座標系でカメラの姿勢を計算します。

ENU 座標系では、カメラの姿勢表現は通常、方向余弦行列 (DCM、方向余弦行列) によって表されます。DCM は次のように計算できます。

DCM_enu = R * R_ref.T

ここで、R_ref.T は、参照点の回転行列の転置です (同上)。これら 2 つの手順により、カメラの位置と姿勢を ECEF 座標系から ENU 座標系に変換できます。同じ座標単位とポーズ表現を必ず使用してください。ENU 座標系はローカル座標系であるため、変換結果は参照点の選択によって異なることに注意してください。

以下は Python コードの例です

import numpy as np
import math

def geodetic_to_ecef(lon, lat, alt):
    a = 6378137.0  # 地球的半长轴(赤道半径,单位:米)
    f = 1 / 298.257223563  # 扁率
    
    lon_rad = np.radians(lon)
    lat_rad = np.radians(lat)
    
    N = a / np.sqrt(1 - (f * (2 - f)) * np.sin(lat_rad)**2)
    
    x = (N + alt) * np.cos(lat_rad) * np.cos(lon_rad)
    y = (N + alt) * np.cos(lat_rad) * np.sin(lon_rad)
    z = (N * (1 - f)**2 + alt) * np.sin(lat_rad)
    
    return np.array([x, y, z])


#已知的地固坐标系下的位置和姿态
ecef_x= -2108290.78524083 
ecef_y= 4588675.69211609 
ecef_z= 3883213.009044
#R
ecef_matrix = np.array([[-0.924619168850922, -0.37082528979597, -0.0869942356778073],
                             [0.192895998529247, -0.258938143907446, -0.946436564900771],
                             [0.328436487535772, -0.891874229966031, 0.310949885958594]])

# 为了验证的enu坐标系下的正确位置和姿态
enu_x = -5.25326294611772 
enu_y = -88.1162361244917
enu_z = 91.8780135626621			
enu_matrix = np.array([[0.994999772929298, -0.0988252823926444, -0.0144573659655384],
                           [-0.067174196729575, -0.555035783385474,-0.829109707128924],
                           [0.0739126454971252, 0.825935132272315, -0.55889898739748]])

# 参考点的经纬度
lon = 114.676720
lat = 37.746420
alt = 0  # 参考点的海拔高度(单位:米)
rclat, rclng = np.radians(lat), np.radians(lon) 
#R_ref
rot_ECEF2ENUV = np.array([[-math.sin(rclng),                math.cos(rclng),                              0],
                              [-math.sin(rclat)*math.cos(rclng), -math.sin(rclat)*math.sin(rclng), math.cos(rclat)],
                              [math.cos(rclat)*math.cos(rclng),  math.cos(rclat)*math.sin(rclng),  math.sin(rclat)]])

# 计算参考点的ECEF坐标
Xecef_ref = geodetic_to_ecef(lon, lat, alt)
print('参考点位置-地固坐标系')
print(Xecef_ref)
print('\n')

# 相机位置在ECEF坐标系中
Xecef_cam = np.array([ecef_x, ecef_y, ecef_z])  

# 计算相机位置在ENU坐标系中的坐标
dXecef = Xecef_cam - Xecef_ref
print('dXecef')
print(dXecef)
print('\n')

#Xenu_cam = np.dot(ecef_matrix.T, dXecef)
Xenu_cam = np.dot(dXecef, rot_ECEF2ENUV.T)
print('相机在ENU坐标中的位置')
print(Xenu_cam)
print('\n')


# 计算相机的ENU坐标系中的姿态
DCM_enu = np.dot(ecef_matrix, rot_ECEF2ENUV.T)
print('相机在ENU坐标中姿态')
print(DCM_enu)
print('\n')

演算結果

# 正しい位置とポーズ

enu_x =-5.25326294611772

enu_y =-88.1162361244917

enu_z =91.8780135626621

enu_matrix = np.array([[0.994999772929298,-0.0988252823926444,-0.0144573659655384],[-0.067174196729575,-0.555035783385474,-0.829109 707128924]、[0.0739126454971252、0.825935132272315、-0.55889898739748]])

ご覧のとおり、変換は正しく行われています

おすすめ

転載: blog.csdn.net/sinat_34816302/article/details/132356521