Android GNSS 通过原始数据计算伪距
伪距是GNSS定位中最重要的基本参数之一,而智能终端一般不显式地提供伪距,需要通过GNSS原始数据进行计算。关于GNSS原始数据如何获取,请参考上一篇博客:Android获取GNSS原始数据
一、理论部分
伪距计算公式如下:
ρ
=
(
t
R
X
−
t
T
X
)
×
c
×
1
0
9
\rho= (t_{RX}-t_{TX})\times c\times10^9
ρ=(tRX−tTX)×c×109
其中:tRX为智能手机接收到信号的时间,tTX为卫星发射信号的时间(从当前GNSS周开始),c为光速。
tTX可以直接通过GnssTime.ReceivedSvTimeNanos()获取;而tRX则无法直接获取,需要经过计算,由于卫星系统的时间基准不同,采用不同的方法。
tRX的计算
1、首先定义在完整GNSS时间中测得的时间tRX_GNSS
t
R
X
g
n
s
s
=
T
i
m
e
N
a
n
o
s
−
(
F
u
l
l
B
i
a
s
N
a
n
o
s
+
B
i
a
s
N
a
n
o
s
)
t_{RXgnss}= TimeNanos-(FullBiasNanos+BiasNanos)
tRXgnss=TimeNanos−(FullBiasNanos+BiasNanos)
2、将其化为GNSS周内秒(取值范围在0~604800s),即将其与604800取模
t
R
X
g
p
s
=
t
R
X
g
n
s
s
m
o
d
(
w
e
e
k
s
e
c
N
a
n
o
s
)
t_{RXgps}= t_{RXgnss}\mod (weeksecNanos)
tRXgps=tRXgnssmod(weeksecNanos)
上面计算的值是GPS时间下的tRX,接下来只需要将BDS、GLONASS 和 Galileo 系统的时间转换到 GPStime 中即可。
3、分系统计算tRX
-
对BDS系统: t R X = t R X g p s − 14 s t_{RX}=t_{RXgps}-14s tRX=tRXgps−14s
-
对 Galileo系统:该系统不使用周内秒,而是使用(0~100ms内的部分)
t R X = t R X g n s s m o d ( m i l l i S e c o n d s N a n o s ) t_{RX}=t_{RXgnss}\mod (milliSecondsNanos) tRX=tRXgnssmod(milliSecondsNanos) -
对 GLONASS系统:该系统采用日内秒(0~86400s内的部分)
t R X = t R X g n s s m o d ( d a y s e c N a n o s ) + 3 h − l e a p s e c o n d t_{RX}=t_{RXgnss}\mod (daysecNanos) +3h-leapsecond tRX=tRXgnssmod(daysecNanos)+3h−leapsecond
二、代码部分
1、建立一个类,定义需要用到的常量,并设置构造函数传入GNSS原始数据
public class GNSSData {
private GnssMeasurement gnssMeasurement;
private GnssClock gnssClock;
private double Pseudorange;//伪距
private double TRxGnssNanos;//Gnss完整测量时
private int PRN;
private int SVType;//卫星类型
private static final double c=299792458E-9;//光速 单位:m/ns
private static final double WEEK_SEC = 604800;//周化秒
private static final double DAY_SEC=86400;//日化秒
public GNSSData(GnssMeasurement gnssMeasurement, GnssClock gnssClock) {
this.gnssMeasurement = gnssMeasurement;
this.gnssClock = gnssClock;
}
}
2、计算tTX
double tTx=gnssMeasurement.getReceivedSvTimeNanos()+gnssMeasurement.getTimeOffsetNanos();
3、计算tRx_GNSS
public double getTRxGnssNanos() {
double bias=0;
if (gnssClock.hasBiasNanos())
bias+=gnssClock.getBiasNanos();
if (gnssClock.hasFullBiasNanos())
bias+=gnssClock.getFullBiasNanos();
if (gnssClock.hasLeapSecond())
bias+=gnssClock.getLeapSecond()*1000_000_000;
TRxGnssNanos =gnssClock.getTimeNanos()-bias;
return TRxGnssNanos;
}
4、获取当前卫星类型,并计算tRX和伪距
因为涉及大数取余,使用BigDecimal避免计算出错
public double getPseudorange() {
BigDecimal tRx;
int SvType=gnssMeasurement.getConstellationType();//获取当前卫星类型
BigDecimal decimal_tRxGnssNanos=BigDecimal.valueOf(getTRxGnssNanos());
BigDecimal decimal_weekNanos=BigDecimal.valueOf(WEEK_SEC*1e9);
BigDecimal decimal_dayNanos=BigDecimal.valueOf(DAY_SEC*1e9);
switch(SvType){
case GnssStatus.CONSTELLATION_GPS:
tRx=decimal_tRxGnssNanos.remainder(decimal_weekNanos);//GPS系统
break;
case GnssStatus.CONSTELLATION_GLONASS:
tRx=decimal_tRxGnssNanos.remainder(decimal_dayNanos).add(BigDecimal.valueOf((3*3600)*1E9));//GLONASS系统
break;
case GnssStatus.CONSTELLATION_BEIDOU:
tRx=decimal_tRxGnssNanos.remainder(decimal_weekNanos).subtract(BigDecimal.valueOf(14E9));//BeiDou系统
break;
default:tRx=BigDecimal.valueOf(-1);//未定义的卫星类型
}
BigDecimal decimal_deltaTime=tRx.subtract(BigDecimal.valueOf(tTx));
Pseudorange=decimal_deltaTime.abs().multiply(BigDecimal.valueOf(c)).doubleValue();
if (Pseudorange<1e8 && Pseudorange>1e6)return Pseudorange;//单位:米
else return -1;
}