{"version":"0.1.0","code":"0000","result":true,"message":"处理成功","errdetail":"","timestamp":1671518026540,"data":{"id":71712473,"title":"4.2 定位适配对接指南","slug":"be2ikc","format":"lake","bookId":26046811,"body":null,"body_draft":null,"body_html":"

时序图

对接说明

说明:函数详情,请复制函数名称到在线API搜索。

1. 获取定位服务

synchronized IService com.autonavi.gbl.servicemanager.ServiceMgr.getBLService(@SingleServiceID.SingleServiceID1 int serviceID) 

调用 PosService mPosService = (PosService) ServiceMgr.getServiceMgrInstance().getBLService(PosSingleServiceID)接口以获取高德定位服务。

1.1 服务初始化配置

virtual ErrorCode IPosService::Init\t(\tconst PosWorkPath & \tpath,\n\t\t\t\t\t\t\t\t\t\tconst LocModeType & \tlocModeType,\n\t\t\t\t\t\t\t\t\t\tconst IThreadObserver * \tthreadObserver \n)

定位服务只有在PosService.init方法成功调用后才能正常使用,init时需要设置几个参数:

PosWorkPath path(定位工作目录)

LocModeType locModeType(定位工作模式配置)

IThreadObserver threadObserver(线程执行观察者)

其中最为复杂且容易出错的在locModeType的适配上。path / threadObserver 参考DEMO代码根据实际情况配置即可,这里不展开讲。

如下是LocModeType的数据结构,该数据结构的正确配置与否,是适配成功的很大关键所在。

public class LocModeType {\n    @LocType1\n    public int locType;\n    public int funcs;\n    public LocMountAngle mountAngle;\n    public LocSensorOption sensorOption;\n    public int signalTypes;\n    @PlatformType1\n    public int platformType;\n    ...\n}

以下展开各字段的配置详细说明。

1.2 配置定位模式

LocModeType.locType : 定位模式类型,目前包含三种模式,项目根据情况赋值

枚举值

LocTypeUnknown 

未知

LocTypeGNSS 

GPS定位模式

纯GPS模式:需要配置LocSensorOption.pulseFreq=0

GPS+脉冲模式:需要配置LocSensorOption.pulseFreq= 1 

LocTypeDrBack 

DR模式(后端融合)

LocTypeDrFront 

DR模式(前端融合)

⚠️定位引擎工作在什么模式下,此信息从项目的《定位信息调查表》中获取。

1.3 配置定位功能开关插件

LocModeType.funcs 使用  LocFuncSwitch 进行位运算组合得到。

定位引擎的部分功能目前已实现插件化,允许上层通过开关进行控制,方便各项目根据实际情况(能开启哪些功能主要取决于定位模式和具备哪些信号)进行调整。项目需要在需求阶段就明确需要开启的功能,尤其是对信号有较强依赖的功能,例如,高架识别、主辅路识别等。

建议功能组合

⚠️以下组合为默认推荐的配置,仅供参考,实际项目适配时需要根据自身项目情况,与项目经理确认后灵活配置。

GNSS模式

funcs = LocFuncDelayTurningLowSpeed | LocFuncTurningMainSideRoad | LocFuncConfusingTurning | LocFuncPosDataEnable\n        | LocFuncReroutingRejectorPassOver | LocFuncReroutingRejectorARS | LocFuncReroutingRejectorDist\n        | LocFuncReroutingByCruiseTunnelCorrection; 

前端融合模式

funcs =  LocFuncConfusingTurning | LocFuncMainSideRoadDecision | LocFuncForkQuickCorrection | LocFuncPosDataEnable | LocFuncParallelRecognize | LocFuncDivergingPathsRecognize\n         | LocFuncReroutingRejectorPassOver | LocFuncReroutingRejectorARS | LocFuncReroutingRejectorDist; 

后端融合模式(单轴陀螺或三轴陀螺)

funcs =  LocFuncDivergingPathsRecognize | LocFuncTurningSmooth | LocFuncTurningMainSideRoad\n          | LocFuncUTurnMatch | LocFuncTunnelCorrection | LocFuncLeaveRoundabout | LocFuncPosDataEnable\n          | LocFuncReroutingRejectorPassOver | LocFuncReroutingRejectorARS | LocFuncReroutingRejectorDist\n          | LocFuncReroutingRejectorCross;           

后端融合(三轴陀螺+三轴加速度计)

funcs = LocFuncParallelRecognize| LocFuncDivergingPathsRecognize | LocFuncTurningSmooth\n         | LocFuncTurningMainSideRoad  | LocFuncUTurnMatch | LocFuncAbsolutePosCorrection\n         | LocFuncTunnelCorrection | LocFuncLeaveRoundabout | LocFuncPosDataEnable\n         | LocFuncReroutingRejectorPassOver | LocFuncReroutingRejectorARS | LocFuncReroutingRejectorDist\n         | LocFuncReroutingRejectorCross;      

⚠️如下功能只有在项目有特定要求的情况下开启:

  1. 高架识别(LocFuncViaductRecognize)
  2. 偏航辅助–巡航高架识别(LocFuncReroutingByCruiseViaduct)
  3. 云+端EHP功能(LocFuncEHPEnable)

⚠️如下功能当前不允许开启:

  1. 偏航辅助–巡航主辅路识别(LocFuncReroutingByCruiseMainSideRoad)
  2. 偏航辅助–巡航分岔路识别(LocFuncReroutingByCruiseDivergingPaths)

1.4 配置信号组合方式

LocModeType.signalTypes: 信号类型,可选,设置后端融合模式下信号组合方式,该值为枚举LocDataType的位运算组合,引擎支持的组合方式参见LocSignalCombine。(当LocType == LocTypeDrBack时为必传参数,否则默认为0)。

⚠️当前此接口只有后端融合需要配置

定位数据类型: 详见API文档中LocModeType

1.5 配置安装角

LocMountAngle LocModeType::mountAngle 安装角

public class LocMountAngle {\n    public boolean isValid;\n    public double yaw;\n    public double pitch;\n    public double roll;\n    ...\n}
  1. 此信息只有后端融合需要配置。
  2. 安装角信息从项目的《定位信息调查表》中获取。
  3. 安装角确认方式请参考【什么是安装角】、【如何获取安装角】,【台面转动测试实操获取安装角

1.6 配置传感器选项

LocSensorOption LocModeType::sensorOption 传感器参数,可选,设置后端融合模式下传感器相关参数(当LocType == LocTypeDrBack时为必传参数,否则默认不传)。

public class LocSensorOption {\n    public int hasAcc;       /**< 加速度计轴数 {0|1|3}, 0 表示没有 */\n    public int hasGyro;      /**< 陀螺仪轴数 {0|1|3} , 0 表示没有 */\n    public int hasTemp;      /**< 有无陀螺温度传感器  0无 1有 */\n    public int hasPressure;  /**< 有无气压计  0无 1有 */\n    public int hasMag;       /**< 有无磁力计  0无 1有 */\n    public int hasW4m;       /**< 有无四轮速传感器  0无 1有 */\n    public int hasGsv;       /**< 有无GSV信息(星历信息), 0无 1有 */\n    \n    public int pulseFreq;    /**< 脉冲信息输入频率,单位 Hz */\n    public int gyroFreq;     /**< 陀螺仪信息输入频率,单位 Hz */\n    public int gpsFreq;      /**< GNSS信息输入频率,单位 Hz */\n    public int accFreq;      /**< 加速度计信息输入频率,单位 Hz */\n    public int w4mFreq;      /**< 四轮速信息输信息入频率,单位 Hz */\n    ...\n}


2. 定位日志开启

调用:com.autonavi.gbl.pos.PosService.signalRecordSwitch开启定位日志,生成的日志为ckr文件。

日志开启接口:

void com.autonavi.gbl.pos.PosService.signalRecordSwitch(boolean open,LocLogConf conf)

日志配置参数:

com.autonavi.gbl.pos.model.LocLogConf.LocLogConf\t(\t\n    int \tfileLimit, \t\t\t\t\t\t\t// 单个文件上限值,默认60MB,单位:MB\n\tint \tspaceLimit, \t\t\t\t\t\t// 定位LOC日志总空间上限值,默认240MB,单位:MB\n\tint \tlogLevel,\t\t\t\t\t\t\t// loc日志等级,0:简单定位信息;1:全部信息输出。默认值:1\n\tboolean \tisEncryption, \t\t\t\t\t// loc是否加密,false:不加密;true:加密。默认值:false \n\t@LocLogType.LocLogType1 int \tlogType, \t// 定位信号记录文件类型。默认值:LocLogLOC \n    int     logRedirect;\t\t\t\t\t\t// 定位日志定向位置。0:定位日志只输出skg形式;1:定位日志输出到ALC日志,不输出skg形式;2:skg日志和ALC日志都输出定位日志。默认0。\n    boolean \tisRedirectALC\t\t\t\t\t// 是否将skg日志重定向到ALC \n)\t

3. 添加观察者

使用者根据业务需要注册观察者,之后可以通过观察者获取相应的信息。

具体接口信息见在线API

⚠️ 如下所有信息输出接口都是在引擎线程内触发的,严禁做大规模运算或调用可能导致线程挂起的接口,如IO操作、同步类接口(同步DBUS)等

virtual void 

AddLocInfoObserver (const IPosLocInfoObserver *pObserver, int32_t nFlag)=0

 

添加定位信息观察者

virtual void 

RemoveLocInfoObserver (const IPosLocInfoObserver *pObserver)=0

 

删除定位信息观察者

virtual void 

AddParallelRoadObserver (const IPosParallelRoadObserver *pObserver)=0

 

添加主辅路信息观察者

virtual void 

RemoveParallelRoadObserver (const IPosParallelRoadObserver *pObserver)=0

 

删除主辅路信息观察者

virtual void 

AddSwitchParallelRoadObserver (const IPosSwitchParallelRoadObserver *pObserver)=0

 

添加切换平行路观察者

virtual void 

RemoveSwitchParallelRoadObserver (const IPosSwitchParallelRoadObserver *pObserver)=0

 

删除切换平行路观察者

virtual void 

AddSignInfoObserver (const IPosSignInfoObserver *pObserver)=0

 

添加源始信号观察者

virtual void 

RemoveSignInfoObserver (const IPosSignInfoObserver *pObserver)=0

 

删除源始信号观察者

virtual void 

AddDebugInfoObserver (const IPosDebugInfoObserver *pObserver)=0

 

添加定位调试信息观察者

virtual void 

RemoveDebugInfoObserver (const IPosDebugInfoObserver *pObserver)=0

 

删除定位调试信息观察者

virtual void 

AddMapMatchFeedbackObserver (const IPosMapMatchFeedbackObserver *pObserver)=0

 

添加地图匹配反馈信息观察者

virtual void 

RemoveMapMatchFeedbackObserver (const IPosMapMatchFeedbackObserver *pObserver)=0

 

删除地图匹配反馈信息观察者

virtual void 

AddFeedbackMessageObserver (const IFeedbackMessageObserver *pObserver)=0

 

添加定位'埋点回传'信息观察者

virtual void 

RemoveFeedbackMessageObserver (const IFeedbackMessageObserver *pObserver)=0

 

删除定位'埋点回传'信息观察者

virtual void 

AddNgmInfoObserver (const INgmInfoObserver *pObserver)=0

 

添加定位'NGM信息反馈'观察者

virtual void 

RemoveNgmInfoObserver (const INgmInfoObserver *pObserver)=0

 

删除定位'NGM信息反馈'观察者

virtual void 

AddSensorParaObserver (const IPosSensorParaObserver *pObserver)=0

 

添加定位'传感器标定信息回传'观察者

virtual void 

RemoveSensorParaObserver (const IPosSensorParaObserver *pObserver)=0

 

删除定位'传感器标定信息回传'观察者

virtual void 

AddPosDrInfoObserver (const IPosDrInfoObserver *pObserver)=0

 

添加DR相关信息观察者

virtual void 

RemovePosDrInfoObserver (const IPosDrInfoObserver *pObserver)=0

 

删除DR相关信息观察者


4. 设置信号

定位引擎所有信号均通过virtual void IPosService.setSignInfo(LocSignData pLocSignData)接口设置。不同的工作模式所需的信号也不同。

IPosService.setSignInfo是异步接口,客户端可使用多线程分别发送不同类型的数据,但是不能在不同线程同时发送同类型数据。

IPosService.setSignInfo接口里面LocSignData里面对应每个字段HMI都需要一一核实并填充,对于未使用的需要HMI填充默认值(如,一般为0或者-1,具体以对应字段描述或者与高德确认后为准)。

⚠️

  1. 传感器信号(脉冲、陀螺、3D加速度计,四轮速)的频率需保持一致
  2. 后端融合适配前,建议先了解一些【传感器基本知识

不同工作模式需要适配的信号如下表:

模式

LocType

处理信号

数据结构

输入频率

是否必须

说明

GPS(脉冲)

LocTypeGNSS 

定位信号

LocGnss

1HZ

Y

  • 定位引擎工作在纯GPS模式。
  • 此模式以GPS信号为主,其它信号不输入也可以正常工作。
  • 脉冲信号要用于隧道内的位置推算。
  • 此模式定位引擎的主要工作是地图匹配。

卫星星历

LocGpgsv

1HZ

N

脉冲

LocPulse

1HZ

N

电子罗盘

LocECompass

10HZ

N

仪表盘车速

LocSpeedometer

1HZ

N

后端融合

LocTypeDrBack

定位信号

LocGnss

1HZ

Y

  • 定位引擎工作在后端融合模式。
  • 此模式定位引擎的主要工作是位置融合和地图匹配。
  • 此模式支持如下信号组合模式
    • GPS+星历+脉冲+陀螺+加速度计

卫星星历

LocGpgsv

1HZ

Y

脉冲

LocPulse

10HZ

Y

陀螺

LocGyro

10HZ

Y

3D加速度计

LocAcce3d

10HZ

Y

仪表盘车速

LocSpeedometer

1HZ

N

前端融合

LocTypeDrFront

组合定位数据

LocDrPos

1HZ

Y

  • 定位引擎工作在前端融合模式。
  • 此模式定位引擎的主要工作是地图匹配
  • 此模式融合信号和星历都是必须信号

卫星星历

LocGpgsv

1HZ

Y

仪表盘车速

LocSpeedometer

1HZ

N

⚠️设置陀螺和加速度计信号之前,先学习一下传感器基础知识一章中的【对接陀螺和加速度前先看这里一节

5. 销毁定位服务

退出导航时需要销毁定位引擎。调用接口:

 ServiceMgr.getServiceMgrInstance().RemoveBLService(PosSingleServiceID)

销毁定位引擎的时候,引擎会自动保存上下文。客户端也可以自行调用IPosService.SaveLocStorage()方法来保存上下文。详见【参数持久化】说明。

示例代码


package com.autonavi.auto.activity.guide;\n\nimport android.content.Context;\nimport android.content.Intent;\nimport android.hardware.Sensor;\nimport android.hardware.SensorEvent;\nimport android.hardware.SensorEventListener;\nimport android.hardware.SensorManager;\nimport android.location.GpsSatellite;\nimport android.location.GpsStatus;\nimport android.location.Location;\nimport android.location.LocationListener;\nimport android.location.LocationManager;\nimport android.os.Bundle;\nimport android.os.SystemClock;\nimport android.provider.Settings;\nimport android.text.format.Time;\nimport android.util.Log;\nimport android.view.View;\nimport android.widget.TextView;\n\nimport com.autonavi.auto.R;\nimport com.autonavi.auto.activity.base.BaseMapActivity;\nimport com.autonavi.auto.common.AutoConstant;\nimport com.autonavi.auto.presenter.MapManager;\nimport com.autonavi.gbl.cobase.model.ErrorCode;\nimport com.autonavi.gbl.cobase.model.SingleServiceID;\nimport com.autonavi.gbl.common.model.Coord2DDouble;\nimport com.autonavi.gbl.common.observer.IThreadObserver;\nimport com.autonavi.gbl.pos.PosService;\nimport com.autonavi.gbl.pos.model.LocAcce3d;\nimport com.autonavi.gbl.pos.model.LocAirPressure;\nimport com.autonavi.gbl.pos.model.LocDataType;\nimport com.autonavi.gbl.pos.model.LocDrPos;\nimport com.autonavi.gbl.pos.model.LocDrType;\nimport com.autonavi.gbl.pos.model.LocECompass;\nimport com.autonavi.gbl.pos.model.LocFuncSwitch;\nimport com.autonavi.gbl.pos.model.LocGnss;\nimport com.autonavi.gbl.pos.model.LocGpgsv;\nimport com.autonavi.gbl.pos.model.LocGyro;\nimport com.autonavi.gbl.pos.model.LocInfo;\nimport com.autonavi.gbl.pos.model.LocLogConf;\nimport com.autonavi.gbl.pos.model.LocLogType;\nimport com.autonavi.gbl.pos.model.LocModeType;\nimport com.autonavi.gbl.pos.model.LocMountAngle;\nimport com.autonavi.gbl.pos.model.LocMoveStatus;\nimport com.autonavi.gbl.pos.model.LocPulse;\nimport com.autonavi.gbl.pos.model.LocSensorOption;\nimport com.autonavi.gbl.pos.model.LocSignData;\nimport com.autonavi.gbl.pos.model.LocThreeAxis;\nimport com.autonavi.gbl.pos.model.LocType;\nimport com.autonavi.gbl.pos.model.PlatformType;\nimport com.autonavi.gbl.pos.model.PosWorkPath;\nimport com.autonavi.gbl.pos.observer.IPosLocInfoObserver;\nimport com.autonavi.gbl.pos.observer.IPosSignInfoObserver;\nimport com.autonavi.gbl.servicemanager.ServiceMgr;\n\nimport java.math.BigInteger;\nimport java.util.Iterator;\n\npublic class GNSSDemoActivity extends BaseMapActivity implements IThreadObserver, IPosLocInfoObserver, IPosSignInfoObserver {\n\n    public static final String TAG = GNSSDemoActivity.class.getName();\n    private TextView tv_msg1, tv_msg2, tv_msg3, tv_msg4, tv_msg5, tv_msg6;\n    PosService mPosService;\n    LocationManager mLocationManager;\n    int mSatellitesCnt;\n\n    @Override\n    public int getLayoutRes() {\n        return (R.layout.activity_gnss_demo);\n    }\n\n    @Override\n    public void initViewAndData() {\n        initView();\n    }\n\n    private void initView() {\n        tv_msg1 = findViewById(R.id.tv_msg1);\n        tv_msg2 = findViewById(R.id.tv_msg2);\n        tv_msg3 = findViewById(R.id.tv_msg3);\n        tv_msg4 = findViewById(R.id.tv_msg4);\n        tv_msg5 = findViewById(R.id.tv_msg5);\n        tv_msg6 = findViewById(R.id.tv_msg6);\n    }\n\n    @Override\n    protected void onClickImpl(View v) {\n        super.onClickImpl(v);\n        switch (v.getId()) {\n            case R.id.btn_siwtch_mode: // 切换模式\n                switchMode(v);\n                break;\n            case R.id.btn_open_pos_service: // 开启定位\n                openSystemGpsLocation();\n                break;\n            case R.id.btn_close_pos_service: // 关闭定位\n                closeSystemGpsService();\n                break;\n        }\n    }\n\n    @Override\n    public void afterCreate() {\n        super.afterCreate();\n        switchMode(null);\n    }\n\n    /**\n     * 以下为系统开启定位服务设置相关处理,仅供参考\n     */\n    private void openSystemGpsLocation() {\n        mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);\n        if (mLocationManager != null) {\n            if (!mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {\n                showShortToast("请打开GPS");\n                startActivityForResult(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS), 0);\n                tv_msg1.setText("请开启GPS后重试");\n                return;\n            }\n            // 获取定位信息\n            mSatellitesCnt = 0;\n            setSignInfo(mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER));\n            mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, locationListener);\n            mLocationManager.addGpsStatusListener(gpsStatusListener);\n            tv_msg1.setText("开启定位成功");\n        } else {\n            tv_msg1.setText("开启定位失败: mLocationManager is null");\n        }\n    }\n\n    // 星历信息获取\n    private GpsStatus.Listener gpsStatusListener = new GpsStatus.Listener() {\n        @Override\n        public void onGpsStatusChanged(int event) {\n            //卫星状态改变\n            if (event == GpsStatus.GPS_EVENT_SATELLITE_STATUS) {\n                final LocGpgsv locGpgsvData = new LocGpgsv();\n                GpsStatus gpsStatus = mLocationManager.getGpsStatus(null);\n                locGpgsvData.prn = new int[16];\n                locGpgsvData.snr = new int[16];\n                locGpgsvData.elevation = new int[16];\n                locGpgsvData.azimuth = new int[16];\n                //获取卫星颗数的默认最大值\n                int maxSatellites = gpsStatus.getMaxSatellites();\n                //获取所有的卫星\n                Iterator<GpsSatellite> iters = gpsStatus.getSatellites().iterator();\n                //获取所有的卫星数据\n                int count = 0;\n                while (iters.hasNext() && count <= maxSatellites) {\n                    GpsSatellite s = iters.next();\n                    if (s.usedInFix()) {\n                        if (count < 16) {\n                            locGpgsvData.prn[count] = s.getPrn();\n                            locGpgsvData.snr[count] = Math.round(s.getSnr());\n                            locGpgsvData.elevation[count] = Math.round(s.getElevation());\n                            locGpgsvData.azimuth[count] = Math.round(s.getAzimuth());\n                        }\n                    }\n                    count++;\n                }\n                locGpgsvData.num = count < 16 ? count : 16;\n                if (locGpgsvData.num > 0) {\n                    locGpgsvData.type = 0; // 定位系统。0:GPS;1:北斗;2:glonass 有些安卓原生系统,没有这个星历系统类型输出,需要通过卫星编号来判断,HMI请根据自身系统情况对接\n                    locGpgsvData.tickTime = BigInteger.valueOf(SystemClock.elapsedRealtime());\n                    // 回调数据给高德定位服务\n                    mHandler.post(new Runnable() {\n                        @Override\n                        public void run() {\n                            LocSignData locSignData = new LocSignData();\n                            locSignData.dataType = LocDataType.LocDataGpgsv;\n                            locSignData.gpgsv = locGpgsvData;\n                            mPosService.setSignInfo(locSignData);\n                        }\n                    });\n                }\n                // 输出信息\n                final int finalCount = count;\n                runOnUiThread(new Runnable() {\n                    @Override\n                    public void run() {\n                        tv_msg1.setText("当前接收到" + finalCount + "颗卫星数据");\n                    }\n                });\n            }\n        }\n    };\n\n    // 定位信息获取\n    private LocationListener locationListener = new LocationListener() {\n        @Override\n        public void onLocationChanged(Location location) {\n            tv_msg1.setText("onLocationChanged");\n            setSignInfo(location);\n        }\n\n        @Override\n        public void onStatusChanged(String provider, int status, Bundle extras) {\n            tv_msg1.setText("onStatusChanged");\n        }\n\n        @Override\n        public void onProviderEnabled(String provider) {\n            tv_msg1.setText("onProviderEnabled");\n        }\n\n        @Override\n        public void onProviderDisabled(String provider) {\n            tv_msg1.setText("onProviderDisabled");\n        }\n    };\n\n    private void setSignInfo(Location location) {\n        if (location == null)\n            return;\n\n        // 输出位置信息\n        final StringBuilder sb = new StringBuilder();\n        sb.append("当前位置信息:")\n                .append("\\n精度:").append(location.getLongitude())\n                .append("\\n纬度:").append(location.getLatitude())\n                .append("\\n高度:").append(location.getAltitude())\n                .append("\\n速度:").append(location.getSpeed())\n                .append("\\n方向:").append(location.getBearing())\n                .append("\\n定位精度:").append(location.getAccuracy());\n        runOnUiThread(new Runnable() {\n            @Override\n            public void run() {\n                tv_msg2.setText(sb.toString());\n            }\n        });\n\n        LocSignData locSignData = new LocSignData();\n        switch (currentLocType) {\n            case LocType.LocTypeGNSS:\n            case LocType.LocTypeDrBack:\n                LocGnss locGnss = getLocGnssByLocation(location);\n                // 回调新位置给高德定位服务\n                locSignData.dataType = LocDataType.LocDataGnss;\n                locSignData.gnss = locGnss;\n                break;\n            case LocType.LocTypeDrFront:\n                LocDrPos locDrPos = getLocDrPosByLocation(location);\n                // 回调新位置给高德定位服务\n                MapManager.getInstance().setMapCenter(location.getLongitude(), location.getLatitude(), 0, true, true);\n                locSignData.dataType = LocDataType.LocDataDrFusion;\n                locSignData.drPos = locDrPos;\n                break;\n            default:\n                return;\n        }\n        if (mPosService != null) {\n            mPosService.setSignInfo(locSignData);\n        }\n    }\n\n    //卫星颗数统计\n    private int getSatellitesNum(LocationManager lm) {\n        int count = 0;\n        if (lm != null) {\n            //获取当前状态\n            GpsStatus gpsStatus = lm.getGpsStatus(null);\n            if (gpsStatus != null) {\n                //获取卫星颗数的默认最大值\n                int maxSatellites = gpsStatus.getMaxSatellites();\n                //获取所有的卫星\n                Iterator<GpsSatellite> iters = gpsStatus.getSatellites().iterator();\n                while (iters.hasNext() && count <= maxSatellites) {\n                    count++;\n                }\n            }\n        }\n        return count;\n    }\n\n    /**\n     * 关闭系统定位服务\n     */\n    private void closeSystemGpsService() {\n        if (null != mLocationManager) {\n            mLocationManager.removeUpdates(locationListener);\n            mLocationManager.removeGpsStatusListener(gpsStatusListener);\n        }\n        tv_msg1.setText("已关闭系统定位服务");\n        tv_msg2.setText(null);\n    }\n\n    /**\n     * 关闭高德posService\n     */\n    private void closeGDPosService() {\n        if (null != mPosService) {\n            mPosService.removeLocInfoObserver(this);\n            mPosService.removeSignInfoObserver(this);\n            ServiceMgr.getServiceMgrInstance().removeBLService(SingleServiceID.PosSingleServiceID);\n            mPosService = null;\n            tv_msg1.setText("close PosService");\n        }\n    }\n\n    // IThreadObserver\n    @Override\n    public void threadCallback(long l, byte b) {\n        Log.i(TAG, String.format("IThreadObserver threadCallback(%d,%d)", l, b));\n    }\n\n    // IPosLocInfoObserver\n    @Override\n    public void onLocInfoUpdate(LocInfo locInfo) {\n        // TODO: 更新位置信息\n    }\n\n    // IPosSignInfoObserver\n    @Override\n    public void onSignInfoUpdate(LocSignData locSignData) {\n    }\n\n    @Override\n    public void onFinish() {\n        closeGDPosService();\n        closeSystemGpsService();\n    }\n\n    private int[] locTypes = {LocType.LocTypeGNSS, LocType.LocTypeDrBack, LocType.LocTypeDrFront};\n    private String[] locTypeNames = {"纯GPS定位模式", "DR模式(后端融合)", "DR模式(前端融合)"};\n\n    private int currentMode = -1;\n    private int currentLocType = LocType.LocTypeGNSS;\n\n    /**\n     * 切换定位模式\n     *\n     * @param view 触发该操作的按钮\n     */\n    private void switchMode(View view) {\n        if (mPosService == null) {// 获取高德定位服务\n            mPosService = (PosService) ServiceMgr.getServiceMgrInstance().getBLService(SingleServiceID.PosSingleServiceID);\n        }\n\n        currentMode = (currentMode + 1) % locTypeNames.length;\n        currentLocType = locTypes[currentMode];\n        updateViewText(view, locTypeNames[currentMode]);\n\n\n        PosWorkPath path = new PosWorkPath();\n        path.contextPath = AutoConstant.POS_DIR; // 存放定位上下文、流量统计文件,可读写\n        path.locPath = AutoConstant.POS_DIR; // 存放定位loc日志文件,可读写\n\n        // 定位工作模式\n        LocModeType locModeType = new LocModeType();\n        locModeType.locType = currentLocType;\n\n        switch (currentLocType) {\n            case LocType.LocTypeGNSS: // 纯GPS定位模式\n                // 功能插件,设置要启用的决策插件类型,该值为枚举LocFuncSwitch的位运算组合。\n                // GNSS模式(0x8724c0或者8856768)\n                locModeType.funcs = LocFuncSwitch.LocFuncDelayTurningLowSpeed | LocFuncSwitch.LocFuncTurningMainSideRoad | LocFuncSwitch.LocFuncConfusingTurning | LocFuncSwitch.LocFuncPosDataEnable |   //巡航\n                        LocFuncSwitch.LocFuncReroutingRejectorPassOver | LocFuncSwitch.LocFuncReroutingRejectorARS | LocFuncSwitch.LocFuncReroutingRejectorDist |           // 导航偏航抑制器\n                        LocFuncSwitch.LocFuncReroutingByCruiseTunnelCorrection; //导航辅助偏航插件\n                break;\n            case LocType.LocTypeDrBack: // DR模式(后端融合)\n                // 信号类型,设置后端融合模式下信号组合方式,该值为枚举LocDataType的位运算组合,引擎支持的组合方式参见LocSignalCombine。(当LocType == LocTypeDrBack时为必传参数,否则默认为0)\n                locModeType.signalTypes =\n                        LocDataType.LocDataAcce3D | LocDataType.LocDataAirPressure | LocDataType.LocDataGnss |\n                                LocDataType.LocDataECompass | LocDataType.LocDataGpgsv | LocDataType.LocDataGyro | LocDataType.LocDataPulse;\n                // 功能插件,设置要启用的决策插件类型,该值为枚举LocFuncSwitch的位运算组合。\n                // 后端融合(三轴陀螺+三轴加速度计)(0xf39ba或者997818)\n                locModeType.funcs =\n                        LocFuncSwitch.LocFuncParallelRecognize | LocFuncSwitch.LocFuncDivergingPathsRecognize | LocFuncSwitch.LocFuncTurningSmooth   // 巡航\n                                | LocFuncSwitch.LocFuncTurningMainSideRoad | LocFuncSwitch.LocFuncUTurnMatch | LocFuncSwitch.LocFuncAbsolutePosCorrection   // 巡航\n                                | LocFuncSwitch.LocFuncTunnelCorrection | LocFuncSwitch.LocFuncLeaveRoundabout | LocFuncSwitch.LocFuncPosDataEnable          // 巡航\n                                | LocFuncSwitch.LocFuncReroutingRejectorPassOver | LocFuncSwitch.LocFuncReroutingRejectorARS | LocFuncSwitch.LocFuncReroutingRejectorDist    // 导航\n                                | LocFuncSwitch.LocFuncReroutingRejectorCross;\n                /*/ 后端融合模式(单轴陀螺或三轴陀螺)(0xf39b0或者997808)\n                locModeType.funcs |=  LocFuncSwitch.LocFuncDivergingPathsRecognize | LocFuncSwitch.LocFuncTurningSmooth | LocFuncSwitch.LocFuncTurningMainSideRoad                 // 巡航\n                        | LocFuncSwitch.LocFuncUTurnMatch | LocFuncSwitch.LocFuncTunnelCorrection | LocFuncSwitch.LocFuncLeaveRoundabout | LocFuncSwitch.LocFuncPosDataEnable              // 巡航\n                        | LocFuncSwitch.LocFuncReroutingRejectorPassOver | LocFuncSwitch.LocFuncReroutingRejectorARS | LocFuncSwitch.LocFuncReroutingRejectorDist   // 导航\n                        | LocFuncSwitch.LocFuncReroutingRejectorCross;   // 导航*/\n                // 传感器参数,设置后端融合模式下传感器相关参数(当LocType == LocTypeDrBack时为必传参数,否则默认不传)\n                locModeType.sensorOption = getSensorOption();\n                // 安装角,设置后端融合模式下设备安装角信息。(当LocType == LocTypeDrBack时为必传参数,否则默认不传)。\n\n                locModeType.mountAngle = getMountAngle();\n                // 运行的平台类型,需要设置相应的平台amap或者auto,车机版默认为auto;\n                locModeType.platformType = PlatformType.PlatformAuto;\n                break;\n            case LocType.LocTypeDrFront: // DR模式(前端融合)\n                // 功能插件,设置要启用的决策插件类型,该值为枚举LocFuncSwitch的位运算组合。\n                // 前端融合模式(0x72604或者468484)\n                locModeType.funcs = LocFuncSwitch.LocFuncConfusingTurning | LocFuncSwitch.LocFuncMainSideRoadDecision | LocFuncSwitch.LocFuncForkQuickCorrection | LocFuncSwitch.LocFuncPosDataEnable     // 巡航\n                        | LocFuncSwitch.LocFuncReroutingRejectorPassOver | LocFuncSwitch.LocFuncReroutingRejectorARS | LocFuncSwitch.LocFuncReroutingRejectorDist;   // 导航\n                break;\n        }\n        // 定位服务初始化\n        int iErrorCode = mPosService.init(path, locModeType, this);\n        if (iErrorCode != ErrorCode.ErrorCodeOK) {\n            ServiceMgr.getServiceMgrInstance().removeBLService(SingleServiceID.PosSingleServiceID);\n            showShortToast("定位服务初始化失败,模式: " + locTypeNames[currentMode]);\n            mPosService = null;\n            return;\n        }\n        // 添加位置信息观察者\n        mPosService.addLocInfoObserver(this, 0);\n        // 添加原始位置信号观察者\n        mPosService.addSignInfoObserver(this);\n        // 信号记录功能开关\n        mPosService.signalRecordSwitch(true, new LocLogConf(\n                60, 240, 1,\n                false, LocLogType.LocLogEmpty, 0, true));\n\n        // 传感器回调\n        if (currentLocType == LocType.LocTypeDrBack) {\n            updateSensorObserver();\n        }\n\n        tv_msg1.setText("openSystemGpsLocation: " + locTypeNames[currentMode]);\n    }\n\n    private SensorManager mSensorManager = null;\n\n    private LocSensorOption getSensorOption() {\n        LocSensorOption sensorOption = new LocSensorOption();\n        mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);\n        if (mSensorManager == null) {\n            return sensorOption;\n        }\n\n        if (mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null) {\n            sensorOption.hasAcc = 3; // 加速度计轴数 {0|1|3}, 0 表示没有 后端融合项目可选\n        }\n        if (mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE) != null) {\n            sensorOption.hasGyro = 3; // 陀螺仪轴数 {0|1|3} , 0 表示没有 后端融合项目必须有\n        }\n        if (mSensorManager.getDefaultSensor(Sensor.TYPE_AMBIENT_TEMPERATURE) != null) {\n            sensorOption.hasTemp = 1; // 有无陀螺温度传感器  0无 1有 后端融合项目必须有\n        }\n        if (mSensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE) != null) {\n            sensorOption.hasPressure = 1; // 有无气压计  0无 1有, 一般可不配置\n        }\n        if (mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null) {\n            sensorOption.hasMag = 1; // 有无磁力计  0无 1有, 一般可不配置\n        }\n        sensorOption.hasW4m = 0; // 有无四轮速传感器  0无 1有 未使用,可不配置\n        sensorOption.hasGsv = 1;// 有无GSV信息(星历信息), 0无 1有 TODO :根据项目情况配置,推荐1hz,后端融合项目必须有\n        sensorOption.pulseFreq = 10; // 脉冲信息输入频率,单位 Hz TODO :根据项目情况配置,推荐10hz,后端融合项目必须有\n        sensorOption.gyroFreq = 10; // 陀螺仪信息输入频率,单位 Hz TODO :根据项目情况配置,推荐10hz,后端融合项目必须有\n        sensorOption.gpsFreq = 1; // GNSS信息输入频率,单位 Hz TODO :根据项目情况配置,推荐1hz,后端融合项目必须有\n        sensorOption.accFreq = 10; // 加速度计信息输入频率,单位 Hz TODO :根据项目情况配置,推荐10hz,后端融合项目可选\n        sensorOption.w4mFreq = 10; //四轮速信息输信息入频率,单位 Hz 未使用,可不配置\n        return sensorOption;\n    }\n\n    /**\n     * 设置传感器回调\n     */\n    private void updateSensorObserver() {\n        if (mSensorManager == null) return;\n\n        int samplingPeriodUs = SensorManager.SENSOR_DELAY_GAME; // 采样率\n        // 设置传感器回调\n        Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);\n        mSensorManager.getSensorList(Sensor.TYPE_ALL);\n        if (sensor != null) {\n            mSensorManager.registerListener(sensorEventListener, sensor, samplingPeriodUs);\n        }\n        sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);\n        if (sensor != null) {\n            mSensorManager.registerListener(sensorEventListener, sensor, samplingPeriodUs);\n        }\n        sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_AMBIENT_TEMPERATURE);\n        if (sensor != null) {\n            mSensorManager.registerListener(sensorEventListener, sensor, samplingPeriodUs);\n        }\n        sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE);\n        if (sensor != null) {\n            mSensorManager.registerListener(sensorEventListener, sensor, samplingPeriodUs);\n        }\n        sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);\n        if (sensor != null) {\n            mSensorManager.registerListener(sensorEventListener, sensor, samplingPeriodUs);\n        }\n        sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);\n        if (sensor != null) {\n            mSensorManager.registerListener(sensorEventListener, sensor, samplingPeriodUs);\n        }\n    }\n\n    private LocMountAngle getMountAngle() {\n        LocMountAngle locMountAngle = new LocMountAngle();\n        locMountAngle.isValid = true; // TODO: 安装角是否可用,需根据项目情况正确配置\n        locMountAngle.yaw = 0.0f;   // TODO: 安装角yaw值,需根据项目情况正确配置\n        locMountAngle.roll = 0.0f;  // TODO: 安装角roll值,需根据项目情况正确配置\n        locMountAngle.pitch = 0.0f; // TODO: 安装角pitch值,需根据项目情况正确配置\n        return locMountAngle;\n    }\n\n    private long tickTimeACC = 0;\n    private long tickTimeGRAVITY = 0;\n    private long tickTimePRESSURE = 0;\n    private long tickTimeORIENTATION = 0;\n    private float mSpeed = 0.0f;\n    float mTemperature = 0.0f;\n    private SensorEventListener sensorEventListener = new SensorEventListener() {\n\n        @Override\n        public void onSensorChanged(SensorEvent event) {\n            if (null != event && null != event.sensor && mPosService != null) {\n                switch (event.sensor.getType()) {\n                    case Sensor.TYPE_ACCELEROMETER: {// 3D加速度计,后端融合必须提供,频率必须为10hz\n                        LocAcce3d sensorData = new LocAcce3d();\n                        sensorData.axis = LocThreeAxis.LocAxisAll; // 有效数据轴\n                        sensorData.acceX = event.values[0];\n                        sensorData.acceY = event.values[1];\n                        sensorData.acceZ = event.values[2];\n                        long elapsedRealtime = SystemClock.elapsedRealtime();\n                        if (tickTimeACC > 0) {\n                            sensorData.interval = (int) (elapsedRealtime - tickTimeACC);\n                        } else {\n                            tickTimeACC = elapsedRealtime;\n                        }\n                        sensorData.tickTime = BigInteger.valueOf(elapsedRealtime); // 推荐使用系统滴答数,而非信号源的时间戳\n                        if (sensorData.interval >= 95) {\n                            // 因安卓的接口不能准确控制回调频率为10HZ,这里仅做演示用\n                            // 简单增加if判断以达到控制接收数据的频率,可能导致DR推算不准确。\n                            // !实际项目勿复用这个if判断!\n                            tickTimeACC = elapsedRealtime;\n\n                            LocSignData locSignData = new LocSignData();\n                            locSignData.dataType = LocDataType.LocDataAcce3D;\n                            locSignData.acce3D = sensorData;\n                            mPosService.setSignInfo(locSignData);\n\n                            // 脉冲数据,因安卓手机没有脉冲数据,这里使用GPS速度进行模拟;实际使用时必须使用项目的脉冲数据进行输入,后端融合必须有脉冲数据,否则不能定位\n                            LocPulse locPulseData = new LocPulse();\n                            locPulseData.value = mSpeed;\n                            locPulseData.tickTime = BigInteger.valueOf(elapsedRealtime);\n                            locPulseData.interval = sensorData.interval;\n\n                            locSignData = new LocSignData();\n                            locSignData.dataType = LocDataType.LocDataPulse;\n                            locSignData.pulse = locPulseData;\n                            mPosService.setSignInfo(locSignData);\n\n                            tv_msg3.setText("加速度计:" + sensorData.interval + "\\n" + event.values[0] + "\\n" + event.values[1] + "\\n" + event.values[2] + "\\n速度:" + mSpeed);\n                        }\n                    }\n                    break;\n                    case Sensor.TYPE_GYROSCOPE: {// 陀螺数据,后端融合必须提供,频率必须为10hz\n                        LocGyro sensorData = new LocGyro();\n                        sensorData.axis = LocThreeAxis.LocAxisAll; // 有效数据轴\n                        sensorData.valueX = event.values[0];\n                        sensorData.valueY = event.values[1];\n                        sensorData.valueZ = event.values[2];\n                        sensorData.temperature = mTemperature;\n\n                        long elapsedRealtime = SystemClock.elapsedRealtime();\n                        if (tickTimeGRAVITY > 0) {\n                            sensorData.interval = (int) (elapsedRealtime - tickTimeGRAVITY);\n                        } else {\n                            tickTimeGRAVITY = elapsedRealtime;\n                        }\n                        sensorData.tickTime = BigInteger.valueOf(elapsedRealtime); // 推荐使用系统滴答数,而非信号源的时间戳\n                        if (sensorData.interval >= 95) {\n                            // 因安卓的接口不能准确控制回调频率为10HZ,这里仅做演示用\n                            // 简单增加if判断以达到控制接收数据的频率,可能导致DR推算不准确。\n                            // !实际项目勿复用这个if判断!\n                            tickTimeGRAVITY = elapsedRealtime;\n                            LocSignData locSignData = new LocSignData();\n                            locSignData.dataType = LocDataType.LocDataGyro;\n                            locSignData.gyro = sensorData;\n                            mPosService.setSignInfo(locSignData);\n                            tv_msg4.setText("陀螺:" + sensorData.interval + "\\n" + event.values[0] + "\\n" + event.values[1] + "\\n" + event.values[2] + "\\n温度:" + mTemperature);\n                        }\n                    }\n                    break;\n                    case Sensor.TYPE_AMBIENT_TEMPERATURE: {// 温度传感器,根据实际情况赋值\n                        mTemperature = event.values[0];\n                    }\n                    break;\n                    case Sensor.TYPE_PRESSURE: {// 气压数据,手机Amap所需信号,车机版无需提供\n                        LocAirPressure sensorData = new LocAirPressure();\n                        sensorData.hpa = event.values[0];\n\n                        long elapsedRealtime = SystemClock.elapsedRealtime();\n                        int interval = 0;\n                        if (tickTimePRESSURE > 0) {\n                            interval = (int) (elapsedRealtime - tickTimePRESSURE);\n                        } else {\n                            tickTimePRESSURE = elapsedRealtime;\n                        }\n                        sensorData.tickTime = BigInteger.valueOf(elapsedRealtime); // 推荐使用系统滴答数,而非信号源的时间戳\n                        if (interval >= 95) {\n                            // 因安卓的接口不能准确控制回调频率为10HZ,这里仅做演示用\n                            // 简单增加if判断以达到控制接收数据的频率,可能导致DR推算不准确。\n                            // !实际项目勿复用这个if判断!\n                            tickTimePRESSURE = elapsedRealtime;\n                            LocSignData locSignData = new LocSignData();\n                            locSignData.dataType = LocDataType.LocDataAirPressure;\n                            locSignData.airPressure = sensorData;\n                            mPosService.setSignInfo(locSignData);\n                            tv_msg5.setText("气压:" + interval + "\\n" + event.values[0]);\n                        }\n                    }\n                    break;\n                    case Sensor.TYPE_ORIENTATION: { // 电子罗盘\n                        LocECompass sensorData = new LocECompass();\n                        sensorData.azi = event.values[0];\n\n                        long elapsedRealtime = SystemClock.elapsedRealtime();\n                        int interval = 0;\n                        if (tickTimeORIENTATION > 0) {\n                            interval = (int) (elapsedRealtime - tickTimeORIENTATION);\n                        } else {\n                            tickTimeORIENTATION = elapsedRealtime;\n                        }\n                        sensorData.tickTime = BigInteger.valueOf(elapsedRealtime); // 推荐使用系统滴答数,而非信号源的时间戳\n                        if (interval >= 95) {\n                            // 因安卓的接口不能准确控制回调频率为10HZ,这里仅做演示用\n                            // 简单增加if判断以达到控制接收数据的频率,可能导致DR推算不准确。\n                            // !实际项目勿复用这个if判断!\n                            tickTimeORIENTATION = elapsedRealtime;\n                            LocSignData locSignData = new LocSignData();\n                            locSignData.dataType = LocDataType.LocDataECompass;\n                            locSignData.eCompass = sensorData;\n                            mPosService.setSignInfo(locSignData);\n                            tv_msg6.setText("罗盘:" + interval + "\\n" + event.values[0]);\n                        }\n                    }\n                    break;\n                    // 磁力计,暂无用\n                    case Sensor.TYPE_MAGNETIC_FIELD:\n                        break;\n                }\n            }\n        }\n\n        @Override\n        public void onAccuracyChanged(Sensor sensor, int accuracy) {\n\n        }\n    };\n\n\n    private LocGnss getLocGnssByLocation(Location location) {\n        final LocGnss locData = new LocGnss();\n        //locGnssData.dataType = LocDataType.LocDataGnss; // 本结构体所表示的数据类型\n        locData.mode = 'A'; // 定位模式('A','D','E','N')。此字段暂时未使用,赋'A'\n        switch (location.getProvider()) {\n            case LocationManager.GPS_PROVIDER:\n                locData.sourType = 0; // 信号来源: 0 GPS定位  1 网络定位(包括室内定位和基站定位)\n                locData.status = 'A';// GPS定位状态位。'A':有效定位;\n                break;\n            case LocationManager.NETWORK_PROVIDER:\n                locData.sourType = 1; // 信号来源: 0 GPS定位  1 网络定位(包括室内定位和基站定位)\n                locData.status = 'V'; // GPS定位状态位。'V':无效定位\n                break;\n            default:\n                locData.sourType = 1; // 信号来源: 0 GPS定位  1 网络定位(包括室内定位和基站定位)\n                locData.status = 'V'; // GPS定位状态位。'V':无效定位\n                break;\n        }\n        locData.stPt = new Coord2DDouble(0.0, 0.0);\n        locData.stPtS = new Coord2DDouble(0.0, 0.0);\n        locData.stPtS.lon = location.getLongitude();\n        locData.stPtS.lat = location.getLatitude();\n        locData.stPt = locData.stPtS;\n        locData.isEncrypted = 0; // 位置是否加密偏移: 0未偏移,1已经偏移\n        locData.isNS = (byte) ((locData.stPtS.lat > 0) ? 'N' : 'S');\n        locData.isEW = (byte) ((locData.stPtS.lon > 0) ? 'E' : 'W');\n        locData.speed = (float) (location.getSpeed() * 3.6);\n        if (location.hasBearing())\n            locData.course = location.getBearing();\n        if (location.hasAltitude())\n            locData.alt = (float) location.getAltitude();\n\n        // 卫星颗数从星历信息获取\n        locData.num = getSatellitesNum(mLocationManager);\n\n        // TODO 参考GpsStatus.NmeaListener进行实现,未知使用-1.0f\n        locData.hdop = -1.0f;\n        locData.vdop = -1.0f;\n        locData.pdop = -1.0f;\n        // time\n        Time time = new Time();\n        time.set(location.getTime());\n        locData.year = time.year;\n        locData.month = time.month + 1;\n        locData.day = time.monthDay;\n        locData.hour = time.hour;\n        locData.minute = time.minute;\n        locData.second = time.second;\n        if (location.hasAccuracy())\n            locData.accuracy = location.getAccuracy(); // 精度半径。米\n        // 推荐使用系统滴答数,而非信号源的时间戳\n        locData.tickTime = BigInteger.valueOf(SystemClock.elapsedRealtime());\n        return locData;\n    }\n\n    private LocDrPos getLocDrPosByLocation(Location location) {\n        final LocDrPos locData = new LocDrPos();\n        //locGnssData.dataType = LocDataType.LocDataDrFusion; // 本结构体所表示的数据类型\n        switch (location.getProvider()) {\n            case LocationManager.GPS_PROVIDER:\n                locData.gpsStatus = 'A';// GPS定位状态位。'A':有效定位;\n                break;\n            case LocationManager.NETWORK_PROVIDER:\n                locData.gpsStatus = 'V'; // GPS定位状态位。'V':无效定位\n                break;\n            default:\n                locData.gpsStatus = 'V'; // GPS定位状态位。'V':无效定位\n                break;\n        }\n        locData.isEncrypted = 0; // 位置是否加密偏移: 0未偏移,1已经偏移\n        locData.stPos = new Coord2DDouble(0.0, 0.0);\n        locData.stPosRaw = new Coord2DDouble(0.0, 0.0);\n        locData.stPos.lon = location.getLongitude();\n        locData.stPos.lat = location.getLatitude();\n        locData.stPosRaw = locData.stPos;\n        locData.NS = (byte) ((locData.stPos.lat > 0) ? 'N' : 'S');\n        locData.EW = (byte) ((locData.stPos.lon > 0) ? 'E' : 'W');\n        locData.speed = (float) (location.getSpeed() * 3.6); // 速度。单位:公里/小时\n\n        if (location.hasBearing())\n            locData.course = location.getBearing(); // 航向。单位:度。范围:[0-360),北零顺时针,0 => 北, 90 => 东, 180 => 南, 270 => 西\n        if (location.hasAltitude())\n            locData.alt = (float) location.getAltitude(); // 海拔高度。单位:米\n        if (location.hasAccuracy())\n            locData.posAcc = location.getAccuracy(); // 精度半径。米\n        locData.courseAcc = 0.0f; // 航向精度。单位:度 TODO 安卓标准接口无此参数,根据项目的情况进行赋值。\n        locData.altAcc = 0.0f; // 海拔精度。单位:米 TODO 安卓标准接口无此参数,根据项目的情况进行赋值。\n        locData.speedAcc = 0.0f; // 车速精度。单位:公里/小时 TODO 安卓标准接口无此参数,根据项目的情况进行赋值。\n        // 卫星颗数从星历信息获取\n        locData.satNum = getSatellitesNum(mLocationManager);\n\n        // TODO 安卓标准接口参考GpsStatus.NmeaListener进行实现,其它项目根据硬件方接口进行赋值,未知使用-1.0f\n        locData.hdop = -1.0f; // GPS的DOP值\n        locData.vdop = -1.0f;\n        locData.pdop = -1.0f;\n        // time\n        Time time = new Time();\n        time.set(location.getTime());\n        locData.dateTime.year = time.year;\n        locData.dateTime.month = time.month + 1;\n        locData.dateTime.day = time.monthDay;\n        locData.dateTime.hour = time.hour;\n        locData.dateTime.minute = time.minute;\n        locData.dateTime.second = time.second;\n\n        // 推荐使用系统滴答数,而非信号源的时间戳\n        locData.tickTime = BigInteger.valueOf(SystemClock.elapsedRealtime());\n        locData.drType = LocDrType.LocDrTypeGNSS; // DR信号来源,无法提供时赋值:LocDrTypeDRGNSS\n        locData.moveStatus = LocMoveStatus.LocMoveInvalid;// 运动状态定义,不支持输入LocMoveInvalid\n        // 定义高架识别每个字段的有效性 TODO 根据项目的情况进行赋值。\n        locData.validField.deltaAlt = false;\n        locData.validField.deltaAltAcc = false;\n        locData.validField.slopeValue = false;\n        locData.validField.slopeAcc = false;\n        locData.validField.moveDist = false;\n        locData.deltaAlt = 0.0f; // 高程差。单位:米, 无法提供时赋值:0\n        locData.deltaAltAcc = 0.0f; // 高程差精度。单位:米, 无法提供时赋值:0\n        locData.slopeValue = 0.0f; // 角度。单位:度\n        locData.slopeAcc = 0.0f; // 坡角精度。单位:度, 无法提供时赋值:0\n        locData.moveDist = 0.0f; // 移动距离。单位:米\n        return locData;\n    }\n}\n



","body_lake":null,"pub_level":null,"status":"0","updated_at":"2022-11-22 12:18:25","deleted_at":null,"nameSpace":"mnlcaa/v610","browseCount":709,"collectCount":0,"estimateDate":86,"docStatus":0,"permissions":true,"overView":false}}