航位推算
功能介绍
航位推算(Dead Reckoning) 是车载多源融合定位 SDK,在 GNSS、IMU、车身信号与地图匹配反馈基础上输出连续、稳定的车辆位姿。
| 能力 |
说明 |
| 多源融合 |
GNSS、陀螺仪、加速度计、车速/档位等 |
| 位置输出 |
经纬高、航向、速度、姿态、精度、解算状态 |
| 地图匹配闭环 |
接收地图匹配反馈,提升隧道与复杂路网定位连续性,见地图匹配 |
| 日志回放 |
路测日志录制与离线回放验证 |
时序图

核心接口
对外唯一入口类为 com.telenav.auto.dr.DrEngineManager(单例)。初始化、获取数据通道、注册输出监听均通过该类完成;涉及的数据类型在对应方法下展开说明。
| DrEngineManager.getInstance()
├── init(DrEngineConfig) → DrEngineConfig / DrEngineInitStatus / CustomParam
├── getGnssDataSender() → GnssDataSender → GnssFixBean
├── getSensorDataSender() → SensorDataSender
├── getVehicleDataSender() → VehicleDataSender → VehicleDataBean
├── getMapMatchingFeedbackSender()→ MapMatchingFeedbackSender → MapMatchingFeedbackPositionBean
├── addDrOutListener() → DrOutListener → VehiclePositionBean
├── addDrReplayStatusListener() → DrReplayStatusListener
└── destroy()
|
DrEngineManager
| 项目 |
说明 |
| 类型 |
public class,单例 |
| 职责 |
引擎生命周期、分发 *Sender、注册 *Listener |
getInstance()
| public static DrEngineManager getInstance()
|
获取全局唯一实例,后续所有操作均通过该对象进行。
init(DrEngineConfig drEngineConfig)
| public DrEngineInitStatus init(@NonNull DrEngineConfig drEngineConfig)
|
| 项目 |
说明 |
| 调用时机 |
应用或定位 Service 启动时,同步调用 |
| 返回值 |
DrEngineInitStatus,仅 Success 后可获取 Sender |
| 重复调用 |
已成功初始化后直接返回 Success,不重新加载配置;需重启请先 destroy() |
关联类:DrEngineConfig
通过 DrEngineConfig.newBuilder(context).build() 构建,传给 init()。
| Builder 方法 |
类型 |
默认值 |
说明 |
setMode |
DrEngineMode |
GNSS_3GYRO_3ACC_ODM_MODE |
传感器组合,须与实车一致 |
setConfigName |
ConfigName |
Default |
车型预置配置,见下文 ConfigName |
setConfigFilePath |
String |
{externalFilesDir}/drEngine |
配置根目录;build() 自动追加 /config |
setLogPath |
String |
.../logs/drEngine |
日志目录 |
setDiagnosticPath |
String |
.../diagnosticPath |
诊断数据目录 |
setTrigger |
Trigger |
Period |
Period 周期输出 / Event 事件输出 |
setPeriod |
int |
100 |
周期 ms,建议 ≥ 50 |
setReplay |
boolean |
false |
回放模式 |
setReplayDataPath |
String |
同 logPath |
replay=true 时必填 |
setDrEngineLogEnabled |
boolean |
false |
日志总开关 |
setLogicLogLevel |
LogicLogLevel |
Disable |
Disable~Debug |
setCustomParam |
CustomParam |
null |
见下文 |
DrEngineMode(setMode 使用)
| 常量 |
传感器组合 |
ONLY_GNSS_MODE |
仅 GNSS |
GNSS_3GYRO_3ACC_ODM_MODE |
GNSS + 三轴陀螺 + 三轴加速度 + 里程(默认) |
GNSS_GYRO_2ACC_ODM_MODE |
GNSS + 单轴陀螺 + 双轴加速度 + 里程 |
GNSS_GYRO_1ACC_ODM_MODE |
GNSS + 单轴陀螺 + 单轴加速度 + 里程 |
GNSS_GYRO_ODM_MODE |
GNSS + 单轴陀螺 + 里程 |
GNSS_4W1S_MODE |
GNSS + 四轮速 + 方向盘转角 |
GNSS_2RW_MODE |
GNSS + 后轮双轮速 |
ConfigName(setConfigName 使用)
ConfigName 为顶层枚举(com.telenav.auto.dr.ConfigName),通过 setConfigName 指定 SDK 内置的车型预置配置:
| import com.telenav.auto.dr.ConfigName;
DrEngineConfig.newBuilder(context)
.setConfigName(ConfigName.Default)
.build();
|
build() 会将 SDK 内对应配置拷贝到 setConfigFilePath 指定目录;本地已存在且版本未变则跳过拷贝。
关联类:CustomParam(可选,经 setCustomParam 传入)
| 子类型 |
说明 |
MountingAngles |
IMU 相对车体安装角 pitch / roll / yaw(°),三者须齐全 |
LeverArm gnssCoordinates |
GNSS 天线在 IMU 系下 x/y/z(m) |
LeverArm vrpCoordinates |
车辆参考点(后轴中心)在 IMU 系下 x/y/z(m) |
返回值:DrEngineInitStatus
| 枚举值 |
含义 |
处理建议 |
Success |
成功 |
注册 Listener、获取 Sender |
ConfigNotFound |
配置缺失 |
检查 ConfigName、存储权限 |
LogPathNotSet |
未设日志路径 |
开日志时调用 setLogPath |
ReplayDataPathNotSet / ReplayDataNotFound |
回放路径/数据异常 |
检查 setReplayDataPath |
ConfigNotSet / TriggerNotSet / PeriodNotSet |
配置项缺失 |
补全 Builder |
NoDrProxy / UnknownInitError |
其它错误 |
查日志 |
init(Context context)
| public void init(@NonNull Context context)
|
使用 SDK 内置默认 DrEngineConfig 初始化,等价于 init(DrEngineConfig.newBuilder(context).build())。快速验证可用,量产建议使用带车型配置的 init(DrEngineConfig)。
destroy()
关闭引擎并释放资源;应用或定位 Service 退出时必须调用。销毁后 getXxxDataSender() 返回 null,需重新 init()。
getGnssDataSender()
| @Nullable
public GnssDataSender getGnssDataSender()
|
| 项目 |
说明 |
| 前置条件 |
init() 返回 Success |
| 返回值 |
GnssDataSender 实例;未初始化时为 null |
| 用途 |
将 GNSS 定位结果送入 DR |
关联接口:GnssDataSender
| void onLocationChanged(@NonNull GnssFixBean location);
|
关联类:GnssFixBean(com.telenav.auto.dr.bean)
使用 GnssFixBean.newBuilder()...build() 构建。
| Builder / 字段 |
说明 |
setTimestamp(long) |
必填,SystemClock.elapsedRealtime() |
setUtcTimestamp(long) |
UTC 毫秒 |
setLatitude / setLongitude / setAltitude |
位置 |
setSpeed(float) |
m/s,调用后标记速度有效 |
setHeading(float) |
°,北 0、顺时针 0–359 |
setAccuracy(h, v) |
水平/垂直精度 m |
setSatelliteInUse / setSatelliteInView |
不可用填 -1 |
getSensorDataSender()
| @Nullable
public SensorDataSender getSensorDataSender()
|
关联接口:SensorDataSender
| 方法 |
参数说明 |
onGyroscopeDataReceived(gx, gy, gz, timestamp) |
角速度 rad/s;timestamp = elapsedRealtime |
onAccelerometerDataReceived(ax, ay, az, timestamp) |
加速度 m/s² |
onPressureDataReceived(pressure, timestamp) |
气压 hPa(可选) |
getVehicleDataSender()
| @Nullable
public VehicleDataSender getVehicleDataSender()
|
关联接口:VehicleDataSender
| void onVehicleDataReceived(@NonNull VehicleDataBean vehicleDataBean);
|
关联类:VehicleDataBean
| Builder 方法 |
说明 |
setTimestamp(long) |
elapsedRealtime |
setSpeed(float) |
车速 m/s |
setGearStatus(GearStatus) |
GEAR_PARK / NEUTRAL / REVERSE / DRIVE 等 |
setWheelSpeed(fl, fr, rl, rr) |
四轮速 m/s(GNSS_4W1S_MODE 等) |
setSteeringAngle(float) |
方向盘转角 ° |
setAngularRate(float) |
垂向陀螺 Z,rad/s |
setHorizontalAcceleration(ax, ay) |
水平加速度 m/s² |
getMapMatchingFeedbackSender()
| @Nullable
public MapMatchingFeedbackSender getMapMatchingFeedbackSender()
|
可选能力,接入地图匹配闭环时使用。
关联接口:MapMatchingFeedbackSender
| void onMapMatchingFeedback(@NonNull MapMatchingFeedbackPositionBean bean);
|
关联类:MapMatchingFeedbackPositionBean
| Builder 方法 |
说明 |
setTimestamp(long) |
elapsedRealtime |
setDrTimestamp(long) |
须与最近一次 VehiclePositionBean.drTimestamp 一致 |
setRawLat/Lon/Heading/... |
DR 原始位姿 |
setMmLat/Lon/Heading/Speed |
匹配后位姿 |
setMmConfidence(int) |
0–6 |
setMmProbability(int) |
0–30 |
setOffRoad / setInTunnel |
离路 / 隧道 |
setRoadCandidates(int) |
0 表示离路 |
addDrOutListener / removeDrOutListener
| public void addDrOutListener(@NonNull DrOutListener drOutListener)
public void removeDrOutListener(@NonNull DrOutListener drOutListener)
|
| 项目 |
说明 |
| 调用时机 |
init 成功前后均可注册;建议 init 后立即 add |
| 线程 |
回调可能在非主线程,更新 UI 需切换主线程 |
| 多监听 |
支持注册多个 DrOutListener |
关联接口:DrOutListener
| void onVehiclePositionReceived(@NonNull VehiclePositionBean vehiclePositionBean);
|
关联类:VehiclePositionBean(输出)
| 字段 |
类型 |
说明 |
timestamp |
long |
UTC ms |
drTimestamp |
long |
与 MM 同步用,回灌时原样传入 |
latitude / longitude / altitude |
— |
位置 |
speed |
float |
m/s |
heading |
float |
航向 °,与档位对齐 |
yaw |
float |
偏航 °,与档位无关 |
horizontalPrecision |
float |
水平精度 m |
drStatus |
DrStatus |
DR_STATUS_GPS / DR_STATUS_DR / DR_STATUS_DR_GPS / DR_STATUS_DR_MMF |
synchronousCount |
int |
0–255,与 MM 同步 |
satelliteNum |
int |
0 表示 GNSS 无效 |
addDrReplayStatusListener / removeDrReplayStatusListener
| public void addDrReplayStatusListener(@NonNull DrReplayStatusListener listener)
public void removeDrReplayStatusListener(@NonNull DrReplayStatusListener listener)
|
关联接口:DrReplayStatusListener
| void onReplayLogFinished();
|
仅在 DrEngineConfig.setReplay(true) 时有效,表示离线日志回放结束。
resetForReplay(String replayDataPath)
| public void resetForReplay(@NonNull String replayDataPath)
|
| 项目 |
说明 |
| 用途 |
运行中切换回放数据目录 |
| 前置条件 |
init() 已成功,否则抛 IllegalStateException |
| 配置 |
须与 setReplay(true)、setReplayDataPath 配合使用 |
示例代码
以下示例以 DrEngineManager 为入口,演示初始化、注册输出、通过各 *Sender 喂数及 MM 回灌。完整工程可参考 app 模块中的 com.telenav.dr.DrClient。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141 | import android.content.Context;
import android.os.SystemClock;
import android.util.Log;
import androidx.annotation.NonNull;
import com.telenav.auto.dr.ConfigName;
import com.telenav.auto.dr.DrEngineConfig;
import com.telenav.auto.dr.DrEngineInitStatus;
import com.telenav.auto.dr.DrEngineManager;
import com.telenav.auto.dr.DrEngineMode;
import com.telenav.auto.dr.DrOutListener;
import com.telenav.auto.dr.GnssDataSender;
import com.telenav.auto.dr.MapMatchingFeedbackSender;
import com.telenav.auto.dr.SensorDataSender;
import com.telenav.auto.dr.VehicleDataSender;
import com.telenav.auto.dr.bean.GnssFixBean;
import com.telenav.auto.dr.bean.MapMatchingFeedbackPositionBean;
import com.telenav.auto.dr.bean.VehicleDataBean;
import com.telenav.auto.dr.bean.VehiclePositionBean;
/**
* 航位推算 SDK 接入示例(Java)
*/
public class DrLocationHelper {
private static final String TAG = "DrLocationHelper";
private final Context context;
private long lastDrTimestamp;
private final DrOutListener drOutListener = new DrOutListener() {
@Override
public void onVehiclePositionReceived(@NonNull VehiclePositionBean position) {
onDrPosition(position);
}
};
public DrLocationHelper(@NonNull Context context) {
this.context = context.getApplicationContext();
}
/** 启动 DR:init + 注册输出监听 */
public void start() {
DrEngineConfig config = DrEngineConfig.newBuilder(context)
.setMode(DrEngineMode.GNSS_3GYRO_3ACC_ODM_MODE)
.setConfigName(ConfigName.Default)
.setTrigger(DrEngineConfig.Trigger.Period)
.setPeriod(100)
.setDrEngineLogEnabled(false)
.build();
DrEngineInitStatus status = DrEngineManager.getInstance().init(config);
if (status == DrEngineInitStatus.Success) {
DrEngineManager.getInstance().addDrOutListener(drOutListener);
Log.i(TAG, "DR engine started");
} else {
Log.e(TAG, "DR init failed: " + status);
}
}
/** 停止 DR */
public void stop() {
DrEngineManager.getInstance().removeDrOutListener(drOutListener);
DrEngineManager.getInstance().destroy();
}
/** GNSS 定位回调中调用 */
public void onGnssUpdate(double lat, double lon, double alt, float speedMps) {
GnssDataSender sender = DrEngineManager.getInstance().getGnssDataSender();
if (sender == null) {
return;
}
long ts = SystemClock.elapsedRealtime();
GnssFixBean.Builder builder = GnssFixBean.newBuilder()
.setTimestamp(ts)
.setUtcTimestamp(System.currentTimeMillis())
.setLatitude(lat)
.setLongitude(lon)
.setAltitude(alt);
if (speedMps >= 0f) {
builder.setSpeed(speedMps);
}
sender.onLocationChanged(builder.build());
}
/** IMU 传感器回调中调用 */
public void onImuUpdate(float gx, float gy, float gz,
float ax, float ay, float az) {
SensorDataSender sender = DrEngineManager.getInstance().getSensorDataSender();
if (sender == null) {
return;
}
long ts = SystemClock.elapsedRealtime();
sender.onGyroscopeDataReceived(gx, gy, gz, ts);
sender.onAccelerometerDataReceived(ax, ay, az, ts);
}
/** 车身信号回调中调用 */
public void onVehicleUpdate(float speedMps, @NonNull VehicleDataBean.GearStatus gear) {
VehicleDataSender sender = DrEngineManager.getInstance().getVehicleDataSender();
if (sender == null) {
return;
}
VehicleDataBean data = VehicleDataBean.newBuilder()
.setTimestamp(SystemClock.elapsedRealtime())
.setSpeed(speedMps)
.setGearStatus(gear)
.build();
sender.onVehicleDataReceived(data);
}
private void onDrPosition(@NonNull VehiclePositionBean position) {
lastDrTimestamp = position.drTimestamp;
// 送给导航 / 地图匹配
// mapMatching.update(position.latitude, position.longitude, position.heading, ...);
}
/** 地图匹配结果回调中调用 */
public void onMapMatchingResult(double mmLat, double mmLon, float mmHeading,
double rawLat, double rawLon, float rawHeading,
int confidence) {
MapMatchingFeedbackSender sender =
DrEngineManager.getInstance().getMapMatchingFeedbackSender();
if (sender == null) {
return;
}
MapMatchingFeedbackPositionBean feedback = MapMatchingFeedbackPositionBean.newBuilder()
.setTimestamp(SystemClock.elapsedRealtime())
.setDrTimestamp(lastDrTimestamp)
.setRawLat(rawLat)
.setRawLon(rawLon)
.setRawHeading(rawHeading)
.setMmLat(mmLat)
.setMmLon(mmLon)
.setMmHeading(mmHeading)
.setMmConfidence(confidence)
.build();
sender.onMapMatchingFeedback(feedback);
}
}
|
注意事项
初始化与生命周期
- 必须先
init() 且返回 Success,再获取 getXxxDataSender();否则返回 null。
- 已成功初始化后再次
init() 会直接返回 Success,不会重新加载配置;需重启请先 destroy() 再 init()。
时间戳与数据质量
- 传感器 / 车身
timestamp 必须使用 elapsedRealtime。
- MM 反馈的
drTimestamp 必须与最近一次 VehiclePositionBean.drTimestamp 一致。
线程与回调
onVehiclePositionReceived 可能在非主线程触发,更新 UI 需切换主线程。
- Listener 内勿做阻塞操作,避免拖慢引擎回调。
配置与存储
- 需保证
configFilePath、logPath 对应目录可写;
- 开启日志(
setDrEngineLogEnabled(true))时必须设置 setLogPath。
回放模式
setReplay(true) 时必须设置有效的 setReplayDataPath。
resetForReplay(path) 仅在初始化成功后调用,否则抛 IllegalStateException。
兼容性
- SDK API 为 Java 实现,可直接在 Java 或 Kotlin 工程中调用。