本文仅介绍航位推算(Dead Reckoning,DR)的简要原理。航位推算基于初始位置,姿态角,速度信息,推算后续的位置。主要可分为两步。
(1)东北天向速度计算
基于偏航角yaw,俯仰角pitch,横滚角roll,可以计算出旋转矩阵
R
=
[
c
o
s
(
r
o
l
l
)
c
o
s
(
y
a
w
)
−
s
i
n
(
p
i
t
c
h
)
s
i
n
(
r
o
l
l
)
s
i
n
(
y
a
w
)
−
c
o
s
(
p
i
t
c
h
)
s
i
n
(
y
a
w
)
c
o
s
(
y
a
w
)
s
i
n
(
r
o
l
l
)
+
c
o
s
(
r
o
l
l
)
s
i
n
(
p
i
t
c
h
)
s
i
n
(
y
a
w
)
c
o
s
(
r
o
l
l
)
s
i
n
(
y
a
w
)
+
c
o
s
(
y
a
w
)
s
i
n
(
p
i
t
c
h
)
s
i
n
(
r
o
l
l
)
c
o
s
(
p
i
t
c
h
)
c
o
s
(
y
a
w
)
s
i
n
(
r
o
l
l
)
s
i
n
(
y
a
w
)
−
c
o
s
(
r
o
l
l
)
c
o
s
(
y
a
w
)
s
i
n
(
p
i
t
c
h
)
−
c
o
s
(
p
i
t
c
h
)
s
i
n
(
r
o
l
l
)
s
i
n
(
p
i
t
c
h
)
c
o
s
(
p
i
t
c
h
)
c
o
s
(
r
o
l
l
)
]
R= \begin{bmatrix} cos(roll)cos(yaw)-sin(pitch)sin(roll)sin(yaw) & -cos(pitch)sin(yaw) & cos(yaw)sin(roll)+cos(roll)sin(pitch)sin(yaw)\\ cos(roll)sin(yaw)+cos(yaw)sin(pitch)sin(roll) & cos(pitch)cos(yaw) & sin(roll)sin(yaw)-cos(roll)cos(yaw)sin(pitch)\\ -cos(pitch)sin(roll) & sin(pitch) & cos(pitch)cos(roll) \end{bmatrix}
R=
cos(roll)cos(yaw)−sin(pitch)sin(roll)sin(yaw)cos(roll)sin(yaw)+cos(yaw)sin(pitch)sin(roll)−cos(pitch)sin(roll)−cos(pitch)sin(yaw)cos(pitch)cos(yaw)sin(pitch)cos(yaw)sin(roll)+cos(roll)sin(pitch)sin(yaw)sin(roll)sin(yaw)−cos(roll)cos(yaw)sin(pitch)cos(pitch)cos(roll)
载体速度有右向速度
v
x
v_x
vx,前向速度
v
y
v_y
vy,上向速度
v
z
v_z
vz。基于载体速度和旋转矩阵,可得东向速度
v
E
=
[
c
o
s
(
r
o
l
l
)
c
o
s
(
y
a
w
)
−
s
i
n
(
p
i
t
c
h
)
s
i
n
(
r
o
l
l
)
s
i
n
(
y
a
w
)
]
v
x
−
[
c
o
s
(
p
i
t
c
h
)
s
i
n
(
y
a
w
)
]
v
y
+
[
c
o
s
(
y
a
w
)
s
i
n
(
r
o
l
l
)
+
c
o
s
(
r
o
l
l
)
s
i
n
(
p
i
t
c
h
)
s
i
n
(
y
a
w
)
]
v
z
v_E=[cos(roll)cos(yaw)-sin(pitch)sin(roll)sin(yaw)]v_x-[cos(pitch)sin(yaw)]v_y+[cos(yaw)sin(roll)+cos(roll)sin(pitch)sin(yaw)]v_z
vE=[cos(roll)cos(yaw)−sin(pitch)sin(roll)sin(yaw)]vx−[cos(pitch)sin(yaw)]vy+[cos(yaw)sin(roll)+cos(roll)sin(pitch)sin(yaw)]vz
北向速度
v
N
=
[
c
o
s
(
r
o
l
l
)
s
i
n
(
y
a
w
)
+
c
o
s
(
y
a
w
)
s
i
n
(
p
i
t
c
h
)
s
i
n
(
r
o
l
l
)
]
v
x
+
[
c
o
s
(
p
i
t
c
h
)
c
o
s
(
y
a
w
)
]
v
y
+
[
s
i
n
(
r
o
l
l
)
s
i
n
(
y
a
w
)
−
c
o
s
(
r
o
l
l
)
c
o
s
(
y
a
w
)
s
i
n
(
p
i
t
c
h
)
]
v
z
v_N=[cos(roll)sin(yaw)+cos(yaw)sin(pitch)sin(roll)]v_x+[cos(pitch)cos(yaw)]v_y+[sin(roll)sin(yaw)-cos(roll)cos(yaw)sin(pitch)]v_z
vN=[cos(roll)sin(yaw)+cos(yaw)sin(pitch)sin(roll)]vx+[cos(pitch)cos(yaw)]vy+[sin(roll)sin(yaw)−cos(roll)cos(yaw)sin(pitch)]vz
天向速度
v
U
=
[
−
c
o
s
(
p
i
t
c
h
)
s
i
n
(
r
o
l
l
)
]
v
x
+
[
s
i
n
(
p
i
t
c
h
)
]
v
y
+
[
c
o
s
(
p
i
t
c
h
)
c
o
s
(
r
o
l
l
)
]
v
z
v_U=[-cos(pitch)sin(roll)]v_x+[sin(pitch)]v_y+[cos(pitch)cos(roll)]v_z
vU=[−cos(pitch)sin(roll)]vx+[sin(pitch)]vy+[cos(pitch)cos(roll)]vz
(2)位置更新
位置更新与惯性导航的位置更新方程一致。纬度更新方程为
l
a
t
˙
=
1
R
M
+
h
v
N
\.{lat}=\frac{1}{R_M+h}v_N
lat˙=RM+h1vN
经度更新方程为
l
o
n
˙
=
1
(
R
N
+
h
)
c
o
s
(
l
a
t
)
v
E
\.{lon}=\frac{1}{(R_N+h)cos(lat)}v_E
lon˙=(RN+h)cos(lat)1vE
高度更新方程为
h
˙
=
v
U
\.{h}=v_U
h˙=vU
其中,
R
N
R_N
RN是地球卯酉圈主曲率半径
R
N
=
R
e
(
1
−
e
2
s
i
n
2
(
l
a
t
)
)
1
2
R_N=\frac{R_e}{(1-e^2sin^2(lat))^\frac{1}{2}}
RN=(1−e2sin2(lat))21Re
R
M
R_M
RM是地球子午圈主曲率半径
R
M
=
R
e
(
1
−
e
2
)
(
1
−
e
2
s
i
n
2
(
l
a
t
)
)
3
2
R_M=\frac{R_e(1-e^2)}{(1-e^2sin^2(lat))^\frac{3}{2}}
RM=(1−e2sin2(lat))23Re(1−e2)
其中,
R
e
R_e
Re为地球赤道半径,
e
e
e为地球的椭圆偏心率。若参考WGS-84坐标系,则
R
e
=
6378137
R_e=6378137
Re=6378137,
e
2
=
0.00669437999014
e^2=0.00669437999014
e2=0.00669437999014。
则,在t时间间隔后,纬度更新为:
l
a
t
i
=
l
a
t
i
−
1
+
1
R
M
i
−
1
+
h
i
−
1
v
N
i
t
lat_i=lat_{i-1}+\frac{1}{{R_M}_{i-1}+h_{i-1}}{v_N}_{i}t
lati=lati−1+RMi−1+hi−11vNit
经度更新为:
l
o
n
i
=
l
o
n
i
−
1
+
1
(
R
N
i
−
1
+
h
i
−
1
)
c
o
s
(
l
a
t
i
−
1
)
v
E
i
t
lon_i=lon_{i-1}+\frac{1}{({R_N}_{i-1}+h_{i-1})cos(lat_{i-1})}{v_E}_{i}t
loni=loni−1+(RNi−1+hi−1)cos(lati−1)1vEit
高度更新为:
h
i
=
h
i
−
1
+
v
U
i
t
h_i=h_{i-1}+{v_U}_{i}t
hi=hi−1+vUit
C++示例代码如下
#include <iostream>
#include <cmath>
const double WGS84_Re = 6378137;
const double WGS84_e2 = 0.00669437999014;
const double PI = 3.14159265358979323846;
const double D2R = (PI / 180.0);
const double R2D = (180.0 / PI);
void dead_rockoning(double& lon, double& lat, double& height,double yaw, double pitch, double roll, double forward_speed, double right_speed, double up_speod, double time)
{
double sin_yaw = std::sin(yaw * D2R);
double cos_yaw = std::cos(yaw * D2R);
double sin_pitch = std::sin(pitch * D2R);
double cos_pitch = std::cos(pitch * D2R);
double sin_roll = std::sin(roll * D2R);
double cos_roll = std::cos(roll * D2R);
double rotation_matrix[3][3];
rotation_matrix[0][0] = cos_roll * cos_yaw - sin_pitch * sin_roll * sin_yaw;
rotation_matrix[0][1] = -cos_pitch * sin_yaw;
rotation_matrix[0][2] = cos_yaw * sin_roll * cos_roll * sin_pitch * sin_yaw;
rotation_matrix[1][0] = cos_roll * sin_yaw + cos_yaw * sin_pitch * sin_roll;
rotation_matrix[1][1] = cos_pitch * cos_yaw;
rotation_matrix[1][2] = sin_roll * sin_yaw - cos_roll * cos_yaw * sin_pitch;
rotation_matrix[2][0] = -cos_pitch * sin_roll;
rotation_matrix[2][1] = sin_pitch;
rotation_matrix[2][2] = cos_pitch * cos_roll;
double east_speed = rotation_matrix[0][0] * right_speed + rotation_matrix[0][1] * forward_speed + rotation_matrix[0][2] * up_speod;
double north_speed = rotation_matrix[1][0] * right_speed + rotation_matrix[1][1] * forward_speed + rotation_matrix[1][2] * up_speod;
double sky_speed = rotation_matrix[2][0] * right_speed + rotation_matrix[2][1] * forward_speed + rotation_matrix[2][2] * up_speod;
double RNh = (WGS84_Re / std::sqrt(1.0 - WGS84_e2 * std::sin(lat * D2R) * std::sin(lat * D2R)) + height) * std::cos(lat * D2R);
double RMh= WGS84_Re *(1.0- WGS84_e2)/ (1.0 - WGS84_e2 * std::sin(lat * D2R) * std::sin(lat * D2R))*(std::sqrt(1.0 - WGS84_e2 * std::sin(lat * D2R) * std::sin(lat * D2R))) + height;
double lat_update = north_speed * time * R2D / RMh;
double lon_update = east_speed * time * R2D / RMh;
double height_update = sky_speed * time;
lon = lon + lon_update;
lat = lat + lat_update;
height = height + height_update;
}