地球科学とナビゲーションの分野では、通常、地球を中心とした地球固定座標系 (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]])
ご覧のとおり、変換は正しく行われています