|
|
|
@ -6,18 +6,19 @@ import itertools |
|
|
|
|
import math |
|
|
|
|
import time |
|
|
|
|
from typing import NoReturn |
|
|
|
|
from struct import unpack_from, calcsize |
|
|
|
|
from struct import unpack_from, calcsize, pack |
|
|
|
|
|
|
|
|
|
import cereal.messaging as messaging |
|
|
|
|
from cereal import log |
|
|
|
|
from selfdrive.swaglog import cloudlog |
|
|
|
|
|
|
|
|
|
from selfdrive.sensord.rawgps.modemdiag import ModemDiag, DIAG_LOG_F, setup_logs |
|
|
|
|
from selfdrive.sensord.rawgps.modemdiag import ModemDiag, DIAG_LOG_F, setup_logs, send_recv |
|
|
|
|
from selfdrive.sensord.rawgps.structs import dict_unpacker |
|
|
|
|
from selfdrive.sensord.rawgps.structs import gps_measurement_report, gps_measurement_report_sv |
|
|
|
|
from selfdrive.sensord.rawgps.structs import glonass_measurement_report, glonass_measurement_report_sv |
|
|
|
|
from selfdrive.sensord.rawgps.structs import oemdre_measurement_report, oemdre_measurement_report_sv |
|
|
|
|
from selfdrive.sensord.rawgps.structs import LOG_GNSS_GPS_MEASUREMENT_REPORT, LOG_GNSS_GLONASS_MEASUREMENT_REPORT |
|
|
|
|
from selfdrive.sensord.rawgps.structs import position_report, LOG_GNSS_POSITION_REPORT |
|
|
|
|
from selfdrive.sensord.rawgps.structs import position_report, LOG_GNSS_POSITION_REPORT, LOG_GNSS_OEMDRE_MEASUREMENT_REPORT |
|
|
|
|
|
|
|
|
|
DEBUG = int(os.getenv("DEBUG", "0"))==1 |
|
|
|
|
|
|
|
|
@ -71,9 +72,13 @@ def main() -> NoReturn: |
|
|
|
|
unpack_glonass_meas, size_glonass_meas = dict_unpacker(glonass_measurement_report, True) |
|
|
|
|
unpack_glonass_meas_sv, size_glonass_meas_sv = dict_unpacker(glonass_measurement_report_sv, True) |
|
|
|
|
|
|
|
|
|
unpack_oemdre_meas, size_oemdre_meas = dict_unpacker(oemdre_measurement_report, True) |
|
|
|
|
unpack_oemdre_meas_sv, size_oemdre_meas_sv = dict_unpacker(oemdre_measurement_report_sv, True) |
|
|
|
|
|
|
|
|
|
log_types = [ |
|
|
|
|
LOG_GNSS_GPS_MEASUREMENT_REPORT, |
|
|
|
|
LOG_GNSS_GLONASS_MEASUREMENT_REPORT, |
|
|
|
|
LOG_GNSS_OEMDRE_MEASUREMENT_REPORT, |
|
|
|
|
] |
|
|
|
|
pub_types = ['qcomGnss'] |
|
|
|
|
if int(os.getenv("PUBLISH_EXTERNAL", "0")) == 1: |
|
|
|
@ -81,11 +86,18 @@ def main() -> NoReturn: |
|
|
|
|
log_types.append(LOG_GNSS_POSITION_REPORT) |
|
|
|
|
pub_types.append("gpsLocationExternal") |
|
|
|
|
|
|
|
|
|
# disable DPO power savings for more accuracy |
|
|
|
|
os.system("mmcli -m 0 --command='AT+QGPSCFG=\"dpoenable\",0'") |
|
|
|
|
os.system("mmcli -m 0 --location-enable-gps-raw --location-enable-gps-nmea") |
|
|
|
|
# connect to modem |
|
|
|
|
diag = ModemDiag() |
|
|
|
|
|
|
|
|
|
# NV enable OEMDRE |
|
|
|
|
# TODO: it has to reboot for this to take effect |
|
|
|
|
DIAG_NV_READ_F = 38 |
|
|
|
|
DIAG_NV_WRITE_F = 39 |
|
|
|
|
NV_GNSS_OEM_FEATURE_MASK = 7165 |
|
|
|
|
|
|
|
|
|
opcode, payload = send_recv(diag, DIAG_NV_WRITE_F, pack('<HI', NV_GNSS_OEM_FEATURE_MASK, 1)) |
|
|
|
|
opcode, payload = send_recv(diag, DIAG_NV_READ_F, pack('<H', NV_GNSS_OEM_FEATURE_MASK)) |
|
|
|
|
|
|
|
|
|
def try_setup_logs(diag, log_types): |
|
|
|
|
for _ in range(5): |
|
|
|
|
try: |
|
|
|
@ -104,6 +116,29 @@ def main() -> NoReturn: |
|
|
|
|
try_setup_logs(diag, log_types) |
|
|
|
|
cloudlog.warning("rawgpsd: setup logs done") |
|
|
|
|
|
|
|
|
|
# disable DPO power savings for more accuracy |
|
|
|
|
os.system("mmcli -m 0 --command='AT+QGPSCFG=\"dpoenable\",0'") |
|
|
|
|
os.system("mmcli -m 0 --location-enable-gps-raw --location-enable-gps-nmea") |
|
|
|
|
|
|
|
|
|
# enable OEMDRE mode |
|
|
|
|
DIAG_SUBSYS_CMD_F = 75 |
|
|
|
|
DIAG_SUBSYS_GPS = 13 |
|
|
|
|
CGPS_DIAG_PDAPI_CMD = 0x64 |
|
|
|
|
CGPS_OEM_CONTROL = 202 |
|
|
|
|
GPSDIAG_OEMFEATURE_DRE = 1 |
|
|
|
|
GPSDIAG_OEM_DRE_ON = 1 |
|
|
|
|
|
|
|
|
|
# gpsdiag_OemControlReqType |
|
|
|
|
opcode, payload = send_recv(diag, DIAG_SUBSYS_CMD_F, pack('<BHBBIIII', |
|
|
|
|
DIAG_SUBSYS_GPS, # Subsystem Id |
|
|
|
|
CGPS_DIAG_PDAPI_CMD, # Subsystem Command Code |
|
|
|
|
CGPS_OEM_CONTROL, # CGPS Command Code |
|
|
|
|
0, # Version |
|
|
|
|
GPSDIAG_OEMFEATURE_DRE, |
|
|
|
|
GPSDIAG_OEM_DRE_ON, |
|
|
|
|
0,0 |
|
|
|
|
)) |
|
|
|
|
|
|
|
|
|
pm = messaging.PubMaster(pub_types) |
|
|
|
|
|
|
|
|
|
while 1: |
|
|
|
@ -118,8 +153,51 @@ def main() -> NoReturn: |
|
|
|
|
if log_type not in log_types: |
|
|
|
|
continue |
|
|
|
|
if DEBUG: |
|
|
|
|
print("%.2f: got log: %x len %d" % (time.time(), log_type, len(log_payload))) |
|
|
|
|
if log_type == LOG_GNSS_POSITION_REPORT: |
|
|
|
|
print("%.4f: got log: %x len %d" % (time.time(), log_type, len(log_payload))) |
|
|
|
|
if log_type == LOG_GNSS_OEMDRE_MEASUREMENT_REPORT: |
|
|
|
|
msg = messaging.new_message('qcomGnss') |
|
|
|
|
|
|
|
|
|
gnss = msg.qcomGnss |
|
|
|
|
gnss.logTs = log_time |
|
|
|
|
gnss.init('drMeasurementReport') |
|
|
|
|
report = gnss.drMeasurementReport |
|
|
|
|
|
|
|
|
|
dat = unpack_oemdre_meas(log_payload) |
|
|
|
|
for k,v in dat.items(): |
|
|
|
|
if k in ["gpsTimeBias", "gpsClockTimeUncertainty"]: |
|
|
|
|
k += "Ms" |
|
|
|
|
if k == "version": |
|
|
|
|
assert v == 2 |
|
|
|
|
elif k == "svCount" or k.startswith("cdmaClockInfo["): |
|
|
|
|
# TODO: should we save cdmaClockInfo? |
|
|
|
|
pass |
|
|
|
|
elif k == "systemRtcValid": |
|
|
|
|
setattr(report, k, bool(v)) |
|
|
|
|
else: |
|
|
|
|
setattr(report, k, v) |
|
|
|
|
|
|
|
|
|
report.init('sv', dat['svCount']) |
|
|
|
|
sats = log_payload[size_oemdre_meas:] |
|
|
|
|
for i in range(dat['svCount']): |
|
|
|
|
sat = unpack_oemdre_meas_sv(sats[size_oemdre_meas_sv*i:size_oemdre_meas_sv*(i+1)]) |
|
|
|
|
sv = report.sv[i] |
|
|
|
|
sv.init('measurementStatus') |
|
|
|
|
for k,v in sat.items(): |
|
|
|
|
if k in ["unkn", "measurementStatus2"]: |
|
|
|
|
pass |
|
|
|
|
elif k == "multipathEstimateValid": |
|
|
|
|
sv.measurementStatus.multipathEstimateIsValid = bool(v) |
|
|
|
|
elif k == "directionValid": |
|
|
|
|
sv.measurementStatus.directionIsValid = bool(v) |
|
|
|
|
elif k == "goodParity": |
|
|
|
|
setattr(sv, k, bool(v)) |
|
|
|
|
elif k == "measurementStatus": |
|
|
|
|
for kk,vv in measurementStatusFields.items(): |
|
|
|
|
setattr(sv.measurementStatus, kk, bool(v & (1<<vv))) |
|
|
|
|
else: |
|
|
|
|
setattr(sv, k, v) |
|
|
|
|
pm.send('qcomGnss', msg) |
|
|
|
|
elif log_type == LOG_GNSS_POSITION_REPORT: |
|
|
|
|
report = unpack_position(log_payload) |
|
|
|
|
if report["u_PosSource"] != 2: |
|
|
|
|
continue |
|
|
|
|