mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-07-06 01:42:14 +08:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 829eeafae8 |
@@ -46,7 +46,6 @@ selfdrive/boardd/boardd
|
||||
selfdrive/logcatd/logcatd
|
||||
selfdrive/mapd/default_speeds_by_region.json
|
||||
system/proclogd/proclogd
|
||||
selfdrive/ui/_ui
|
||||
selfdrive/ui/translations/alerts_generated.h
|
||||
selfdrive/ui/translations/tmp
|
||||
selfdrive/test/longitudinal_maneuvers/out
|
||||
|
||||
@@ -1,3 +1,65 @@
|
||||
sunnypilot - 0.9.6.1 (2024-02-27)
|
||||
========================
|
||||
* New driving model
|
||||
* Vision model trained on more data
|
||||
* Improved driving performance
|
||||
* Directly outputs curvature for lateral control
|
||||
* New driver monitoring model
|
||||
* Trained on larger dataset
|
||||
* AGNOS 9
|
||||
* comma body streaming and controls over WebRTC
|
||||
* Improved fuzzy fingerprinting for many makes and models
|
||||
* Alpha longitudinal support for new Toyota models
|
||||
* Chevrolet Equinox 2019-22 support thanks to JasonJShuler and nworb-cire!
|
||||
* Dodge Durango 2020-21 support
|
||||
* Hyundai Staria 2023 support thanks to sunnyhaibin!
|
||||
* Kia Niro Plug-in Hybrid 2022 support thanks to sunnyhaibin!
|
||||
* Lexus LC 2024 support thanks to nelsonjchen!
|
||||
* Toyota RAV4 2023-24 support
|
||||
* Toyota RAV4 Hybrid 2023-24 support
|
||||
************************
|
||||
* UPDATED: Synced with commaai's openpilot
|
||||
* master commit db57a21 (February 22, 2024)
|
||||
* v0.9.6 release (February 27, 2024)
|
||||
* UPDATED: Dynamic Experimental Control (DEC)
|
||||
* Synced with dragonpilot-community/dragonpilot:beta3 commit f4ee52f
|
||||
* NEW❗: Default Driving Model: Certified Herbalist v2 (February 13, 2024)
|
||||
* UPDATED: Driving Model Selector v3
|
||||
* NEW❗: Driving Model additions
|
||||
* Certified Herbalist v2 (February 13, 2024) - CHv2
|
||||
* Certified Herbalist (February 5, 2024) - CH
|
||||
* Los Angeles v2 (January 24, 2024) - LAv2
|
||||
* Los Angeles (January 22, 2024) - LAv1
|
||||
* NEW❗: Model Caching thanks to DevTekVE!
|
||||
* Model caching allows the selection of previously downloaded Driving Model
|
||||
* Users can now access cached versions of selected models, eliminating redundant downloads for previously fetched models
|
||||
* Legacy Driving Models support
|
||||
* New Delhi (December 21, 2023) - ND
|
||||
* Blue Diamond v2 (December 11, 2023) - BDv2
|
||||
* Blue Diamond (November 18, 2023) - BDv1
|
||||
* Farmville (November 7, 2023) - FV
|
||||
* Night Strike (October 3, 2023) - NS
|
||||
* Certain features are deprecated with newer Driving Models
|
||||
* Dynamic Lane Profile (DLP)
|
||||
* Custom Offsets
|
||||
* UPDATED: Dynamic Lane Profile (DLP)
|
||||
* Continued support for Legacy Driving Models (e.g., ND, BDv2, BDv1, FV, NS)
|
||||
* Deprecated support for newer Driving Models (e.g., CHv2, CH, LAv2, LAv1)
|
||||
* UPDATED: Custom Offsets
|
||||
* Continued support for Legacy Driving Models (e.g., ND, BDv2, BDv1, FV, NS)
|
||||
* Deprecated support for newer Driving Models (e.g., CHv2, CH, LAv2, LAv1)
|
||||
* UPDATED: Hyundai/Kia/Genesis - ESCC Radar Interceptor
|
||||
* Message parsing improvements with the latest firmware update: https://github.com/sunnypilot/panda/tree/test-escc-smdps
|
||||
* UI Updates
|
||||
* NEW❗: Visuals: Display Feature Status toggle
|
||||
* Display the statuses of certain features on the driving screen
|
||||
* NEW❗: Visuals: Enable Onroad Settings toggle
|
||||
* Display the Onroad Settings button on the driving screen to adjust feature options on the driving screen, without navigating into the settings menu
|
||||
* REMOVED: "Device ambient" temperature option on the sidebar
|
||||
* FIXED: New comma 3X support
|
||||
* FIXED: New comma eSIM support
|
||||
* Bug fixes and performance improvements
|
||||
|
||||
sunnypilot - 0.9.5.3 (2023-12-24)
|
||||
========================
|
||||
* UPDATED: Dynamic Experimental Control (DEC)
|
||||
|
||||
@@ -27,7 +27,7 @@ Table of Contents
|
||||
---
|
||||
|
||||
Join the official sunnypilot Discord server to stay up to date with all the latest features and be a part of shaping the future of sunnypilot!
|
||||
* https://discord.sunnypilot.com
|
||||
* https://discord.gg/sunnypilot
|
||||
|
||||
 
|
||||
|
||||
|
||||
+28
-3
@@ -1,4 +1,28 @@
|
||||
Version 0.9.5 (2023-11-16)
|
||||
Version 0.9.7 (2024-XX-XX)
|
||||
========================
|
||||
* New driving model
|
||||
|
||||
Version 0.9.6 (2024-02-27)
|
||||
========================
|
||||
* New driving model
|
||||
* Vision model trained on more data
|
||||
* Improved driving performance
|
||||
* Directly outputs curvature for lateral control
|
||||
* New driver monitoring model
|
||||
* Trained on larger dataset
|
||||
* AGNOS 9
|
||||
* comma body streaming and controls over WebRTC
|
||||
* Improved fuzzy fingerprinting for many makes and models
|
||||
* Alpha longitudinal support for new Toyota models
|
||||
* Chevrolet Equinox 2019-22 support thanks to JasonJShuler and nworb-cire!
|
||||
* Dodge Durango 2020-21 support
|
||||
* Hyundai Staria 2023 support thanks to sunnyhaibin!
|
||||
* Kia Niro Plug-in Hybrid 2022 support thanks to sunnyhaibin!
|
||||
* Lexus LC 2024 support thanks to nelsonjchen!
|
||||
* Toyota RAV4 2023-24 support
|
||||
* Toyota RAV4 Hybrid 2023-24 support
|
||||
|
||||
Version 0.9.5 (2023-11-17)
|
||||
========================
|
||||
* New driving model
|
||||
* Improved navigate on openpilot performance using navigation instructions as an additional model input
|
||||
@@ -8,11 +32,12 @@ Version 0.9.5 (2023-11-16)
|
||||
* Hyundai Azera 2022 support thanks to sunnyhaibin!
|
||||
* Hyundai Azera Hybrid 2020 support thanks to chanhojung and haram-KONA!
|
||||
* Hyundai Custin 2023 support thanks to sunnyhaibin and Saber422!
|
||||
* Hyundai Ioniq 6 2023 support thanks to sunnyhaibin, alamo3, and sshane!
|
||||
* Hyundai Ioniq 6 2023 support thanks to sunnyhaibin and alamo3!
|
||||
* Hyundai Kona Electric 2023 (Korean version) support thanks to sunnyhaibin and haram-KONA!
|
||||
* Kia K8 Hybrid (with HDA II) 2023 support thanks to sunnyhaibin!
|
||||
* Kia Sorento Hybrid 2023 support thanks to sunnyhaibin!
|
||||
* Kia Optima Hybrid 2019 support
|
||||
* Kia Sorento Hybrid 2023 support thanks to sunnyhaibin!
|
||||
* Lexus GS F 2016 support thanks to snyperifle!
|
||||
* Lexus IS 2023 support thanks to L3R5!
|
||||
|
||||
Version 0.9.4 (2023-07-27)
|
||||
|
||||
+22
-39
@@ -9,11 +9,16 @@ import SCons.Errors
|
||||
|
||||
SCons.Warnings.warningAsException(True)
|
||||
|
||||
# pending upstream fix - https://github.com/SCons/scons/issues/4461
|
||||
#SetOption('warn', 'all')
|
||||
|
||||
TICI = os.path.isfile('/TICI')
|
||||
AGNOS = TICI
|
||||
|
||||
Decider('MD5-timestamp')
|
||||
|
||||
SetOption('num_jobs', int(os.cpu_count()/2))
|
||||
|
||||
AddOption('--kaitai',
|
||||
action='store_true',
|
||||
help='Regenerate kaitai struct parsers')
|
||||
@@ -37,7 +42,7 @@ AddOption('--clazy',
|
||||
AddOption('--compile_db',
|
||||
action='store_true',
|
||||
help='build clang compilation database')
|
||||
|
||||
|
||||
AddOption('--ccflags',
|
||||
action='store',
|
||||
type='string',
|
||||
@@ -62,7 +67,7 @@ AddOption('--pc-thneed',
|
||||
AddOption('--minimal',
|
||||
action='store_false',
|
||||
dest='extras',
|
||||
default=os.path.islink(Dir('#laika/').abspath),
|
||||
default=os.path.islink(Dir('#rednose/').abspath), # minimal by default on release branch (where rednose is not a link)
|
||||
help='the minimum build to run openpilot. no tests, tools, etc.')
|
||||
|
||||
## Architecture name breakdown (arch)
|
||||
@@ -116,10 +121,7 @@ else:
|
||||
cflags = []
|
||||
cxxflags = []
|
||||
cpppath = []
|
||||
rpath += [
|
||||
Dir("#cereal").abspath,
|
||||
Dir("#common").abspath
|
||||
]
|
||||
rpath += []
|
||||
|
||||
# MacOS
|
||||
if arch == "Darwin":
|
||||
@@ -143,9 +145,6 @@ else:
|
||||
libpath = [
|
||||
f"#third_party/acados/{arch}/lib",
|
||||
f"#third_party/libyuv/{arch}/lib",
|
||||
f"#third_party/mapbox-gl-native-qt/{arch}",
|
||||
"#cereal",
|
||||
"#common",
|
||||
"/usr/lib",
|
||||
"/usr/local/lib",
|
||||
]
|
||||
@@ -208,11 +207,12 @@ env = Environment(
|
||||
"#third_party/json11",
|
||||
"#third_party/linux/include",
|
||||
"#third_party/snpe/include",
|
||||
"#third_party/mapbox-gl-native-qt/include",
|
||||
"#third_party/qrcode",
|
||||
"#third_party",
|
||||
"#cereal",
|
||||
"#opendbc/can",
|
||||
"#third_party/maplibre-native-qt/include",
|
||||
f"#third_party/maplibre-native-qt/{arch}/include"
|
||||
],
|
||||
|
||||
CC='clang',
|
||||
@@ -229,10 +229,13 @@ env = Environment(
|
||||
"#opendbc/can",
|
||||
"#selfdrive/boardd",
|
||||
"#common",
|
||||
"#rednose/helpers",
|
||||
],
|
||||
CYTHONCFILESUFFIX=".cpp",
|
||||
COMPILATIONDB_USE_ABSPATH=True,
|
||||
tools=["default", "cython", "compilation_db"],
|
||||
REDNOSE_ROOT="#",
|
||||
tools=["default", "cython", "compilation_db", "rednose_filter"],
|
||||
toolpath=["#rednose_repo/site_scons/site_tools"],
|
||||
)
|
||||
|
||||
if arch == "Darwin":
|
||||
@@ -295,8 +298,11 @@ else:
|
||||
qt_env['QTDIR'] = qt_install_prefix
|
||||
qt_dirs = [
|
||||
f"{qt_install_headers}",
|
||||
f"{qt_install_headers}/QtGui/5.12.8/QtGui",
|
||||
]
|
||||
|
||||
qt_gui_path = os.path.join(qt_install_headers, "QtGui")
|
||||
qt_gui_dirs = [d for d in os.listdir(qt_gui_path) if os.path.isdir(os.path.join(qt_gui_path, d))]
|
||||
qt_dirs += [f"{qt_install_headers}/QtGui/{qt_gui_dirs[0]}/QtGui", ] if qt_gui_dirs else []
|
||||
qt_dirs += [f"{qt_install_headers}/Qt{m}" for m in qt_modules]
|
||||
|
||||
qt_libs = [f"Qt5{m}" for m in qt_modules]
|
||||
@@ -313,7 +319,7 @@ try:
|
||||
except SCons.Errors.UserError:
|
||||
qt_env.Tool('qt')
|
||||
|
||||
qt_env['CPPPATH'] += qt_dirs + ["#selfdrive/ui/qt/"]
|
||||
qt_env['CPPPATH'] += qt_dirs# + ["#selfdrive/ui/qt/"]
|
||||
qt_flags = [
|
||||
"-D_REENTRANT",
|
||||
"-DQT_NO_DEBUG",
|
||||
@@ -326,7 +332,8 @@ qt_flags = [
|
||||
"-DQT_MESSAGELOGCONTEXT",
|
||||
]
|
||||
qt_env['CXXFLAGS'] += qt_flags
|
||||
qt_env['LIBPATH'] += ['#selfdrive/ui']
|
||||
qt_env['LIBPATH'] += ['#selfdrive/ui', f"#third_party/maplibre-native-qt/{arch}/lib"]
|
||||
qt_env['RPATH'] += [Dir(f"#third_party/maplibre-native-qt/{arch}/lib").srcnode().abspath]
|
||||
qt_env['LIBS'] = qt_libs
|
||||
|
||||
if GetOption("clazy"):
|
||||
@@ -368,31 +375,7 @@ SConscript([
|
||||
'panda/SConscript',
|
||||
])
|
||||
|
||||
# Build rednose library and ekf models
|
||||
rednose_deps = [
|
||||
"#selfdrive/locationd/models/constants.py",
|
||||
"#selfdrive/locationd/models/gnss_helpers.py",
|
||||
]
|
||||
|
||||
rednose_config = {
|
||||
'generated_folder': '#selfdrive/locationd/models/generated',
|
||||
'to_build': {
|
||||
'gnss': ('#selfdrive/locationd/models/gnss_kf.py', True, [], rednose_deps),
|
||||
'live': ('#selfdrive/locationd/models/live_kf.py', True, ['live_kf_constants.h'], rednose_deps),
|
||||
'car': ('#selfdrive/locationd/models/car_kf.py', True, [], rednose_deps),
|
||||
},
|
||||
}
|
||||
|
||||
if arch != "larch64":
|
||||
rednose_config['to_build'].update({
|
||||
'loc_4': ('#selfdrive/locationd/models/loc_kf.py', True, [], rednose_deps),
|
||||
'lane': ('#selfdrive/locationd/models/lane_kf.py', True, [], rednose_deps),
|
||||
'pos_computer_4': ('#rednose/helpers/lst_sq_computer.py', False, [], []),
|
||||
'pos_computer_5': ('#rednose/helpers/lst_sq_computer.py', False, [], []),
|
||||
'feature_handler_5': ('#rednose/helpers/feature_handler.py', False, [], []),
|
||||
})
|
||||
|
||||
Export('rednose_config')
|
||||
# Build rednose library
|
||||
SConscript(['rednose/SConscript'])
|
||||
|
||||
# Build system services
|
||||
|
||||
@@ -31,7 +31,7 @@ if os.getenv("RELEASE"):
|
||||
assert os.path.exists(cert_fn), 'Certificate file not found. Please specify absolute path'
|
||||
else:
|
||||
BUILD_TYPE = "DEBUG"
|
||||
cert_fn = File("../certs/debug").srcnode().abspath
|
||||
cert_fn = File("../certs/debug").srcnode().relpath
|
||||
common_flags += ["-DALLOW_DEBUG"]
|
||||
|
||||
if os.getenv("DEBUG"):
|
||||
@@ -99,7 +99,7 @@ def to_c_uint32(x):
|
||||
def get_key_header(name):
|
||||
from Crypto.PublicKey import RSA
|
||||
|
||||
public_fn = File(f'../certs/{name}.pub').srcnode().abspath
|
||||
public_fn = f'../certs/{name}.pub'
|
||||
rsa = RSA.importKey(open(public_fn).read())
|
||||
assert(rsa.size_in_bits() == 1024)
|
||||
|
||||
@@ -132,7 +132,7 @@ with open("obj/cert.h", "w") as f:
|
||||
|
||||
for project_name in build_projects:
|
||||
project = build_projects[project_name]
|
||||
linkerscript_fn = File(project["LINKER_SCRIPT"]).srcnode().abspath
|
||||
linkerscript_fn = File(project["LINKER_SCRIPT"]).srcnode().relpath
|
||||
|
||||
flags = [
|
||||
"-Wall",
|
||||
@@ -193,5 +193,5 @@ for project_name in build_projects:
|
||||
main_bin = project_env.Objcopy(f"obj/{project_name}.bin", main_elf)
|
||||
|
||||
# Sign main
|
||||
sign_py = File("../crypto/sign.py").srcnode().abspath
|
||||
sign_py = File("../crypto/sign.py").srcnode().relpath
|
||||
panda_bin_signed = project_env.Command(f"obj/{project_name}.bin.signed", main_bin, f"SETLEN=1 {sign_py} $SOURCE $TARGET {cert_fn}")
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
* is using in the C source code, usually in main.c. This file contains:
|
||||
* - Configuration section that allows to select:
|
||||
* - The STM32F4xx device used in the target application
|
||||
* - To use or not the peripheral’s drivers in application code(i.e.
|
||||
* code will be based on direct access to peripheral’s registers
|
||||
* - To use or not the peripheral's drivers in application code(i.e.
|
||||
* code will be based on direct access to peripheral's registers
|
||||
* rather than drivers API), this option is controlled by
|
||||
* "#define USE_HAL_DRIVER"
|
||||
*
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# pylint: skip-file
|
||||
import os
|
||||
import capnp
|
||||
|
||||
|
||||
+8
-5
@@ -51,7 +51,6 @@ struct CarEvent @0x9b1657f34caf3ad3 {
|
||||
parkBrake @29;
|
||||
manualRestart @30;
|
||||
lowSpeedLockout @31;
|
||||
plannerError @32;
|
||||
joystickDebug @34;
|
||||
steerTempUnavailableSilent @35;
|
||||
resumeRequired @36;
|
||||
@@ -162,6 +161,7 @@ struct CarEvent @0x9b1657f34caf3ad3 {
|
||||
startupFuzzyFingerprintDEPRECATED @97;
|
||||
noTargetDEPRECATED @25;
|
||||
brakeUnavailableDEPRECATED @2;
|
||||
plannerErrorDEPRECATED @32;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -479,9 +479,9 @@ struct CarParams {
|
||||
enableBsm @56 :Bool; # blind spot monitoring
|
||||
flags @64 :UInt32; # flags for car specific quirks
|
||||
experimentalLongitudinalAvailable @71 :Bool;
|
||||
pcmCruiseSpeed @73 :Bool; # is openpilot's state tied to the PCM's cruise speed?
|
||||
customStockLongAvailable @74 :Bool;
|
||||
spFlags @75 :UInt32; # flags for car specific quirks in sunnypilot
|
||||
pcmCruiseSpeed @74 :Bool; # is openpilot's state tied to the PCM's cruise speed?
|
||||
customStockLongAvailable @75 :Bool;
|
||||
spFlags @76 :UInt32; # flags for car specific quirks in sunnypilot
|
||||
|
||||
minEnableSpeed @7 :Float32;
|
||||
minSteerSpeed @8 :Float32;
|
||||
@@ -533,6 +533,7 @@ struct CarParams {
|
||||
openpilotLongitudinalControl @37 :Bool; # is openpilot doing the longitudinal control?
|
||||
carVin @38 :Text; # VIN number queried during fingerprinting
|
||||
dashcamOnly @41: Bool;
|
||||
passive @73: Bool; # is openpilot in control?
|
||||
transmissionType @43 :TransmissionType;
|
||||
carFw @44 :List(CarFw);
|
||||
|
||||
@@ -646,12 +647,14 @@ struct CarParams {
|
||||
body @27;
|
||||
hyundaiCanfd @28;
|
||||
volkswagenMqbEvo @29;
|
||||
chryslerCusw @30;
|
||||
}
|
||||
|
||||
enum SteerControlType {
|
||||
torque @0;
|
||||
angle @1;
|
||||
curvature @2;
|
||||
|
||||
curvatureDEPRECATED @2;
|
||||
}
|
||||
|
||||
enum TransmissionType {
|
||||
|
||||
+8
-6
@@ -116,15 +116,15 @@ struct LateralPlanSP @0xf35cc4560bbf6ec2 {
|
||||
rProb @2 :Float32;
|
||||
|
||||
dProb @3 :Float32;
|
||||
dPathWLinesX @6 :List(Float32);
|
||||
dPathWLinesY @7 :List(Float32);
|
||||
|
||||
laneChangePrev @8 :Bool;
|
||||
laneChangeEdgeBlock @10 :Bool;
|
||||
|
||||
dynamicLaneProfile @4 :Int8;
|
||||
standstillElapsed @5 :Float32;
|
||||
dynamicLaneProfileStatus @9 :Bool;
|
||||
|
||||
dPathWLinesXDEPRECATED @6 :List(Float32);
|
||||
dPathWLinesYDEPRECATED @7 :List(Float32);
|
||||
laneChangePrevDEPRECATED @8 :Bool;
|
||||
laneChangeEdgeBlockDEPRECATED @10 :Bool;
|
||||
}
|
||||
|
||||
struct DriverMonitoringStateSP @0xda96579883444c35 {
|
||||
@@ -175,7 +175,9 @@ struct E2eLongStateSP @0xa5cd762cd951a455 {
|
||||
status @0 :UInt16;
|
||||
}
|
||||
|
||||
struct CustomReserved6 @0xf98d843bfd7004a3 {
|
||||
struct ModelDataV2SP @0xf98d843bfd7004a3 {
|
||||
laneChangePrev @0 :Bool;
|
||||
laneChangeEdgeBlock @1 :Bool;
|
||||
}
|
||||
|
||||
struct CustomReserved7 @0xb86e6369214c01c8 {
|
||||
|
||||
+737
-627
File diff suppressed because it is too large
Load Diff
@@ -6,11 +6,15 @@
|
||||
#include <capnp/generated-header-support.h>
|
||||
#include <kj/windows-sanity.h>
|
||||
|
||||
#if CAPNP_VERSION != 8000
|
||||
#ifndef CAPNP_VERSION
|
||||
#error "CAPNP_VERSION is not defined, is capnp/generated-header-support.h missing?"
|
||||
#elif CAPNP_VERSION != 1000002
|
||||
#error "Version mismatch between generated code and library headers. You must use the same version of the Cap'n Proto compiler and library."
|
||||
#endif
|
||||
|
||||
|
||||
CAPNP_BEGIN_HEADER
|
||||
|
||||
namespace capnp {
|
||||
namespace schemas {
|
||||
|
||||
@@ -49,7 +53,7 @@ enum class EventName_baa8c5d505f727de: uint16_t {
|
||||
PARK_BRAKE,
|
||||
MANUAL_RESTART,
|
||||
LOW_SPEED_LOCKOUT,
|
||||
PLANNER_ERROR,
|
||||
PLANNER_ERROR_D_E_P_R_E_C_A_T_E_D,
|
||||
IPAS_OVERRIDE_D_E_P_R_E_C_A_T_E_D,
|
||||
JOYSTICK_DEBUG,
|
||||
STEER_TEMP_UNAVAILABLE_SILENT,
|
||||
@@ -283,13 +287,14 @@ enum class SafetyModel_95551e5b1edaf451: uint16_t {
|
||||
BODY,
|
||||
HYUNDAI_CANFD,
|
||||
VOLKSWAGEN_MQB_EVO,
|
||||
CHRYSLER_CUSW,
|
||||
};
|
||||
CAPNP_DECLARE_ENUM(SafetyModel, 95551e5b1edaf451);
|
||||
CAPNP_DECLARE_SCHEMA(d661512be2def77f);
|
||||
enum class SteerControlType_d661512be2def77f: uint16_t {
|
||||
TORQUE,
|
||||
ANGLE,
|
||||
CURVATURE,
|
||||
CURVATURE_D_E_P_R_E_C_A_T_E_D,
|
||||
};
|
||||
CAPNP_DECLARE_ENUM(SteerControlType, d661512be2def77f);
|
||||
CAPNP_DECLARE_SCHEMA(8f162eeb14bfc0ec);
|
||||
@@ -2557,6 +2562,8 @@ public:
|
||||
|
||||
inline float getTireStiffnessFactor() const;
|
||||
|
||||
inline bool getPassive() const;
|
||||
|
||||
inline bool getPcmCruiseSpeed() const;
|
||||
|
||||
inline bool getCustomStockLongAvailable() const;
|
||||
@@ -2859,6 +2866,9 @@ public:
|
||||
inline float getTireStiffnessFactor();
|
||||
inline void setTireStiffnessFactor(float value);
|
||||
|
||||
inline bool getPassive();
|
||||
inline void setPassive(bool value);
|
||||
|
||||
inline bool getPcmCruiseSpeed();
|
||||
inline void setPcmCruiseSpeed(bool value);
|
||||
|
||||
@@ -7692,34 +7702,48 @@ inline void CarParams::Builder::setTireStiffnessFactor(float value) {
|
||||
::capnp::bounded<33>() * ::capnp::ELEMENTS, value);
|
||||
}
|
||||
|
||||
inline bool CarParams::Reader::getPcmCruiseSpeed() const {
|
||||
inline bool CarParams::Reader::getPassive() const {
|
||||
return _reader.getDataField<bool>(
|
||||
::capnp::bounded<996>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
|
||||
inline bool CarParams::Builder::getPcmCruiseSpeed() {
|
||||
inline bool CarParams::Builder::getPassive() {
|
||||
return _builder.getDataField<bool>(
|
||||
::capnp::bounded<996>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
inline void CarParams::Builder::setPcmCruiseSpeed(bool value) {
|
||||
inline void CarParams::Builder::setPassive(bool value) {
|
||||
_builder.setDataField<bool>(
|
||||
::capnp::bounded<996>() * ::capnp::ELEMENTS, value);
|
||||
}
|
||||
|
||||
inline bool CarParams::Reader::getCustomStockLongAvailable() const {
|
||||
inline bool CarParams::Reader::getPcmCruiseSpeed() const {
|
||||
return _reader.getDataField<bool>(
|
||||
::capnp::bounded<997>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
|
||||
inline bool CarParams::Builder::getCustomStockLongAvailable() {
|
||||
inline bool CarParams::Builder::getPcmCruiseSpeed() {
|
||||
return _builder.getDataField<bool>(
|
||||
::capnp::bounded<997>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
inline void CarParams::Builder::setCustomStockLongAvailable(bool value) {
|
||||
inline void CarParams::Builder::setPcmCruiseSpeed(bool value) {
|
||||
_builder.setDataField<bool>(
|
||||
::capnp::bounded<997>() * ::capnp::ELEMENTS, value);
|
||||
}
|
||||
|
||||
inline bool CarParams::Reader::getCustomStockLongAvailable() const {
|
||||
return _reader.getDataField<bool>(
|
||||
::capnp::bounded<998>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
|
||||
inline bool CarParams::Builder::getCustomStockLongAvailable() {
|
||||
return _builder.getDataField<bool>(
|
||||
::capnp::bounded<998>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
inline void CarParams::Builder::setCustomStockLongAvailable(bool value) {
|
||||
_builder.setDataField<bool>(
|
||||
::capnp::bounded<998>() * ::capnp::ELEMENTS, value);
|
||||
}
|
||||
|
||||
inline ::uint32_t CarParams::Reader::getSpFlags() const {
|
||||
return _reader.getDataField< ::uint32_t>(
|
||||
::capnp::bounded<34>() * ::capnp::ELEMENTS);
|
||||
@@ -9457,3 +9481,5 @@ inline ::capnp::Orphan< ::cereal::CarParams::LateralTorqueTuning> CarParams::Lat
|
||||
|
||||
} // namespace
|
||||
|
||||
CAPNP_END_HEADER
|
||||
|
||||
|
||||
+179
-66
@@ -50,7 +50,7 @@ static const ::capnp::_::AlignedData<38> b_d92113aa7c18cdf6 = {
|
||||
static const uint16_t m_d92113aa7c18cdf6[] = {0, 1, 3, 2};
|
||||
const ::capnp::_::RawSchema s_d92113aa7c18cdf6 = {
|
||||
0xd92113aa7c18cdf6, b_d92113aa7c18cdf6.words, 38, nullptr, m_d92113aa7c18cdf6,
|
||||
0, 4, nullptr, nullptr, nullptr, { &s_d92113aa7c18cdf6, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 4, nullptr, nullptr, nullptr, { &s_d92113aa7c18cdf6, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
CAPNP_DEFINE_ENUM(LongitudinalPersonalitySP_d92113aa7c18cdf6, d92113aa7c18cdf6);
|
||||
@@ -142,7 +142,7 @@ static const uint16_t m_81c2f05a394cf4af[] = {1, 0};
|
||||
static const uint16_t i_81c2f05a394cf4af[] = {0, 1};
|
||||
const ::capnp::_::RawSchema s_81c2f05a394cf4af = {
|
||||
0x81c2f05a394cf4af, b_81c2f05a394cf4af.words, 77, d_81c2f05a394cf4af, m_81c2f05a394cf4af,
|
||||
1, 2, i_81c2f05a394cf4af, nullptr, nullptr, { &s_81c2f05a394cf4af, nullptr, nullptr, 0, 0, nullptr }
|
||||
1, 2, i_81c2f05a394cf4af, nullptr, nullptr, { &s_81c2f05a394cf4af, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<19> b_b6a9042bc207bf27 = {
|
||||
@@ -170,7 +170,7 @@ static const ::capnp::_::AlignedData<19> b_b6a9042bc207bf27 = {
|
||||
#if !CAPNP_LITE
|
||||
const ::capnp::_::RawSchema s_b6a9042bc207bf27 = {
|
||||
0xb6a9042bc207bf27, b_b6a9042bc207bf27.words, 19, nullptr, nullptr,
|
||||
0, 0, nullptr, nullptr, nullptr, { &s_b6a9042bc207bf27, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 0, nullptr, nullptr, nullptr, { &s_b6a9042bc207bf27, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<19> b_88da8426fae53f07 = {
|
||||
@@ -198,7 +198,7 @@ static const ::capnp::_::AlignedData<19> b_88da8426fae53f07 = {
|
||||
#if !CAPNP_LITE
|
||||
const ::capnp::_::RawSchema s_88da8426fae53f07 = {
|
||||
0x88da8426fae53f07, b_88da8426fae53f07.words, 19, nullptr, nullptr,
|
||||
0, 0, nullptr, nullptr, nullptr, { &s_88da8426fae53f07, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 0, nullptr, nullptr, nullptr, { &s_88da8426fae53f07, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<19> b_a9d235d23de15f34 = {
|
||||
@@ -226,7 +226,7 @@ static const ::capnp::_::AlignedData<19> b_a9d235d23de15f34 = {
|
||||
#if !CAPNP_LITE
|
||||
const ::capnp::_::RawSchema s_a9d235d23de15f34 = {
|
||||
0xa9d235d23de15f34, b_a9d235d23de15f34.words, 19, nullptr, nullptr,
|
||||
0, 0, nullptr, nullptr, nullptr, { &s_a9d235d23de15f34, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 0, nullptr, nullptr, nullptr, { &s_a9d235d23de15f34, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<19> b_be8ceaa2a89de7dd = {
|
||||
@@ -254,7 +254,7 @@ static const ::capnp::_::AlignedData<19> b_be8ceaa2a89de7dd = {
|
||||
#if !CAPNP_LITE
|
||||
const ::capnp::_::RawSchema s_be8ceaa2a89de7dd = {
|
||||
0xbe8ceaa2a89de7dd, b_be8ceaa2a89de7dd.words, 19, nullptr, nullptr,
|
||||
0, 0, nullptr, nullptr, nullptr, { &s_be8ceaa2a89de7dd, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 0, nullptr, nullptr, nullptr, { &s_be8ceaa2a89de7dd, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<39> b_8cd56244b40afff5 = {
|
||||
@@ -304,7 +304,7 @@ static const uint16_t m_8cd56244b40afff5[] = {0};
|
||||
static const uint16_t i_8cd56244b40afff5[] = {0};
|
||||
const ::capnp::_::RawSchema s_8cd56244b40afff5 = {
|
||||
0x8cd56244b40afff5, b_8cd56244b40afff5.words, 39, nullptr, m_8cd56244b40afff5,
|
||||
0, 1, i_8cd56244b40afff5, nullptr, nullptr, { &s_8cd56244b40afff5, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 1, i_8cd56244b40afff5, nullptr, nullptr, { &s_8cd56244b40afff5, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<20> b_f4da5f8564a56edb = {
|
||||
@@ -333,7 +333,7 @@ static const ::capnp::_::AlignedData<20> b_f4da5f8564a56edb = {
|
||||
#if !CAPNP_LITE
|
||||
const ::capnp::_::RawSchema s_f4da5f8564a56edb = {
|
||||
0xf4da5f8564a56edb, b_f4da5f8564a56edb.words, 20, nullptr, nullptr,
|
||||
0, 0, nullptr, nullptr, nullptr, { &s_f4da5f8564a56edb, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 0, nullptr, nullptr, nullptr, { &s_f4da5f8564a56edb, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<19> b_b5044e038567cd31 = {
|
||||
@@ -361,7 +361,7 @@ static const ::capnp::_::AlignedData<19> b_b5044e038567cd31 = {
|
||||
#if !CAPNP_LITE
|
||||
const ::capnp::_::RawSchema s_b5044e038567cd31 = {
|
||||
0xb5044e038567cd31, b_b5044e038567cd31.words, 19, nullptr, nullptr,
|
||||
0, 0, nullptr, nullptr, nullptr, { &s_b5044e038567cd31, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 0, nullptr, nullptr, nullptr, { &s_b5044e038567cd31, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<133> b_8e4c2c83a5d25c2d = {
|
||||
@@ -515,7 +515,7 @@ static const uint16_t m_8e4c2c83a5d25c2d[] = {2, 5, 3, 0, 6, 1, 4};
|
||||
static const uint16_t i_8e4c2c83a5d25c2d[] = {0, 1, 2, 3, 4, 5, 6};
|
||||
const ::capnp::_::RawSchema s_8e4c2c83a5d25c2d = {
|
||||
0x8e4c2c83a5d25c2d, b_8e4c2c83a5d25c2d.words, 133, d_8e4c2c83a5d25c2d, m_8e4c2c83a5d25c2d,
|
||||
8, 7, i_8e4c2c83a5d25c2d, nullptr, nullptr, { &s_8e4c2c83a5d25c2d, nullptr, nullptr, 0, 0, nullptr }
|
||||
8, 7, i_8e4c2c83a5d25c2d, nullptr, nullptr, { &s_8e4c2c83a5d25c2d, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<403> b_aedffd8f31e7b55d = {
|
||||
@@ -936,7 +936,7 @@ static const uint16_t m_aedffd8f31e7b55d[] = {13, 5, 7, 18, 15, 19, 6, 20, 14, 2
|
||||
static const uint16_t i_aedffd8f31e7b55d[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21};
|
||||
const ::capnp::_::RawSchema s_aedffd8f31e7b55d = {
|
||||
0xaedffd8f31e7b55d, b_aedffd8f31e7b55d.words, 403, d_aedffd8f31e7b55d, m_aedffd8f31e7b55d,
|
||||
5, 22, i_aedffd8f31e7b55d, nullptr, nullptr, { &s_aedffd8f31e7b55d, nullptr, nullptr, 0, 0, nullptr }
|
||||
5, 22, i_aedffd8f31e7b55d, nullptr, nullptr, { &s_aedffd8f31e7b55d, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<45> b_9e7784369b990802 = {
|
||||
@@ -991,7 +991,7 @@ static const ::capnp::_::AlignedData<45> b_9e7784369b990802 = {
|
||||
static const uint16_t m_9e7784369b990802[] = {3, 2, 0, 4, 1};
|
||||
const ::capnp::_::RawSchema s_9e7784369b990802 = {
|
||||
0x9e7784369b990802, b_9e7784369b990802.words, 45, nullptr, m_9e7784369b990802,
|
||||
0, 5, nullptr, nullptr, nullptr, { &s_9e7784369b990802, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 5, nullptr, nullptr, nullptr, { &s_9e7784369b990802, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
CAPNP_DEFINE_ENUM(SpeedLimitControlState_9e7784369b990802, 9e7784369b990802);
|
||||
@@ -1042,7 +1042,7 @@ static const ::capnp::_::AlignedData<40> b_d1124e845254aeda = {
|
||||
static const uint16_t m_d1124e845254aeda[] = {0, 1, 3, 2};
|
||||
const ::capnp::_::RawSchema s_d1124e845254aeda = {
|
||||
0xd1124e845254aeda, b_d1124e845254aeda.words, 40, nullptr, m_d1124e845254aeda,
|
||||
0, 4, nullptr, nullptr, nullptr, { &s_d1124e845254aeda, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 4, nullptr, nullptr, nullptr, { &s_d1124e845254aeda, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
CAPNP_DEFINE_ENUM(VisionTurnControllerState_d1124e845254aeda, d1124e845254aeda);
|
||||
@@ -1107,11 +1107,11 @@ static const ::capnp::_::AlignedData<54> b_b53c44b896b6c446 = {
|
||||
static const uint16_t m_b53c44b896b6c446[] = {0, 4, 1, 2, 3, 6, 5, 7};
|
||||
const ::capnp::_::RawSchema s_b53c44b896b6c446 = {
|
||||
0xb53c44b896b6c446, b_b53c44b896b6c446.words, 54, nullptr, m_b53c44b896b6c446,
|
||||
0, 8, nullptr, nullptr, nullptr, { &s_b53c44b896b6c446, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 8, nullptr, nullptr, nullptr, { &s_b53c44b896b6c446, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
CAPNP_DEFINE_ENUM(LongitudinalPlanSource_b53c44b896b6c446, b53c44b896b6c446);
|
||||
static const ::capnp::_::AlignedData<204> b_f35cc4560bbf6ec2 = {
|
||||
static const ::capnp::_::AlignedData<209> b_f35cc4560bbf6ec2 = {
|
||||
{ 0, 0, 0, 0, 5, 0, 6, 0,
|
||||
194, 110, 191, 11, 86, 196, 92, 243,
|
||||
13, 0, 0, 0, 1, 0, 3, 0,
|
||||
@@ -1158,55 +1158,55 @@ static const ::capnp::_::AlignedData<204> b_f35cc4560bbf6ec2 = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
48, 1, 0, 0, 3, 0, 1, 0,
|
||||
60, 1, 0, 0, 2, 0, 1, 0,
|
||||
8, 0, 0, 0, 16, 0, 0, 0,
|
||||
4, 0, 0, 0, 16, 0, 0, 0,
|
||||
0, 0, 1, 0, 4, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
57, 1, 0, 0, 154, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
60, 1, 0, 0, 3, 0, 1, 0,
|
||||
72, 1, 0, 0, 2, 0, 1, 0,
|
||||
9, 0, 0, 0, 5, 0, 0, 0,
|
||||
5, 0, 0, 0, 5, 0, 0, 0,
|
||||
0, 0, 1, 0, 5, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
69, 1, 0, 0, 146, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
72, 1, 0, 0, 3, 0, 1, 0,
|
||||
84, 1, 0, 0, 2, 0, 1, 0,
|
||||
4, 0, 0, 0, 0, 0, 0, 0,
|
||||
7, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 0, 6, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
81, 1, 0, 0, 106, 0, 0, 0,
|
||||
81, 1, 0, 0, 186, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
80, 1, 0, 0, 3, 0, 1, 0,
|
||||
108, 1, 0, 0, 2, 0, 1, 0,
|
||||
5, 0, 0, 0, 1, 0, 0, 0,
|
||||
84, 1, 0, 0, 3, 0, 1, 0,
|
||||
112, 1, 0, 0, 2, 0, 1, 0,
|
||||
8, 0, 0, 0, 1, 0, 0, 0,
|
||||
0, 0, 1, 0, 7, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
105, 1, 0, 0, 106, 0, 0, 0,
|
||||
109, 1, 0, 0, 186, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
104, 1, 0, 0, 3, 0, 1, 0,
|
||||
132, 1, 0, 0, 2, 0, 1, 0,
|
||||
6, 0, 0, 0, 136, 0, 0, 0,
|
||||
0, 0, 1, 0, 8, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
129, 1, 0, 0, 122, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
128, 1, 0, 0, 3, 0, 1, 0,
|
||||
112, 1, 0, 0, 3, 0, 1, 0,
|
||||
140, 1, 0, 0, 2, 0, 1, 0,
|
||||
10, 0, 0, 0, 137, 0, 0, 0,
|
||||
0, 0, 1, 0, 9, 0, 0, 0,
|
||||
9, 0, 0, 0, 136, 0, 0, 0,
|
||||
0, 0, 1, 0, 8, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
137, 1, 0, 0, 202, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
144, 1, 0, 0, 3, 0, 1, 0,
|
||||
156, 1, 0, 0, 2, 0, 1, 0,
|
||||
7, 0, 0, 0, 138, 0, 0, 0,
|
||||
6, 0, 0, 0, 137, 0, 0, 0,
|
||||
0, 0, 1, 0, 9, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
153, 1, 0, 0, 202, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
160, 1, 0, 0, 3, 0, 1, 0,
|
||||
172, 1, 0, 0, 2, 0, 1, 0,
|
||||
10, 0, 0, 0, 138, 0, 0, 0,
|
||||
0, 0, 1, 0, 10, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
153, 1, 0, 0, 162, 0, 0, 0,
|
||||
169, 1, 0, 0, 242, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
156, 1, 0, 0, 3, 0, 1, 0,
|
||||
168, 1, 0, 0, 2, 0, 1, 0,
|
||||
176, 1, 0, 0, 3, 0, 1, 0,
|
||||
188, 1, 0, 0, 2, 0, 1, 0,
|
||||
108, 97, 110, 101, 87, 105, 100, 116,
|
||||
104, 0, 0, 0, 0, 0, 0, 0,
|
||||
10, 0, 0, 0, 0, 0, 0, 0,
|
||||
@@ -1261,7 +1261,8 @@ static const ::capnp::_::AlignedData<204> b_f35cc4560bbf6ec2 = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
100, 80, 97, 116, 104, 87, 76, 105,
|
||||
110, 101, 115, 88, 0, 0, 0, 0,
|
||||
110, 101, 115, 88, 68, 69, 80, 82,
|
||||
69, 67, 65, 84, 69, 68, 0, 0,
|
||||
14, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
@@ -1274,7 +1275,8 @@ static const ::capnp::_::AlignedData<204> b_f35cc4560bbf6ec2 = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
100, 80, 97, 116, 104, 87, 76, 105,
|
||||
110, 101, 115, 89, 0, 0, 0, 0,
|
||||
110, 101, 115, 89, 68, 69, 80, 82,
|
||||
69, 67, 65, 84, 69, 68, 0, 0,
|
||||
14, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
@@ -1287,7 +1289,9 @@ static const ::capnp::_::AlignedData<204> b_f35cc4560bbf6ec2 = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
108, 97, 110, 101, 67, 104, 97, 110,
|
||||
103, 101, 80, 114, 101, 118, 0, 0,
|
||||
103, 101, 80, 114, 101, 118, 68, 69,
|
||||
80, 82, 69, 67, 65, 84, 69, 68,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
@@ -1308,7 +1312,8 @@ static const ::capnp::_::AlignedData<204> b_f35cc4560bbf6ec2 = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
108, 97, 110, 101, 67, 104, 97, 110,
|
||||
103, 101, 69, 100, 103, 101, 66, 108,
|
||||
111, 99, 107, 0, 0, 0, 0, 0,
|
||||
111, 99, 107, 68, 69, 80, 82, 69,
|
||||
67, 65, 84, 69, 68, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
@@ -1322,8 +1327,8 @@ static const ::capnp::_::AlignedData<204> b_f35cc4560bbf6ec2 = {
|
||||
static const uint16_t m_f35cc4560bbf6ec2[] = {6, 7, 3, 4, 9, 1, 10, 8, 0, 2, 5};
|
||||
static const uint16_t i_f35cc4560bbf6ec2[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||
const ::capnp::_::RawSchema s_f35cc4560bbf6ec2 = {
|
||||
0xf35cc4560bbf6ec2, b_f35cc4560bbf6ec2.words, 204, nullptr, m_f35cc4560bbf6ec2,
|
||||
0, 11, i_f35cc4560bbf6ec2, nullptr, nullptr, { &s_f35cc4560bbf6ec2, nullptr, nullptr, 0, 0, nullptr }
|
||||
0xf35cc4560bbf6ec2, b_f35cc4560bbf6ec2.words, 209, nullptr, m_f35cc4560bbf6ec2,
|
||||
0, 11, i_f35cc4560bbf6ec2, nullptr, nullptr, { &s_f35cc4560bbf6ec2, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<57> b_da96579883444c35 = {
|
||||
@@ -1394,7 +1399,7 @@ static const uint16_t m_da96579883444c35[] = {0, 1};
|
||||
static const uint16_t i_da96579883444c35[] = {0, 1};
|
||||
const ::capnp::_::RawSchema s_da96579883444c35 = {
|
||||
0xda96579883444c35, b_da96579883444c35.words, 57, d_da96579883444c35, m_da96579883444c35,
|
||||
1, 2, i_da96579883444c35, nullptr, nullptr, { &s_da96579883444c35, nullptr, nullptr, 0, 0, nullptr }
|
||||
1, 2, i_da96579883444c35, nullptr, nullptr, { &s_da96579883444c35, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<47> b_b5a4fa12beedc9ab = {
|
||||
@@ -1451,7 +1456,7 @@ static const ::capnp::_::AlignedData<47> b_b5a4fa12beedc9ab = {
|
||||
static const uint16_t m_b5a4fa12beedc9ab[] = {4, 2, 0, 1, 5, 3};
|
||||
const ::capnp::_::RawSchema s_b5a4fa12beedc9ab = {
|
||||
0xb5a4fa12beedc9ab, b_b5a4fa12beedc9ab.words, 47, nullptr, m_b5a4fa12beedc9ab,
|
||||
0, 6, nullptr, nullptr, nullptr, { &s_b5a4fa12beedc9ab, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 6, nullptr, nullptr, nullptr, { &s_b5a4fa12beedc9ab, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
CAPNP_DEFINE_ENUM(HandsOnWheelState_b5a4fa12beedc9ab, b5a4fa12beedc9ab);
|
||||
@@ -1852,7 +1857,7 @@ static const uint16_t m_80ae746ee2596b11[] = {13, 20, 18, 19, 17, 14, 15, 16, 12
|
||||
static const uint16_t i_80ae746ee2596b11[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
|
||||
const ::capnp::_::RawSchema s_80ae746ee2596b11 = {
|
||||
0x80ae746ee2596b11, b_80ae746ee2596b11.words, 386, d_80ae746ee2596b11, m_80ae746ee2596b11,
|
||||
1, 21, i_80ae746ee2596b11, nullptr, nullptr, { &s_80ae746ee2596b11, nullptr, nullptr, 0, 0, nullptr }
|
||||
1, 21, i_80ae746ee2596b11, nullptr, nullptr, { &s_80ae746ee2596b11, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<31> b_e3ff45a51e47d36d = {
|
||||
@@ -1893,7 +1898,7 @@ static const ::capnp::_::AlignedData<31> b_e3ff45a51e47d36d = {
|
||||
static const uint16_t m_e3ff45a51e47d36d[] = {0, 1, 2};
|
||||
const ::capnp::_::RawSchema s_e3ff45a51e47d36d = {
|
||||
0xe3ff45a51e47d36d, b_e3ff45a51e47d36d.words, 31, nullptr, m_e3ff45a51e47d36d,
|
||||
0, 3, nullptr, nullptr, nullptr, { &s_e3ff45a51e47d36d, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 3, nullptr, nullptr, nullptr, { &s_e3ff45a51e47d36d, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
CAPNP_DEFINE_ENUM(DataType_e3ff45a51e47d36d, e3ff45a51e47d36d);
|
||||
@@ -1938,33 +1943,69 @@ static const uint16_t m_a5cd762cd951a455[] = {0};
|
||||
static const uint16_t i_a5cd762cd951a455[] = {0};
|
||||
const ::capnp::_::RawSchema s_a5cd762cd951a455 = {
|
||||
0xa5cd762cd951a455, b_a5cd762cd951a455.words, 33, nullptr, m_a5cd762cd951a455,
|
||||
0, 1, i_a5cd762cd951a455, nullptr, nullptr, { &s_a5cd762cd951a455, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 1, i_a5cd762cd951a455, nullptr, nullptr, { &s_a5cd762cd951a455, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<17> b_f98d843bfd7004a3 = {
|
||||
static const ::capnp::_::AlignedData<51> b_f98d843bfd7004a3 = {
|
||||
{ 0, 0, 0, 0, 5, 0, 6, 0,
|
||||
163, 4, 112, 253, 59, 132, 141, 249,
|
||||
13, 0, 0, 0, 1, 0, 0, 0,
|
||||
13, 0, 0, 0, 1, 0, 1, 0,
|
||||
89, 10, 85, 29, 102, 186, 38, 181,
|
||||
0, 0, 7, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
21, 0, 0, 0, 234, 0, 0, 0,
|
||||
21, 0, 0, 0, 218, 0, 0, 0,
|
||||
33, 0, 0, 0, 7, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
29, 0, 0, 0, 119, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
99, 117, 115, 116, 111, 109, 46, 99,
|
||||
97, 112, 110, 112, 58, 67, 117, 115,
|
||||
116, 111, 109, 82, 101, 115, 101, 114,
|
||||
118, 101, 100, 54, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 0, 1, 0, }
|
||||
97, 112, 110, 112, 58, 77, 111, 100,
|
||||
101, 108, 68, 97, 116, 97, 86, 50,
|
||||
83, 80, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 0, 1, 0,
|
||||
8, 0, 0, 0, 3, 0, 4, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
41, 0, 0, 0, 122, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
40, 0, 0, 0, 3, 0, 1, 0,
|
||||
52, 0, 0, 0, 2, 0, 1, 0,
|
||||
1, 0, 0, 0, 1, 0, 0, 0,
|
||||
0, 0, 1, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
49, 0, 0, 0, 162, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
52, 0, 0, 0, 3, 0, 1, 0,
|
||||
64, 0, 0, 0, 2, 0, 1, 0,
|
||||
108, 97, 110, 101, 67, 104, 97, 110,
|
||||
103, 101, 80, 114, 101, 118, 0, 0,
|
||||
1, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
108, 97, 110, 101, 67, 104, 97, 110,
|
||||
103, 101, 69, 100, 103, 101, 66, 108,
|
||||
111, 99, 107, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, }
|
||||
};
|
||||
::capnp::word const* const bp_f98d843bfd7004a3 = b_f98d843bfd7004a3.words;
|
||||
#if !CAPNP_LITE
|
||||
static const uint16_t m_f98d843bfd7004a3[] = {1, 0};
|
||||
static const uint16_t i_f98d843bfd7004a3[] = {0, 1};
|
||||
const ::capnp::_::RawSchema s_f98d843bfd7004a3 = {
|
||||
0xf98d843bfd7004a3, b_f98d843bfd7004a3.words, 17, nullptr, nullptr,
|
||||
0, 0, nullptr, nullptr, nullptr, { &s_f98d843bfd7004a3, nullptr, nullptr, 0, 0, nullptr }
|
||||
0xf98d843bfd7004a3, b_f98d843bfd7004a3.words, 51, nullptr, m_f98d843bfd7004a3,
|
||||
0, 2, i_f98d843bfd7004a3, nullptr, nullptr, { &s_f98d843bfd7004a3, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<17> b_b86e6369214c01c8 = {
|
||||
@@ -1990,7 +2031,7 @@ static const ::capnp::_::AlignedData<17> b_b86e6369214c01c8 = {
|
||||
#if !CAPNP_LITE
|
||||
const ::capnp::_::RawSchema s_b86e6369214c01c8 = {
|
||||
0xb86e6369214c01c8, b_b86e6369214c01c8.words, 17, nullptr, nullptr,
|
||||
0, 0, nullptr, nullptr, nullptr, { &s_b86e6369214c01c8, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 0, nullptr, nullptr, nullptr, { &s_b86e6369214c01c8, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<17> b_f416ec09499d9d19 = {
|
||||
@@ -2016,7 +2057,7 @@ static const ::capnp::_::AlignedData<17> b_f416ec09499d9d19 = {
|
||||
#if !CAPNP_LITE
|
||||
const ::capnp::_::RawSchema s_f416ec09499d9d19 = {
|
||||
0xf416ec09499d9d19, b_f416ec09499d9d19.words, 17, nullptr, nullptr,
|
||||
0, 0, nullptr, nullptr, nullptr, { &s_f416ec09499d9d19, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 0, nullptr, nullptr, nullptr, { &s_f416ec09499d9d19, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<17> b_a1680744031fdb2d = {
|
||||
@@ -2042,7 +2083,7 @@ static const ::capnp::_::AlignedData<17> b_a1680744031fdb2d = {
|
||||
#if !CAPNP_LITE
|
||||
const ::capnp::_::RawSchema s_a1680744031fdb2d = {
|
||||
0xa1680744031fdb2d, b_a1680744031fdb2d.words, 17, nullptr, nullptr,
|
||||
0, 0, nullptr, nullptr, nullptr, { &s_a1680744031fdb2d, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 0, nullptr, nullptr, nullptr, { &s_a1680744031fdb2d, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
} // namespace schemas
|
||||
@@ -2053,147 +2094,219 @@ const ::capnp::_::RawSchema s_a1680744031fdb2d = {
|
||||
namespace cereal {
|
||||
|
||||
// ControlsStateSP
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t ControlsStateSP::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t ControlsStateSP::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind ControlsStateSP::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* ControlsStateSP::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// ControlsStateSP::LateralINDIState
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t ControlsStateSP::LateralINDIState::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t ControlsStateSP::LateralINDIState::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind ControlsStateSP::LateralINDIState::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* ControlsStateSP::LateralINDIState::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// ControlsStateSP::LateralPIDState
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t ControlsStateSP::LateralPIDState::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t ControlsStateSP::LateralPIDState::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind ControlsStateSP::LateralPIDState::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* ControlsStateSP::LateralPIDState::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// ControlsStateSP::LateralAngleState
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t ControlsStateSP::LateralAngleState::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t ControlsStateSP::LateralAngleState::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind ControlsStateSP::LateralAngleState::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* ControlsStateSP::LateralAngleState::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// ControlsStateSP::LateralDebugState
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t ControlsStateSP::LateralDebugState::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t ControlsStateSP::LateralDebugState::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind ControlsStateSP::LateralDebugState::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* ControlsStateSP::LateralDebugState::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// ControlsStateSP::LateralTorqueState
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t ControlsStateSP::LateralTorqueState::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t ControlsStateSP::LateralTorqueState::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind ControlsStateSP::LateralTorqueState::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* ControlsStateSP::LateralTorqueState::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// ControlsStateSP::LateralCurvatureState
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t ControlsStateSP::LateralCurvatureState::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t ControlsStateSP::LateralCurvatureState::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind ControlsStateSP::LateralCurvatureState::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* ControlsStateSP::LateralCurvatureState::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// ControlsStateSP::LateralLQRState
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t ControlsStateSP::LateralLQRState::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t ControlsStateSP::LateralLQRState::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind ControlsStateSP::LateralLQRState::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* ControlsStateSP::LateralLQRState::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// ControlsStateSP::LateralControlState
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t ControlsStateSP::LateralControlState::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t ControlsStateSP::LateralControlState::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind ControlsStateSP::LateralControlState::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* ControlsStateSP::LateralControlState::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// LongitudinalPlanSP
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t LongitudinalPlanSP::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t LongitudinalPlanSP::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind LongitudinalPlanSP::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* LongitudinalPlanSP::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// LateralPlanSP
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t LateralPlanSP::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t LateralPlanSP::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind LateralPlanSP::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* LateralPlanSP::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// DriverMonitoringStateSP
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t DriverMonitoringStateSP::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t DriverMonitoringStateSP::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind DriverMonitoringStateSP::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* DriverMonitoringStateSP::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// LiveMapDataSP
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t LiveMapDataSP::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t LiveMapDataSP::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind LiveMapDataSP::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* LiveMapDataSP::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// E2eLongStateSP
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t E2eLongStateSP::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t E2eLongStateSP::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind E2eLongStateSP::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* E2eLongStateSP::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// CustomReserved6
|
||||
constexpr uint16_t CustomReserved6::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t CustomReserved6::_capnpPrivate::pointerCount;
|
||||
// ModelDataV2SP
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t ModelDataV2SP::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t ModelDataV2SP::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
constexpr ::capnp::Kind CustomReserved6::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* CustomReserved6::_capnpPrivate::schema;
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind ModelDataV2SP::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* ModelDataV2SP::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// CustomReserved7
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t CustomReserved7::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t CustomReserved7::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind CustomReserved7::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* CustomReserved7::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// CustomReserved8
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t CustomReserved8::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t CustomReserved8::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind CustomReserved8::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* CustomReserved8::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// CustomReserved9
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t CustomReserved9::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t CustomReserved9::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind CustomReserved9::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* CustomReserved9::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
|
||||
|
||||
+102
-58
@@ -6,12 +6,16 @@
|
||||
#include <capnp/generated-header-support.h>
|
||||
#include <kj/windows-sanity.h>
|
||||
|
||||
#if CAPNP_VERSION != 8000
|
||||
#ifndef CAPNP_VERSION
|
||||
#error "CAPNP_VERSION is not defined, is capnp/generated-header-support.h missing?"
|
||||
#elif CAPNP_VERSION != 1000002
|
||||
#error "Version mismatch between generated code and library headers. You must use the same version of the Cap'n Proto compiler and library."
|
||||
#endif
|
||||
|
||||
#include "car.capnp.h"
|
||||
|
||||
CAPNP_BEGIN_HEADER
|
||||
|
||||
namespace capnp {
|
||||
namespace schemas {
|
||||
|
||||
@@ -332,15 +336,15 @@ struct E2eLongStateSP {
|
||||
};
|
||||
};
|
||||
|
||||
struct CustomReserved6 {
|
||||
CustomReserved6() = delete;
|
||||
struct ModelDataV2SP {
|
||||
ModelDataV2SP() = delete;
|
||||
|
||||
class Reader;
|
||||
class Builder;
|
||||
class Pipeline;
|
||||
|
||||
struct _capnpPrivate {
|
||||
CAPNP_DECLARE_STRUCT_HEADER(f98d843bfd7004a3, 0, 0)
|
||||
CAPNP_DECLARE_STRUCT_HEADER(f98d843bfd7004a3, 1, 0)
|
||||
#if !CAPNP_LITE
|
||||
static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }
|
||||
#endif // !CAPNP_LITE
|
||||
@@ -1372,17 +1376,17 @@ public:
|
||||
|
||||
inline float getStandstillElapsed() const;
|
||||
|
||||
inline bool hasDPathWLinesX() const;
|
||||
inline ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Reader getDPathWLinesX() const;
|
||||
inline bool hasDPathWLinesXDEPRECATED() const;
|
||||
inline ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Reader getDPathWLinesXDEPRECATED() const;
|
||||
|
||||
inline bool hasDPathWLinesY() const;
|
||||
inline ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Reader getDPathWLinesY() const;
|
||||
inline bool hasDPathWLinesYDEPRECATED() const;
|
||||
inline ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Reader getDPathWLinesYDEPRECATED() const;
|
||||
|
||||
inline bool getLaneChangePrev() const;
|
||||
inline bool getLaneChangePrevDEPRECATED() const;
|
||||
|
||||
inline bool getDynamicLaneProfileStatus() const;
|
||||
|
||||
inline bool getLaneChangeEdgeBlock() const;
|
||||
inline bool getLaneChangeEdgeBlockDEPRECATED() const;
|
||||
|
||||
private:
|
||||
::capnp::_::StructReader _reader;
|
||||
@@ -1430,30 +1434,30 @@ public:
|
||||
inline float getStandstillElapsed();
|
||||
inline void setStandstillElapsed(float value);
|
||||
|
||||
inline bool hasDPathWLinesX();
|
||||
inline ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Builder getDPathWLinesX();
|
||||
inline void setDPathWLinesX( ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Reader value);
|
||||
inline void setDPathWLinesX(::kj::ArrayPtr<const float> value);
|
||||
inline ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Builder initDPathWLinesX(unsigned int size);
|
||||
inline void adoptDPathWLinesX(::capnp::Orphan< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>>&& value);
|
||||
inline ::capnp::Orphan< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>> disownDPathWLinesX();
|
||||
inline bool hasDPathWLinesXDEPRECATED();
|
||||
inline ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Builder getDPathWLinesXDEPRECATED();
|
||||
inline void setDPathWLinesXDEPRECATED( ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Reader value);
|
||||
inline void setDPathWLinesXDEPRECATED(::kj::ArrayPtr<const float> value);
|
||||
inline ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Builder initDPathWLinesXDEPRECATED(unsigned int size);
|
||||
inline void adoptDPathWLinesXDEPRECATED(::capnp::Orphan< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>>&& value);
|
||||
inline ::capnp::Orphan< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>> disownDPathWLinesXDEPRECATED();
|
||||
|
||||
inline bool hasDPathWLinesY();
|
||||
inline ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Builder getDPathWLinesY();
|
||||
inline void setDPathWLinesY( ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Reader value);
|
||||
inline void setDPathWLinesY(::kj::ArrayPtr<const float> value);
|
||||
inline ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Builder initDPathWLinesY(unsigned int size);
|
||||
inline void adoptDPathWLinesY(::capnp::Orphan< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>>&& value);
|
||||
inline ::capnp::Orphan< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>> disownDPathWLinesY();
|
||||
inline bool hasDPathWLinesYDEPRECATED();
|
||||
inline ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Builder getDPathWLinesYDEPRECATED();
|
||||
inline void setDPathWLinesYDEPRECATED( ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Reader value);
|
||||
inline void setDPathWLinesYDEPRECATED(::kj::ArrayPtr<const float> value);
|
||||
inline ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Builder initDPathWLinesYDEPRECATED(unsigned int size);
|
||||
inline void adoptDPathWLinesYDEPRECATED(::capnp::Orphan< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>>&& value);
|
||||
inline ::capnp::Orphan< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>> disownDPathWLinesYDEPRECATED();
|
||||
|
||||
inline bool getLaneChangePrev();
|
||||
inline void setLaneChangePrev(bool value);
|
||||
inline bool getLaneChangePrevDEPRECATED();
|
||||
inline void setLaneChangePrevDEPRECATED(bool value);
|
||||
|
||||
inline bool getDynamicLaneProfileStatus();
|
||||
inline void setDynamicLaneProfileStatus(bool value);
|
||||
|
||||
inline bool getLaneChangeEdgeBlock();
|
||||
inline void setLaneChangeEdgeBlock(bool value);
|
||||
inline bool getLaneChangeEdgeBlockDEPRECATED();
|
||||
inline void setLaneChangeEdgeBlockDEPRECATED(bool value);
|
||||
|
||||
private:
|
||||
::capnp::_::StructBuilder _builder;
|
||||
@@ -1837,9 +1841,9 @@ private:
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
class CustomReserved6::Reader {
|
||||
class ModelDataV2SP::Reader {
|
||||
public:
|
||||
typedef CustomReserved6 Reads;
|
||||
typedef ModelDataV2SP Reads;
|
||||
|
||||
Reader() = default;
|
||||
inline explicit Reader(::capnp::_::StructReader base): _reader(base) {}
|
||||
@@ -1854,6 +1858,10 @@ public:
|
||||
}
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
inline bool getLaneChangePrev() const;
|
||||
|
||||
inline bool getLaneChangeEdgeBlock() const;
|
||||
|
||||
private:
|
||||
::capnp::_::StructReader _reader;
|
||||
template <typename, ::capnp::Kind>
|
||||
@@ -1866,9 +1874,9 @@ private:
|
||||
friend class ::capnp::Orphanage;
|
||||
};
|
||||
|
||||
class CustomReserved6::Builder {
|
||||
class ModelDataV2SP::Builder {
|
||||
public:
|
||||
typedef CustomReserved6 Builds;
|
||||
typedef ModelDataV2SP Builds;
|
||||
|
||||
Builder() = delete; // Deleted to discourage incorrect usage.
|
||||
// You can explicitly initialize to nullptr instead.
|
||||
@@ -1882,6 +1890,12 @@ public:
|
||||
inline ::kj::StringTree toString() const { return asReader().toString(); }
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
inline bool getLaneChangePrev();
|
||||
inline void setLaneChangePrev(bool value);
|
||||
|
||||
inline bool getLaneChangeEdgeBlock();
|
||||
inline void setLaneChangeEdgeBlock(bool value);
|
||||
|
||||
private:
|
||||
::capnp::_::StructBuilder _builder;
|
||||
template <typename, ::capnp::Kind>
|
||||
@@ -1892,9 +1906,9 @@ private:
|
||||
};
|
||||
|
||||
#if !CAPNP_LITE
|
||||
class CustomReserved6::Pipeline {
|
||||
class ModelDataV2SP::Pipeline {
|
||||
public:
|
||||
typedef CustomReserved6 Pipelines;
|
||||
typedef ModelDataV2SP Pipelines;
|
||||
|
||||
inline Pipeline(decltype(nullptr)): _typeless(nullptr) {}
|
||||
inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless)
|
||||
@@ -3054,92 +3068,92 @@ inline void LateralPlanSP::Builder::setStandstillElapsed(float value) {
|
||||
::capnp::bounded<5>() * ::capnp::ELEMENTS, value);
|
||||
}
|
||||
|
||||
inline bool LateralPlanSP::Reader::hasDPathWLinesX() const {
|
||||
inline bool LateralPlanSP::Reader::hasDPathWLinesXDEPRECATED() const {
|
||||
return !_reader.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
|
||||
}
|
||||
inline bool LateralPlanSP::Builder::hasDPathWLinesX() {
|
||||
inline bool LateralPlanSP::Builder::hasDPathWLinesXDEPRECATED() {
|
||||
return !_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
|
||||
}
|
||||
inline ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Reader LateralPlanSP::Reader::getDPathWLinesX() const {
|
||||
inline ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Reader LateralPlanSP::Reader::getDPathWLinesXDEPRECATED() const {
|
||||
return ::capnp::_::PointerHelpers< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>>::get(_reader.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
inline ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Builder LateralPlanSP::Builder::getDPathWLinesX() {
|
||||
inline ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Builder LateralPlanSP::Builder::getDPathWLinesXDEPRECATED() {
|
||||
return ::capnp::_::PointerHelpers< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>>::get(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
inline void LateralPlanSP::Builder::setDPathWLinesX( ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Reader value) {
|
||||
inline void LateralPlanSP::Builder::setDPathWLinesXDEPRECATED( ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Reader value) {
|
||||
::capnp::_::PointerHelpers< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>>::set(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS), value);
|
||||
}
|
||||
inline void LateralPlanSP::Builder::setDPathWLinesX(::kj::ArrayPtr<const float> value) {
|
||||
inline void LateralPlanSP::Builder::setDPathWLinesXDEPRECATED(::kj::ArrayPtr<const float> value) {
|
||||
::capnp::_::PointerHelpers< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>>::set(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS), value);
|
||||
}
|
||||
inline ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Builder LateralPlanSP::Builder::initDPathWLinesX(unsigned int size) {
|
||||
inline ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Builder LateralPlanSP::Builder::initDPathWLinesXDEPRECATED(unsigned int size) {
|
||||
return ::capnp::_::PointerHelpers< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>>::init(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS), size);
|
||||
}
|
||||
inline void LateralPlanSP::Builder::adoptDPathWLinesX(
|
||||
inline void LateralPlanSP::Builder::adoptDPathWLinesXDEPRECATED(
|
||||
::capnp::Orphan< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>>&& value) {
|
||||
::capnp::_::PointerHelpers< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>>::adopt(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value));
|
||||
}
|
||||
inline ::capnp::Orphan< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>> LateralPlanSP::Builder::disownDPathWLinesX() {
|
||||
inline ::capnp::Orphan< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>> LateralPlanSP::Builder::disownDPathWLinesXDEPRECATED() {
|
||||
return ::capnp::_::PointerHelpers< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>>::disown(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
|
||||
inline bool LateralPlanSP::Reader::hasDPathWLinesY() const {
|
||||
inline bool LateralPlanSP::Reader::hasDPathWLinesYDEPRECATED() const {
|
||||
return !_reader.getPointerField(
|
||||
::capnp::bounded<1>() * ::capnp::POINTERS).isNull();
|
||||
}
|
||||
inline bool LateralPlanSP::Builder::hasDPathWLinesY() {
|
||||
inline bool LateralPlanSP::Builder::hasDPathWLinesYDEPRECATED() {
|
||||
return !_builder.getPointerField(
|
||||
::capnp::bounded<1>() * ::capnp::POINTERS).isNull();
|
||||
}
|
||||
inline ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Reader LateralPlanSP::Reader::getDPathWLinesY() const {
|
||||
inline ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Reader LateralPlanSP::Reader::getDPathWLinesYDEPRECATED() const {
|
||||
return ::capnp::_::PointerHelpers< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>>::get(_reader.getPointerField(
|
||||
::capnp::bounded<1>() * ::capnp::POINTERS));
|
||||
}
|
||||
inline ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Builder LateralPlanSP::Builder::getDPathWLinesY() {
|
||||
inline ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Builder LateralPlanSP::Builder::getDPathWLinesYDEPRECATED() {
|
||||
return ::capnp::_::PointerHelpers< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>>::get(_builder.getPointerField(
|
||||
::capnp::bounded<1>() * ::capnp::POINTERS));
|
||||
}
|
||||
inline void LateralPlanSP::Builder::setDPathWLinesY( ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Reader value) {
|
||||
inline void LateralPlanSP::Builder::setDPathWLinesYDEPRECATED( ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Reader value) {
|
||||
::capnp::_::PointerHelpers< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>>::set(_builder.getPointerField(
|
||||
::capnp::bounded<1>() * ::capnp::POINTERS), value);
|
||||
}
|
||||
inline void LateralPlanSP::Builder::setDPathWLinesY(::kj::ArrayPtr<const float> value) {
|
||||
inline void LateralPlanSP::Builder::setDPathWLinesYDEPRECATED(::kj::ArrayPtr<const float> value) {
|
||||
::capnp::_::PointerHelpers< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>>::set(_builder.getPointerField(
|
||||
::capnp::bounded<1>() * ::capnp::POINTERS), value);
|
||||
}
|
||||
inline ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Builder LateralPlanSP::Builder::initDPathWLinesY(unsigned int size) {
|
||||
inline ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Builder LateralPlanSP::Builder::initDPathWLinesYDEPRECATED(unsigned int size) {
|
||||
return ::capnp::_::PointerHelpers< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>>::init(_builder.getPointerField(
|
||||
::capnp::bounded<1>() * ::capnp::POINTERS), size);
|
||||
}
|
||||
inline void LateralPlanSP::Builder::adoptDPathWLinesY(
|
||||
inline void LateralPlanSP::Builder::adoptDPathWLinesYDEPRECATED(
|
||||
::capnp::Orphan< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>>&& value) {
|
||||
::capnp::_::PointerHelpers< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>>::adopt(_builder.getPointerField(
|
||||
::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value));
|
||||
}
|
||||
inline ::capnp::Orphan< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>> LateralPlanSP::Builder::disownDPathWLinesY() {
|
||||
inline ::capnp::Orphan< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>> LateralPlanSP::Builder::disownDPathWLinesYDEPRECATED() {
|
||||
return ::capnp::_::PointerHelpers< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>>::disown(_builder.getPointerField(
|
||||
::capnp::bounded<1>() * ::capnp::POINTERS));
|
||||
}
|
||||
|
||||
inline bool LateralPlanSP::Reader::getLaneChangePrev() const {
|
||||
inline bool LateralPlanSP::Reader::getLaneChangePrevDEPRECATED() const {
|
||||
return _reader.getDataField<bool>(
|
||||
::capnp::bounded<136>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
|
||||
inline bool LateralPlanSP::Builder::getLaneChangePrev() {
|
||||
inline bool LateralPlanSP::Builder::getLaneChangePrevDEPRECATED() {
|
||||
return _builder.getDataField<bool>(
|
||||
::capnp::bounded<136>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
inline void LateralPlanSP::Builder::setLaneChangePrev(bool value) {
|
||||
inline void LateralPlanSP::Builder::setLaneChangePrevDEPRECATED(bool value) {
|
||||
_builder.setDataField<bool>(
|
||||
::capnp::bounded<136>() * ::capnp::ELEMENTS, value);
|
||||
}
|
||||
@@ -3158,16 +3172,16 @@ inline void LateralPlanSP::Builder::setDynamicLaneProfileStatus(bool value) {
|
||||
::capnp::bounded<137>() * ::capnp::ELEMENTS, value);
|
||||
}
|
||||
|
||||
inline bool LateralPlanSP::Reader::getLaneChangeEdgeBlock() const {
|
||||
inline bool LateralPlanSP::Reader::getLaneChangeEdgeBlockDEPRECATED() const {
|
||||
return _reader.getDataField<bool>(
|
||||
::capnp::bounded<138>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
|
||||
inline bool LateralPlanSP::Builder::getLaneChangeEdgeBlock() {
|
||||
inline bool LateralPlanSP::Builder::getLaneChangeEdgeBlockDEPRECATED() {
|
||||
return _builder.getDataField<bool>(
|
||||
::capnp::bounded<138>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
inline void LateralPlanSP::Builder::setLaneChangeEdgeBlock(bool value) {
|
||||
inline void LateralPlanSP::Builder::setLaneChangeEdgeBlockDEPRECATED(bool value) {
|
||||
_builder.setDataField<bool>(
|
||||
::capnp::bounded<138>() * ::capnp::ELEMENTS, value);
|
||||
}
|
||||
@@ -3600,5 +3614,35 @@ inline void E2eLongStateSP::Builder::setStatus( ::uint16_t value) {
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS, value);
|
||||
}
|
||||
|
||||
inline bool ModelDataV2SP::Reader::getLaneChangePrev() const {
|
||||
return _reader.getDataField<bool>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
|
||||
inline bool ModelDataV2SP::Builder::getLaneChangePrev() {
|
||||
return _builder.getDataField<bool>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
inline void ModelDataV2SP::Builder::setLaneChangePrev(bool value) {
|
||||
_builder.setDataField<bool>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS, value);
|
||||
}
|
||||
|
||||
inline bool ModelDataV2SP::Reader::getLaneChangeEdgeBlock() const {
|
||||
return _reader.getDataField<bool>(
|
||||
::capnp::bounded<1>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
|
||||
inline bool ModelDataV2SP::Builder::getLaneChangeEdgeBlock() {
|
||||
return _builder.getDataField<bool>(
|
||||
::capnp::bounded<1>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
inline void ModelDataV2SP::Builder::setLaneChangeEdgeBlock(bool value) {
|
||||
_builder.setDataField<bool>(
|
||||
::capnp::bounded<1>() * ::capnp::ELEMENTS, value);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
CAPNP_END_HEADER
|
||||
|
||||
|
||||
+212
-52
@@ -61,7 +61,7 @@ static const uint16_t m_9811e1f38f62f2d1[] = {1, 0};
|
||||
static const uint16_t i_9811e1f38f62f2d1[] = {0, 1};
|
||||
const ::capnp::_::RawSchema s_9811e1f38f62f2d1 = {
|
||||
0x9811e1f38f62f2d1, b_9811e1f38f62f2d1.words, 48, nullptr, m_9811e1f38f62f2d1,
|
||||
0, 2, i_9811e1f38f62f2d1, nullptr, nullptr, { &s_9811e1f38f62f2d1, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 2, i_9811e1f38f62f2d1, nullptr, nullptr, { &s_9811e1f38f62f2d1, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<81> b_c08240f996aefced = {
|
||||
@@ -153,7 +153,7 @@ static const uint16_t m_c08240f996aefced[] = {1, 2, 3, 0};
|
||||
static const uint16_t i_c08240f996aefced[] = {0, 1, 2, 3};
|
||||
const ::capnp::_::RawSchema s_c08240f996aefced = {
|
||||
0xc08240f996aefced, b_c08240f996aefced.words, 81, nullptr, m_c08240f996aefced,
|
||||
0, 4, i_c08240f996aefced, nullptr, nullptr, { &s_c08240f996aefced, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 4, i_c08240f996aefced, nullptr, nullptr, { &s_c08240f996aefced, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<86> b_88dcce08ad29dda0 = {
|
||||
@@ -253,7 +253,7 @@ static const uint16_t m_88dcce08ad29dda0[] = {0, 2, 3, 1};
|
||||
static const uint16_t i_88dcce08ad29dda0[] = {0, 1, 2, 3};
|
||||
const ::capnp::_::RawSchema s_88dcce08ad29dda0 = {
|
||||
0x88dcce08ad29dda0, b_88dcce08ad29dda0.words, 86, d_88dcce08ad29dda0, m_88dcce08ad29dda0,
|
||||
1, 4, i_88dcce08ad29dda0, nullptr, nullptr, { &s_88dcce08ad29dda0, nullptr, nullptr, 0, 0, nullptr }
|
||||
1, 4, i_88dcce08ad29dda0, nullptr, nullptr, { &s_88dcce08ad29dda0, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<39> b_9917470acf94d285 = {
|
||||
@@ -302,7 +302,7 @@ static const ::capnp::_::AlignedData<39> b_9917470acf94d285 = {
|
||||
static const uint16_t m_9917470acf94d285[] = {0, 1, 2, 4, 3};
|
||||
const ::capnp::_::RawSchema s_9917470acf94d285 = {
|
||||
0x9917470acf94d285, b_9917470acf94d285.words, 39, nullptr, m_9917470acf94d285,
|
||||
0, 5, nullptr, nullptr, nullptr, { &s_9917470acf94d285, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 5, nullptr, nullptr, nullptr, { &s_9917470acf94d285, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
CAPNP_DEFINE_ENUM(App_9917470acf94d285, 9917470acf94d285);
|
||||
@@ -447,7 +447,7 @@ static const uint16_t m_8afd33dc9b35e1aa[] = {0, 5, 4, 2, 3, 1};
|
||||
static const uint16_t i_8afd33dc9b35e1aa[] = {0, 1, 2, 3, 4, 5};
|
||||
const ::capnp::_::RawSchema s_8afd33dc9b35e1aa = {
|
||||
0x8afd33dc9b35e1aa, b_8afd33dc9b35e1aa.words, 133, nullptr, m_8afd33dc9b35e1aa,
|
||||
0, 6, i_8afd33dc9b35e1aa, nullptr, nullptr, { &s_8afd33dc9b35e1aa, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 6, i_8afd33dc9b35e1aa, nullptr, nullptr, { &s_8afd33dc9b35e1aa, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<48> b_a99a9d5b33cf5859 = {
|
||||
@@ -506,7 +506,7 @@ static const uint16_t m_a99a9d5b33cf5859[] = {0, 1};
|
||||
static const uint16_t i_a99a9d5b33cf5859[] = {0, 1};
|
||||
const ::capnp::_::RawSchema s_a99a9d5b33cf5859 = {
|
||||
0xa99a9d5b33cf5859, b_a99a9d5b33cf5859.words, 48, nullptr, m_a99a9d5b33cf5859,
|
||||
0, 2, i_a99a9d5b33cf5859, nullptr, nullptr, { &s_a99a9d5b33cf5859, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 2, i_a99a9d5b33cf5859, nullptr, nullptr, { &s_a99a9d5b33cf5859, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<48> b_cff7566681c277ce = {
|
||||
@@ -565,7 +565,7 @@ static const uint16_t m_cff7566681c277ce[] = {1, 0};
|
||||
static const uint16_t i_cff7566681c277ce[] = {0, 1};
|
||||
const ::capnp::_::RawSchema s_cff7566681c277ce = {
|
||||
0xcff7566681c277ce, b_cff7566681c277ce.words, 48, nullptr, m_cff7566681c277ce,
|
||||
0, 2, i_cff7566681c277ce, nullptr, nullptr, { &s_cff7566681c277ce, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 2, i_cff7566681c277ce, nullptr, nullptr, { &s_cff7566681c277ce, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<260> b_d4df5a192382ba0b = {
|
||||
@@ -839,7 +839,7 @@ static const uint16_t m_d4df5a192382ba0b[] = {0, 2, 6, 7, 8, 13, 14, 3, 11, 4, 9
|
||||
static const uint16_t i_d4df5a192382ba0b[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
|
||||
const ::capnp::_::RawSchema s_d4df5a192382ba0b = {
|
||||
0xd4df5a192382ba0b, b_d4df5a192382ba0b.words, 260, d_d4df5a192382ba0b, m_d4df5a192382ba0b,
|
||||
1, 15, i_d4df5a192382ba0b, nullptr, nullptr, { &s_d4df5a192382ba0b, nullptr, nullptr, 0, 0, nullptr }
|
||||
1, 15, i_d4df5a192382ba0b, nullptr, nullptr, { &s_d4df5a192382ba0b, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<40> b_cb6a279f015f6b51 = {
|
||||
@@ -889,7 +889,7 @@ static const ::capnp::_::AlignedData<40> b_cb6a279f015f6b51 = {
|
||||
static const uint16_t m_cb6a279f015f6b51[] = {3, 0, 1, 2, 4};
|
||||
const ::capnp::_::RawSchema s_cb6a279f015f6b51 = {
|
||||
0xcb6a279f015f6b51, b_cb6a279f015f6b51.words, 40, nullptr, m_cb6a279f015f6b51,
|
||||
0, 5, nullptr, nullptr, nullptr, { &s_cb6a279f015f6b51, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 5, nullptr, nullptr, nullptr, { &s_cb6a279f015f6b51, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
CAPNP_DEFINE_ENUM(ChannelWidth_cb6a279f015f6b51, cb6a279f015f6b51);
|
||||
@@ -949,7 +949,7 @@ static const uint16_t m_94b7baa90c5c321e[] = {0, 1};
|
||||
static const uint16_t i_94b7baa90c5c321e[] = {0, 1};
|
||||
const ::capnp::_::RawSchema s_94b7baa90c5c321e = {
|
||||
0x94b7baa90c5c321e, b_94b7baa90c5c321e.words, 48, nullptr, m_94b7baa90c5c321e,
|
||||
0, 2, i_94b7baa90c5c321e, nullptr, nullptr, { &s_94b7baa90c5c321e, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 2, i_94b7baa90c5c321e, nullptr, nullptr, { &s_94b7baa90c5c321e, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<314> b_b8aad62cffef28a9 = {
|
||||
@@ -1281,7 +1281,7 @@ static const uint16_t m_b8aad62cffef28a9[] = {12, 13, 0, 6, 16, 4, 7, 2, 11, 10,
|
||||
static const uint16_t i_b8aad62cffef28a9[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
|
||||
const ::capnp::_::RawSchema s_b8aad62cffef28a9 = {
|
||||
0xb8aad62cffef28a9, b_b8aad62cffef28a9.words, 314, d_b8aad62cffef28a9, m_b8aad62cffef28a9,
|
||||
5, 17, i_b8aad62cffef28a9, nullptr, nullptr, { &s_b8aad62cffef28a9, nullptr, nullptr, 0, 0, nullptr }
|
||||
5, 17, i_b8aad62cffef28a9, nullptr, nullptr, { &s_b8aad62cffef28a9, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<121> b_8817eeea389e9f08 = {
|
||||
@@ -1413,7 +1413,7 @@ static const uint16_t m_8817eeea389e9f08[] = {0, 4, 1, 2, 3, 5};
|
||||
static const uint16_t i_8817eeea389e9f08[] = {0, 1, 2, 3, 4, 5};
|
||||
const ::capnp::_::RawSchema s_8817eeea389e9f08 = {
|
||||
0x8817eeea389e9f08, b_8817eeea389e9f08.words, 121, nullptr, m_8817eeea389e9f08,
|
||||
0, 6, i_8817eeea389e9f08, nullptr, nullptr, { &s_8817eeea389e9f08, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 6, i_8817eeea389e9f08, nullptr, nullptr, { &s_8817eeea389e9f08, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<154> b_d1c9bef96d26fa91 = {
|
||||
@@ -1578,7 +1578,7 @@ static const uint16_t m_d1c9bef96d26fa91[] = {0, 1, 7, 8, 3, 4, 5, 6, 2};
|
||||
static const uint16_t i_d1c9bef96d26fa91[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
|
||||
const ::capnp::_::RawSchema s_d1c9bef96d26fa91 = {
|
||||
0xd1c9bef96d26fa91, b_d1c9bef96d26fa91.words, 154, nullptr, m_d1c9bef96d26fa91,
|
||||
0, 9, i_d1c9bef96d26fa91, nullptr, nullptr, { &s_d1c9bef96d26fa91, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 9, i_d1c9bef96d26fa91, nullptr, nullptr, { &s_d1c9bef96d26fa91, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<141> b_a26e3710efd3e914 = {
|
||||
@@ -1730,7 +1730,7 @@ static const uint16_t m_a26e3710efd3e914[] = {3, 2, 0, 1, 4, 6, 5};
|
||||
static const uint16_t i_a26e3710efd3e914[] = {0, 1, 2, 3, 4, 5, 6};
|
||||
const ::capnp::_::RawSchema s_a26e3710efd3e914 = {
|
||||
0xa26e3710efd3e914, b_a26e3710efd3e914.words, 141, nullptr, m_a26e3710efd3e914,
|
||||
0, 7, i_a26e3710efd3e914, nullptr, nullptr, { &s_a26e3710efd3e914, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 7, i_a26e3710efd3e914, nullptr, nullptr, { &s_a26e3710efd3e914, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<126> b_9744f25fb60f2bf8 = {
|
||||
@@ -1867,7 +1867,7 @@ static const uint16_t m_9744f25fb60f2bf8[] = {2, 1, 5, 0, 3, 4};
|
||||
static const uint16_t i_9744f25fb60f2bf8[] = {0, 1, 2, 3, 4, 5};
|
||||
const ::capnp::_::RawSchema s_9744f25fb60f2bf8 = {
|
||||
0x9744f25fb60f2bf8, b_9744f25fb60f2bf8.words, 126, nullptr, m_9744f25fb60f2bf8,
|
||||
0, 6, i_9744f25fb60f2bf8, nullptr, nullptr, { &s_9744f25fb60f2bf8, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 6, i_9744f25fb60f2bf8, nullptr, nullptr, { &s_9744f25fb60f2bf8, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<78> b_f98f999c6a071122 = {
|
||||
@@ -1956,7 +1956,7 @@ static const uint16_t m_f98f999c6a071122[] = {1, 2, 0};
|
||||
static const uint16_t i_f98f999c6a071122[] = {0, 1, 2};
|
||||
const ::capnp::_::RawSchema s_f98f999c6a071122 = {
|
||||
0xf98f999c6a071122, b_f98f999c6a071122.words, 78, nullptr, m_f98f999c6a071122,
|
||||
0, 3, i_f98f999c6a071122, nullptr, nullptr, { &s_f98f999c6a071122, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 3, i_f98f999c6a071122, nullptr, nullptr, { &s_f98f999c6a071122, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<62> b_c25bbbd524983447 = {
|
||||
@@ -2029,7 +2029,7 @@ static const uint16_t m_c25bbbd524983447[] = {0, 1, 2};
|
||||
static const uint16_t i_c25bbbd524983447[] = {0, 1, 2};
|
||||
const ::capnp::_::RawSchema s_c25bbbd524983447 = {
|
||||
0xc25bbbd524983447, b_c25bbbd524983447.words, 62, nullptr, m_c25bbbd524983447,
|
||||
0, 3, i_c25bbbd524983447, nullptr, nullptr, { &s_c25bbbd524983447, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 3, i_c25bbbd524983447, nullptr, nullptr, { &s_c25bbbd524983447, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<64> b_e10e21168db0c7f7 = {
|
||||
@@ -2104,7 +2104,7 @@ static const uint16_t m_e10e21168db0c7f7[] = {0, 1, 2};
|
||||
static const uint16_t i_e10e21168db0c7f7[] = {0, 1, 2};
|
||||
const ::capnp::_::RawSchema s_e10e21168db0c7f7 = {
|
||||
0xe10e21168db0c7f7, b_e10e21168db0c7f7.words, 64, nullptr, m_e10e21168db0c7f7,
|
||||
0, 3, i_e10e21168db0c7f7, nullptr, nullptr, { &s_e10e21168db0c7f7, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 3, i_e10e21168db0c7f7, nullptr, nullptr, { &s_e10e21168db0c7f7, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<153> b_ab54c59699f8f9f3 = {
|
||||
@@ -2272,7 +2272,7 @@ static const uint16_t m_ab54c59699f8f9f3[] = {5, 6, 0, 7, 1, 4, 3, 2};
|
||||
static const uint16_t i_ab54c59699f8f9f3[] = {0, 1, 2, 3, 4, 5, 6, 7};
|
||||
const ::capnp::_::RawSchema s_ab54c59699f8f9f3 = {
|
||||
0xab54c59699f8f9f3, b_ab54c59699f8f9f3.words, 153, d_ab54c59699f8f9f3, m_ab54c59699f8f9f3,
|
||||
2, 8, i_ab54c59699f8f9f3, nullptr, nullptr, { &s_ab54c59699f8f9f3, nullptr, nullptr, 0, 0, nullptr }
|
||||
2, 8, i_ab54c59699f8f9f3, nullptr, nullptr, { &s_ab54c59699f8f9f3, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<155> b_f5ad1d90cdc1dd6b = {
|
||||
@@ -2442,7 +2442,7 @@ static const uint16_t m_f5ad1d90cdc1dd6b[] = {4, 6, 5, 1, 3, 2, 0, 7};
|
||||
static const uint16_t i_f5ad1d90cdc1dd6b[] = {0, 1, 2, 3, 4, 5, 6, 7};
|
||||
const ::capnp::_::RawSchema s_f5ad1d90cdc1dd6b = {
|
||||
0xf5ad1d90cdc1dd6b, b_f5ad1d90cdc1dd6b.words, 155, d_f5ad1d90cdc1dd6b, m_f5ad1d90cdc1dd6b,
|
||||
2, 8, i_f5ad1d90cdc1dd6b, nullptr, nullptr, { &s_f5ad1d90cdc1dd6b, nullptr, nullptr, 0, 0, nullptr }
|
||||
2, 8, i_f5ad1d90cdc1dd6b, nullptr, nullptr, { &s_f5ad1d90cdc1dd6b, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<103> b_90c8426c3eaddd3b = {
|
||||
@@ -2562,7 +2562,7 @@ static const uint16_t m_90c8426c3eaddd3b[] = {2, 4, 3, 1, 0};
|
||||
static const uint16_t i_90c8426c3eaddd3b[] = {0, 1, 2, 3, 4};
|
||||
const ::capnp::_::RawSchema s_90c8426c3eaddd3b = {
|
||||
0x90c8426c3eaddd3b, b_90c8426c3eaddd3b.words, 103, d_90c8426c3eaddd3b, m_90c8426c3eaddd3b,
|
||||
4, 5, i_90c8426c3eaddd3b, nullptr, nullptr, { &s_90c8426c3eaddd3b, nullptr, nullptr, 0, 0, nullptr }
|
||||
4, 5, i_90c8426c3eaddd3b, nullptr, nullptr, { &s_90c8426c3eaddd3b, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<53> b_e8db07dcf8fcea05 = {
|
||||
@@ -2625,7 +2625,7 @@ static const ::capnp::_::AlignedData<53> b_e8db07dcf8fcea05 = {
|
||||
static const uint16_t m_e8db07dcf8fcea05[] = {1, 2, 3, 4, 0, 5, 6};
|
||||
const ::capnp::_::RawSchema s_e8db07dcf8fcea05 = {
|
||||
0xe8db07dcf8fcea05, b_e8db07dcf8fcea05.words, 53, nullptr, m_e8db07dcf8fcea05,
|
||||
0, 7, nullptr, nullptr, nullptr, { &s_e8db07dcf8fcea05, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 7, nullptr, nullptr, nullptr, { &s_e8db07dcf8fcea05, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
CAPNP_DEFINE_ENUM(Type_e8db07dcf8fcea05, e8db07dcf8fcea05);
|
||||
@@ -2672,7 +2672,7 @@ static const ::capnp::_::AlignedData<36> b_b9aa88c75ef99a1f = {
|
||||
static const uint16_t m_b9aa88c75ef99a1f[] = {3, 2, 0, 1};
|
||||
const ::capnp::_::RawSchema s_b9aa88c75ef99a1f = {
|
||||
0xb9aa88c75ef99a1f, b_b9aa88c75ef99a1f.words, 36, nullptr, m_b9aa88c75ef99a1f,
|
||||
0, 4, nullptr, nullptr, nullptr, { &s_b9aa88c75ef99a1f, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 4, nullptr, nullptr, nullptr, { &s_b9aa88c75ef99a1f, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
CAPNP_DEFINE_ENUM(Status_b9aa88c75ef99a1f, b9aa88c75ef99a1f);
|
||||
@@ -3094,7 +3094,7 @@ static const uint16_t m_b99b2bc7a57e8128[] = {12, 13, 3, 15, 16, 11, 8, 22, 1, 2
|
||||
static const uint16_t i_b99b2bc7a57e8128[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22};
|
||||
const ::capnp::_::RawSchema s_b99b2bc7a57e8128 = {
|
||||
0xb99b2bc7a57e8128, b_b99b2bc7a57e8128.words, 406, d_b99b2bc7a57e8128, m_b99b2bc7a57e8128,
|
||||
2, 23, i_b99b2bc7a57e8128, nullptr, nullptr, { &s_b99b2bc7a57e8128, nullptr, nullptr, 0, 0, nullptr }
|
||||
2, 23, i_b99b2bc7a57e8128, nullptr, nullptr, { &s_b99b2bc7a57e8128, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<159> b_943dc4625473b03f = {
|
||||
@@ -3264,7 +3264,7 @@ static const uint16_t m_943dc4625473b03f[] = {7, 5, 6, 4, 0, 3, 2, 1};
|
||||
static const uint16_t i_943dc4625473b03f[] = {0, 1, 2, 3, 4, 5, 6, 7};
|
||||
const ::capnp::_::RawSchema s_943dc4625473b03f = {
|
||||
0x943dc4625473b03f, b_943dc4625473b03f.words, 159, nullptr, m_943dc4625473b03f,
|
||||
0, 8, i_943dc4625473b03f, nullptr, nullptr, { &s_943dc4625473b03f, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 8, i_943dc4625473b03f, nullptr, nullptr, { &s_943dc4625473b03f, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<41> b_c871d3cc252af657 = {
|
||||
@@ -3315,7 +3315,7 @@ static const ::capnp::_::AlignedData<41> b_c871d3cc252af657 = {
|
||||
static const uint16_t m_c871d3cc252af657[] = {0, 4, 1, 2, 3};
|
||||
const ::capnp::_::RawSchema s_c871d3cc252af657 = {
|
||||
0xc871d3cc252af657, b_c871d3cc252af657.words, 41, nullptr, m_c871d3cc252af657,
|
||||
0, 5, nullptr, nullptr, nullptr, { &s_c871d3cc252af657, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 5, nullptr, nullptr, nullptr, { &s_c871d3cc252af657, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
CAPNP_DEFINE_ENUM(SensorSource_c871d3cc252af657, c871d3cc252af657);
|
||||
@@ -3445,7 +3445,7 @@ static const uint16_t m_d7700859ed1f5b76[] = {1, 3, 2, 4, 5, 0};
|
||||
static const uint16_t i_d7700859ed1f5b76[] = {0, 1, 2, 3, 4, 5};
|
||||
const ::capnp::_::RawSchema s_d7700859ed1f5b76 = {
|
||||
0xd7700859ed1f5b76, b_d7700859ed1f5b76.words, 118, nullptr, m_d7700859ed1f5b76,
|
||||
0, 6, i_d7700859ed1f5b76, nullptr, nullptr, { &s_d7700859ed1f5b76, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 6, i_d7700859ed1f5b76, nullptr, nullptr, { &s_d7700859ed1f5b76, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<143> b_cd60164a8a0159ef = {
|
||||
@@ -3599,7 +3599,7 @@ static const uint16_t m_cd60164a8a0159ef[] = {3, 6, 4, 0, 5, 1, 2};
|
||||
static const uint16_t i_cd60164a8a0159ef[] = {0, 1, 2, 3, 4, 5, 6};
|
||||
const ::capnp::_::RawSchema s_cd60164a8a0159ef = {
|
||||
0xcd60164a8a0159ef, b_cd60164a8a0159ef.words, 143, nullptr, m_cd60164a8a0159ef,
|
||||
0, 7, i_cd60164a8a0159ef, nullptr, nullptr, { &s_cd60164a8a0159ef, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 7, i_cd60164a8a0159ef, nullptr, nullptr, { &s_cd60164a8a0159ef, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<99> b_d500d30c5803fa4f = {
|
||||
@@ -3709,7 +3709,7 @@ static const uint16_t m_d500d30c5803fa4f[] = {4, 2, 3, 0, 1};
|
||||
static const uint16_t i_d500d30c5803fa4f[] = {0, 1, 2, 3, 4};
|
||||
const ::capnp::_::RawSchema s_d500d30c5803fa4f = {
|
||||
0xd500d30c5803fa4f, b_d500d30c5803fa4f.words, 99, nullptr, m_d500d30c5803fa4f,
|
||||
0, 5, i_d500d30c5803fa4f, nullptr, nullptr, { &s_d500d30c5803fa4f, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 5, i_d500d30c5803fa4f, nullptr, nullptr, { &s_d500d30c5803fa4f, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<83> b_c8233c0345e27e24 = {
|
||||
@@ -3806,7 +3806,7 @@ static const uint16_t m_c8233c0345e27e24[] = {3, 2, 0, 1};
|
||||
static const uint16_t i_c8233c0345e27e24[] = {0, 1, 2, 3};
|
||||
const ::capnp::_::RawSchema s_c8233c0345e27e24 = {
|
||||
0xc8233c0345e27e24, b_c8233c0345e27e24.words, 83, d_c8233c0345e27e24, m_c8233c0345e27e24,
|
||||
1, 4, i_c8233c0345e27e24, nullptr, nullptr, { &s_c8233c0345e27e24, nullptr, nullptr, 0, 0, nullptr }
|
||||
1, 4, i_c8233c0345e27e24, nullptr, nullptr, { &s_c8233c0345e27e24, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<95> b_92e21bb7ea38793a = {
|
||||
@@ -3912,7 +3912,7 @@ static const uint16_t m_92e21bb7ea38793a[] = {1, 3, 0, 2};
|
||||
static const uint16_t i_92e21bb7ea38793a[] = {0, 1, 2, 3};
|
||||
const ::capnp::_::RawSchema s_92e21bb7ea38793a = {
|
||||
0x92e21bb7ea38793a, b_92e21bb7ea38793a.words, 95, nullptr, m_92e21bb7ea38793a,
|
||||
0, 4, i_92e21bb7ea38793a, nullptr, nullptr, { &s_92e21bb7ea38793a, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 4, i_92e21bb7ea38793a, nullptr, nullptr, { &s_92e21bb7ea38793a, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<92> b_9b326d4e436afec7 = {
|
||||
@@ -4015,7 +4015,7 @@ static const uint16_t m_9b326d4e436afec7[] = {2, 3, 1, 0};
|
||||
static const uint16_t i_9b326d4e436afec7[] = {0, 1, 2, 3};
|
||||
const ::capnp::_::RawSchema s_9b326d4e436afec7 = {
|
||||
0x9b326d4e436afec7, b_9b326d4e436afec7.words, 92, nullptr, m_9b326d4e436afec7,
|
||||
0, 4, i_9b326d4e436afec7, nullptr, nullptr, { &s_9b326d4e436afec7, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 4, i_9b326d4e436afec7, nullptr, nullptr, { &s_9b326d4e436afec7, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<91> b_8fdfadb254ea867a = {
|
||||
@@ -4117,7 +4117,7 @@ static const uint16_t m_8fdfadb254ea867a[] = {0, 1, 2, 3};
|
||||
static const uint16_t i_8fdfadb254ea867a[] = {0, 1, 2, 3};
|
||||
const ::capnp::_::RawSchema s_8fdfadb254ea867a = {
|
||||
0x8fdfadb254ea867a, b_8fdfadb254ea867a.words, 91, nullptr, m_8fdfadb254ea867a,
|
||||
0, 4, i_8fdfadb254ea867a, nullptr, nullptr, { &s_8fdfadb254ea867a, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 4, i_8fdfadb254ea867a, nullptr, nullptr, { &s_8fdfadb254ea867a, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<52> b_bd8822120928120c = {
|
||||
@@ -4183,7 +4183,7 @@ static const uint16_t m_bd8822120928120c[] = {1, 0};
|
||||
static const uint16_t i_bd8822120928120c[] = {0, 1};
|
||||
const ::capnp::_::RawSchema s_bd8822120928120c = {
|
||||
0xbd8822120928120c, b_bd8822120928120c.words, 52, d_bd8822120928120c, m_bd8822120928120c,
|
||||
1, 2, i_bd8822120928120c, nullptr, nullptr, { &s_bd8822120928120c, nullptr, nullptr, 0, 0, nullptr }
|
||||
1, 2, i_bd8822120928120c, nullptr, nullptr, { &s_bd8822120928120c, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<153> b_ce7cd672cacc7814 = {
|
||||
@@ -4347,7 +4347,7 @@ static const uint16_t m_ce7cd672cacc7814[] = {4, 6, 8, 3, 1, 2, 7, 5, 0};
|
||||
static const uint16_t i_ce7cd672cacc7814[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
|
||||
const ::capnp::_::RawSchema s_ce7cd672cacc7814 = {
|
||||
0xce7cd672cacc7814, b_ce7cd672cacc7814.words, 153, nullptr, m_ce7cd672cacc7814,
|
||||
0, 9, i_ce7cd672cacc7814, nullptr, nullptr, { &s_ce7cd672cacc7814, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 9, i_ce7cd672cacc7814, nullptr, nullptr, { &s_ce7cd672cacc7814, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<75> b_db98be6565516acb = {
|
||||
@@ -4436,7 +4436,7 @@ static const uint16_t m_db98be6565516acb[] = {1, 0, 2};
|
||||
static const uint16_t i_db98be6565516acb[] = {0, 1, 2};
|
||||
const ::capnp::_::RawSchema s_db98be6565516acb = {
|
||||
0xdb98be6565516acb, b_db98be6565516acb.words, 75, d_db98be6565516acb, m_db98be6565516acb,
|
||||
1, 3, i_db98be6565516acb, nullptr, nullptr, { &s_db98be6565516acb, nullptr, nullptr, 0, 0, nullptr }
|
||||
1, 3, i_db98be6565516acb, nullptr, nullptr, { &s_db98be6565516acb, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<48> b_9eaef9187cadbb9b = {
|
||||
@@ -4495,7 +4495,7 @@ static const uint16_t m_9eaef9187cadbb9b[] = {0, 1};
|
||||
static const uint16_t i_9eaef9187cadbb9b[] = {0, 1};
|
||||
const ::capnp::_::RawSchema s_9eaef9187cadbb9b = {
|
||||
0x9eaef9187cadbb9b, b_9eaef9187cadbb9b.words, 48, nullptr, m_9eaef9187cadbb9b,
|
||||
0, 2, i_9eaef9187cadbb9b, nullptr, nullptr, { &s_9eaef9187cadbb9b, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 2, i_9eaef9187cadbb9b, nullptr, nullptr, { &s_9eaef9187cadbb9b, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<150> b_a5b39b4fc4d7da3f = {
|
||||
@@ -4660,7 +4660,7 @@ static const uint16_t m_a5b39b4fc4d7da3f[] = {4, 3, 5, 0, 6, 7, 1, 2};
|
||||
static const uint16_t i_a5b39b4fc4d7da3f[] = {0, 1, 2, 3, 4, 5, 6, 7};
|
||||
const ::capnp::_::RawSchema s_a5b39b4fc4d7da3f = {
|
||||
0xa5b39b4fc4d7da3f, b_a5b39b4fc4d7da3f.words, 150, d_a5b39b4fc4d7da3f, m_a5b39b4fc4d7da3f,
|
||||
2, 8, i_a5b39b4fc4d7da3f, nullptr, nullptr, { &s_a5b39b4fc4d7da3f, nullptr, nullptr, 0, 0, nullptr }
|
||||
2, 8, i_a5b39b4fc4d7da3f, nullptr, nullptr, { &s_a5b39b4fc4d7da3f, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<117> b_c5417a637451246f = {
|
||||
@@ -4787,7 +4787,7 @@ static const ::capnp::_::AlignedData<117> b_c5417a637451246f = {
|
||||
static const uint16_t m_c5417a637451246f[] = {15, 16, 17, 2, 3, 6, 5, 9, 7, 11, 13, 4, 0, 1, 10, 12, 14, 18, 8, 19};
|
||||
const ::capnp::_::RawSchema s_c5417a637451246f = {
|
||||
0xc5417a637451246f, b_c5417a637451246f.words, 117, nullptr, m_c5417a637451246f,
|
||||
0, 20, nullptr, nullptr, nullptr, { &s_c5417a637451246f, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 20, nullptr, nullptr, nullptr, { &s_c5417a637451246f, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
CAPNP_DEFINE_ENUM(Instruction_c5417a637451246f, c5417a637451246f);
|
||||
@@ -4889,7 +4889,7 @@ static const uint16_t m_acfa74a094e62626[] = {2, 1, 3, 0};
|
||||
static const uint16_t i_acfa74a094e62626[] = {0, 1, 2, 3};
|
||||
const ::capnp::_::RawSchema s_acfa74a094e62626 = {
|
||||
0xacfa74a094e62626, b_acfa74a094e62626.words, 86, d_acfa74a094e62626, m_acfa74a094e62626,
|
||||
2, 4, i_acfa74a094e62626, nullptr, nullptr, { &s_acfa74a094e62626, nullptr, nullptr, 0, 0, nullptr }
|
||||
2, 4, i_acfa74a094e62626, nullptr, nullptr, { &s_acfa74a094e62626, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<43> b_d85d75253435bf4b = {
|
||||
@@ -4942,7 +4942,7 @@ static const ::capnp::_::AlignedData<43> b_d85d75253435bf4b = {
|
||||
static const uint16_t m_d85d75253435bf4b[] = {3, 1, 2, 4, 0};
|
||||
const ::capnp::_::RawSchema s_d85d75253435bf4b = {
|
||||
0xd85d75253435bf4b, b_d85d75253435bf4b.words, 43, nullptr, m_d85d75253435bf4b,
|
||||
0, 5, nullptr, nullptr, nullptr, { &s_d85d75253435bf4b, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 5, nullptr, nullptr, nullptr, { &s_d85d75253435bf4b, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
CAPNP_DEFINE_ENUM(Type_d85d75253435bf4b, d85d75253435bf4b);
|
||||
@@ -4989,7 +4989,7 @@ static const ::capnp::_::AlignedData<36> b_a6f6ce72165ccb49 = {
|
||||
static const uint16_t m_a6f6ce72165ccb49[] = {0, 3, 2, 1};
|
||||
const ::capnp::_::RawSchema s_a6f6ce72165ccb49 = {
|
||||
0xa6f6ce72165ccb49, b_a6f6ce72165ccb49.words, 36, nullptr, m_a6f6ce72165ccb49,
|
||||
0, 4, nullptr, nullptr, nullptr, { &s_a6f6ce72165ccb49, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 4, nullptr, nullptr, nullptr, { &s_a6f6ce72165ccb49, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
CAPNP_DEFINE_ENUM(Action_a6f6ce72165ccb49, a6f6ce72165ccb49);
|
||||
@@ -5065,7 +5065,7 @@ static const uint16_t m_dfdf30d03fc485bd[] = {0, 1};
|
||||
static const uint16_t i_dfdf30d03fc485bd[] = {0, 1};
|
||||
const ::capnp::_::RawSchema s_dfdf30d03fc485bd = {
|
||||
0xdfdf30d03fc485bd, b_dfdf30d03fc485bd.words, 60, d_dfdf30d03fc485bd, m_dfdf30d03fc485bd,
|
||||
2, 2, i_dfdf30d03fc485bd, nullptr, nullptr, { &s_dfdf30d03fc485bd, nullptr, nullptr, 0, 0, nullptr }
|
||||
2, 2, i_dfdf30d03fc485bd, nullptr, nullptr, { &s_dfdf30d03fc485bd, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<61> b_a20710d4f428d6cd = {
|
||||
@@ -5141,7 +5141,7 @@ static const uint16_t m_a20710d4f428d6cd[] = {0, 1};
|
||||
static const uint16_t i_a20710d4f428d6cd[] = {0, 1};
|
||||
const ::capnp::_::RawSchema s_a20710d4f428d6cd = {
|
||||
0xa20710d4f428d6cd, b_a20710d4f428d6cd.words, 61, d_a20710d4f428d6cd, m_a20710d4f428d6cd,
|
||||
2, 2, i_a20710d4f428d6cd, nullptr, nullptr, { &s_a20710d4f428d6cd, nullptr, nullptr, 0, 0, nullptr }
|
||||
2, 2, i_a20710d4f428d6cd, nullptr, nullptr, { &s_a20710d4f428d6cd, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<290> b_a0e27b453a38f450 = {
|
||||
@@ -5442,7 +5442,7 @@ static const uint16_t m_a0e27b453a38f450[] = {9, 11, 13, 15, 7, 1, 8, 10, 12, 14
|
||||
static const uint16_t i_a0e27b453a38f450[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
|
||||
const ::capnp::_::RawSchema s_a0e27b453a38f450 = {
|
||||
0xa0e27b453a38f450, b_a0e27b453a38f450.words, 290, nullptr, m_a0e27b453a38f450,
|
||||
0, 16, i_a0e27b453a38f450, nullptr, nullptr, { &s_a0e27b453a38f450, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 16, i_a0e27b453a38f450, nullptr, nullptr, { &s_a0e27b453a38f450, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<420> b_d949bf717d77614d = {
|
||||
@@ -5877,7 +5877,7 @@ static const uint16_t m_d949bf717d77614d[] = {10, 9, 11, 15, 13, 17, 19, 6, 1, 1
|
||||
static const uint16_t i_d949bf717d77614d[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22};
|
||||
const ::capnp::_::RawSchema s_d949bf717d77614d = {
|
||||
0xd949bf717d77614d, b_d949bf717d77614d.words, 420, d_d949bf717d77614d, m_d949bf717d77614d,
|
||||
2, 23, i_d949bf717d77614d, nullptr, nullptr, { &s_d949bf717d77614d, nullptr, nullptr, 0, 0, nullptr }
|
||||
2, 23, i_d949bf717d77614d, nullptr, nullptr, { &s_d949bf717d77614d, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<50> b_9ef1f3ff0deb5ffb = {
|
||||
@@ -5937,7 +5937,7 @@ static const ::capnp::_::AlignedData<50> b_9ef1f3ff0deb5ffb = {
|
||||
static const uint16_t m_9ef1f3ff0deb5ffb[] = {5, 6, 3, 1, 4, 2, 0};
|
||||
const ::capnp::_::RawSchema s_9ef1f3ff0deb5ffb = {
|
||||
0x9ef1f3ff0deb5ffb, b_9ef1f3ff0deb5ffb.words, 50, nullptr, m_9ef1f3ff0deb5ffb,
|
||||
0, 7, nullptr, nullptr, nullptr, { &s_9ef1f3ff0deb5ffb, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 7, nullptr, nullptr, nullptr, { &s_9ef1f3ff0deb5ffb, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
CAPNP_DEFINE_ENUM(Constellation_9ef1f3ff0deb5ffb, 9ef1f3ff0deb5ffb);
|
||||
@@ -6044,7 +6044,7 @@ static const ::capnp::_::AlignedData<96> b_cbb9490adce12d72 = {
|
||||
static const uint16_t m_cbb9490adce12d72[] = {9, 10, 2, 1, 13, 11, 12, 7, 8, 5, 14, 3, 6, 4, 0};
|
||||
const ::capnp::_::RawSchema s_cbb9490adce12d72 = {
|
||||
0xcbb9490adce12d72, b_cbb9490adce12d72.words, 96, nullptr, m_cbb9490adce12d72,
|
||||
0, 15, nullptr, nullptr, nullptr, { &s_cbb9490adce12d72, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 15, nullptr, nullptr, nullptr, { &s_cbb9490adce12d72, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
CAPNP_DEFINE_ENUM(State_cbb9490adce12d72, cbb9490adce12d72);
|
||||
@@ -6092,7 +6092,7 @@ static const ::capnp::_::AlignedData<37> b_c04e7b6231d4caa8 = {
|
||||
static const uint16_t m_c04e7b6231d4caa8[] = {1, 2, 0};
|
||||
const ::capnp::_::RawSchema s_c04e7b6231d4caa8 = {
|
||||
0xc04e7b6231d4caa8, b_c04e7b6231d4caa8.words, 37, nullptr, m_c04e7b6231d4caa8,
|
||||
0, 3, nullptr, nullptr, nullptr, { &s_c04e7b6231d4caa8, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 3, nullptr, nullptr, nullptr, { &s_c04e7b6231d4caa8, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
CAPNP_DEFINE_ENUM(MultipathIndicator_c04e7b6231d4caa8, c04e7b6231d4caa8);
|
||||
@@ -6222,7 +6222,7 @@ static const uint16_t m_e2517b083095fd4e[] = {4, 2, 5, 3, 1, 0};
|
||||
static const uint16_t i_e2517b083095fd4e[] = {0, 1, 2, 3, 4, 5};
|
||||
const ::capnp::_::RawSchema s_e2517b083095fd4e = {
|
||||
0xe2517b083095fd4e, b_e2517b083095fd4e.words, 115, d_e2517b083095fd4e, m_e2517b083095fd4e,
|
||||
1, 6, i_e2517b083095fd4e, nullptr, nullptr, { &s_e2517b083095fd4e, nullptr, nullptr, 0, 0, nullptr }
|
||||
1, 6, i_e2517b083095fd4e, nullptr, nullptr, { &s_e2517b083095fd4e, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<35> b_ec1ff7996b35366f = {
|
||||
@@ -6267,7 +6267,7 @@ static const ::capnp::_::AlignedData<35> b_ec1ff7996b35366f = {
|
||||
static const uint16_t m_ec1ff7996b35366f[] = {1, 2, 0};
|
||||
const ::capnp::_::RawSchema s_ec1ff7996b35366f = {
|
||||
0xec1ff7996b35366f, b_ec1ff7996b35366f.words, 35, nullptr, m_ec1ff7996b35366f,
|
||||
0, 3, nullptr, nullptr, nullptr, { &s_ec1ff7996b35366f, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 3, nullptr, nullptr, nullptr, { &s_ec1ff7996b35366f, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
CAPNP_DEFINE_ENUM(Status_ec1ff7996b35366f, ec1ff7996b35366f);
|
||||
@@ -6383,7 +6383,7 @@ static const uint16_t m_e3d6685d4e9d8f7a[] = {3, 4, 0, 2, 1};
|
||||
static const uint16_t i_e3d6685d4e9d8f7a[] = {0, 1, 2, 3, 4};
|
||||
const ::capnp::_::RawSchema s_e3d6685d4e9d8f7a = {
|
||||
0xe3d6685d4e9d8f7a, b_e3d6685d4e9d8f7a.words, 104, nullptr, m_e3d6685d4e9d8f7a,
|
||||
0, 5, i_e3d6685d4e9d8f7a, nullptr, nullptr, { &s_e3d6685d4e9d8f7a, nullptr, nullptr, 0, 0, nullptr }
|
||||
0, 5, i_e3d6685d4e9d8f7a, nullptr, nullptr, { &s_e3d6685d4e9d8f7a, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
} // namespace schemas
|
||||
@@ -6394,323 +6394,483 @@ const ::capnp::_::RawSchema s_e3d6685d4e9d8f7a = {
|
||||
namespace cereal {
|
||||
|
||||
// LogRotate
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t LogRotate::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t LogRotate::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind LogRotate::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* LogRotate::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// LiveUI
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t LiveUI::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t LiveUI::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind LiveUI::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* LiveUI::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// UiLayoutState
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t UiLayoutState::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t UiLayoutState::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind UiLayoutState::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* UiLayoutState::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// OrbslamCorrection
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t OrbslamCorrection::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t OrbslamCorrection::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind OrbslamCorrection::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* OrbslamCorrection::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// EthernetPacket
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t EthernetPacket::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t EthernetPacket::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind EthernetPacket::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* EthernetPacket::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// CellInfo
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t CellInfo::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t CellInfo::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind CellInfo::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* CellInfo::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// WifiScan
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t WifiScan::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t WifiScan::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind WifiScan::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* WifiScan::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// LiveEventData
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t LiveEventData::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t LiveEventData::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind LiveEventData::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* LiveEventData::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// ModelData
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t ModelData::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t ModelData::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind ModelData::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* ModelData::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// ModelData::PathData
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t ModelData::PathData::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t ModelData::PathData::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind ModelData::PathData::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* ModelData::PathData::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// ModelData::LeadData
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t ModelData::LeadData::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t ModelData::LeadData::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind ModelData::LeadData::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* ModelData::LeadData::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// ModelData::ModelSettings
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t ModelData::ModelSettings::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t ModelData::ModelSettings::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind ModelData::ModelSettings::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* ModelData::ModelSettings::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// ModelData::MetaData
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t ModelData::MetaData::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t ModelData::MetaData::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind ModelData::MetaData::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* ModelData::MetaData::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// ModelData::LongitudinalData
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t ModelData::LongitudinalData::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t ModelData::LongitudinalData::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind ModelData::LongitudinalData::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* ModelData::LongitudinalData::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// ECEFPoint
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t ECEFPoint::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t ECEFPoint::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind ECEFPoint::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* ECEFPoint::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// ECEFPointDEPRECATED
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t ECEFPointDEPRECATED::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t ECEFPointDEPRECATED::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind ECEFPointDEPRECATED::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* ECEFPointDEPRECATED::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// GPSPlannerPoints
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t GPSPlannerPoints::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t GPSPlannerPoints::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind GPSPlannerPoints::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* GPSPlannerPoints::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// GPSPlannerPlan
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t GPSPlannerPlan::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t GPSPlannerPlan::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind GPSPlannerPlan::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* GPSPlannerPlan::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// UiNavigationEvent
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t UiNavigationEvent::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t UiNavigationEvent::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind UiNavigationEvent::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* UiNavigationEvent::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// LiveLocationData
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t LiveLocationData::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t LiveLocationData::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind LiveLocationData::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* LiveLocationData::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// LiveLocationData::Accuracy
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t LiveLocationData::Accuracy::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t LiveLocationData::Accuracy::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind LiveLocationData::Accuracy::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* LiveLocationData::Accuracy::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// OrbOdometry
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t OrbOdometry::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t OrbOdometry::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind OrbOdometry::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* OrbOdometry::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// OrbFeatures
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t OrbFeatures::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t OrbFeatures::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind OrbFeatures::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* OrbFeatures::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// OrbFeaturesSummary
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t OrbFeaturesSummary::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t OrbFeaturesSummary::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind OrbFeaturesSummary::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* OrbFeaturesSummary::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// OrbKeyFrame
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t OrbKeyFrame::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t OrbKeyFrame::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind OrbKeyFrame::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* OrbKeyFrame::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// KalmanOdometry
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t KalmanOdometry::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t KalmanOdometry::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind KalmanOdometry::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* KalmanOdometry::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// OrbObservation
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t OrbObservation::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t OrbObservation::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind OrbObservation::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* OrbObservation::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// CalibrationFeatures
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t CalibrationFeatures::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t CalibrationFeatures::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind CalibrationFeatures::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* CalibrationFeatures::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// NavStatus
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t NavStatus::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t NavStatus::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind NavStatus::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* NavStatus::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// NavStatus::Address
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t NavStatus::Address::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t NavStatus::Address::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind NavStatus::Address::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* NavStatus::Address::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// NavUpdate
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t NavUpdate::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t NavUpdate::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind NavUpdate::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* NavUpdate::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// NavUpdate::LatLng
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t NavUpdate::LatLng::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t NavUpdate::LatLng::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind NavUpdate::LatLng::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* NavUpdate::LatLng::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// NavUpdate::Segment
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t NavUpdate::Segment::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t NavUpdate::Segment::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind NavUpdate::Segment::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* NavUpdate::Segment::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// TrafficEvent
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t TrafficEvent::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t TrafficEvent::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind TrafficEvent::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* TrafficEvent::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// AndroidGnss
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t AndroidGnss::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t AndroidGnss::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind AndroidGnss::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* AndroidGnss::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// AndroidGnss::Measurements
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t AndroidGnss::Measurements::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t AndroidGnss::Measurements::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind AndroidGnss::Measurements::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* AndroidGnss::Measurements::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// AndroidGnss::Measurements::Clock
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t AndroidGnss::Measurements::Clock::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t AndroidGnss::Measurements::Clock::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind AndroidGnss::Measurements::Clock::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* AndroidGnss::Measurements::Clock::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// AndroidGnss::Measurements::Measurement
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t AndroidGnss::Measurements::Measurement::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t AndroidGnss::Measurements::Measurement::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind AndroidGnss::Measurements::Measurement::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* AndroidGnss::Measurements::Measurement::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// AndroidGnss::NavigationMessage
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t AndroidGnss::NavigationMessage::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t AndroidGnss::NavigationMessage::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind AndroidGnss::NavigationMessage::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* AndroidGnss::NavigationMessage::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// LidarPts
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t LidarPts::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t LidarPts::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind LidarPts::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* LidarPts::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
|
||||
|
||||
@@ -6,11 +6,15 @@
|
||||
#include <capnp/generated-header-support.h>
|
||||
#include <kj/windows-sanity.h>
|
||||
|
||||
#if CAPNP_VERSION != 8000
|
||||
#ifndef CAPNP_VERSION
|
||||
#error "CAPNP_VERSION is not defined, is capnp/generated-header-support.h missing?"
|
||||
#elif CAPNP_VERSION != 1000002
|
||||
#error "Version mismatch between generated code and library headers. You must use the same version of the Cap'n Proto compiler and library."
|
||||
#endif
|
||||
|
||||
|
||||
CAPNP_BEGIN_HEADER
|
||||
|
||||
namespace capnp {
|
||||
namespace schemas {
|
||||
|
||||
@@ -11407,3 +11411,5 @@ inline ::capnp::Orphan< ::capnp::Data> LidarPts::Builder::disownPkt() {
|
||||
|
||||
} // namespace
|
||||
|
||||
CAPNP_END_HEADER
|
||||
|
||||
|
||||
+1958
-1172
File diff suppressed because it is too large
Load Diff
+571
-227
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+52
-15
@@ -33,6 +33,7 @@ struct InitData {
|
||||
deviceType @3 :DeviceType;
|
||||
version @4 :Text;
|
||||
gitCommit @10 :Text;
|
||||
gitCommitDate @21 :Text;
|
||||
gitBranch @11 :Text;
|
||||
gitRemote @13 :Text;
|
||||
|
||||
@@ -130,8 +131,9 @@ struct InitData {
|
||||
|
||||
struct FrameData {
|
||||
frameId @0 :UInt32;
|
||||
encodeId @1 :UInt32; # DEPRECATED
|
||||
frameIdSensor @25 :UInt32;
|
||||
requestId @28 :UInt32;
|
||||
encodeId @1 :UInt32;
|
||||
|
||||
frameType @7 :FrameType;
|
||||
|
||||
@@ -166,6 +168,7 @@ struct FrameData {
|
||||
unknown @0;
|
||||
ar0231 @1;
|
||||
ox03c10 @2;
|
||||
os04c10 @3;
|
||||
}
|
||||
|
||||
frameLengthDEPRECATED @3 :Int32;
|
||||
@@ -297,6 +300,29 @@ struct GpsLocationData {
|
||||
}
|
||||
}
|
||||
|
||||
enum Desire {
|
||||
none @0;
|
||||
turnLeft @1;
|
||||
turnRight @2;
|
||||
laneChangeLeft @3;
|
||||
laneChangeRight @4;
|
||||
keepLeft @5;
|
||||
keepRight @6;
|
||||
}
|
||||
|
||||
enum LaneChangeState {
|
||||
off @0;
|
||||
preLaneChange @1;
|
||||
laneChangeStarting @2;
|
||||
laneChangeFinishing @3;
|
||||
}
|
||||
|
||||
enum LaneChangeDirection {
|
||||
none @0;
|
||||
left @1;
|
||||
right @2;
|
||||
}
|
||||
|
||||
struct CanData {
|
||||
address @0 :UInt32;
|
||||
busTime @1 :UInt16;
|
||||
@@ -331,7 +357,6 @@ struct DeviceState @0xa4d8b5af2aa492eb {
|
||||
cpuTempC @26 :List(Float32);
|
||||
gpuTempC @27 :List(Float32);
|
||||
memoryTempC @28 :Float32;
|
||||
ambientTempC @30 :Float32;
|
||||
nvmeTempC @35 :List(Float32);
|
||||
modemTempC @36 :List(Float32);
|
||||
pmicTempC @39 :List(Float32);
|
||||
@@ -404,11 +429,11 @@ struct DeviceState @0xa4d8b5af2aa492eb {
|
||||
chargingErrorDEPRECATED @17 :Bool;
|
||||
chargingDisabledDEPRECATED @18 :Bool;
|
||||
usbOnlineDEPRECATED @12 :Bool;
|
||||
ambientTempCDEPRECATED @30 :Float32;
|
||||
}
|
||||
|
||||
struct PandaState @0xa7649e2575e4591e {
|
||||
ignitionLine @2 :Bool;
|
||||
gasInterceptorDetected @4 :Bool;
|
||||
rxBufferOverflow @7 :UInt32;
|
||||
txBufferOverflow @8 :UInt32;
|
||||
gmlanSendErrs @9 :UInt32;
|
||||
@@ -494,6 +519,7 @@ struct PandaState @0xa7649e2575e4591e {
|
||||
redPanda @7;
|
||||
redPandaV2 @8;
|
||||
tres @9;
|
||||
cuatro @10;
|
||||
}
|
||||
|
||||
enum HarnessStatus {
|
||||
@@ -541,6 +567,7 @@ struct PandaState @0xa7649e2575e4591e {
|
||||
}
|
||||
}
|
||||
|
||||
gasInterceptorDetectedDEPRECATED @4 :Bool;
|
||||
startedSignalDetectedDEPRECATED @5 :Bool;
|
||||
hasGpsDEPRECATED @6 :Bool;
|
||||
fanSpeedRpmDEPRECATED @11 :UInt16;
|
||||
@@ -666,7 +693,6 @@ struct ControlsState @0x97ff69c53601abf1 {
|
||||
aTarget @35 :Float32;
|
||||
curvature @37 :Float32; # path curvature from vehicle model
|
||||
desiredCurvature @61 :Float32; # lag adjusted curvatures used by lateral controllers
|
||||
desiredCurvatureRate @62 :Float32;
|
||||
forceDecel @51 :Bool;
|
||||
|
||||
# UI alerts
|
||||
@@ -688,8 +714,8 @@ struct ControlsState @0x97ff69c53601abf1 {
|
||||
angleState @58 :LateralAngleState;
|
||||
debugState @59 :LateralDebugState;
|
||||
torqueState @60 :LateralTorqueState;
|
||||
curvatureState @65 :LateralCurvatureState;
|
||||
|
||||
curvatureStateDEPRECATED @65 :LateralCurvatureState;
|
||||
lqrStateDEPRECATED @55 :LateralLQRState;
|
||||
}
|
||||
|
||||
@@ -824,6 +850,7 @@ struct ControlsState @0x97ff69c53601abf1 {
|
||||
steerOverrideDEPRECATED @20 :Bool;
|
||||
steeringAngleDesiredDegDEPRECATED @29 :Float32;
|
||||
canMonoTimesDEPRECATED @21 :List(UInt64);
|
||||
desiredCurvatureRateDEPRECATED @62 :Float32;
|
||||
}
|
||||
|
||||
# All SI units and in device frame
|
||||
@@ -875,7 +902,8 @@ struct ModelDataV2 {
|
||||
locationMonoTime @24 :UInt64;
|
||||
|
||||
# e2e lateral planner
|
||||
lateralPlannerSolution @25: LateralPlannerSolution;
|
||||
lateralPlannerSolutionDEPRECATED @25: LateralPlannerSolution;
|
||||
action @26: Action;
|
||||
|
||||
struct LeadDataV2 {
|
||||
prob @0 :Float32; # probability that car is your lead at time t
|
||||
@@ -913,6 +941,9 @@ struct ModelDataV2 {
|
||||
desireState @5 :List(Float32);
|
||||
disengagePredictions @6 :DisengagePredictions;
|
||||
hardBrakePredicted @7 :Bool;
|
||||
laneChangeState @8 :LaneChangeState;
|
||||
laneChangeDirection @9 :LaneChangeDirection;
|
||||
|
||||
|
||||
# deprecated
|
||||
brakeDisengageProbDEPRECATED @2 :Float32;
|
||||
@@ -954,6 +985,9 @@ struct ModelDataV2 {
|
||||
yawRateStd @7 :List(Float32);
|
||||
}
|
||||
|
||||
struct Action {
|
||||
desiredCurvature @0 :Float32;
|
||||
}
|
||||
}
|
||||
|
||||
struct EncodeIndex {
|
||||
@@ -1844,11 +1878,12 @@ struct QcomGnss @0xde94674b07ae51c1 {
|
||||
}
|
||||
|
||||
struct Clocks {
|
||||
bootTimeNanos @0 :UInt64;
|
||||
monotonicNanos @1 :UInt64;
|
||||
monotonicRawNanos @2 :UInt64;
|
||||
wallTimeNanos @3 :UInt64;
|
||||
modemUptimeMillis @4 :UInt64;
|
||||
wallTimeNanos @3 :UInt64; # unix epoch time
|
||||
|
||||
bootTimeNanosDEPRECATED @0 :UInt64;
|
||||
monotonicNanosDEPRECATED @1 :UInt64;
|
||||
monotonicRawNanosDEPRECATD @2 :UInt64;
|
||||
modemUptimeMillisDEPRECATED @4 :UInt64;
|
||||
}
|
||||
|
||||
struct LiveMpcData {
|
||||
@@ -2167,6 +2202,8 @@ struct EncodeData {
|
||||
data @1 :Data;
|
||||
header @2 :Data;
|
||||
unixTimestampNanos @3 :UInt64;
|
||||
width @4 :UInt32;
|
||||
height @5 :UInt32;
|
||||
}
|
||||
|
||||
struct UserFlag {
|
||||
@@ -2214,7 +2251,6 @@ struct Event {
|
||||
carState @22 :Car.CarState;
|
||||
carControl @23 :Car.CarControl;
|
||||
longitudinalPlan @24 :LongitudinalPlan;
|
||||
lateralPlan @64 :LateralPlan;
|
||||
uiPlan @106 :UiPlan;
|
||||
ubloxGnss @34 :UbloxGnss;
|
||||
ubloxRaw @39 :Data;
|
||||
@@ -2226,7 +2262,7 @@ struct Event {
|
||||
liveTorqueParameters @94 :LiveTorqueParametersData;
|
||||
cameraOdometry @63 :CameraOdometry;
|
||||
thumbnail @66: Thumbnail;
|
||||
carEvents @68: List(Car.CarEvent);
|
||||
onroadEvents @68: List(Car.CarEvent);
|
||||
carParams @69: Car.CarParams;
|
||||
driverMonitoringState @71: DriverMonitoringState;
|
||||
liveLocationKalman @72 :LiveLocationKalman;
|
||||
@@ -2288,11 +2324,11 @@ struct Event {
|
||||
# *********** Custom: reserved for forks ***********
|
||||
controlsStateSP @107 :Custom.ControlsStateSP;
|
||||
longitudinalPlanSP @108 :Custom.LongitudinalPlanSP;
|
||||
lateralPlanSP @109 :Custom.LateralPlanSP;
|
||||
lateralPlanSPDEPRECATED @109 :Custom.LateralPlanSP;
|
||||
driverMonitoringStateSP @110 :Custom.DriverMonitoringStateSP;
|
||||
liveMapDataSP @111 :Custom.LiveMapDataSP;
|
||||
e2eLongStateSP @112 :Custom.E2eLongStateSP;
|
||||
customReserved6 @113 :Custom.CustomReserved6;
|
||||
modelV2SP @113 :Custom.ModelDataV2SP;
|
||||
customReserved7 @114 :Custom.CustomReserved7;
|
||||
customReserved8 @115 :Custom.CustomReserved8;
|
||||
customReserved9 @116 :Custom.CustomReserved9;
|
||||
@@ -2335,5 +2371,6 @@ struct Event {
|
||||
pandaStateDEPRECATED @12 :PandaState;
|
||||
driverStateDEPRECATED @59 :DriverStateDEPRECATED;
|
||||
sensorEventsDEPRECATED @11 :List(SensorEventData);
|
||||
lateralPlanDEPRECATED @64 :LateralPlan;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ assert delete_fake_prefix
|
||||
assert wait_for_one_event
|
||||
|
||||
NO_TRAVERSAL_LIMIT = 2**64-1
|
||||
AVG_FREQ_HISTORY = 100
|
||||
|
||||
context = Context()
|
||||
|
||||
@@ -41,10 +40,13 @@ def log_from_bytes(dat: bytes) -> capnp.lib.capnp._DynamicStructReader:
|
||||
return msg
|
||||
|
||||
|
||||
def new_message(service: Optional[str] = None, size: Optional[int] = None) -> capnp.lib.capnp._DynamicStructBuilder:
|
||||
dat = log.Event.new_message()
|
||||
dat.logMonoTime = int(time.monotonic() * 1e9)
|
||||
dat.valid = True
|
||||
def new_message(service: Optional[str], size: Optional[int] = None, **kwargs) -> capnp.lib.capnp._DynamicStructBuilder:
|
||||
args = {
|
||||
'valid': False,
|
||||
'logMonoTime': int(time.monotonic() * 1e9),
|
||||
**kwargs
|
||||
}
|
||||
dat = log.Event.new_message(**args)
|
||||
if service is not None:
|
||||
if size is None:
|
||||
dat.init(service)
|
||||
@@ -114,14 +116,14 @@ def recv_sock(sock: SubSocket, wait: bool = False) -> Optional[capnp.lib.capnp._
|
||||
|
||||
while 1:
|
||||
if wait and dat is None:
|
||||
rcv = sock.receive()
|
||||
recv = sock.receive()
|
||||
else:
|
||||
rcv = sock.receive(non_blocking=True)
|
||||
recv = sock.receive(non_blocking=True)
|
||||
|
||||
if rcv is None: # Timeout hit
|
||||
if recv is None: # Timeout hit
|
||||
break
|
||||
|
||||
dat = rcv
|
||||
dat = recv
|
||||
|
||||
if dat is not None:
|
||||
dat = log_from_bytes(dat)
|
||||
@@ -152,53 +154,76 @@ def recv_one_retry(sock: SubSocket) -> capnp.lib.capnp._DynamicStructReader:
|
||||
|
||||
|
||||
class SubMaster:
|
||||
def __init__(self, services: List[str], poll: Optional[List[str]] = None,
|
||||
def __init__(self, services: List[str], poll: Optional[str] = None,
|
||||
ignore_alive: Optional[List[str]] = None, ignore_avg_freq: Optional[List[str]] = None,
|
||||
addr: str = "127.0.0.1"):
|
||||
ignore_valid: Optional[List[str]] = None, addr: str = "127.0.0.1", frequency: Optional[float] = None):
|
||||
self.frame = -1
|
||||
self.seen = {s: False for s in services}
|
||||
self.updated = {s: False for s in services}
|
||||
self.rcv_time = {s: 0. for s in services}
|
||||
self.rcv_frame = {s: 0 for s in services}
|
||||
self.recv_time = {s: 0. for s in services}
|
||||
self.recv_frame = {s: 0 for s in services}
|
||||
self.alive = {s: False for s in services}
|
||||
self.freq_ok = {s: False for s in services}
|
||||
self.recv_dts: Dict[str, Deque[float]] = {s: deque(maxlen=AVG_FREQ_HISTORY) for s in services}
|
||||
self.recv_dts: Dict[str, Deque[float]] = {}
|
||||
self.sock = {}
|
||||
self.freq = {}
|
||||
self.data = {}
|
||||
self.valid = {}
|
||||
self.logMonoTime = {}
|
||||
|
||||
self.max_freq = {}
|
||||
self.min_freq = {}
|
||||
|
||||
self.poller = Poller()
|
||||
self.non_polled_services = [s for s in services if poll is not None and
|
||||
len(poll) and s not in poll]
|
||||
polled_services = set([poll, ] if poll is not None else services)
|
||||
self.non_polled_services = set(services) - polled_services
|
||||
|
||||
self.ignore_average_freq = [] if ignore_avg_freq is None else ignore_avg_freq
|
||||
self.ignore_alive = [] if ignore_alive is None else ignore_alive
|
||||
self.simulation = bool(int(os.getenv("SIMULATION", "0")))
|
||||
self.ignore_valid = [] if ignore_valid is None else ignore_valid
|
||||
if bool(int(os.getenv("SIMULATION", "0"))):
|
||||
self.ignore_alive = services
|
||||
self.ignore_average_freq = services
|
||||
|
||||
# if freq and poll aren't specified, assume the max to be conservative
|
||||
assert frequency is None or poll is None, "Do not specify 'frequency' - frequency of the polled service will be used."
|
||||
self.update_freq = frequency or max([SERVICE_LIST[s].frequency for s in polled_services])
|
||||
|
||||
for s in services:
|
||||
if addr is not None:
|
||||
p = self.poller if s not in self.non_polled_services else None
|
||||
self.sock[s] = sub_sock(s, poller=p, addr=addr, conflate=True)
|
||||
self.freq[s] = SERVICE_LIST[s].frequency
|
||||
p = self.poller if s not in self.non_polled_services else None
|
||||
self.sock[s] = sub_sock(s, poller=p, addr=addr, conflate=True)
|
||||
|
||||
try:
|
||||
data = new_message(s)
|
||||
except capnp.lib.capnp.KjException: # pylint: disable=c-extension-no-member
|
||||
except capnp.lib.capnp.KjException:
|
||||
data = new_message(s, 0) # lists
|
||||
|
||||
self.data[s] = getattr(data, s)
|
||||
self.data[s] = getattr(data.as_reader(), s)
|
||||
self.logMonoTime[s] = 0
|
||||
self.valid[s] = data.valid
|
||||
self.valid[s] = True # FIXME: this should default to False
|
||||
|
||||
freq = max(min([SERVICE_LIST[s].frequency, self.update_freq]), 1.)
|
||||
if s == poll:
|
||||
max_freq = freq
|
||||
min_freq = freq
|
||||
else:
|
||||
max_freq = min(freq, self.update_freq)
|
||||
if SERVICE_LIST[s].frequency >= 2*self.update_freq:
|
||||
min_freq = self.update_freq
|
||||
elif self.update_freq >= 2*SERVICE_LIST[s].frequency:
|
||||
min_freq = freq
|
||||
else:
|
||||
min_freq = min(freq, freq / 2.)
|
||||
self.max_freq[s] = max_freq*1.2
|
||||
self.min_freq[s] = min_freq*0.8
|
||||
self.recv_dts[s] = deque(maxlen=int(10*freq))
|
||||
|
||||
def __getitem__(self, s: str) -> capnp.lib.capnp._DynamicStructReader:
|
||||
return self.data[s]
|
||||
|
||||
def _check_avg_freq(self, s):
|
||||
return self.rcv_time[s] > 1e-5 and self.freq[s] > 1e-5 and (s not in self.non_polled_services) \
|
||||
and (s not in self.ignore_average_freq)
|
||||
def _check_avg_freq(self, s: str) -> bool:
|
||||
return SERVICE_LIST[s].frequency > 0.99 and (s not in self.ignore_average_freq) and (s not in self.ignore_alive)
|
||||
|
||||
def update(self, timeout: int = 1000) -> None:
|
||||
def update(self, timeout: int = 100) -> None:
|
||||
msgs = []
|
||||
for sock in self.poller.poll(timeout):
|
||||
msgs.append(recv_one_or_none(sock))
|
||||
@@ -216,64 +241,57 @@ class SubMaster:
|
||||
continue
|
||||
|
||||
s = msg.which()
|
||||
self.seen[s] = True
|
||||
self.updated[s] = True
|
||||
|
||||
if self._check_avg_freq(s):
|
||||
self.recv_dts[s].append(cur_time - self.rcv_time[s])
|
||||
|
||||
self.rcv_time[s] = cur_time
|
||||
self.rcv_frame[s] = self.frame
|
||||
if self.recv_time[s] > 1e-5:
|
||||
self.recv_dts[s].append(cur_time - self.recv_time[s])
|
||||
self.recv_time[s] = cur_time
|
||||
self.recv_frame[s] = self.frame
|
||||
self.data[s] = getattr(msg, s)
|
||||
self.logMonoTime[s] = msg.logMonoTime
|
||||
self.valid[s] = msg.valid
|
||||
|
||||
if self.simulation:
|
||||
for s in self.data:
|
||||
if SERVICE_LIST[s].frequency > 1e-5:
|
||||
# alive if delay is within 10x the expected frequency
|
||||
self.alive[s] = (cur_time - self.recv_time[s]) < (10. / SERVICE_LIST[s].frequency)
|
||||
|
||||
# check average frequency; slow to fall, quick to recover
|
||||
dts = self.recv_dts[s]
|
||||
assert dts.maxlen is not None
|
||||
recent_dts = list(dts)[-int(dts.maxlen / 10):]
|
||||
try:
|
||||
avg_freq = 1 / (sum(dts) / len(dts))
|
||||
avg_freq_recent = 1 / (sum(recent_dts) / len(recent_dts))
|
||||
except ZeroDivisionError:
|
||||
avg_freq = 0
|
||||
avg_freq_recent = 0
|
||||
|
||||
avg_freq_ok = self.min_freq[s] <= avg_freq <= self.max_freq[s]
|
||||
recent_freq_ok = self.min_freq[s] <= avg_freq_recent <= self.max_freq[s]
|
||||
self.freq_ok[s] = avg_freq_ok or recent_freq_ok
|
||||
else:
|
||||
self.freq_ok[s] = True
|
||||
self.alive[s] = True
|
||||
|
||||
if not self.simulation:
|
||||
for s in self.data:
|
||||
# arbitrary small number to avoid float comparison. If freq is 0, we can skip the check
|
||||
if self.freq[s] > 1e-5:
|
||||
# alive if delay is within 10x the expected frequency
|
||||
self.alive[s] = (cur_time - self.rcv_time[s]) < (10. / self.freq[s])
|
||||
|
||||
# TODO: check if update frequency is high enough to not drop messages
|
||||
# freq_ok if average frequency is higher than 90% of expected frequency
|
||||
if self._check_avg_freq(s):
|
||||
if len(self.recv_dts[s]) > 0:
|
||||
avg_dt = sum(self.recv_dts[s]) / len(self.recv_dts[s])
|
||||
expected_dt = 1 / (self.freq[s] * 0.90)
|
||||
self.freq_ok[s] = (avg_dt < expected_dt)
|
||||
else:
|
||||
self.freq_ok[s] = False
|
||||
else:
|
||||
self.freq_ok[s] = True
|
||||
else:
|
||||
self.freq_ok[s] = True
|
||||
self.alive[s] = True
|
||||
|
||||
def all_alive(self, service_list=None) -> bool:
|
||||
if service_list is None: # check all
|
||||
service_list = self.alive.keys()
|
||||
def all_alive(self, service_list: Optional[List[str]] = None) -> bool:
|
||||
if service_list is None:
|
||||
service_list = list(self.sock.keys())
|
||||
return all(self.alive[s] for s in service_list if s not in self.ignore_alive)
|
||||
|
||||
def all_freq_ok(self, service_list=None) -> bool:
|
||||
if service_list is None: # check all
|
||||
service_list = self.alive.keys()
|
||||
return all(self.freq_ok[s] for s in service_list if s not in self.ignore_alive)
|
||||
def all_freq_ok(self, service_list: Optional[List[str]] = None) -> bool:
|
||||
if service_list is None:
|
||||
service_list = list(self.sock.keys())
|
||||
return all(self.freq_ok[s] for s in service_list if self._check_avg_freq(s))
|
||||
|
||||
def all_valid(self, service_list=None) -> bool:
|
||||
if service_list is None: # check all
|
||||
service_list = self.valid.keys()
|
||||
return all(self.valid[s] for s in service_list)
|
||||
def all_valid(self, service_list: Optional[List[str]] = None) -> bool:
|
||||
if service_list is None:
|
||||
service_list = list(self.sock.keys())
|
||||
return all(self.valid[s] for s in service_list if s not in self.ignore_valid)
|
||||
|
||||
def all_checks(self, service_list=None) -> bool:
|
||||
if service_list is None: # check all
|
||||
service_list = self.alive.keys()
|
||||
return self.all_alive(service_list=service_list) \
|
||||
and self.all_freq_ok(service_list=service_list) \
|
||||
and self.all_valid(service_list=service_list)
|
||||
def all_checks(self, service_list: Optional[List[str]] = None) -> bool:
|
||||
return self.all_alive(service_list) and self.all_freq_ok(service_list) and self.all_valid(service_list)
|
||||
|
||||
|
||||
class PubMaster:
|
||||
|
||||
Binary file not shown.
+1679
-450
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+20
-19
@@ -37,14 +37,14 @@ static std::map<std::string, service> services = {
|
||||
{ "ubloxGnss", {"ubloxGnss", 8031, true, 10, -1}},
|
||||
{ "qcomGnss", {"qcomGnss", 8032, true, 2, -1}},
|
||||
{ "gnssMeasurements", {"gnssMeasurements", 8033, true, 10, 10}},
|
||||
{ "clocks", {"clocks", 8034, true, 1, 1}},
|
||||
{ "clocks", {"clocks", 8034, true, 0, 1}},
|
||||
{ "ubloxRaw", {"ubloxRaw", 8035, true, 20, -1}},
|
||||
{ "liveLocationKalman", {"liveLocationKalman", 8036, true, 20, 5}},
|
||||
{ "liveParameters", {"liveParameters", 8037, true, 20, 5}},
|
||||
{ "cameraOdometry", {"cameraOdometry", 8038, true, 20, 5}},
|
||||
{ "lateralPlan", {"lateralPlan", 8039, true, 20, 5}},
|
||||
{ "lateralPlanDEPRECATED", {"lateralPlanDEPRECATED", 8039, true, 20, 5}},
|
||||
{ "thumbnail", {"thumbnail", 8040, true, 0, 1}},
|
||||
{ "carEvents", {"carEvents", 8041, true, 1, 1}},
|
||||
{ "onroadEvents", {"onroadEvents", 8041, true, 1, 1}},
|
||||
{ "carParams", {"carParams", 8042, true, 0, 1}},
|
||||
{ "roadCameraState", {"roadCameraState", 8043, true, 20, 20}},
|
||||
{ "driverCameraState", {"driverCameraState", 8044, true, 20, 20}},
|
||||
@@ -67,25 +67,26 @@ static std::map<std::string, service> services = {
|
||||
{ "microphone", {"microphone", 8061, true, 10, 10}},
|
||||
{ "controlsStateSP", {"controlsStateSP", 8062, true, 100, 10}},
|
||||
{ "longitudinalPlanSP", {"longitudinalPlanSP", 8063, true, 20, 5}},
|
||||
{ "lateralPlanSP", {"lateralPlanSP", 8064, true, 20, 5}},
|
||||
{ "lateralPlanSPDEPRECATED", {"lateralPlanSPDEPRECATED", 8064, true, 20, 5}},
|
||||
{ "driverMonitoringStateSP", {"driverMonitoringStateSP", 8065, true, 20, 10}},
|
||||
{ "liveMapDataSP", {"liveMapDataSP", 8066, true, 0, -1}},
|
||||
{ "e2eLongStateSP", {"e2eLongStateSP", 8067, true, 0, -1}},
|
||||
{ "uiDebug", {"uiDebug", 8068, true, 0, 1}},
|
||||
{ "testJoystick", {"testJoystick", 8069, true, 0, -1}},
|
||||
{ "roadEncodeData", {"roadEncodeData", 8070, false, 20, -1}},
|
||||
{ "driverEncodeData", {"driverEncodeData", 8071, false, 20, -1}},
|
||||
{ "wideRoadEncodeData", {"wideRoadEncodeData", 8072, false, 20, -1}},
|
||||
{ "qRoadEncodeData", {"qRoadEncodeData", 8073, false, 20, -1}},
|
||||
{ "livestreamWideRoadEncodeIdx", {"livestreamWideRoadEncodeIdx", 8074, false, 20, -1}},
|
||||
{ "livestreamRoadEncodeIdx", {"livestreamRoadEncodeIdx", 8075, false, 20, -1}},
|
||||
{ "livestreamDriverEncodeIdx", {"livestreamDriverEncodeIdx", 8076, false, 20, -1}},
|
||||
{ "livestreamWideRoadEncodeData", {"livestreamWideRoadEncodeData", 8077, false, 20, -1}},
|
||||
{ "livestreamRoadEncodeData", {"livestreamRoadEncodeData", 8078, false, 20, -1}},
|
||||
{ "livestreamDriverEncodeData", {"livestreamDriverEncodeData", 8079, false, 20, -1}},
|
||||
{ "customReservedRawData0", {"customReservedRawData0", 8080, true, 0, -1}},
|
||||
{ "customReservedRawData1", {"customReservedRawData1", 8081, true, 0, -1}},
|
||||
{ "customReservedRawData2", {"customReservedRawData2", 8082, true, 0, -1}},
|
||||
{ "modelV2SP", {"modelV2SP", 8068, true, 20, 40}},
|
||||
{ "uiDebug", {"uiDebug", 8069, true, 0, 1}},
|
||||
{ "testJoystick", {"testJoystick", 8070, true, 0, -1}},
|
||||
{ "roadEncodeData", {"roadEncodeData", 8071, false, 20, -1}},
|
||||
{ "driverEncodeData", {"driverEncodeData", 8072, false, 20, -1}},
|
||||
{ "wideRoadEncodeData", {"wideRoadEncodeData", 8073, false, 20, -1}},
|
||||
{ "qRoadEncodeData", {"qRoadEncodeData", 8074, false, 20, -1}},
|
||||
{ "livestreamWideRoadEncodeIdx", {"livestreamWideRoadEncodeIdx", 8075, false, 20, -1}},
|
||||
{ "livestreamRoadEncodeIdx", {"livestreamRoadEncodeIdx", 8076, false, 20, -1}},
|
||||
{ "livestreamDriverEncodeIdx", {"livestreamDriverEncodeIdx", 8077, false, 20, -1}},
|
||||
{ "livestreamWideRoadEncodeData", {"livestreamWideRoadEncodeData", 8078, false, 20, -1}},
|
||||
{ "livestreamRoadEncodeData", {"livestreamRoadEncodeData", 8079, false, 20, -1}},
|
||||
{ "livestreamDriverEncodeData", {"livestreamDriverEncodeData", 8080, false, 20, -1}},
|
||||
{ "customReservedRawData0", {"customReservedRawData0", 8081, true, 0, -1}},
|
||||
{ "customReservedRawData1", {"customReservedRawData1", 8082, true, 0, -1}},
|
||||
{ "customReservedRawData2", {"customReservedRawData2", 8083, true, 0, -1}},
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
+5
-4
@@ -53,14 +53,14 @@ services: dict[str, tuple] = {
|
||||
"ubloxGnss": (True, 10.),
|
||||
"qcomGnss": (True, 2.),
|
||||
"gnssMeasurements": (True, 10., 10),
|
||||
"clocks": (True, 1., 1),
|
||||
"clocks": (True, 0.1, 1),
|
||||
"ubloxRaw": (True, 20.),
|
||||
"liveLocationKalman": (True, 20., 5),
|
||||
"liveParameters": (True, 20., 5),
|
||||
"cameraOdometry": (True, 20., 5),
|
||||
"lateralPlan": (True, 20., 5),
|
||||
"lateralPlanDEPRECATED": (True, 20., 5),
|
||||
"thumbnail": (True, 0.2, 1),
|
||||
"carEvents": (True, 1., 1),
|
||||
"onroadEvents": (True, 1., 1),
|
||||
"carParams": (True, 0.02, 1),
|
||||
"roadCameraState": (True, 20., 20),
|
||||
"driverCameraState": (True, 20., 20),
|
||||
@@ -84,10 +84,11 @@ services: dict[str, tuple] = {
|
||||
|
||||
"controlsStateSP": (True, 100., 10),
|
||||
"longitudinalPlanSP": (True, 20., 5),
|
||||
"lateralPlanSP": (True, 20., 5),
|
||||
"lateralPlanSPDEPRECATED": (True, 20., 5),
|
||||
"driverMonitoringStateSP": (True, 20., 10),
|
||||
"liveMapDataSP": (True, 0.),
|
||||
"e2eLongStateSP": (True, 0.),
|
||||
"modelV2SP": (True, 20., 40),
|
||||
|
||||
# debug
|
||||
"uiDebug": (True, 0., 1),
|
||||
|
||||
@@ -2,11 +2,8 @@
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "cereal/messaging/messaging.h"
|
||||
#include "cereal/visionipc/visionipc.h"
|
||||
#include "cereal/visionipc/visionbuf.h"
|
||||
|
||||
class VisionIpcClient {
|
||||
|
||||
+3205
-1382
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -6,10 +6,10 @@
|
||||
#include <map>
|
||||
|
||||
#include "cereal/messaging/messaging.h"
|
||||
#include "cereal/visionipc/visionipc.h"
|
||||
#include "cereal/visionipc/visionbuf.h"
|
||||
|
||||
std::string get_endpoint_name(std::string name, VisionStreamType type);
|
||||
std::string get_ipc_path(const std::string &name);
|
||||
|
||||
class VisionIpcServer {
|
||||
private:
|
||||
|
||||
+4
-6
@@ -2,7 +2,6 @@ Import('env', 'envCython', 'arch')
|
||||
|
||||
common_libs = [
|
||||
'params.cc',
|
||||
'statlog.cc',
|
||||
'swaglog.cc',
|
||||
'util.cc',
|
||||
'i2c.cc',
|
||||
@@ -24,18 +23,17 @@ Export('_common', '_gpucommon')
|
||||
|
||||
if GetOption('extras'):
|
||||
env.Program('tests/test_common',
|
||||
['tests/test_runner.cc', 'tests/test_util.cc', 'tests/test_swaglog.cc', 'tests/test_ratekeeper.cc'],
|
||||
['tests/test_runner.cc', 'tests/test_params.cc', 'tests/test_util.cc', 'tests/test_swaglog.cc'],
|
||||
LIBS=[_common, 'json11', 'zmq', 'pthread'])
|
||||
|
||||
# Cython bindings
|
||||
params_python = envCython.Program('params_pyx.so', 'params_pyx.pyx', LIBS=envCython['LIBS'] + [_common, 'zmq', 'json11'])
|
||||
|
||||
SConscript([
|
||||
'kalman/SConscript',
|
||||
'transformations/SConscript'
|
||||
'transformations/SConscript',
|
||||
])
|
||||
|
||||
Import('simple_kalman_python', 'transformations_python')
|
||||
common_python = [params_python, simple_kalman_python, transformations_python]
|
||||
Import('transformations_python')
|
||||
common_python = [params_python, transformations_python]
|
||||
|
||||
Export('common_python')
|
||||
|
||||
@@ -2,7 +2,7 @@ import jwt
|
||||
import os
|
||||
import requests
|
||||
from datetime import datetime, timedelta
|
||||
from openpilot.common.basedir import PERSIST
|
||||
from openpilot.system.hardware.hw import Paths
|
||||
from openpilot.system.version import get_version
|
||||
|
||||
API_HOST = os.getenv('API_HOST', 'https://api.commadotai.com')
|
||||
@@ -10,7 +10,7 @@ API_HOST = os.getenv('API_HOST', 'https://api.commadotai.com')
|
||||
class Api():
|
||||
def __init__(self, dongle_id):
|
||||
self.dongle_id = dongle_id
|
||||
with open(PERSIST+'/comma/id_rsa') as f:
|
||||
with open(Paths.persist_root()+'/comma/id_rsa') as f:
|
||||
self.private_key = f.read()
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
|
||||
@@ -1,11 +1,4 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from openpilot.system.hardware import PC
|
||||
|
||||
BASEDIR = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), "../"))
|
||||
|
||||
if PC:
|
||||
PERSIST = os.path.join(str(Path.home()), ".comma", "persist")
|
||||
else:
|
||||
PERSIST = "/persist"
|
||||
|
||||
+1
-48
@@ -1,55 +1,8 @@
|
||||
import os
|
||||
import sys
|
||||
import fcntl
|
||||
import hashlib
|
||||
import platform
|
||||
from cffi import FFI
|
||||
|
||||
|
||||
def suffix():
|
||||
if platform.system() == "Darwin":
|
||||
return ".dylib"
|
||||
else:
|
||||
return ".so"
|
||||
|
||||
def ffi_wrap(name, c_code, c_header, tmpdir="/tmp/ccache", cflags="", libraries=None):
|
||||
if libraries is None:
|
||||
libraries = []
|
||||
|
||||
cache = name + "_" + hashlib.sha1(c_code.encode('utf-8')).hexdigest()
|
||||
try:
|
||||
os.mkdir(tmpdir)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
fd = os.open(tmpdir, 0)
|
||||
fcntl.flock(fd, fcntl.LOCK_EX)
|
||||
try:
|
||||
sys.path.append(tmpdir)
|
||||
try:
|
||||
mod = __import__(cache)
|
||||
except Exception:
|
||||
print(f"cache miss {cache}")
|
||||
compile_code(cache, c_code, c_header, tmpdir, cflags, libraries)
|
||||
mod = __import__(cache)
|
||||
finally:
|
||||
os.close(fd)
|
||||
|
||||
return mod.ffi, mod.lib
|
||||
|
||||
|
||||
def compile_code(name, c_code, c_header, directory, cflags="", libraries=None):
|
||||
if libraries is None:
|
||||
libraries = []
|
||||
|
||||
ffibuilder = FFI()
|
||||
ffibuilder.set_source(name, c_code, source_extension='.cpp', libraries=libraries)
|
||||
ffibuilder.cdef(c_header)
|
||||
os.environ['OPT'] = "-fwrapv -O2 -DNDEBUG -std=c++1z"
|
||||
os.environ['CFLAGS'] = cflags
|
||||
ffibuilder.compile(verbose=True, debug=False, tmpdir=directory)
|
||||
|
||||
|
||||
def wrap_compiled(name, directory):
|
||||
sys.path.append(directory)
|
||||
mod = __import__(name)
|
||||
return mod.ffi, mod.lib
|
||||
|
||||
+13
-74
@@ -1,60 +1,7 @@
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
from atomicwrites import AtomicWriter
|
||||
|
||||
|
||||
def mkdirs_exists_ok(path):
|
||||
if path.startswith(('http://', 'https://')):
|
||||
raise ValueError('URL path')
|
||||
try:
|
||||
os.makedirs(path)
|
||||
except OSError:
|
||||
if not os.path.isdir(path):
|
||||
raise
|
||||
|
||||
|
||||
def rm_not_exists_ok(path):
|
||||
try:
|
||||
os.remove(path)
|
||||
except OSError:
|
||||
if os.path.exists(path):
|
||||
raise
|
||||
|
||||
|
||||
def rm_tree_or_link(path):
|
||||
if os.path.islink(path):
|
||||
os.unlink(path)
|
||||
elif os.path.isdir(path):
|
||||
shutil.rmtree(path)
|
||||
|
||||
|
||||
def get_tmpdir_on_same_filesystem(path):
|
||||
normpath = os.path.normpath(path)
|
||||
parts = normpath.split("/")
|
||||
if len(parts) > 1 and parts[1] == "scratch":
|
||||
return "/scratch/tmp"
|
||||
elif len(parts) > 2 and parts[2] == "runner":
|
||||
return f"/{parts[1]}/runner/tmp"
|
||||
return "/tmp"
|
||||
|
||||
|
||||
class NamedTemporaryDir():
|
||||
def __init__(self, temp_dir=None):
|
||||
self._path = tempfile.mkdtemp(dir=temp_dir)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._path
|
||||
|
||||
def close(self):
|
||||
shutil.rmtree(self._path)
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
self.close()
|
||||
import contextlib
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class CallbackReader:
|
||||
@@ -76,24 +23,16 @@ class CallbackReader:
|
||||
return chunk
|
||||
|
||||
|
||||
def _get_fileobject_func(writer, temp_dir):
|
||||
def _get_fileobject():
|
||||
return writer.get_fileobject(dir=temp_dir)
|
||||
return _get_fileobject
|
||||
@contextlib.contextmanager
|
||||
def atomic_write_in_dir(path: str, mode: str = 'w', buffering: int = -1, encoding: Optional[str] = None, newline: Optional[str] = None,
|
||||
overwrite: bool = False):
|
||||
"""Write to a file atomically using a temporary file in the same directory as the destination file."""
|
||||
dir_name = os.path.dirname(path)
|
||||
|
||||
def atomic_write_on_fs_tmp(path, **kwargs):
|
||||
"""Creates an atomic writer using a temporary file in a temporary directory
|
||||
on the same filesystem as path.
|
||||
"""
|
||||
# TODO(mgraczyk): This use of AtomicWriter relies on implementation details to set the temp
|
||||
# directory.
|
||||
writer = AtomicWriter(path, **kwargs)
|
||||
return writer._open(_get_fileobject_func(writer, get_tmpdir_on_same_filesystem(path)))
|
||||
if not overwrite and os.path.exists(path):
|
||||
raise FileExistsError(f"File '{path}' already exists. To overwrite it, set 'overwrite' to True.")
|
||||
|
||||
|
||||
def atomic_write_in_dir(path, **kwargs):
|
||||
"""Creates an atomic writer using a temporary file in the same directory
|
||||
as the destination file.
|
||||
"""
|
||||
writer = AtomicWriter(path, **kwargs)
|
||||
return writer._open(_get_fileobject_func(writer, os.path.dirname(path)))
|
||||
with tempfile.NamedTemporaryFile(mode=mode, buffering=buffering, encoding=encoding, newline=newline, dir=dir_name, delete=False) as tmp_file:
|
||||
yield tmp_file
|
||||
tmp_file_name = tmp_file.name
|
||||
os.replace(tmp_file_name, path)
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
simple_kalman_impl.c
|
||||
@@ -1,5 +0,0 @@
|
||||
Import('envCython')
|
||||
|
||||
simple_kalman_python = envCython.Program('simple_kalman_impl.so', 'simple_kalman_impl.pyx')
|
||||
|
||||
Export('simple_kalman_python')
|
||||
@@ -1,12 +0,0 @@
|
||||
from openpilot.common.kalman.simple_kalman_impl import KF1D as KF1D
|
||||
assert KF1D
|
||||
import numpy as np
|
||||
|
||||
def get_kalman_gain(dt, A, C, Q, R, iterations=100):
|
||||
P = np.zeros_like(Q)
|
||||
for _ in range(iterations):
|
||||
P = A.dot(P).dot(A.T) + dt * Q
|
||||
S = C.dot(P).dot(C.T) + R
|
||||
K = P.dot(C.T).dot(np.linalg.inv(S))
|
||||
P = (np.eye(len(P)) - K.dot(C)).dot(P)
|
||||
return K
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,18 +0,0 @@
|
||||
# cython: language_level = 3
|
||||
|
||||
cdef class KF1D:
|
||||
cdef public:
|
||||
double x0_0
|
||||
double x1_0
|
||||
double K0_0
|
||||
double K1_0
|
||||
double A0_0
|
||||
double A0_1
|
||||
double A1_0
|
||||
double A1_1
|
||||
double C0_0
|
||||
double C0_1
|
||||
double A_K_0
|
||||
double A_K_1
|
||||
double A_K_2
|
||||
double A_K_3
|
||||
@@ -1,37 +0,0 @@
|
||||
# distutils: language = c++
|
||||
# cython: language_level=3
|
||||
|
||||
cdef class KF1D:
|
||||
def __init__(self, x0, A, C, K):
|
||||
self.x0_0 = x0[0][0]
|
||||
self.x1_0 = x0[1][0]
|
||||
self.A0_0 = A[0][0]
|
||||
self.A0_1 = A[0][1]
|
||||
self.A1_0 = A[1][0]
|
||||
self.A1_1 = A[1][1]
|
||||
self.C0_0 = C[0]
|
||||
self.C0_1 = C[1]
|
||||
self.K0_0 = K[0][0]
|
||||
self.K1_0 = K[1][0]
|
||||
|
||||
self.A_K_0 = self.A0_0 - self.K0_0 * self.C0_0
|
||||
self.A_K_1 = self.A0_1 - self.K0_0 * self.C0_1
|
||||
self.A_K_2 = self.A1_0 - self.K1_0 * self.C0_0
|
||||
self.A_K_3 = self.A1_1 - self.K1_0 * self.C0_1
|
||||
|
||||
def update(self, meas):
|
||||
cdef double x0_0 = self.A_K_0 * self.x0_0 + self.A_K_1 * self.x1_0 + self.K0_0 * meas
|
||||
cdef double x1_0 = self.A_K_2 * self.x0_0 + self.A_K_3 * self.x1_0 + self.K1_0 * meas
|
||||
self.x0_0 = x0_0
|
||||
self.x1_0 = x1_0
|
||||
|
||||
return [self.x0_0, self.x1_0]
|
||||
|
||||
@property
|
||||
def x(self):
|
||||
return [[self.x0_0], [self.x1_0]]
|
||||
|
||||
@x.setter
|
||||
def x(self, x):
|
||||
self.x0_0 = x[0][0]
|
||||
self.x1_0 = x[1][0]
|
||||
Binary file not shown.
@@ -1,23 +0,0 @@
|
||||
import numpy as np
|
||||
|
||||
|
||||
class KF1D:
|
||||
# this EKF assumes constant covariance matrix, so calculations are much simpler
|
||||
# the Kalman gain also needs to be precomputed using the control module
|
||||
|
||||
def __init__(self, x0, A, C, K):
|
||||
self.x = x0
|
||||
self.A = A
|
||||
self.C = np.atleast_2d(C)
|
||||
self.K = K
|
||||
|
||||
self.A_K = self.A - np.dot(self.K, self.C)
|
||||
|
||||
# K matrix needs to be pre-computed as follow:
|
||||
# import control
|
||||
# (x, l, K) = control.dare(np.transpose(self.A), np.transpose(self.C), Q, R)
|
||||
# self.K = np.transpose(K)
|
||||
|
||||
def update(self, meas):
|
||||
self.x = np.dot(self.A_K, self.x) + np.dot(self.K, meas)
|
||||
return self.x
|
||||
@@ -1,87 +0,0 @@
|
||||
import unittest
|
||||
import random
|
||||
import timeit
|
||||
import numpy as np
|
||||
|
||||
from openpilot.common.kalman.simple_kalman import KF1D
|
||||
from openpilot.common.kalman.simple_kalman_old import KF1D as KF1D_old
|
||||
|
||||
|
||||
class TestSimpleKalman(unittest.TestCase):
|
||||
def setUp(self):
|
||||
dt = 0.01
|
||||
x0_0 = 0.0
|
||||
x1_0 = 0.0
|
||||
A0_0 = 1.0
|
||||
A0_1 = dt
|
||||
A1_0 = 0.0
|
||||
A1_1 = 1.0
|
||||
C0_0 = 1.0
|
||||
C0_1 = 0.0
|
||||
K0_0 = 0.12287673
|
||||
K1_0 = 0.29666309
|
||||
|
||||
self.kf_old = KF1D_old(x0=np.array([[x0_0], [x1_0]]),
|
||||
A=np.array([[A0_0, A0_1], [A1_0, A1_1]]),
|
||||
C=np.array([C0_0, C0_1]),
|
||||
K=np.array([[K0_0], [K1_0]]))
|
||||
|
||||
self.kf = KF1D(x0=[[x0_0], [x1_0]],
|
||||
A=[[A0_0, A0_1], [A1_0, A1_1]],
|
||||
C=[C0_0, C0_1],
|
||||
K=[[K0_0], [K1_0]])
|
||||
|
||||
def test_getter_setter(self):
|
||||
self.kf.x = [[1.0], [1.0]]
|
||||
self.assertEqual(self.kf.x, [[1.0], [1.0]])
|
||||
|
||||
def update_returns_state(self):
|
||||
x = self.kf.update(100)
|
||||
self.assertEqual(x, self.kf.x)
|
||||
|
||||
def test_old_equal_new(self):
|
||||
for _ in range(1000):
|
||||
v_wheel = random.uniform(0, 200)
|
||||
|
||||
x_old = self.kf_old.update(v_wheel)
|
||||
x = self.kf.update(v_wheel)
|
||||
|
||||
# Compare the output x, verify that the error is less than 1e-4
|
||||
np.testing.assert_almost_equal(x_old[0], x[0])
|
||||
np.testing.assert_almost_equal(x_old[1], x[1])
|
||||
|
||||
def test_new_is_faster(self):
|
||||
setup = """
|
||||
import numpy as np
|
||||
|
||||
from openpilot.common.kalman.simple_kalman import KF1D
|
||||
from openpilot.common.kalman.simple_kalman_old import KF1D as KF1D_old
|
||||
|
||||
dt = 0.01
|
||||
x0_0 = 0.0
|
||||
x1_0 = 0.0
|
||||
A0_0 = 1.0
|
||||
A0_1 = dt
|
||||
A1_0 = 0.0
|
||||
A1_1 = 1.0
|
||||
C0_0 = 1.0
|
||||
C0_1 = 0.0
|
||||
K0_0 = 0.12287673
|
||||
K1_0 = 0.29666309
|
||||
|
||||
kf_old = KF1D_old(x0=np.array([[x0_0], [x1_0]]),
|
||||
A=np.array([[A0_0, A0_1], [A1_0, A1_1]]),
|
||||
C=np.array([C0_0, C0_1]),
|
||||
K=np.array([[K0_0], [K1_0]]))
|
||||
|
||||
kf = KF1D(x0=[[x0_0], [x1_0]],
|
||||
A=[[A0_0, A0_1], [A1_0, A1_1]],
|
||||
C=[C0_0, C0_1],
|
||||
K=[[K0_0], [K1_0]])
|
||||
"""
|
||||
kf_speed = timeit.timeit("kf.update(1234)", setup=setup, number=10000)
|
||||
kf_old_speed = timeit.timeit("kf_old.update(1234)", setup=setup, number=10000)
|
||||
self.assertTrue(kf_speed < kf_old_speed / 4)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -65,7 +65,7 @@ class SwagFormatter(logging.Formatter):
|
||||
|
||||
return record_dict
|
||||
|
||||
def format(self, record): # noqa: A003
|
||||
def format(self, record):
|
||||
if self.swaglogger is None:
|
||||
raise Exception("must set swaglogger before calling format()")
|
||||
return json_robust_dumps(self.format_dict(record))
|
||||
@@ -95,7 +95,7 @@ class SwagLogFileFormatter(SwagFormatter):
|
||||
k += "$a"
|
||||
return k, v
|
||||
|
||||
def format(self, record): # noqa: A003
|
||||
def format(self, record):
|
||||
if isinstance(record, str):
|
||||
v = json.loads(record)
|
||||
else:
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
#define CURRENT_MODEL "Farmville (November 7, 2023)"
|
||||
#define CURRENT_MODEL "Los Angeles v2 (January 24, 2024)"
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include "common/mat.h"
|
||||
#include "system/hardware/hw.h"
|
||||
|
||||
const int TRAJECTORY_SIZE = 33;
|
||||
const int LAT_MPC_N = 16;
|
||||
const int LON_MPC_N = 32;
|
||||
const float MIN_DRAW_DISTANCE = 10.0;
|
||||
const float MAX_DRAW_DISTANCE = 100.0;
|
||||
|
||||
const float RYG_GREEN = 0.01165;
|
||||
const float RYG_YELLOW = 0.06157;
|
||||
|
||||
template <typename T, size_t size>
|
||||
constexpr std::array<T, size> build_idxs(float max_val) {
|
||||
std::array<T, size> result{};
|
||||
for (int i = 0; i < size; ++i) {
|
||||
result[i] = max_val * ((i / (double)(size - 1)) * (i / (double)(size - 1)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
constexpr auto T_IDXS = build_idxs<double, TRAJECTORY_SIZE>(10.0);
|
||||
constexpr auto T_IDXS_FLOAT = build_idxs<float, TRAJECTORY_SIZE>(10.0);
|
||||
constexpr auto X_IDXS = build_idxs<double, TRAJECTORY_SIZE>(192.0);
|
||||
constexpr auto X_IDXS_FLOAT = build_idxs<float, TRAJECTORY_SIZE>(192.0);
|
||||
|
||||
const mat3 FCAM_INTRINSIC_MATRIX = (mat3){{2648.0, 0.0, 1928.0 / 2,
|
||||
0.0, 2648.0, 1208.0 / 2,
|
||||
0.0, 0.0, 1.0}};
|
||||
|
||||
// tici ecam focal probably wrong? magnification is not consistent across frame
|
||||
// Need to retrain model before this can be changed
|
||||
const mat3 ECAM_INTRINSIC_MATRIX = (mat3){{567.0, 0.0, 1928.0 / 2,
|
||||
0.0, 567.0, 1208.0 / 2,
|
||||
0.0, 0.0, 1.0}};
|
||||
+19
-2
@@ -1,21 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <future>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "common/queue.h"
|
||||
|
||||
enum ParamKeyType {
|
||||
PERSISTENT = 0x02,
|
||||
CLEAR_ON_MANAGER_START = 0x04,
|
||||
CLEAR_ON_ONROAD_TRANSITION = 0x08,
|
||||
CLEAR_ON_OFFROAD_TRANSITION = 0x10,
|
||||
DONT_LOG = 0x20,
|
||||
DEVELOPMENT_ONLY = 0x40,
|
||||
ALL = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
class Params {
|
||||
public:
|
||||
explicit Params(const std::string &path = {});
|
||||
~Params();
|
||||
// Not copyable.
|
||||
Params(const Params&) = delete;
|
||||
Params& operator=(const Params&) = delete;
|
||||
@@ -24,7 +31,7 @@ public:
|
||||
bool checkKey(const std::string &key);
|
||||
ParamKeyType getKeyType(const std::string &key);
|
||||
inline std::string getParamPath(const std::string &key = {}) {
|
||||
return params_path + prefix + (key.empty() ? "" : "/" + key);
|
||||
return params_path + params_prefix + (key.empty() ? "" : "/" + key);
|
||||
}
|
||||
|
||||
// Delete a value
|
||||
@@ -46,8 +53,18 @@ public:
|
||||
inline int putBool(const std::string &key, bool val) {
|
||||
return put(key.c_str(), val ? "1" : "0", 1);
|
||||
}
|
||||
void putNonBlocking(const std::string &key, const std::string &val);
|
||||
inline void putBoolNonBlocking(const std::string &key, bool val) {
|
||||
putNonBlocking(key, val ? "1" : "0");
|
||||
}
|
||||
|
||||
private:
|
||||
void asyncWriteThread();
|
||||
|
||||
std::string params_path;
|
||||
std::string prefix;
|
||||
std::string params_prefix;
|
||||
|
||||
// for nonblocking write
|
||||
std::future<void> future;
|
||||
SafeQueue<std::pair<std::string, std::string>> queue;
|
||||
};
|
||||
|
||||
+1
-4
@@ -1,10 +1,7 @@
|
||||
from openpilot.common.params_pyx import Params, ParamKeyType, UnknownKeyName, put_nonblocking, \
|
||||
put_bool_nonblocking
|
||||
from openpilot.common.params_pyx import Params, ParamKeyType, UnknownKeyName
|
||||
assert Params
|
||||
assert ParamKeyType
|
||||
assert UnknownKeyName
|
||||
assert put_nonblocking
|
||||
assert put_bool_nonblocking
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
||||
+4145
-3550
File diff suppressed because it is too large
Load Diff
+16
-9
@@ -3,7 +3,6 @@
|
||||
from libcpp cimport bool
|
||||
from libcpp.string cimport string
|
||||
from libcpp.vector cimport vector
|
||||
import threading
|
||||
|
||||
cdef extern from "common/params.h":
|
||||
cpdef enum ParamKeyType:
|
||||
@@ -11,6 +10,7 @@ cdef extern from "common/params.h":
|
||||
CLEAR_ON_MANAGER_START
|
||||
CLEAR_ON_ONROAD_TRANSITION
|
||||
CLEAR_ON_OFFROAD_TRANSITION
|
||||
DEVELOPMENT_ONLY
|
||||
ALL
|
||||
|
||||
cdef cppclass c_Params "Params":
|
||||
@@ -19,6 +19,8 @@ cdef extern from "common/params.h":
|
||||
bool getBool(string, bool) nogil
|
||||
int remove(string) nogil
|
||||
int put(string, string) nogil
|
||||
void putNonBlocking(string, string) nogil
|
||||
void putBoolNonBlocking(string, bool) nogil
|
||||
int putBool(string, bool) nogil
|
||||
bool checkKey(string) nogil
|
||||
string getParamPath(string) nogil
|
||||
@@ -27,7 +29,7 @@ cdef extern from "common/params.h":
|
||||
|
||||
|
||||
def ensure_bytes(v):
|
||||
return v.encode() if isinstance(v, str) else v;
|
||||
return v.encode() if isinstance(v, str) else v
|
||||
|
||||
class UnknownKeyName(Exception):
|
||||
pass
|
||||
@@ -79,7 +81,7 @@ cdef class Params:
|
||||
"""
|
||||
Warning: This function blocks until the param is written to disk!
|
||||
In very rare cases this can take over a second, and your code will hang.
|
||||
Use the put_nonblocking helper function in time sensitive code, but
|
||||
Use the put_nonblocking, put_bool_nonblocking in time sensitive code, but
|
||||
in general try to avoid writing params as much as possible.
|
||||
"""
|
||||
cdef string k = self.check_key(key)
|
||||
@@ -92,6 +94,17 @@ cdef class Params:
|
||||
with nogil:
|
||||
self.p.putBool(k, val)
|
||||
|
||||
def put_nonblocking(self, key, dat):
|
||||
cdef string k = self.check_key(key)
|
||||
cdef string dat_bytes = ensure_bytes(dat)
|
||||
with nogil:
|
||||
self.p.putNonBlocking(k, dat_bytes)
|
||||
|
||||
def put_bool_nonblocking(self, key, bool val):
|
||||
cdef string k = self.check_key(key)
|
||||
with nogil:
|
||||
self.p.putBoolNonBlocking(k, val)
|
||||
|
||||
def remove(self, key):
|
||||
cdef string k = self.check_key(key)
|
||||
with nogil:
|
||||
@@ -103,9 +116,3 @@ cdef class Params:
|
||||
|
||||
def all_keys(self):
|
||||
return self.p.allKeys()
|
||||
|
||||
def put_nonblocking(key, val, d=""):
|
||||
threading.Thread(target=lambda: Params(d).put(key, val)).start()
|
||||
|
||||
def put_bool_nonblocking(key, bool val, d=""):
|
||||
threading.Thread(target=lambda: Params(d).put_bool(key, val)).start()
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,52 @@
|
||||
import os
|
||||
import shutil
|
||||
import uuid
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from openpilot.common.params import Params
|
||||
from openpilot.system.hardware.hw import Paths
|
||||
from openpilot.system.hardware.hw import DEFAULT_DOWNLOAD_CACHE_ROOT
|
||||
|
||||
class OpenpilotPrefix:
|
||||
def __init__(self, prefix: Optional[str] = None, clean_dirs_on_exit: bool = True, shared_download_cache: bool = False):
|
||||
self.prefix = prefix if prefix else str(uuid.uuid4().hex[0:15])
|
||||
self.msgq_path = os.path.join('/dev/shm', self.prefix)
|
||||
self.clean_dirs_on_exit = clean_dirs_on_exit
|
||||
self.shared_download_cache = shared_download_cache
|
||||
|
||||
def __enter__(self):
|
||||
self.original_prefix = os.environ.get('OPENPILOT_PREFIX', None)
|
||||
os.environ['OPENPILOT_PREFIX'] = self.prefix
|
||||
try:
|
||||
os.mkdir(self.msgq_path)
|
||||
except FileExistsError:
|
||||
pass
|
||||
os.makedirs(Paths.log_root(), exist_ok=True)
|
||||
|
||||
if self.shared_download_cache:
|
||||
os.environ["COMMA_CACHE"] = DEFAULT_DOWNLOAD_CACHE_ROOT
|
||||
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_obj, exc_tb):
|
||||
if self.clean_dirs_on_exit:
|
||||
self.clean_dirs()
|
||||
try:
|
||||
del os.environ['OPENPILOT_PREFIX']
|
||||
if self.original_prefix is not None:
|
||||
os.environ['OPENPILOT_PREFIX'] = self.original_prefix
|
||||
except KeyError:
|
||||
pass
|
||||
return False
|
||||
|
||||
def clean_dirs(self):
|
||||
symlink_path = Params().get_param_path()
|
||||
if os.path.exists(symlink_path):
|
||||
shutil.rmtree(os.path.realpath(symlink_path), ignore_errors=True)
|
||||
os.remove(symlink_path)
|
||||
shutil.rmtree(self.msgq_path, ignore_errors=True)
|
||||
shutil.rmtree(Paths.log_root(), ignore_errors=True)
|
||||
if not os.environ.get("COMMA_CACHE", False):
|
||||
shutil.rmtree(Paths.download_cache_root(), ignore_errors=True)
|
||||
shutil.rmtree(Paths.comma_home(), ignore_errors=True)
|
||||
@@ -1,45 +0,0 @@
|
||||
import time
|
||||
|
||||
class Profiler():
|
||||
def __init__(self, enabled=False):
|
||||
self.enabled = enabled
|
||||
self.cp = {}
|
||||
self.cp_ignored = []
|
||||
self.iter = 0
|
||||
self.start_time = time.time()
|
||||
self.last_time = self.start_time
|
||||
self.tot = 0.
|
||||
|
||||
def reset(self, enabled=False):
|
||||
self.enabled = enabled
|
||||
self.cp = {}
|
||||
self.cp_ignored = []
|
||||
self.iter = 0
|
||||
self.start_time = time.time()
|
||||
self.last_time = self.start_time
|
||||
|
||||
def checkpoint(self, name, ignore=False):
|
||||
# ignore flag needed when benchmarking threads with ratekeeper
|
||||
if not self.enabled:
|
||||
return
|
||||
tt = time.time()
|
||||
if name not in self.cp:
|
||||
self.cp[name] = 0.
|
||||
if ignore:
|
||||
self.cp_ignored.append(name)
|
||||
self.cp[name] += tt - self.last_time
|
||||
if not ignore:
|
||||
self.tot += tt - self.last_time
|
||||
self.last_time = tt
|
||||
|
||||
def display(self):
|
||||
if not self.enabled:
|
||||
return
|
||||
self.iter += 1
|
||||
print("******* Profiling %d *******" % self.iter)
|
||||
for n, ms in sorted(self.cp.items(), key=lambda x: -x[1]):
|
||||
if n in self.cp_ignored:
|
||||
print("%30s: %9.2f avg: %7.2f percent: %3.0f IGNORED" % (n, ms*1000.0, ms*1000.0/self.iter, ms/self.tot*100))
|
||||
else:
|
||||
print("%30s: %9.2f avg: %7.2f percent: %3.0f" % (n, ms*1000.0, ms*1000.0/self.iter, ms/self.tot*100))
|
||||
print(f"Iter clock: {self.tot / self.iter:2.6f} TOTAL: {self.tot:2.2f}")
|
||||
+1
-1
@@ -88,7 +88,7 @@ class Ratekeeper:
|
||||
time.sleep(self._remaining)
|
||||
return lagged
|
||||
|
||||
# this only monitor the cumulative lag, but does not enforce a rate
|
||||
# Monitors the cumulative lag, but does not enforce a rate
|
||||
def monitor_time(self) -> bool:
|
||||
prev = self._last_monitor_time
|
||||
self._last_monitor_time = time.monotonic()
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import time
|
||||
import functools
|
||||
|
||||
from openpilot.common.swaglog import cloudlog
|
||||
|
||||
|
||||
def retry(attempts=3, delay=1.0, ignore_failure=False):
|
||||
def decorator(func):
|
||||
@functools.wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
for _ in range(attempts):
|
||||
try:
|
||||
return func(*args, **kwargs)
|
||||
except Exception:
|
||||
cloudlog.exception(f"{func.__name__} failed, trying again")
|
||||
time.sleep(delay)
|
||||
|
||||
if ignore_failure:
|
||||
cloudlog.error(f"{func.__name__} failed after retry")
|
||||
else:
|
||||
raise Exception(f"{func.__name__} failed after retry")
|
||||
return wrapper
|
||||
return decorator
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
@retry(attempts=10)
|
||||
def abc():
|
||||
raise ValueError("abc failed :(")
|
||||
abc()
|
||||
@@ -0,0 +1,54 @@
|
||||
import numpy as np
|
||||
|
||||
|
||||
def get_kalman_gain(dt, A, C, Q, R, iterations=100):
|
||||
P = np.zeros_like(Q)
|
||||
for _ in range(iterations):
|
||||
P = A.dot(P).dot(A.T) + dt * Q
|
||||
S = C.dot(P).dot(C.T) + R
|
||||
K = P.dot(C.T).dot(np.linalg.inv(S))
|
||||
P = (np.eye(len(P)) - K.dot(C)).dot(P)
|
||||
return K
|
||||
|
||||
|
||||
class KF1D:
|
||||
# this EKF assumes constant covariance matrix, so calculations are much simpler
|
||||
# the Kalman gain also needs to be precomputed using the control module
|
||||
|
||||
def __init__(self, x0, A, C, K):
|
||||
self.x0_0 = x0[0][0]
|
||||
self.x1_0 = x0[1][0]
|
||||
self.A0_0 = A[0][0]
|
||||
self.A0_1 = A[0][1]
|
||||
self.A1_0 = A[1][0]
|
||||
self.A1_1 = A[1][1]
|
||||
self.C0_0 = C[0]
|
||||
self.C0_1 = C[1]
|
||||
self.K0_0 = K[0][0]
|
||||
self.K1_0 = K[1][0]
|
||||
|
||||
self.A_K_0 = self.A0_0 - self.K0_0 * self.C0_0
|
||||
self.A_K_1 = self.A0_1 - self.K0_0 * self.C0_1
|
||||
self.A_K_2 = self.A1_0 - self.K1_0 * self.C0_0
|
||||
self.A_K_3 = self.A1_1 - self.K1_0 * self.C0_1
|
||||
|
||||
# K matrix needs to be pre-computed as follow:
|
||||
# import control
|
||||
# (x, l, K) = control.dare(np.transpose(self.A), np.transpose(self.C), Q, R)
|
||||
# self.K = np.transpose(K)
|
||||
|
||||
def update(self, meas):
|
||||
#self.x = np.dot(self.A_K, self.x) + np.dot(self.K, meas)
|
||||
x0_0 = self.A_K_0 * self.x0_0 + self.A_K_1 * self.x1_0 + self.K0_0 * meas
|
||||
x1_0 = self.A_K_2 * self.x0_0 + self.A_K_3 * self.x1_0 + self.K1_0 * meas
|
||||
self.x0_0 = x0_0
|
||||
self.x1_0 = x1_0
|
||||
return [self.x0_0, self.x1_0]
|
||||
|
||||
@property
|
||||
def x(self):
|
||||
return [[self.x0_0], [self.x1_0]]
|
||||
|
||||
def set_x(self, x):
|
||||
self.x0_0 = x[0][0]
|
||||
self.x1_0 = x[1][0]
|
||||
@@ -1,10 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#define STATLOG_GAUGE "g"
|
||||
#define STATLOG_SAMPLE "sa"
|
||||
|
||||
void statlog_log(const char* metric_type, const char* metric, int value);
|
||||
void statlog_log(const char* metric_type, const char* metric, float value);
|
||||
|
||||
#define statlog_gauge(metric, value) statlog_log(STATLOG_GAUGE, metric, value)
|
||||
#define statlog_sample(metric, value) statlog_log(STATLOG_SAMPLE, metric, value)
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
import datetime
|
||||
|
||||
MIN_DATE = datetime.datetime(year=2023, month=6, day=1)
|
||||
MIN_DATE = datetime.datetime(year=2024, month=1, day=28)
|
||||
|
||||
def system_time_valid():
|
||||
return datetime.datetime.now() > MIN_DATE
|
||||
return datetime.datetime.now() > MIN_DATE
|
||||
|
||||
+2181
-1145
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
#cython: language_level=3
|
||||
# cython: language_level=3
|
||||
from libcpp cimport bool
|
||||
|
||||
cdef extern from "orientation.cc":
|
||||
|
||||
@@ -17,7 +17,6 @@ from openpilot.common.transformations.transformations cimport ecef2geodetic as e
|
||||
from openpilot.common.transformations.transformations cimport LocalCoord_c
|
||||
|
||||
|
||||
import cython
|
||||
import numpy as np
|
||||
cimport numpy as np
|
||||
|
||||
@@ -34,14 +33,14 @@ cdef Matrix3 numpy2matrix(np.ndarray[double, ndim=2, mode="fortran"] m):
|
||||
return Matrix3(<double*>m.data)
|
||||
|
||||
cdef ECEF list2ecef(ecef):
|
||||
cdef ECEF e;
|
||||
cdef ECEF e
|
||||
e.x = ecef[0]
|
||||
e.y = ecef[1]
|
||||
e.z = ecef[2]
|
||||
return e
|
||||
|
||||
cdef NED list2ned(ned):
|
||||
cdef NED n;
|
||||
cdef NED n
|
||||
n.n = ned[0]
|
||||
n.e = ned[1]
|
||||
n.d = ned[2]
|
||||
@@ -61,7 +60,7 @@ def euler2quat_single(euler):
|
||||
|
||||
def quat2euler_single(quat):
|
||||
cdef Quaternion q = Quaternion(quat[0], quat[1], quat[2], quat[3])
|
||||
cdef Vector3 e = quat2euler_c(q);
|
||||
cdef Vector3 e = quat2euler_c(q)
|
||||
return [e(0), e(1), e(2)]
|
||||
|
||||
def quat2rot_single(quat):
|
||||
|
||||
Binary file not shown.
@@ -3,7 +3,6 @@
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <zmq.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
@@ -180,36 +179,3 @@ void update_max_atomic(std::atomic<T>& max, T const& value) {
|
||||
T prev = max;
|
||||
while (prev < value && !max.compare_exchange_weak(prev, value)) {}
|
||||
}
|
||||
|
||||
class LogState {
|
||||
public:
|
||||
bool initialized = false;
|
||||
std::mutex lock;
|
||||
void *zctx = nullptr;
|
||||
void *sock = nullptr;
|
||||
int print_level;
|
||||
std::string endpoint;
|
||||
|
||||
LogState(std::string _endpoint) {
|
||||
endpoint = _endpoint;
|
||||
}
|
||||
|
||||
inline void initialize() {
|
||||
zctx = zmq_ctx_new();
|
||||
sock = zmq_socket(zctx, ZMQ_PUSH);
|
||||
|
||||
// Timeout on shutdown for messages to be received by the logging process
|
||||
int timeout = 100;
|
||||
zmq_setsockopt(sock, ZMQ_LINGER, &timeout, sizeof(timeout));
|
||||
|
||||
zmq_connect(sock, endpoint.c_str());
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
~LogState() {
|
||||
if (initialized) {
|
||||
zmq_close(sock);
|
||||
zmq_ctx_destroy(zctx);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
#define COMMA_VERSION "0.9.5.3-release"
|
||||
#define COMMA_VERSION "0.9.6.1-release"
|
||||
|
||||
+104
-91
@@ -4,37 +4,40 @@
|
||||
|
||||
A supported vehicle is one that just works when you install a comma device. All supported cars provide a better experience than any stock system. Supported vehicles reference the US market unless otherwise specified.
|
||||
|
||||
# 267 Supported Cars
|
||||
# 279 Supported Cars
|
||||
|
||||
|Make|Model|Supported Package|ACC|No ACC accel below|No ALC below|Steering Torque|Resume from stop|<a href="##"><img width=2000></a>Hardware Needed<br> |Video|
|
||||
|---|---|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
|
||||
|Acura|ILX 2016-19|AcuraWatch Plus|openpilot|25 mph|25 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Acura&model=ILX 2016-19">Buy Here</a></sub></details>||
|
||||
|Acura|RDX 2016-18|AcuraWatch Plus|openpilot|25 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Acura&model=RDX 2016-18">Buy Here</a></sub></details>||
|
||||
|Acura|RDX 2019-22|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|3 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Acura&model=RDX 2019-22">Buy Here</a></sub></details>||
|
||||
|Audi|A3 2014-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Audi&model=A3 2014-19">Buy Here</a></sub></details>||
|
||||
|Audi|A3 Sportback e-tron 2017-18|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Audi&model=A3 Sportback e-tron 2017-18">Buy Here</a></sub></details>||
|
||||
|Audi|Q2 2018|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Audi&model=Q2 2018">Buy Here</a></sub></details>||
|
||||
|Audi|Q3 2019-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Audi&model=Q3 2019-23">Buy Here</a></sub></details>||
|
||||
|Audi|RS3 2018|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Audi&model=RS3 2018">Buy Here</a></sub></details>||
|
||||
|Audi|S3 2015-17|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Audi&model=S3 2015-17">Buy Here</a></sub></details>||
|
||||
|Audi|A3 2014-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Audi&model=A3 2014-19">Buy Here</a></sub></details>||
|
||||
|Audi|A3 Sportback e-tron 2017-18|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Audi&model=A3 Sportback e-tron 2017-18">Buy Here</a></sub></details>||
|
||||
|Audi|Q2 2018|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Audi&model=Q2 2018">Buy Here</a></sub></details>||
|
||||
|Audi|Q3 2019-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Audi&model=Q3 2019-23">Buy Here</a></sub></details>||
|
||||
|Audi|RS3 2018|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Audi&model=RS3 2018">Buy Here</a></sub></details>||
|
||||
|Audi|S3 2015-17|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Audi&model=S3 2015-17">Buy Here</a></sub></details>||
|
||||
|Buick|LaCrosse 2017-19[<sup>4</sup>](#footnotes)|Driver Confidence Package 2|openpilot|18 mph|7 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-II connector<br>- 1 comma 3X<br>- 2 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Buick&model=LaCrosse 2017-19">Buy Here</a></sub></details>||
|
||||
|Cadillac|Escalade 2017[<sup>4</sup>](#footnotes)|Driver Assist Package|openpilot|0 mph|7 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-II connector<br>- 1 comma 3X<br>- 2 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Cadillac&model=Escalade 2017">Buy Here</a></sub></details>||
|
||||
|Cadillac|Escalade ESV 2016[<sup>4</sup>](#footnotes)|Adaptive Cruise Control (ACC) & LKAS|openpilot|0 mph|7 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-II connector<br>- 1 comma 3X<br>- 2 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Cadillac&model=Escalade ESV 2016">Buy Here</a></sub></details>||
|
||||
|Cadillac|Escalade ESV 2019[<sup>4</sup>](#footnotes)|Adaptive Cruise Control (ACC) & LKAS|openpilot|0 mph|7 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-II connector<br>- 1 comma 3X<br>- 2 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Cadillac&model=Escalade ESV 2019">Buy Here</a></sub></details>||
|
||||
|Chevrolet|Bolt EUV 2022-23|Premier or Premier Redline Trim without Super Cruise Package|openpilot available[<sup>1</sup>](#footnotes)|3 mph|6 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 GM connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chevrolet&model=Bolt EUV 2022-23">Buy Here</a></sub></details>|<a href="https://youtu.be/xvwzGMUA210" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Chevrolet|Bolt EV 2022-23|2LT Trim with Adaptive Cruise Control Package|openpilot available[<sup>1</sup>](#footnotes)|3 mph|6 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 GM connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chevrolet&model=Bolt EV 2022-23">Buy Here</a></sub></details>||
|
||||
|Chevrolet|Equinox 2019-22|Adaptive Cruise Control (ACC)|openpilot available[<sup>1</sup>](#footnotes)|3 mph|6 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 GM connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chevrolet&model=Equinox 2019-22">Buy Here</a></sub></details>||
|
||||
|Chevrolet|Silverado 1500 2020-21|Safety Package II|openpilot available[<sup>1</sup>](#footnotes)|0 mph|6 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 GM connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chevrolet&model=Silverado 1500 2020-21">Buy Here</a></sub></details>||
|
||||
|Chevrolet|Trailblazer 2021-22|Adaptive Cruise Control (ACC)|openpilot available[<sup>1</sup>](#footnotes)|3 mph|6 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 GM connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chevrolet&model=Trailblazer 2021-22">Buy Here</a></sub></details>||
|
||||
|Chevrolet|Volt 2017-18[<sup>4</sup>](#footnotes)|Adaptive Cruise Control (ACC)|openpilot|0 mph|7 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-II connector<br>- 1 comma 3X<br>- 2 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chevrolet&model=Volt 2017-18">Buy Here</a></sub></details>|<a href="https://youtu.be/QeMCN_4TFfQ" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Chrysler|Pacifica 2017-18|Adaptive Cruise Control (ACC)|Stock|0 mph|9 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chrysler&model=Pacifica 2017-18">Buy Here</a></sub></details>||
|
||||
|Chrysler|Pacifica 2019-20|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chrysler&model=Pacifica 2019-20">Buy Here</a></sub></details>||
|
||||
|Chrysler|Pacifica 2021|All|Stock|0 mph|39 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chrysler&model=Pacifica 2021">Buy Here</a></sub></details>||
|
||||
|Chrysler|Pacifica Hybrid 2017-18|Adaptive Cruise Control (ACC)|Stock|0 mph|9 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chrysler&model=Pacifica Hybrid 2017-18">Buy Here</a></sub></details>||
|
||||
|Chrysler|Pacifica 2021-23|All|Stock|0 mph|39 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chrysler&model=Pacifica 2021-23">Buy Here</a></sub></details>||
|
||||
|Chrysler|Pacifica Hybrid 2017|Adaptive Cruise Control (ACC)|Stock|0 mph|9 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chrysler&model=Pacifica Hybrid 2017">Buy Here</a></sub></details>||
|
||||
|Chrysler|Pacifica Hybrid 2018|Adaptive Cruise Control (ACC)|Stock|0 mph|9 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chrysler&model=Pacifica Hybrid 2018">Buy Here</a></sub></details>||
|
||||
|Chrysler|Pacifica Hybrid 2019-23|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chrysler&model=Pacifica Hybrid 2019-23">Buy Here</a></sub></details>||
|
||||
|comma|body|All|openpilot|0 mph|0 mph|[](##)|[](##)|None||
|
||||
|Dodge|Durango 2020-21|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Dodge&model=Durango 2020-21">Buy Here</a></sub></details>||
|
||||
|Ford|Bronco Sport 2021-22|Co-Pilot360 Assist+|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Bronco Sport 2021-22">Buy Here</a></sub></details>||
|
||||
|Ford|Escape 2020-22|Co-Pilot360 Assist+|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Escape 2020-22">Buy Here</a></sub></details>||
|
||||
|Ford|Explorer 2020-22|Co-Pilot360 Assist+|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Explorer 2020-22">Buy Here</a></sub></details>||
|
||||
|Ford|Explorer 2020-23|Co-Pilot360 Assist+|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Explorer 2020-23">Buy Here</a></sub></details>||
|
||||
|Ford|Focus 2018[<sup>3</sup>](#footnotes)|Adaptive Cruise Control with Lane Centering|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Focus 2018">Buy Here</a></sub></details>||
|
||||
|Ford|Kuga 2020-22|Adaptive Cruise Control with Lane Centering|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Kuga 2020-22">Buy Here</a></sub></details>||
|
||||
|Ford|Maverick 2022|LARIAT Luxury|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Maverick 2022">Buy Here</a></sub></details>||
|
||||
@@ -60,7 +63,7 @@ A supported vehicle is one that just works when you install a comma device. All
|
||||
|Honda|Civic Hatchback 2022-23|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch B connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=Civic Hatchback 2022-23">Buy Here</a></sub></details>|<a href="https://youtu.be/ytiOT5lcp6Q" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Honda|CR-V 2015-16|Touring Trim|openpilot|25 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=CR-V 2015-16">Buy Here</a></sub></details>||
|
||||
|Honda|CR-V 2017-22|Honda Sensing|openpilot available[<sup>1</sup>](#footnotes)|0 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=CR-V 2017-22">Buy Here</a></sub></details>||
|
||||
|Honda|CR-V Hybrid 2017-19|Honda Sensing|openpilot available[<sup>1</sup>](#footnotes)|0 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=CR-V Hybrid 2017-19">Buy Here</a></sub></details>||
|
||||
|Honda|CR-V Hybrid 2017-20|Honda Sensing|openpilot available[<sup>1</sup>](#footnotes)|0 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=CR-V Hybrid 2017-20">Buy Here</a></sub></details>||
|
||||
|Honda|e 2020|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|3 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=e 2020">Buy Here</a></sub></details>||
|
||||
|Honda|Fit 2018-20|Honda Sensing|openpilot|25 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=Fit 2018-20">Buy Here</a></sub></details>||
|
||||
|Honda|Freed 2020|Honda Sensing|openpilot|25 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=Freed 2020">Buy Here</a></sub></details>||
|
||||
@@ -71,8 +74,9 @@ A supported vehicle is one that just works when you install a comma device. All
|
||||
|Honda|Odyssey 2018-20|Honda Sensing|openpilot|25 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=Odyssey 2018-20">Buy Here</a></sub></details>||
|
||||
|Honda|Passport 2019-23|All|openpilot|25 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=Passport 2019-23">Buy Here</a></sub></details>||
|
||||
|Honda|Pilot 2016-22|Honda Sensing|openpilot|25 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=Pilot 2016-22">Buy Here</a></sub></details>||
|
||||
|Honda|Ridgeline 2017-23|Honda Sensing|openpilot|25 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=Ridgeline 2017-23">Buy Here</a></sub></details>||
|
||||
|Honda|Ridgeline 2017-24|Honda Sensing|openpilot|25 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=Ridgeline 2017-24">Buy Here</a></sub></details>||
|
||||
|Hyundai|Azera 2022|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Azera 2022">Buy Here</a></sub></details>||
|
||||
|Hyundai|Azera Hybrid 2019|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Azera Hybrid 2019">Buy Here</a></sub></details>||
|
||||
|Hyundai|Azera Hybrid 2020|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Azera Hybrid 2020">Buy Here</a></sub></details>||
|
||||
|Hyundai|Custin 2023|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Custin 2023">Buy Here</a></sub></details>||
|
||||
|Hyundai|Elantra 2017-18|Smart Cruise Control (SCC)|Stock|19 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai B connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Elantra 2017-18">Buy Here</a></sub></details>||
|
||||
@@ -96,25 +100,26 @@ A supported vehicle is one that just works when you install a comma device. All
|
||||
|Hyundai|Kona Electric 2018-21|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai G connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Kona Electric 2018-21">Buy Here</a></sub></details>||
|
||||
|Hyundai|Kona Electric 2022-23|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai O connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Kona Electric 2022-23">Buy Here</a></sub></details>||
|
||||
|Hyundai|Kona Electric (with HDA II, Korea only) 2023[<sup>6</sup>](#footnotes)|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai R connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Kona Electric (with HDA II, Korea only) 2023">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=U2fOCmcQ8hw" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Hyundai|Kona Hybrid 2020|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai I connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Kona Hybrid 2020">Buy Here</a></sub></details>|<a href="https://youtu.be/0dwpAHiZgFo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Hyundai|Kona Hybrid 2020|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai I connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Kona Hybrid 2020">Buy Here</a></sub></details>||
|
||||
|Hyundai|Palisade 2020-22|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Palisade 2020-22">Buy Here</a></sub></details>|<a href="https://youtu.be/TAnDqjF4fDY?t=456" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Hyundai|Santa Cruz 2022-23[<sup>6</sup>](#footnotes)|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai N connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Santa Cruz 2022-23">Buy Here</a></sub></details>||
|
||||
|Hyundai|Santa Fe 2019-20|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai D connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Santa Fe 2019-20">Buy Here</a></sub></details>||
|
||||
|Hyundai|Santa Cruz 2022-23[<sup>6</sup>](#footnotes)|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai N connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Santa Cruz 2022-23">Buy Here</a></sub></details>||
|
||||
|Hyundai|Santa Fe 2019-20|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai D connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Santa Fe 2019-20">Buy Here</a></sub></details>|<a href="https://youtu.be/bjDR0YjM__s" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Hyundai|Santa Fe 2021-23|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai L connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Santa Fe 2021-23">Buy Here</a></sub></details>|<a href="https://youtu.be/VnHzSTygTS4" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Hyundai|Santa Fe Hybrid 2022-23|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai L connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Santa Fe Hybrid 2022-23">Buy Here</a></sub></details>||
|
||||
|Hyundai|Santa Fe Plug-in Hybrid 2022-23|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai L connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Santa Fe Plug-in Hybrid 2022-23">Buy Here</a></sub></details>||
|
||||
|Hyundai|Sonata 2018-19|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Sonata 2018-19">Buy Here</a></sub></details>||
|
||||
|Hyundai|Sonata 2020-23|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Sonata 2020-23">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=ix63r9kE3Fw" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Hyundai|Sonata Hybrid 2020-23|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Sonata Hybrid 2020-23">Buy Here</a></sub></details>||
|
||||
|Hyundai|Staria 2023[<sup>6</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Staria 2023">Buy Here</a></sub></details>||
|
||||
|Hyundai|Tucson 2021|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai L connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Tucson 2021">Buy Here</a></sub></details>||
|
||||
|Hyundai|Tucson 2022[<sup>6</sup>](#footnotes)|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai N connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Tucson 2022">Buy Here</a></sub></details>||
|
||||
|Hyundai|Tucson 2023[<sup>6</sup>](#footnotes)|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai N connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Tucson 2023">Buy Here</a></sub></details>||
|
||||
|Hyundai|Tucson 2022[<sup>6</sup>](#footnotes)|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai N connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Tucson 2022">Buy Here</a></sub></details>||
|
||||
|Hyundai|Tucson 2023[<sup>6</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai N connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Tucson 2023">Buy Here</a></sub></details>||
|
||||
|Hyundai|Tucson Diesel 2019|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai L connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Tucson Diesel 2019">Buy Here</a></sub></details>||
|
||||
|Hyundai|Tucson Hybrid 2022-24[<sup>6</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai N connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Tucson Hybrid 2022-24">Buy Here</a></sub></details>||
|
||||
|Hyundai|Veloster 2019-20|Smart Cruise Control (SCC)|Stock|5 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Veloster 2019-20">Buy Here</a></sub></details>||
|
||||
|Jeep|Grand Cherokee 2016-18|Adaptive Cruise Control (ACC)|Stock|0 mph|9 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Jeep&model=Grand Cherokee 2016-18">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=eLR9o2JkuRk" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Jeep|Grand Cherokee 2019-21|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Jeep&model=Grand Cherokee 2019-21">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=jBe4lWnRSu4" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Kia|Carnival 2023-24[<sup>6</sup>](#footnotes)|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Carnival 2023-24">Buy Here</a></sub></details>||
|
||||
|Kia|Carnival 2022-24[<sup>6</sup>](#footnotes)|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Carnival 2022-24">Buy Here</a></sub></details>||
|
||||
|Kia|Carnival (China only) 2023[<sup>6</sup>](#footnotes)|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Carnival (China only) 2023">Buy Here</a></sub></details>||
|
||||
|Kia|Ceed 2019|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Ceed 2019">Buy Here</a></sub></details>||
|
||||
|Kia|EV6 (Southeast Asia only) 2022-23[<sup>6</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai P connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=EV6 (Southeast Asia only) 2022-23">Buy Here</a></sub></details>||
|
||||
@@ -130,10 +135,13 @@ A supported vehicle is one that just works when you install a comma device. All
|
||||
|Kia|Niro EV 2021|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Niro EV 2021">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=lT7zcG6ZpGo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Kia|Niro EV 2022|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Niro EV 2022">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=lT7zcG6ZpGo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Kia|Niro EV 2023[<sup>6</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Niro EV 2023">Buy Here</a></sub></details>||
|
||||
|Kia|Niro Hybrid 2021-22|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai F connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Niro Hybrid 2021-22">Buy Here</a></sub></details>||
|
||||
|Kia|Niro Hybrid 2021|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai D connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Niro Hybrid 2021">Buy Here</a></sub></details>||
|
||||
|Kia|Niro Hybrid 2022|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai F connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Niro Hybrid 2022">Buy Here</a></sub></details>||
|
||||
|Kia|Niro Hybrid 2023[<sup>6</sup>](#footnotes)|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Niro Hybrid 2023">Buy Here</a></sub></details>||
|
||||
|Kia|Niro Plug-in Hybrid 2018-19|All|Stock|10 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Niro Plug-in Hybrid 2018-19">Buy Here</a></sub></details>||
|
||||
|Kia|Niro Plug-in Hybrid 2020|All|Stock|0 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai D connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Niro Plug-in Hybrid 2020">Buy Here</a></sub></details>||
|
||||
|Kia|Niro Plug-in Hybrid 2021|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai D connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Niro Plug-in Hybrid 2021">Buy Here</a></sub></details>||
|
||||
|Kia|Niro Plug-in Hybrid 2022|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai F connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Niro Plug-in Hybrid 2022">Buy Here</a></sub></details>||
|
||||
|Kia|Optima 2017|Advanced Smart Cruise Control|Stock|0 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai B connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Optima 2017">Buy Here</a></sub></details>||
|
||||
|Kia|Optima 2019-20|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai G connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Optima 2019-20">Buy Here</a></sub></details>||
|
||||
|Kia|Optima Hybrid 2019|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Optima Hybrid 2019">Buy Here</a></sub></details>||
|
||||
@@ -143,18 +151,20 @@ A supported vehicle is one that just works when you install a comma device. All
|
||||
|Kia|Sorento 2021-23[<sup>6</sup>](#footnotes)|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Sorento 2021-23">Buy Here</a></sub></details>||
|
||||
|Kia|Sorento Hybrid 2021-23[<sup>6</sup>](#footnotes)|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Sorento Hybrid 2021-23">Buy Here</a></sub></details>||
|
||||
|Kia|Sorento Plug-in Hybrid 2022-23[<sup>6</sup>](#footnotes)|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Sorento Plug-in Hybrid 2022-23">Buy Here</a></sub></details>||
|
||||
|Kia|Sportage 2023[<sup>6</sup>](#footnotes)|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai N connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Sportage 2023">Buy Here</a></sub></details>||
|
||||
|Kia|Sportage 2023[<sup>6</sup>](#footnotes)|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai N connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Sportage 2023">Buy Here</a></sub></details>||
|
||||
|Kia|Sportage Hybrid 2023[<sup>6</sup>](#footnotes)|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai N connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Sportage Hybrid 2023">Buy Here</a></sub></details>||
|
||||
|Kia|Stinger 2018-20|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Stinger 2018-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=MJ94qoofYw0" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Kia|Stinger 2022|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Stinger 2022">Buy Here</a></sub></details>||
|
||||
|Kia|Stinger 2022-23|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Stinger 2022-23">Buy Here</a></sub></details>||
|
||||
|Kia|Telluride 2020-22|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Telluride 2020-22">Buy Here</a></sub></details>||
|
||||
|Lexus|CT Hybrid 2017-18|Lexus Safety System+|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=CT Hybrid 2017-18">Buy Here</a></sub></details>||
|
||||
|Lexus|ES 2017-18|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=ES 2017-18">Buy Here</a></sub></details>||
|
||||
|Lexus|ES 2019-24|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=ES 2019-24">Buy Here</a></sub></details>||
|
||||
|Lexus|ES Hybrid 2017-18|All|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=ES Hybrid 2017-18">Buy Here</a></sub></details>||
|
||||
|Lexus|ES Hybrid 2019-23|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=ES Hybrid 2019-23">Buy Here</a></sub></details>|<a href="https://youtu.be/BZ29osRVJeg?t=12" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Lexus|ES Hybrid 2017-18|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=ES Hybrid 2017-18">Buy Here</a></sub></details>||
|
||||
|Lexus|ES Hybrid 2019-24|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=ES Hybrid 2019-24">Buy Here</a></sub></details>|<a href="https://youtu.be/BZ29osRVJeg?t=12" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Lexus|GS F 2016|All|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=GS F 2016">Buy Here</a></sub></details>||
|
||||
|Lexus|IS 2017-19|All|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=IS 2017-19">Buy Here</a></sub></details>||
|
||||
|Lexus|IS 2022-23|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=IS 2022-23">Buy Here</a></sub></details>||
|
||||
|Lexus|LC 2024|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=LC 2024">Buy Here</a></sub></details>||
|
||||
|Lexus|NX 2018-19|All|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=NX 2018-19">Buy Here</a></sub></details>||
|
||||
|Lexus|NX 2020-21|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=NX 2020-21">Buy Here</a></sub></details>||
|
||||
|Lexus|NX Hybrid 2018-19|All|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=NX Hybrid 2018-19">Buy Here</a></sub></details>||
|
||||
@@ -168,35 +178,35 @@ A supported vehicle is one that just works when you install a comma device. All
|
||||
|Lexus|RX Hybrid 2020-22|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=RX Hybrid 2020-22">Buy Here</a></sub></details>||
|
||||
|Lexus|UX Hybrid 2019-23|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=UX Hybrid 2019-23">Buy Here</a></sub></details>||
|
||||
|Lincoln|Aviator 2020-21|Co-Pilot360 Plus|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lincoln&model=Aviator 2020-21">Buy Here</a></sub></details>||
|
||||
|MAN|eTGE 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=MAN&model=eTGE 2020-23">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|MAN|TGE 2017-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=MAN&model=TGE 2017-23">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|MAN|eTGE 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=MAN&model=eTGE 2020-23">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|MAN|TGE 2017-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=MAN&model=TGE 2017-23">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Mazda|CX-5 2022-24|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Mazda connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Mazda&model=CX-5 2022-24">Buy Here</a></sub></details>||
|
||||
|Mazda|CX-9 2021-23|All|Stock|0 mph|28 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Mazda connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Mazda&model=CX-9 2021-23">Buy Here</a></sub></details>|<a href="https://youtu.be/dA3duO4a0O4" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Nissan|Altima 2019-20|ProPILOT Assist|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Nissan B connector<br>- 1 RJ45 cable (7 ft)<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Nissan&model=Altima 2019-20">Buy Here</a></sub></details>||
|
||||
|Nissan|Leaf 2018-23|ProPILOT Assist|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Nissan A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Nissan&model=Leaf 2018-23">Buy Here</a></sub></details>|<a href="https://youtu.be/vaMbtAh_0cY" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Nissan|Rogue 2018-20|ProPILOT Assist|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Nissan A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Nissan&model=Rogue 2018-20">Buy Here</a></sub></details>||
|
||||
|Nissan|X-Trail 2017|ProPILOT Assist|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Nissan A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Nissan&model=X-Trail 2017">Buy Here</a></sub></details>||
|
||||
|Ram|1500 2019-23|Adaptive Cruise Control (ACC)|Stock|0 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Ram connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ram&model=1500 2019-23">Buy Here</a></sub></details>||
|
||||
|SEAT|Ateca 2018|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=SEAT&model=Ateca 2018">Buy Here</a></sub></details>||
|
||||
|SEAT|Leon 2014-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=SEAT&model=Leon 2014-20">Buy Here</a></sub></details>||
|
||||
|Subaru|Ascent 2019-21|All[<sup>7</sup>](#footnotes)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Subaru&model=Ascent 2019-21">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>||
|
||||
|Subaru|Crosstrek 2018-19|EyeSight Driver Assistance[<sup>7</sup>](#footnotes)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Subaru&model=Crosstrek 2018-19">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|<a href="https://youtu.be/Agww7oE1k-s?t=26" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Subaru|Crosstrek 2020-23|EyeSight Driver Assistance[<sup>7</sup>](#footnotes)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Subaru&model=Crosstrek 2020-23">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>||
|
||||
|Subaru|Forester 2019-21|All[<sup>7</sup>](#footnotes)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Subaru&model=Forester 2019-21">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>||
|
||||
|Subaru|Impreza 2017-19|EyeSight Driver Assistance[<sup>7</sup>](#footnotes)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Subaru&model=Impreza 2017-19">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>||
|
||||
|Subaru|Impreza 2020-22|EyeSight Driver Assistance[<sup>7</sup>](#footnotes)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Subaru&model=Impreza 2020-22">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>||
|
||||
|Ram|1500 2019-24|Adaptive Cruise Control (ACC)|Stock|0 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Ram connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ram&model=1500 2019-24">Buy Here</a></sub></details>||
|
||||
|SEAT|Ateca 2018|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=SEAT&model=Ateca 2018">Buy Here</a></sub></details>||
|
||||
|SEAT|Leon 2014-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=SEAT&model=Leon 2014-20">Buy Here</a></sub></details>||
|
||||
|Subaru|Ascent 2019-21|All[<sup>7</sup>](#footnotes)|openpilot available[<sup>1,8</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Subaru&model=Ascent 2019-21">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>||
|
||||
|Subaru|Crosstrek 2018-19|EyeSight Driver Assistance[<sup>7</sup>](#footnotes)|openpilot available[<sup>1,8</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Subaru&model=Crosstrek 2018-19">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|<a href="https://youtu.be/Agww7oE1k-s?t=26" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Subaru|Crosstrek 2020-23|EyeSight Driver Assistance[<sup>7</sup>](#footnotes)|openpilot available[<sup>1,8</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Subaru&model=Crosstrek 2020-23">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>||
|
||||
|Subaru|Forester 2019-21|All[<sup>7</sup>](#footnotes)|openpilot available[<sup>1,8</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Subaru&model=Forester 2019-21">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>||
|
||||
|Subaru|Impreza 2017-19|EyeSight Driver Assistance[<sup>7</sup>](#footnotes)|openpilot available[<sup>1,8</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Subaru&model=Impreza 2017-19">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>||
|
||||
|Subaru|Impreza 2020-22|EyeSight Driver Assistance[<sup>7</sup>](#footnotes)|openpilot available[<sup>1,8</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Subaru&model=Impreza 2020-22">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>||
|
||||
|Subaru|Legacy 2020-22|All[<sup>7</sup>](#footnotes)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru B connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Subaru&model=Legacy 2020-22">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>||
|
||||
|Subaru|Outback 2020-22|All[<sup>7</sup>](#footnotes)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru B connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Subaru&model=Outback 2020-22">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>||
|
||||
|Subaru|XV 2018-19|EyeSight Driver Assistance[<sup>7</sup>](#footnotes)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Subaru&model=XV 2018-19">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|<a href="https://youtu.be/Agww7oE1k-s?t=26" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Subaru|XV 2020-21|EyeSight Driver Assistance[<sup>7</sup>](#footnotes)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Subaru&model=XV 2020-21">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>||
|
||||
|Škoda|Fabia 2022-23[<sup>11</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Škoda&model=Fabia 2022-23">Buy Here</a></sub></details>[<sup>13</sup>](#footnotes)||
|
||||
|Škoda|Kamiq 2021[<sup>9,11</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Škoda&model=Kamiq 2021">Buy Here</a></sub></details>[<sup>13</sup>](#footnotes)||
|
||||
|Škoda|Karoq 2019-23[<sup>11</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Škoda&model=Karoq 2019-23">Buy Here</a></sub></details>||
|
||||
|Škoda|Kodiaq 2017-23[<sup>11</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Škoda&model=Kodiaq 2017-23">Buy Here</a></sub></details>||
|
||||
|Škoda|Octavia 2015-19[<sup>11</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Škoda&model=Octavia 2015-19">Buy Here</a></sub></details>||
|
||||
|Škoda|Octavia RS 2016[<sup>11</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Škoda&model=Octavia RS 2016">Buy Here</a></sub></details>||
|
||||
|Škoda|Scala 2020-23[<sup>11</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Škoda&model=Scala 2020-23">Buy Here</a></sub></details>[<sup>13</sup>](#footnotes)||
|
||||
|Škoda|Superb 2015-22[<sup>11</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Škoda&model=Superb 2015-22">Buy Here</a></sub></details>||
|
||||
|Subaru|XV 2018-19|EyeSight Driver Assistance[<sup>7</sup>](#footnotes)|openpilot available[<sup>1,8</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Subaru&model=XV 2018-19">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|<a href="https://youtu.be/Agww7oE1k-s?t=26" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Subaru|XV 2020-21|EyeSight Driver Assistance[<sup>7</sup>](#footnotes)|openpilot available[<sup>1,8</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Subaru&model=XV 2020-21">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>||
|
||||
|Škoda|Fabia 2022-23[<sup>12</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Škoda&model=Fabia 2022-23">Buy Here</a></sub></details>[<sup>14</sup>](#footnotes)||
|
||||
|Škoda|Kamiq 2021-23[<sup>10,12</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Škoda&model=Kamiq 2021-23">Buy Here</a></sub></details>[<sup>14</sup>](#footnotes)||
|
||||
|Škoda|Karoq 2019-23[<sup>12</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Škoda&model=Karoq 2019-23">Buy Here</a></sub></details>||
|
||||
|Škoda|Kodiaq 2017-23[<sup>12</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Škoda&model=Kodiaq 2017-23">Buy Here</a></sub></details>||
|
||||
|Škoda|Octavia 2015-19[<sup>12</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Škoda&model=Octavia 2015-19">Buy Here</a></sub></details>||
|
||||
|Škoda|Octavia RS 2016[<sup>12</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Škoda&model=Octavia RS 2016">Buy Here</a></sub></details>||
|
||||
|Škoda|Scala 2020-23[<sup>12</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Škoda&model=Scala 2020-23">Buy Here</a></sub></details>[<sup>14</sup>](#footnotes)||
|
||||
|Škoda|Superb 2015-22[<sup>12</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Škoda&model=Superb 2015-22">Buy Here</a></sub></details>||
|
||||
|Toyota|Alphard 2019-20|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Alphard 2019-20">Buy Here</a></sub></details>||
|
||||
|Toyota|Alphard Hybrid 2021|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Alphard Hybrid 2021">Buy Here</a></sub></details>||
|
||||
|Toyota|Avalon 2016|Toyota Safety Sense P|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Avalon 2016">Buy Here</a></sub></details>||
|
||||
@@ -206,11 +216,11 @@ A supported vehicle is one that just works when you install a comma device. All
|
||||
|Toyota|Avalon Hybrid 2019-21|All|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Avalon Hybrid 2019-21">Buy Here</a></sub></details>||
|
||||
|Toyota|Avalon Hybrid 2022|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Avalon Hybrid 2022">Buy Here</a></sub></details>||
|
||||
|Toyota|C-HR 2017-20|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=C-HR 2017-20">Buy Here</a></sub></details>||
|
||||
|Toyota|C-HR 2021|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=C-HR 2021">Buy Here</a></sub></details>||
|
||||
|Toyota|C-HR 2021|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=C-HR 2021">Buy Here</a></sub></details>||
|
||||
|Toyota|C-HR Hybrid 2017-20|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=C-HR Hybrid 2017-20">Buy Here</a></sub></details>||
|
||||
|Toyota|C-HR Hybrid 2021-22|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=C-HR Hybrid 2021-22">Buy Here</a></sub></details>||
|
||||
|Toyota|Camry 2018-20|All|Stock|0 mph[<sup>8</sup>](#footnotes)|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Camry 2018-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=fkcjviZY9CM" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Toyota|Camry 2021-23|All|openpilot|0 mph[<sup>8</sup>](#footnotes)|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Camry 2021-23">Buy Here</a></sub></details>||
|
||||
|Toyota|C-HR Hybrid 2021-22|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=C-HR Hybrid 2021-22">Buy Here</a></sub></details>||
|
||||
|Toyota|Camry 2018-20|All|Stock|0 mph[<sup>9</sup>](#footnotes)|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Camry 2018-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=fkcjviZY9CM" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Toyota|Camry 2021-24|All|openpilot|0 mph[<sup>9</sup>](#footnotes)|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Camry 2021-24">Buy Here</a></sub></details>||
|
||||
|Toyota|Camry Hybrid 2018-20|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Camry Hybrid 2018-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=Q2DYY0AWKgk" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Toyota|Camry Hybrid 2021-24|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Camry Hybrid 2021-24">Buy Here</a></sub></details>||
|
||||
|Toyota|Corolla 2017-19|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Corolla 2017-19">Buy Here</a></sub></details>||
|
||||
@@ -234,47 +244,49 @@ A supported vehicle is one that just works when you install a comma device. All
|
||||
|Toyota|RAV4 2016|Toyota Safety Sense P|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=RAV4 2016">Buy Here</a></sub></details>||
|
||||
|Toyota|RAV4 2017-18|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=RAV4 2017-18">Buy Here</a></sub></details>||
|
||||
|Toyota|RAV4 2019-21|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=RAV4 2019-21">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=wJxjDd42gGA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Toyota|RAV4 2022|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=RAV4 2022">Buy Here</a></sub></details>||
|
||||
|Toyota|RAV4 2022|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=RAV4 2022">Buy Here</a></sub></details>||
|
||||
|Toyota|RAV4 2023-24|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=RAV4 2023-24">Buy Here</a></sub></details>||
|
||||
|Toyota|RAV4 Hybrid 2016|Toyota Safety Sense P|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=RAV4 Hybrid 2016">Buy Here</a></sub></details>|<a href="https://youtu.be/LhT5VzJVfNI?t=26" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Toyota|RAV4 Hybrid 2017-18|All|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=RAV4 Hybrid 2017-18">Buy Here</a></sub></details>|<a href="https://youtu.be/LhT5VzJVfNI?t=26" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Toyota|RAV4 Hybrid 2019-21|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=RAV4 Hybrid 2019-21">Buy Here</a></sub></details>||
|
||||
|Toyota|RAV4 Hybrid 2022|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=RAV4 Hybrid 2022">Buy Here</a></sub></details>|<a href="https://youtu.be/U0nH9cnrFB0" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Toyota|RAV4 Hybrid 2022|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=RAV4 Hybrid 2022">Buy Here</a></sub></details>|<a href="https://youtu.be/U0nH9cnrFB0" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Toyota|RAV4 Hybrid 2023-24|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=RAV4 Hybrid 2023-24">Buy Here</a></sub></details>||
|
||||
|Toyota|Sienna 2018-20|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Sienna 2018-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=q1UPOo4Sh68" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Volkswagen|Arteon 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Arteon 2018-23">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Volkswagen|Arteon eHybrid 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Arteon eHybrid 2020-23">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Volkswagen|Arteon R 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Arteon R 2020-23">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Volkswagen|Atlas 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Atlas 2018-23">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Atlas Cross Sport 2020-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Atlas Cross Sport 2020-22">Buy Here</a></sub></details>||
|
||||
|Volkswagen|California 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=California 2021-23">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Caravelle 2020|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Caravelle 2020">Buy Here</a></sub></details>||
|
||||
|Volkswagen|CC 2018-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=CC 2018-22">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Volkswagen|Crafter 2017-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Crafter 2017-23">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Volkswagen|e-Crafter 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=e-Crafter 2018-23">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Volkswagen|e-Golf 2014-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=e-Golf 2014-20">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Golf 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Golf 2015-20">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Golf Alltrack 2015-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Golf Alltrack 2015-19">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Golf GTD 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Golf GTD 2015-20">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Golf GTE 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Golf GTE 2015-20">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Golf GTI 2015-21|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Golf GTI 2015-21">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Golf R 2015-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Golf R 2015-19">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Golf SportsVan 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Golf SportsVan 2015-20">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Grand California 2019-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Grand California 2019-23">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Volkswagen|Jetta 2018-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Jetta 2018-22">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Jetta GLI 2021-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Jetta GLI 2021-22">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Passat 2015-22[<sup>10</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Passat 2015-22">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Passat Alltrack 2015-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Passat Alltrack 2015-22">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Passat GTE 2015-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Passat GTE 2015-22">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Polo 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Polo 2018-23">Buy Here</a></sub></details>[<sup>13</sup>](#footnotes)||
|
||||
|Volkswagen|Polo GTI 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Polo GTI 2018-23">Buy Here</a></sub></details>[<sup>13</sup>](#footnotes)||
|
||||
|Volkswagen|T-Cross 2021|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=T-Cross 2021">Buy Here</a></sub></details>[<sup>13</sup>](#footnotes)||
|
||||
|Volkswagen|T-Roc 2021|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=T-Roc 2021">Buy Here</a></sub></details>[<sup>13</sup>](#footnotes)||
|
||||
|Volkswagen|Taos 2022-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Taos 2022-23">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Teramont 2018-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Teramont 2018-22">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Teramont Cross Sport 2021-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Teramont Cross Sport 2021-22">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Teramont X 2021-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Teramont X 2021-22">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Tiguan 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Tiguan 2018-23">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Tiguan eHybrid 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Tiguan eHybrid 2021-23">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Touran 2016-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Touran 2016-23">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Arteon 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Arteon 2018-23">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Volkswagen|Arteon eHybrid 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Arteon eHybrid 2020-23">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Volkswagen|Arteon R 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Arteon R 2020-23">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Volkswagen|Atlas 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Atlas 2018-23">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Atlas Cross Sport 2020-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Atlas Cross Sport 2020-22">Buy Here</a></sub></details>||
|
||||
|Volkswagen|California 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=California 2021-23">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Caravelle 2020|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Caravelle 2020">Buy Here</a></sub></details>||
|
||||
|Volkswagen|CC 2018-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=CC 2018-22">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Volkswagen|Crafter 2017-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Crafter 2017-23">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Volkswagen|e-Crafter 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=e-Crafter 2018-23">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Volkswagen|e-Golf 2014-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=e-Golf 2014-20">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Golf 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Golf 2015-20">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Golf Alltrack 2015-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Golf Alltrack 2015-19">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Golf GTD 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Golf GTD 2015-20">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Golf GTE 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Golf GTE 2015-20">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Golf GTI 2015-21|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Golf GTI 2015-21">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Golf R 2015-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Golf R 2015-19">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Golf SportsVan 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Golf SportsVan 2015-20">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Grand California 2019-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Grand California 2019-23">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Volkswagen|Jetta 2018-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Jetta 2018-24">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Jetta GLI 2021-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Jetta GLI 2021-24">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Passat 2015-22[<sup>11</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Passat 2015-22">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Passat Alltrack 2015-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Passat Alltrack 2015-22">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Passat GTE 2015-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Passat GTE 2015-22">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Polo 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Polo 2018-23">Buy Here</a></sub></details>[<sup>14</sup>](#footnotes)||
|
||||
|Volkswagen|Polo GTI 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Polo GTI 2018-23">Buy Here</a></sub></details>[<sup>14</sup>](#footnotes)||
|
||||
|Volkswagen|T-Cross 2021|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=T-Cross 2021">Buy Here</a></sub></details>[<sup>14</sup>](#footnotes)||
|
||||
|Volkswagen|T-Roc 2018-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=T-Roc 2018-22">Buy Here</a></sub></details>[<sup>14</sup>](#footnotes)||
|
||||
|Volkswagen|Taos 2022-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Taos 2022-23">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Teramont 2018-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Teramont 2018-22">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Teramont Cross Sport 2021-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Teramont Cross Sport 2021-22">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Teramont X 2021-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Teramont X 2021-22">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Tiguan 2018-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Tiguan 2018-24">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Tiguan eHybrid 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Tiguan eHybrid 2021-23">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Touran 2016-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Touran 2016-23">Buy Here</a></sub></details>||
|
||||
|
||||
### Footnotes
|
||||
<sup>1</sup>openpilot Longitudinal Control (Alpha) is available behind a toggle; the toggle is only available in non-release branches such as `devel` or `master-ci`. <br />
|
||||
@@ -284,12 +296,13 @@ A supported vehicle is one that just works when you install a comma device. All
|
||||
<sup>5</sup>2019 Honda Civic 1.6L Diesel Sedan does not have ALC below 12mph. <br />
|
||||
<sup>6</sup>Requires a <a href="https://comma.ai/shop/can-fd-panda-kit" target="_blank">CAN FD panda kit</a> if not using comma 3X for this <a href="https://en.wikipedia.org/wiki/CAN_FD" target="_blank">CAN FD car</a>. <br />
|
||||
<sup>7</sup>In the non-US market, openpilot requires the car to come equipped with EyeSight with Lane Keep Assistance. <br />
|
||||
<sup>8</sup>openpilot operates above 28mph for Camry 4CYL L, 4CYL LE and 4CYL SE which don't have Full-Speed Range Dynamic Radar Cruise Control. <br />
|
||||
<sup>9</sup>Not including the China market Kamiq, which is based on the (currently) unsupported PQ34 platform. <br />
|
||||
<sup>10</sup>Refers only to the MQB-based European B8 Passat, not the NMS Passat in the USA/China/Mideast markets. <br />
|
||||
<sup>11</sup>Some Škoda vehicles are equipped with heated windshields, which are known to block GPS signal needed for some comma 3X functionality. <br />
|
||||
<sup>12</sup>Only available for vehicles using a gateway (J533) harness. At this time, vehicles using a camera harness are limited to using stock ACC. <br />
|
||||
<sup>13</sup>Model-years 2022 and beyond may have a combined CAN gateway and BCM, which is supported by openpilot in software, but doesn't yet have a harness available from the comma store. <br />
|
||||
<sup>8</sup>Enabling longitudinal control (alpha) will disable all EyeSight functionality, including AEB, LDW, and RAB. <br />
|
||||
<sup>9</sup>openpilot operates above 28mph for Camry 4CYL L, 4CYL LE and 4CYL SE which don't have Full-Speed Range Dynamic Radar Cruise Control. <br />
|
||||
<sup>10</sup>Not including the China market Kamiq, which is based on the (currently) unsupported PQ34 platform. <br />
|
||||
<sup>11</sup>Refers only to the MQB-based European B8 Passat, not the NMS Passat in the USA/China/Mideast markets. <br />
|
||||
<sup>12</sup>Some Škoda vehicles are equipped with heated windshields, which are known to block GPS signal needed for some comma 3X functionality. <br />
|
||||
<sup>13</sup>Only available for vehicles using a gateway (J533) harness. At this time, vehicles using a camera harness are limited to using stock ACC. <br />
|
||||
<sup>14</sup>Model-years 2022 and beyond may have a combined CAN gateway and BCM, which is supported by openpilot in software, but doesn't yet have a harness available from the comma store. <br />
|
||||
|
||||
## Community Maintained Cars
|
||||
Although they're not upstream, the community has openpilot running on other makes and models. See the 'Community Supported Models' section of each make [on our wiki](https://wiki.comma.ai/).
|
||||
|
||||
+43
-26
@@ -1,26 +1,50 @@
|
||||
# How to contribute
|
||||
|
||||
Our software is open source so you can solve your own problems without needing help from others. And if you solve a problem and are so kind, you can upstream it for the rest of the world to use. Check out our [post about externalization](https://blog.comma.ai/a-2020-theme-externalization/).
|
||||
|
||||
Most open source development activity is coordinated through our [GitHub Discussions](https://github.com/commaai/openpilot/discussions) and [Discord](https://discord.comma.ai). A lot of documentation is available at https://docs.comma.ai and on our [blog](https://blog.comma.ai/).
|
||||
Our software is open source so you can solve your own problems without needing help from others. And if you solve a problem and are so kind, you can upstream it for the rest of the world to use. Check out our [post about externalization](https://blog.comma.ai/a-2020-theme-externalization/). Development activity is coordinated through our GitHub Issues, [GitHub Discussions](https://github.com/commaai/openpilot/discussions), and [Discord](https://discord.comma.ai).
|
||||
|
||||
### Getting Started
|
||||
|
||||
* Setup your [development environment](../tools/)
|
||||
* Join our [Discord](https://discord.comma.ai)
|
||||
* Make sure you have a [GitHub account](https://github.com/signup/free)
|
||||
* Fork [our repositories](https://github.com/commaai) on GitHub
|
||||
* Setup your [development environment](../tools/)
|
||||
* Read about the [development workflow](WORKFLOW.md)
|
||||
* Join our [Discord](https://discord.comma.ai)
|
||||
* Docs are at https://docs.comma.ai and https://blog.comma.ai
|
||||
|
||||
## What contributions are we looking for?
|
||||
|
||||
**openpilot's priorities are [safety](SAFETY.md), stability, quality, and features, in that order.** openpilot is part of comma's mission to *solve self-driving cars while delivering shippable intermediaries*, and **all** development is towards that goal.
|
||||
|
||||
### What gets merged?
|
||||
|
||||
The probability of a pull request being merged is a function of its value to the project and the effort it will take us to get it merged.
|
||||
If a PR offers *some* value but will take lots of time to get merged, it will be closed.
|
||||
Simple, well-tested bug fixes are the easiest to merge, and new features are the hardest to get merged.
|
||||
|
||||
All of these are examples of good PRs:
|
||||
* typo fix: https://github.com/commaai/openpilot/pull/30678
|
||||
* removing unused code: https://github.com/commaai/openpilot/pull/30573
|
||||
* simple car model port: https://github.com/commaai/openpilot/pull/30245
|
||||
* car brand port: https://github.com/commaai/openpilot/pull/23331
|
||||
|
||||
### What doesn't get merged?
|
||||
|
||||
* **arbitrary style changes**: code is art, and it's up to the author to make it beautiful
|
||||
* **500+ line PRs**: clean it up, break it up into smaller PRs, or both
|
||||
* **PRs without a clear goal**: every PR must have a singular and clear goal
|
||||
* **UI design changes**: we do not have a good review process for this yet
|
||||
* **New features**: We believe openpilot is mostly feature-complete, and the rest is a matter of refinement and fixing bugs. As a result of this, most feature PRs will be immediately closed, however the beauty of open source is that forks can and do offer features that upstream openpilot doesn't.
|
||||
|
||||
### First contribution
|
||||
Try out some of these first pull requests ideas to dive into the codebase:
|
||||
|
||||
* Increase our [mypy](http://mypy-lang.org/) coverage
|
||||
* Write some documentation
|
||||
* Tackle an open [good first issue](https://github.com/commaai/openpilot/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)
|
||||
Check out any [good first issue](https://github.com/commaai/openpilot/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) to get started.
|
||||
|
||||
### What do I need to contribute?
|
||||
|
||||
A lot of openpilot work requires only a PC, and some requires a comma device.
|
||||
Most car-related contributions require access to that car, plus a comma device installed in the car.
|
||||
|
||||
## Pull Requests
|
||||
|
||||
Pull requests should be against the master branch. Welcomed contributions include bug reports, car ports, and any [open issue](https://github.com/commaai/openpilot/issues). If you're unsure about a contribution, feel free to open a discussion, issue, or draft PR to discuss the problem you're trying to solve.
|
||||
Pull requests should be against the master branch. If you're unsure about a contribution, feel free to open a discussion, issue, or draft PR to discuss the problem you're trying to solve.
|
||||
|
||||
A good pull request has all of the following:
|
||||
* a clearly stated purpose
|
||||
@@ -31,18 +55,11 @@ A good pull request has all of the following:
|
||||
* if you've improved your car's tuning, post before and after plots
|
||||
* passes the CI tests
|
||||
|
||||
### Car Ports
|
||||
## Contributing without Code
|
||||
|
||||
We've released a [Model Port guide](https://blog.comma.ai/openpilot-port-guide-for-toyota-models/) for porting to Toyota/Lexus models.
|
||||
|
||||
If you port openpilot to a substantially new car brand, see this more generic [Brand Port guide](https://blog.comma.ai/how-to-write-a-car-port-for-openpilot/).
|
||||
|
||||
## Testing
|
||||
|
||||
### Automated Testing
|
||||
|
||||
All PRs and commits are automatically checked by GitHub Actions. Check out `.github/workflows/` for what GitHub Actions runs. Any new tests should be added to GitHub Actions.
|
||||
|
||||
### Code Style and Linting
|
||||
|
||||
Code is automatically checked for style by GitHub Actions as part of the automated tests. You can also run these tests yourself by running `pre-commit run --all`.
|
||||
* Report bugs in GitHub issues.
|
||||
* Report driving issues in the `#driving-feedback` Discord channel.
|
||||
* Consider opting into driver camera uploads to improve the driver monitoring model.
|
||||
* Connect your device to Wi-Fi regularly, so that we can pull data for training better driving models.
|
||||
* Run the `nightly` branch and report issues. This branch is like `master` but it's built just like a release.
|
||||
* Annotate images in the [comma10k dateset](https://github.com/commaai/comma10k).
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
import logging
|
||||
import os
|
||||
|
||||
from .astro_dog import AstroDog
|
||||
assert AstroDog is not None
|
||||
|
||||
# setup logging
|
||||
LOGLEVEL = os.environ.get('LOGLEVEL', 'INFO').upper()
|
||||
logging.basicConfig(level=LOGLEVEL, format='%(message)s')
|
||||
@@ -1,396 +0,0 @@
|
||||
from collections import defaultdict
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from typing import DefaultDict, Dict, Iterable, List, Optional, Union
|
||||
|
||||
from .constants import SECS_IN_DAY, SECS_IN_HR
|
||||
from .helpers import ConstellationId, get_constellation, get_closest, get_el_az, TimeRangeHolder
|
||||
from .ephemeris import Ephemeris, EphemerisType, GLONASSEphemeris, GPSEphemeris, PolyEphemeris, parse_sp3_orbits, parse_rinex_nav_msg_gps, \
|
||||
parse_rinex_nav_msg_glonass
|
||||
from .downloader import download_orbits_gps, download_orbits_russia_src, download_nav, download_ionex, download_dcb, download_prediction_orbits_russia_src
|
||||
from .downloader import download_cors_station
|
||||
from .trop import saast
|
||||
from .iono import IonexMap, parse_ionex, get_slant_delay
|
||||
from .dcb import DCB, parse_dcbs
|
||||
from .gps_time import GPSTime
|
||||
from .dgps import get_closest_station_names, parse_dgps
|
||||
from . import constants
|
||||
|
||||
MAX_DGPS_DISTANCE = 100_000 # in meters, because we're not barbarians
|
||||
|
||||
|
||||
class AstroDog:
|
||||
'''
|
||||
auto_update: flag indicating whether laika should fetch files from web automatically
|
||||
cache_dir: directory where data files are downloaded to and cached
|
||||
dgps: flag indicating whether laika should use dgps (CORS)
|
||||
data to calculate pseudorange corrections
|
||||
valid_const: list of constellation identifiers laika will try process
|
||||
valid_ephem_types: set of ephemeris types that are allowed to use and download.
|
||||
Default is set to use all orbit ephemeris types
|
||||
clear_old_ephemeris: flag indicating if ephemeris for an individual satellite should be overwritten when new ephemeris is added.
|
||||
'''
|
||||
|
||||
def __init__(self, auto_update=True,
|
||||
cache_dir='/tmp/gnss/',
|
||||
dgps=False,
|
||||
valid_const=(ConstellationId.GPS, ConstellationId.GLONASS),
|
||||
valid_ephem_types=EphemerisType.all_orbits(),
|
||||
clear_old_ephemeris=False):
|
||||
|
||||
for const in valid_const:
|
||||
if not isinstance(const, ConstellationId):
|
||||
raise TypeError(f"valid_const must be a list of ConstellationId, got {const}")
|
||||
|
||||
self.auto_update = auto_update
|
||||
self.cache_dir = cache_dir
|
||||
self.clear_old_ephemeris = clear_old_ephemeris
|
||||
self.dgps = dgps
|
||||
if not isinstance(valid_ephem_types, Iterable):
|
||||
valid_ephem_types = [valid_ephem_types]
|
||||
self.pull_orbit = len(set(EphemerisType.all_orbits()) & set(valid_ephem_types)) > 0
|
||||
self.pull_nav = EphemerisType.NAV in valid_ephem_types
|
||||
self.use_qcom_poly = EphemerisType.QCOM_POLY in valid_ephem_types
|
||||
self.valid_const = valid_const
|
||||
self.valid_ephem_types = valid_ephem_types
|
||||
|
||||
self.orbit_fetched_times = TimeRangeHolder()
|
||||
self.navs_fetched_times = TimeRangeHolder()
|
||||
self.dcbs_fetched_times = TimeRangeHolder()
|
||||
|
||||
self.dgps_delays = []
|
||||
self.ionex_maps: List[IonexMap] = []
|
||||
self.orbits: DefaultDict[str, List[PolyEphemeris]] = defaultdict(list)
|
||||
self.qcom_polys: DefaultDict[str, List[PolyEphemeris]] = defaultdict(list)
|
||||
self.navs: DefaultDict[str, List[Union[GPSEphemeris, GLONASSEphemeris]]] = defaultdict(list)
|
||||
self.dcbs: DefaultDict[str, List[DCB]] = defaultdict(list)
|
||||
|
||||
self.cached_ionex: Optional[IonexMap] = None
|
||||
self.cached_dgps = None
|
||||
self.cached_orbit: DefaultDict[str, Optional[PolyEphemeris]] = defaultdict(lambda: None)
|
||||
self.cached_qcom_polys: DefaultDict[str, Optional[PolyEphemeris]] = defaultdict(lambda: None)
|
||||
self.cached_nav: DefaultDict[str, Union[GPSEphemeris, GLONASSEphemeris, None]] = defaultdict(lambda: None)
|
||||
self.cached_dcb: DefaultDict[str, Optional[DCB]] = defaultdict(lambda: None)
|
||||
|
||||
def get_ionex(self, time) -> Optional[IonexMap]:
|
||||
ionex: Optional[IonexMap] = self._get_latest_valid_data(self.ionex_maps, self.cached_ionex, self.get_ionex_data, time)
|
||||
if ionex is None:
|
||||
if self.auto_update:
|
||||
raise RuntimeError("Pulled ionex, but still can't get valid for time " + str(time))
|
||||
else:
|
||||
self.cached_ionex = ionex
|
||||
return ionex
|
||||
|
||||
def get_nav(self, prn, time):
|
||||
skip_download = time in self.navs_fetched_times
|
||||
nav = self._get_latest_valid_data(self.navs[prn], self.cached_nav[prn], self.get_nav_data, time, skip_download)
|
||||
if nav is not None:
|
||||
self.cached_nav[prn] = nav
|
||||
return nav
|
||||
|
||||
@staticmethod
|
||||
def _select_valid_temporal_items(item_dict, time, cache):
|
||||
'''Returns only valid temporal item for specific time from currently fetched
|
||||
data.'''
|
||||
result = {}
|
||||
for prn, temporal_objects in item_dict.items():
|
||||
cached = cache[prn]
|
||||
if cached is not None and cached.valid(time):
|
||||
obj = cached
|
||||
else:
|
||||
obj = get_closest(time, temporal_objects)
|
||||
if obj is None or not obj.valid(time):
|
||||
continue
|
||||
cache[prn] = obj
|
||||
result[prn] = obj
|
||||
return result
|
||||
|
||||
def get_all_ephem_prns(self):
|
||||
return set(self.orbits.keys()).union(set(self.navs.keys())).union(set(self.qcom_polys.keys()))
|
||||
|
||||
def get_navs(self, time):
|
||||
if time not in self.navs_fetched_times:
|
||||
self.get_nav_data(time)
|
||||
return AstroDog._select_valid_temporal_items(self.navs, time, self.cached_nav)
|
||||
|
||||
def get_orbit(self, prn: str, time: GPSTime):
|
||||
skip_download = time in self.orbit_fetched_times
|
||||
orbit = self._get_latest_valid_data(self.orbits[prn], self.cached_orbit[prn], self.get_orbit_data, time, skip_download)
|
||||
if orbit is not None:
|
||||
self.cached_orbit[prn] = orbit
|
||||
return orbit
|
||||
|
||||
def get_qcom_poly(self, prn: str, time: GPSTime):
|
||||
poly = self._get_latest_valid_data(self.qcom_polys[prn], self.cached_qcom_polys[prn], None, time, True)
|
||||
if poly is not None:
|
||||
self.cached_qcom_polys[prn] = poly
|
||||
return poly
|
||||
|
||||
def get_orbits(self, time):
|
||||
if time not in self.orbit_fetched_times:
|
||||
self.get_orbit_data(time)
|
||||
return AstroDog._select_valid_temporal_items(self.orbits, time, self.cached_orbit)
|
||||
|
||||
def get_dcb(self, prn, time):
|
||||
skip_download = time in self.dcbs_fetched_times
|
||||
dcb = self._get_latest_valid_data(self.dcbs[prn], self.cached_dcb[prn], self.get_dcb_data, time, skip_download)
|
||||
if dcb is not None:
|
||||
self.cached_dcb[prn] = dcb
|
||||
return dcb
|
||||
|
||||
def get_dgps_corrections(self, time, recv_pos):
|
||||
latest_data = self._get_latest_valid_data(self.dgps_delays, self.cached_dgps, self.get_dgps_data, time, recv_pos=recv_pos)
|
||||
if latest_data is None:
|
||||
if self.auto_update:
|
||||
raise RuntimeError("Pulled dgps, but still can't get valid for time " + str(time))
|
||||
else:
|
||||
self.cached_dgps = latest_data
|
||||
return latest_data
|
||||
|
||||
def add_qcom_polys(self, new_ephems: Dict[str, List[Ephemeris]]):
|
||||
self._add_ephems(new_ephems, self.qcom_polys)
|
||||
|
||||
def add_orbits(self, new_ephems: Dict[str, List[Ephemeris]]):
|
||||
self._add_ephems(new_ephems, self.orbits)
|
||||
|
||||
def add_navs(self, new_ephems: Dict[str, List[Ephemeris]]):
|
||||
self._add_ephems(new_ephems, self.navs)
|
||||
|
||||
def _add_ephems(self, new_ephems: Dict[str, List[Ephemeris]], ephems_dict):
|
||||
for k, v in new_ephems.items():
|
||||
if len(v) > 0:
|
||||
if self.clear_old_ephemeris:
|
||||
ephems_dict[k] = v
|
||||
else:
|
||||
ephems_dict[k].extend(v)
|
||||
|
||||
def add_ephem_fetched_time(self, ephems, fetched_times):
|
||||
min_epochs = []
|
||||
max_epochs = []
|
||||
for v in ephems.values():
|
||||
if len(v) > 0:
|
||||
min_ephem, max_ephem = self.get_epoch_range(v)
|
||||
min_epochs.append(min_ephem)
|
||||
max_epochs.append(max_ephem)
|
||||
if len(min_epochs) > 0:
|
||||
min_epoch = min(min_epochs)
|
||||
max_epoch = max(max_epochs)
|
||||
fetched_times.add(min_epoch, max_epoch)
|
||||
|
||||
def get_nav_data(self, time):
|
||||
def download_and_parse(constellation, parse_rinex_nav_func):
|
||||
file_path = download_nav(time, cache_dir=self.cache_dir, constellation=constellation)
|
||||
return parse_rinex_nav_func(file_path) if file_path else {}
|
||||
|
||||
fetched_ephems = {}
|
||||
|
||||
if ConstellationId.GPS in self.valid_const:
|
||||
fetched_ephems = download_and_parse(ConstellationId.GPS, parse_rinex_nav_msg_gps)
|
||||
if ConstellationId.GLONASS in self.valid_const:
|
||||
for k, v in download_and_parse(ConstellationId.GLONASS, parse_rinex_nav_msg_glonass).items():
|
||||
fetched_ephems.setdefault(k, []).extend(v)
|
||||
self.add_navs(fetched_ephems)
|
||||
|
||||
if sum([len(v) for v in fetched_ephems.values()]) == 0:
|
||||
begin_day = GPSTime(time.week, SECS_IN_DAY * (time.tow // SECS_IN_DAY))
|
||||
end_day = GPSTime(time.week, SECS_IN_DAY * (1 + (time.tow // SECS_IN_DAY)))
|
||||
self.navs_fetched_times.add(begin_day, end_day)
|
||||
|
||||
def download_parse_orbit(self, gps_time: GPSTime, skip_before_epoch=None) -> Dict[str, List[PolyEphemeris]]:
|
||||
# Download multiple days to be able to polyfit at the start-end of the day
|
||||
time_steps = [gps_time - SECS_IN_DAY, gps_time, gps_time + SECS_IN_DAY]
|
||||
with ThreadPoolExecutor() as executor:
|
||||
futures_other = [executor.submit(download_orbits_russia_src, t, self.cache_dir, self.valid_ephem_types) for t in time_steps]
|
||||
futures_gps = None
|
||||
if ConstellationId.GPS in self.valid_const:
|
||||
futures_gps = [executor.submit(download_orbits_gps, t, self.cache_dir, self.valid_ephem_types) for t in time_steps]
|
||||
|
||||
ephems_other = parse_sp3_orbits([f.result() for f in futures_other if f.result()], self.valid_const, skip_before_epoch)
|
||||
ephems_us = parse_sp3_orbits([f.result() for f in futures_gps if f.result()], self.valid_const, skip_before_epoch) if futures_gps else {}
|
||||
|
||||
return {k: ephems_other.get(k, []) + ephems_us.get(k, []) for k in set(list(ephems_other.keys()) + list(ephems_us.keys()))}
|
||||
|
||||
def download_parse_prediction_orbit(self, gps_time: GPSTime):
|
||||
assert EphemerisType.ULTRA_RAPID_ORBIT in self.valid_ephem_types
|
||||
skip_until_epoch = gps_time - 2 * SECS_IN_HR
|
||||
|
||||
result = download_prediction_orbits_russia_src(gps_time, self.cache_dir)
|
||||
if result is not None:
|
||||
result = [result]
|
||||
elif ConstellationId.GPS in self.valid_const:
|
||||
# Slower fallback. Russia src prediction orbits are published from 2022
|
||||
result = [download_orbits_gps(t, self.cache_dir, self.valid_ephem_types) for t in [gps_time - SECS_IN_DAY, gps_time]]
|
||||
if result is None:
|
||||
return {}
|
||||
return parse_sp3_orbits(result, self.valid_const, skip_until_epoch=skip_until_epoch)
|
||||
|
||||
def get_orbit_data(self, time: GPSTime, only_predictions=False):
|
||||
if only_predictions:
|
||||
ephems_sp3 = self.download_parse_prediction_orbit(time)
|
||||
else:
|
||||
ephems_sp3 = self.download_parse_orbit(time)
|
||||
if sum([len(v) for v in ephems_sp3.values()]) < 5:
|
||||
raise RuntimeError(f'No orbit data found. For Time {time.as_datetime()} constellations {self.valid_const} valid ephem types {self.valid_ephem_types}')
|
||||
self.add_ephem_fetched_time(ephems_sp3, self.orbit_fetched_times)
|
||||
self.add_orbits(ephems_sp3)
|
||||
|
||||
def get_dcb_data(self, time):
|
||||
file_path_dcb = download_dcb(time, cache_dir=self.cache_dir)
|
||||
dcbs = parse_dcbs(file_path_dcb, self.valid_const)
|
||||
for dcb in dcbs:
|
||||
self.dcbs[dcb.prn].append(dcb)
|
||||
|
||||
if len(dcbs) != 0:
|
||||
min_epoch, max_epoch = self.get_epoch_range(dcbs)
|
||||
self.dcbs_fetched_times.add(min_epoch, max_epoch)
|
||||
|
||||
def get_epoch_range(self, new_ephems):
|
||||
min_ephem = min(new_ephems, key=lambda e: e.epoch)
|
||||
max_ephem = max(new_ephems, key=lambda e: e.epoch)
|
||||
min_epoch = min_ephem.epoch - min_ephem.max_time_diff
|
||||
max_epoch = max_ephem.epoch + max_ephem.max_time_diff
|
||||
return min_epoch, max_epoch
|
||||
|
||||
def get_ionex_data(self, time):
|
||||
file_path_ionex = download_ionex(time, cache_dir=self.cache_dir)
|
||||
ionex_maps = parse_ionex(file_path_ionex)
|
||||
for im in ionex_maps:
|
||||
self.ionex_maps.append(im)
|
||||
|
||||
def get_dgps_data(self, time, recv_pos):
|
||||
station_names = get_closest_station_names(recv_pos, k=8, max_distance=MAX_DGPS_DISTANCE, cache_dir=self.cache_dir)
|
||||
for station_name in station_names:
|
||||
file_path_station = download_cors_station(time, station_name, cache_dir=self.cache_dir)
|
||||
if file_path_station:
|
||||
dgps = parse_dgps(station_name, file_path_station,
|
||||
self, max_distance=MAX_DGPS_DISTANCE,
|
||||
required_constellations=self.valid_const)
|
||||
if dgps is not None:
|
||||
self.dgps_delays.append(dgps)
|
||||
break
|
||||
|
||||
def get_tgd_from_nav(self, prn, time):
|
||||
if get_constellation(prn) not in self.valid_const:
|
||||
return None
|
||||
|
||||
eph = self.get_nav(prn, time)
|
||||
|
||||
if eph:
|
||||
return eph.get_tgd()
|
||||
return None
|
||||
|
||||
def get_eph(self, prn, time):
|
||||
if get_constellation(prn) not in self.valid_const:
|
||||
return None
|
||||
eph = None
|
||||
if self.pull_orbit:
|
||||
eph = self.get_orbit(prn, time)
|
||||
if not eph and self.pull_nav:
|
||||
eph = self.get_nav(prn, time)
|
||||
if not eph and self.use_qcom_poly:
|
||||
eph = self.get_qcom_poly(prn, time)
|
||||
return eph
|
||||
|
||||
def get_sat_info(self, prn, time):
|
||||
eph = self.get_eph(prn, time)
|
||||
if eph:
|
||||
return eph.get_sat_info(time)
|
||||
return None
|
||||
|
||||
def get_all_sat_info(self, time):
|
||||
ephs = {}
|
||||
if self.pull_orbit:
|
||||
ephs = self.get_orbits(time)
|
||||
if len(ephs) == 0 and self.pull_nav:
|
||||
ephs = self.get_navs(time)
|
||||
|
||||
return {prn: eph.get_sat_info(time) for prn, eph in ephs.items()}
|
||||
|
||||
def get_glonass_channel(self, prn, time):
|
||||
nav = self.get_nav(prn, time)
|
||||
if nav:
|
||||
return nav.channel
|
||||
return None
|
||||
|
||||
def get_frequency(self, prn, time, signal='C1C'):
|
||||
if get_constellation(prn) == ConstellationId.GPS:
|
||||
switch = {'1': constants.GPS_L1,
|
||||
'2': constants.GPS_L2,
|
||||
'5': constants.GPS_L5,
|
||||
'6': constants.GALILEO_E6,
|
||||
'7': constants.GALILEO_E5B,
|
||||
'8': constants.GALILEO_E5AB}
|
||||
freq = switch.get(signal[1])
|
||||
if freq:
|
||||
return freq
|
||||
raise NotImplementedError("Dont know this GPS frequency: ", signal, prn)
|
||||
elif get_constellation(prn) == ConstellationId.GLONASS:
|
||||
n = self.get_glonass_channel(prn, time)
|
||||
if n is None:
|
||||
return None
|
||||
switch = {'1': constants.GLONASS_L1 + n * constants.GLONASS_L1_DELTA,
|
||||
'2': constants.GLONASS_L2 + n * constants.GLONASS_L2_DELTA,
|
||||
'5': constants.GLONASS_L5 + n * constants.GLONASS_L5_DELTA,
|
||||
'6': constants.GALILEO_E6,
|
||||
'7': constants.GALILEO_E5B,
|
||||
'8': constants.GALILEO_E5AB}
|
||||
freq = switch.get(signal[1])
|
||||
if freq:
|
||||
return freq
|
||||
raise NotImplementedError("Dont know this GLONASS frequency: ", signal, prn)
|
||||
|
||||
def get_delay(self, prn, time, rcv_pos, no_dgps=False, signal='C1C', freq=None):
|
||||
sat_info = self.get_sat_info(prn, time)
|
||||
if sat_info is None:
|
||||
return None
|
||||
sat_pos = sat_info[0]
|
||||
el, az = get_el_az(rcv_pos, sat_pos)
|
||||
if el < 0.2:
|
||||
return None
|
||||
if self.dgps and not no_dgps:
|
||||
return self._get_delay_dgps(prn, rcv_pos, time)
|
||||
|
||||
ionex = self.get_ionex(time)
|
||||
if not freq and ionex is not None:
|
||||
freq = self.get_frequency(prn, time, signal)
|
||||
dcb = self.get_dcb(prn, time)
|
||||
# When using internet we expect all data or return None
|
||||
if self.auto_update and (ionex is None or dcb is None or freq is None):
|
||||
return None
|
||||
if ionex is not None:
|
||||
iono_delay = ionex.get_delay(rcv_pos, az, el, sat_pos, time, freq)
|
||||
else:
|
||||
# 5m vertical delay is a good default
|
||||
iono_delay = get_slant_delay(rcv_pos, az, el, sat_pos, time, freq, vertical_delay=5.0)
|
||||
trop_delay = saast(rcv_pos, el)
|
||||
code_bias = dcb.get_delay(signal) if dcb is not None else 0.
|
||||
return iono_delay + trop_delay + code_bias
|
||||
|
||||
def _get_delay_dgps(self, prn, rcv_pos, time):
|
||||
dgps_corrections = self.get_dgps_corrections(time, rcv_pos)
|
||||
if dgps_corrections is None:
|
||||
return None
|
||||
return dgps_corrections.get_delay(prn, time)
|
||||
|
||||
def _get_latest_valid_data(self, data, latest_data, download_data_func, time, skip_download=False, recv_pos=None):
|
||||
def is_valid(latest_data):
|
||||
if recv_pos is None:
|
||||
return latest_data is not None and latest_data.valid(time)
|
||||
else:
|
||||
return latest_data is not None and latest_data.valid(time, recv_pos)
|
||||
|
||||
if is_valid(latest_data):
|
||||
return latest_data
|
||||
|
||||
latest_data = get_closest(time, data, recv_pos=recv_pos)
|
||||
if is_valid(latest_data):
|
||||
return latest_data
|
||||
if skip_download or not self.auto_update:
|
||||
return None
|
||||
if recv_pos is not None:
|
||||
download_data_func(time, recv_pos)
|
||||
else:
|
||||
download_data_func(time)
|
||||
latest_data = get_closest(time, data, recv_pos=recv_pos)
|
||||
if is_valid(latest_data):
|
||||
return latest_data
|
||||
return None
|
||||
@@ -1,34 +0,0 @@
|
||||
# These are all from IS-GPS-200G unless otherwise noted
|
||||
|
||||
SPEED_OF_LIGHT = 2.99792458e8 # m/s
|
||||
|
||||
# Physical parameters of the Earth
|
||||
EARTH_GM = 3.986005e14 # m^3/s^2 (gravitational constant * mass of earth)
|
||||
EARTH_RADIUS = 6.3781e6 # m
|
||||
EARTH_ROTATION_RATE = 7.2921151467e-005 # rad/s (WGS84 earth rotation rate)
|
||||
|
||||
# GPS system parameters:
|
||||
GPS_L1 = l1 = 1.57542e9 # Hz
|
||||
GPS_L2 = l2 = 1.22760e9 # Hz
|
||||
GPS_L5 = l5 = 1.17645e9 # Hz Also E5
|
||||
|
||||
#GLONASS system parameters
|
||||
#TODO this is old convention
|
||||
GLONASS_L1 = 1.602e9
|
||||
GLONASS_L1_DELTA = 0.5625e6
|
||||
GLONASS_L2 = 1.246e9
|
||||
GLONASS_L2_DELTA = 0.4375e6
|
||||
GLONASS_L5 = 1.201e9
|
||||
GLONASS_L5_DELTA = 0.4375e6
|
||||
|
||||
#Galileo system parameters: # Has additional frequencies on E6
|
||||
#Source RINEX 2.11 document
|
||||
GALILEO_E5B = 1.207140e9 # Hz
|
||||
GALILEO_E5AB = 1.191795e9 # Hz
|
||||
GALILEO_E6 = 1.27875e9 # Hz
|
||||
|
||||
SECS_IN_MIN = 60
|
||||
SECS_IN_HR = 60*SECS_IN_MIN
|
||||
SECS_IN_DAY = 24*SECS_IN_HR
|
||||
SECS_IN_WEEK = 7*SECS_IN_DAY
|
||||
SECS_IN_YEAR = 365*SECS_IN_DAY
|
||||
@@ -1,84 +0,0 @@
|
||||
from datetime import datetime
|
||||
from .constants import SECS_IN_HR, SECS_IN_WEEK, \
|
||||
SPEED_OF_LIGHT, GPS_L1, GPS_L2
|
||||
from .gps_time import GPSTime
|
||||
from .helpers import get_constellation
|
||||
import warnings
|
||||
|
||||
|
||||
class DCB:
|
||||
def __init__(self, prn, data):
|
||||
self.max_time_diff = 2*SECS_IN_WEEK
|
||||
self.prn = prn
|
||||
self.epoch = data['epoch']
|
||||
self.healthy = True
|
||||
if 'C1W_C2W' in data:
|
||||
self.C1W_C2W = data['C1W_C2W']
|
||||
elif 'C1P_C2P' in data:
|
||||
self.C1W_C2W = data['C1P_C2P']
|
||||
else:
|
||||
self.healthy = False
|
||||
if 'C1C_C1W' in data:
|
||||
self.C1C_C1W = data['C1C_C1W']
|
||||
elif 'C1C_C1P' in data:
|
||||
self.C1C_C1W = data['C1C_C1P']
|
||||
else:
|
||||
self.healthy = False
|
||||
|
||||
def valid(self, time):
|
||||
return abs(time - self.epoch) <= self.max_time_diff and self.healthy
|
||||
|
||||
def get_delay(self, signal):
|
||||
if signal == 'C1C':
|
||||
return (- SPEED_OF_LIGHT*1e-9*self.C1W_C2W*GPS_L2**2/(GPS_L1**2 - GPS_L2**2)
|
||||
+ SPEED_OF_LIGHT*1e-9*self.C1C_C1W)
|
||||
if signal == 'C2P':
|
||||
return (- SPEED_OF_LIGHT*1e-9*self.C1W_C2W*GPS_L1**2/(GPS_L1**2 - GPS_L2**2))
|
||||
if signal == 'C1P':
|
||||
return (SPEED_OF_LIGHT*1e-9*self.C1C_C1W)
|
||||
## Todo: update dcb database and get delay to include additional signals
|
||||
if signal == 'C2C':
|
||||
warnings.warn("Differential code bias not implemented for signal C2C", UserWarning)
|
||||
return 0
|
||||
if signal == 'C5C':
|
||||
warnings.warn("Differential code bias not implemented for signal C5C", UserWarning)
|
||||
return 0
|
||||
if signal == 'C6C':
|
||||
warnings.warn("Differential code bias not implemented for signal C6C", UserWarning)
|
||||
return 0
|
||||
if signal == 'C7C':
|
||||
warnings.warn("Differential code bias not implemented for signal C7C", UserWarning)
|
||||
return 0
|
||||
if signal == 'C8C':
|
||||
warnings.warn("Differential code bias not implemented for signal C8C", UserWarning)
|
||||
return 0
|
||||
|
||||
|
||||
def parse_dcbs(file_name, SUPPORTED_CONSTELLATIONS):
|
||||
with open(file_name, 'r+') as DCB_file:
|
||||
contents = DCB_file.readlines()
|
||||
data_started = False
|
||||
dcbs_dict = {}
|
||||
for line in contents:
|
||||
if not data_started:
|
||||
if line[1:4] == 'DSB':
|
||||
data_started = True
|
||||
else:
|
||||
continue
|
||||
line_components = line.split()
|
||||
if len(line_components[2]) < 3:
|
||||
break
|
||||
prn = line_components[2]
|
||||
if get_constellation(prn) not in SUPPORTED_CONSTELLATIONS:
|
||||
continue
|
||||
dcb_type = line_components[3] + '_' + line_components[4]
|
||||
epoch = GPSTime.from_datetime(datetime.strptime(line_components[5], '%Y:%j:%f')) + 12*SECS_IN_HR
|
||||
if prn not in dcbs_dict:
|
||||
dcbs_dict[prn] = {}
|
||||
dcbs_dict[prn][dcb_type] = float(line_components[8])
|
||||
dcbs_dict[prn]['epoch'] = epoch
|
||||
|
||||
dcbs = []
|
||||
for prn in dcbs_dict:
|
||||
dcbs.append(DCB(prn, dcbs_dict[prn]))
|
||||
return dcbs
|
||||
-161
@@ -1,161 +0,0 @@
|
||||
import os
|
||||
import numpy as np
|
||||
from datetime import datetime
|
||||
|
||||
from .gps_time import GPSTime
|
||||
from .constants import SECS_IN_YEAR
|
||||
from . import raw_gnss as raw
|
||||
from . import opt
|
||||
from .rinex_file import RINEXFile
|
||||
from .downloader import download_cors_coords
|
||||
from .helpers import get_constellation, ConstellationId
|
||||
|
||||
def mean_filter(delay):
|
||||
d2 = delay.copy()
|
||||
max_step = 10
|
||||
for i in range(max_step, len(delay) - max_step):
|
||||
finite_idxs = np.where(np.isfinite(delay[i - max_step:i + max_step]))
|
||||
if max_step in finite_idxs[0]:
|
||||
step = min([max_step, finite_idxs[0][-1] - max_step, max_step - finite_idxs[0][0]])
|
||||
d2[i] = np.nanmean(delay[i - step:i + step + 1])
|
||||
return d2
|
||||
|
||||
|
||||
def download_and_parse_station_postions(cors_station_positions_path, cache_dir):
|
||||
if not os.path.isfile(cors_station_positions_path):
|
||||
cors_stations = {}
|
||||
coord_file_paths = download_cors_coords(cache_dir=cache_dir)
|
||||
for coord_file_path in coord_file_paths:
|
||||
try:
|
||||
station_id = coord_file_path.split('/')[-1][:4]
|
||||
with open(coord_file_path, 'r+') as coord_file:
|
||||
contents = coord_file.readlines()
|
||||
phase_center = False
|
||||
for line_number in range(len(contents)):
|
||||
if 'L1 Phase Center' in contents[line_number]:
|
||||
phase_center = True
|
||||
if not phase_center and 'ITRF2014 POSITION' in contents[line_number]:
|
||||
velocity = [float(contents[line_number+8].split()[3]),
|
||||
float(contents[line_number+9].split()[3]),
|
||||
float(contents[line_number+10].split()[3])]
|
||||
if phase_center and 'ITRF2014 POSITION' in contents[line_number]:
|
||||
epoch = GPSTime.from_datetime(datetime(2005,1,1))
|
||||
position = [float(contents[line_number+2].split()[3]),
|
||||
float(contents[line_number+3].split()[3]),
|
||||
float(contents[line_number+4].split()[3])]
|
||||
cors_stations[station_id] = [epoch, position, velocity]
|
||||
break
|
||||
except ValueError:
|
||||
pass
|
||||
cors_station_positions_file = open(cors_station_positions_path, 'wb')
|
||||
np.save(cors_station_positions_file, cors_stations)
|
||||
cors_station_positions_file.close()
|
||||
|
||||
|
||||
def get_closest_station_names(pos, k=5, max_distance=100000, cache_dir='/tmp/gnss/'):
|
||||
from scipy.spatial import cKDTree
|
||||
|
||||
cors_station_positions_dict = load_cors_station_positions(cache_dir)
|
||||
station_ids = list(cors_station_positions_dict.keys())
|
||||
station_positions = []
|
||||
for station_id in station_ids:
|
||||
station_positions.append(cors_station_positions_dict[station_id][1])
|
||||
tree = cKDTree(station_positions)
|
||||
distances, idxs = tree.query(pos, k=k, distance_upper_bound=max_distance)
|
||||
return np.array(station_ids)[idxs]
|
||||
|
||||
|
||||
def load_cors_station_positions(cache_dir):
|
||||
cors_station_positions_path = cache_dir + 'cors_coord/cors_station_positions'
|
||||
download_and_parse_station_postions(cors_station_positions_path, cache_dir)
|
||||
with open(cors_station_positions_path, 'rb') as f:
|
||||
return np.load(f, allow_pickle=True).item() # pylint: disable=unexpected-keyword-arg
|
||||
|
||||
|
||||
def get_station_position(station_id, cache_dir='/tmp/gnss/', time=GPSTime.from_datetime(datetime.utcnow())):
|
||||
cors_station_positions_dict = load_cors_station_positions(cache_dir)
|
||||
epoch, pos, vel = cors_station_positions_dict[station_id]
|
||||
return ((time - epoch)/SECS_IN_YEAR)*np.array(vel) + np.array(pos)
|
||||
|
||||
|
||||
def parse_dgps(station_id, station_obs_file_path, dog, max_distance=100000, required_constellations=[ConstellationId.GPS]):
|
||||
station_pos = get_station_position(station_id, cache_dir=dog.cache_dir)
|
||||
obsdata = RINEXFile(station_obs_file_path)
|
||||
measurements = raw.read_rinex_obs(obsdata)
|
||||
|
||||
# if not all constellations in first 100 epochs bail
|
||||
detected_constellations = set()
|
||||
for m in sum(measurements[:100],[]):
|
||||
detected_constellations.add(get_constellation(m.prn))
|
||||
for constellation in required_constellations:
|
||||
if constellation not in detected_constellations:
|
||||
return None
|
||||
|
||||
proc_measurements = []
|
||||
for measurement in measurements:
|
||||
proc_measurements.append(raw.process_measurements(measurement, dog=dog))
|
||||
# sample at 30s
|
||||
if len(proc_measurements) > 2880:
|
||||
proc_measurements = proc_measurements[::int(len(proc_measurements)/2880)]
|
||||
if len(proc_measurements) != 2880:
|
||||
return None
|
||||
|
||||
station_delays = {}
|
||||
n = len(proc_measurements)
|
||||
for signal in ['C1C', 'C2P']:
|
||||
times = []
|
||||
station_delays[signal] = {}
|
||||
for i, proc_measurement in enumerate(proc_measurements):
|
||||
times.append(proc_measurement[0].recv_time)
|
||||
Fx_pos = opt.pr_residual(proc_measurement, signal=signal)
|
||||
residual, _ = Fx_pos(list(station_pos) + [0,0])
|
||||
residual = -np.array(residual)
|
||||
for j, m in enumerate(proc_measurement):
|
||||
prn = m.prn
|
||||
if prn not in station_delays[signal]:
|
||||
station_delays[signal][prn] = np.nan*np.ones(n)
|
||||
station_delays[signal][prn][i] = residual[j]
|
||||
assert len(times) == n
|
||||
|
||||
# TODO crude way to get dgps station's clock errors,
|
||||
# could this be biased? Only use GPS for convenience.
|
||||
model_delays = {}
|
||||
for prn in station_delays['C1C']:
|
||||
if get_constellation(prn) == ConstellationId.GPS:
|
||||
model_delays[prn] = np.nan*np.zeros(n)
|
||||
for i in range(n):
|
||||
model_delays[prn][i] = dog.get_delay(prn, times[i], station_pos, no_dgps=True)
|
||||
station_clock_errs = np.zeros(n)
|
||||
for i in range(n):
|
||||
station_clock_errs[i] = np.nanmean([(station_delays['C1C'][prn][i] - model_delays[prn][i]) for prn in model_delays])
|
||||
|
||||
# remove clock errors and smooth out signal
|
||||
for prn in station_delays['C1C']:
|
||||
station_delays['C1C'][prn] = mean_filter(station_delays['C1C'][prn] - station_clock_errs)
|
||||
for prn in station_delays['C2P']:
|
||||
station_delays['C2P'][prn] = station_delays['C2P'][prn] - station_clock_errs
|
||||
|
||||
return DGPSDelay(station_id, station_pos, station_delays,
|
||||
times, max_distance)
|
||||
|
||||
|
||||
class DGPSDelay:
|
||||
def __init__(self, station_id, station_pos,
|
||||
station_delays, station_delays_t, max_distance):
|
||||
self.id = station_id
|
||||
self.pos = station_pos
|
||||
self.delays = station_delays
|
||||
self.delays_t = station_delays_t
|
||||
self.max_distance = max_distance
|
||||
|
||||
def get_delay(self, prn, time, signal='C1C'):
|
||||
time_index = int((time - self.delays_t[0])/30)
|
||||
assert abs(self.delays_t[time_index] - time) < 30
|
||||
if prn in self.delays[signal] and np.isfinite(self.delays[signal][prn][time_index]):
|
||||
return self.delays[signal][prn][time_index]
|
||||
return None
|
||||
|
||||
def valid(self, time, recv_pos):
|
||||
return (np.linalg.norm(recv_pos - self.pos) <= self.max_distance and
|
||||
time - self.delays_t[0] > -30 and
|
||||
self.delays_t[-1] - time > -30)
|
||||
@@ -1,473 +0,0 @@
|
||||
import certifi
|
||||
import ftplib
|
||||
import hatanaka
|
||||
import os
|
||||
import pycurl
|
||||
import re
|
||||
import time
|
||||
import socket
|
||||
import logging
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from urllib.parse import urlparse
|
||||
from io import BytesIO
|
||||
from ftplib import FTP_TLS, FTP
|
||||
|
||||
from atomicwrites import atomic_write
|
||||
|
||||
from laika.ephemeris import EphemerisType
|
||||
from .constants import SECS_IN_HR, SECS_IN_DAY, SECS_IN_WEEK
|
||||
from .gps_time import GPSTime, tow_to_datetime
|
||||
from .helpers import ConstellationId
|
||||
|
||||
dir_path = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
class DownloadFailed(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def retryable(f):
|
||||
"""
|
||||
Decorator to allow us to pass multiple URLs from which to download.
|
||||
Automatically retry the request with the next URL on failure
|
||||
"""
|
||||
def wrapped(url_bases, *args, **kwargs):
|
||||
if isinstance(url_bases, str):
|
||||
# only one url passed, don't do the retry thing
|
||||
return f(url_bases, *args, **kwargs)
|
||||
|
||||
# not a string, must be a list of url_bases
|
||||
for url_base in url_bases:
|
||||
try:
|
||||
return f(url_base, *args, **kwargs)
|
||||
except DownloadFailed as e:
|
||||
logging.warning(e)
|
||||
# none of them succeeded
|
||||
raise DownloadFailed("Multiple URL failures attempting to pull file(s)")
|
||||
return wrapped
|
||||
|
||||
|
||||
def ftp_connect(url):
|
||||
parsed = urlparse(url)
|
||||
assert parsed.scheme == 'ftp'
|
||||
try:
|
||||
domain = parsed.netloc
|
||||
ftp = ftplib.FTP(domain, timeout=10)
|
||||
ftp.login()
|
||||
except (OSError, ftplib.error_perm):
|
||||
raise DownloadFailed("Could not connect/auth to: " + domain)
|
||||
try:
|
||||
ftp.cwd(parsed.path)
|
||||
except ftplib.error_perm:
|
||||
raise DownloadFailed("Permission failure with folder: " + url)
|
||||
return ftp
|
||||
|
||||
|
||||
@retryable
|
||||
def list_dir(url):
|
||||
parsed = urlparse(url)
|
||||
if parsed.scheme == 'ftp':
|
||||
try:
|
||||
ftp = ftp_connect(url)
|
||||
return ftp.nlst()
|
||||
except ftplib.error_perm:
|
||||
raise DownloadFailed("Permission failure listing folder: " + url)
|
||||
else:
|
||||
# just connect and do simple url parsing
|
||||
listing = https_download_file(url)
|
||||
urls = re.findall(b"<a href=\"([^\"]+)\">", listing)
|
||||
# decode the urls to normal strings. If they are complicated paths, ignore them
|
||||
return [name.decode("latin1") for name in urls if name and b"/" not in name[1:]]
|
||||
|
||||
|
||||
def ftp_download_files(url_base, folder_path, cacheDir, filenames):
|
||||
"""
|
||||
Like download file, but more of them. Keeps a persistent FTP connection open
|
||||
to be more efficient.
|
||||
"""
|
||||
folder_path_abs = os.path.join(cacheDir, folder_path)
|
||||
|
||||
ftp = ftp_connect(url_base + folder_path)
|
||||
|
||||
filepaths = []
|
||||
for filename in filenames:
|
||||
# os.path.join will be dumb if filename has a leading /
|
||||
# if there is a / in the filename, then it's using a different folder
|
||||
filename = filename.lstrip("/")
|
||||
if "/" in filename:
|
||||
continue
|
||||
filepath = os.path.join(folder_path_abs, filename)
|
||||
logging.debug("pulling from", url_base, "to", filepath)
|
||||
|
||||
if not os.path.isfile(filepath):
|
||||
os.makedirs(folder_path_abs, exist_ok=True)
|
||||
try:
|
||||
ftp.retrbinary('RETR ' + filename, open(filepath, 'wb').write)
|
||||
except (ftplib.error_perm):
|
||||
raise DownloadFailed("Could not download file from: " + url_base + folder_path + filename)
|
||||
except (socket.timeout):
|
||||
raise DownloadFailed("Read timed out from: " + url_base + folder_path + filename)
|
||||
filepaths.append(filepath)
|
||||
else:
|
||||
filepaths.append(filepath)
|
||||
return filepaths
|
||||
|
||||
|
||||
def http_download_files(url_base, folder_path, cacheDir, filenames):
|
||||
"""
|
||||
Similar to ftp_download_files, attempt to download multiple files faster than
|
||||
just downloading them one-by-one.
|
||||
Returns a list of filepaths instead of the raw data
|
||||
"""
|
||||
folder_path_abs = os.path.join(cacheDir, folder_path)
|
||||
|
||||
def write_function(disk_path, handle):
|
||||
def do_write(data):
|
||||
open(disk_path, "wb").write(data)
|
||||
|
||||
return do_write
|
||||
|
||||
fetcher = pycurl.CurlMulti()
|
||||
fetcher.setopt(pycurl.M_PIPELINING, 3)
|
||||
fetcher.setopt(pycurl.M_MAX_HOST_CONNECTIONS, 64)
|
||||
fetcher.setopt(pycurl.M_MAX_TOTAL_CONNECTIONS, 64)
|
||||
filepaths = []
|
||||
for filename in filenames:
|
||||
# os.path.join will be dumb if filename has a leading /
|
||||
# if there is a / in the filename, then it's using a different folder
|
||||
filename = filename.lstrip("/")
|
||||
if "/" in filename:
|
||||
continue
|
||||
filepath = os.path.join(folder_path_abs, filename)
|
||||
if not os.path.isfile(filepath):
|
||||
logging.debug("pulling from", url_base, "to", filepath)
|
||||
os.makedirs(folder_path_abs, exist_ok=True)
|
||||
url_path = url_base + folder_path + filename
|
||||
handle = pycurl.Curl()
|
||||
handle.setopt(pycurl.URL, url_path)
|
||||
handle.setopt(pycurl.CONNECTTIMEOUT, 10)
|
||||
handle.setopt(pycurl.WRITEFUNCTION, write_function(filepath, handle))
|
||||
fetcher.add_handle(handle)
|
||||
filepaths.append(filepath)
|
||||
|
||||
requests_processing = len(filepaths)
|
||||
timeout = 10.0 # after 10 seconds of nothing happening, restart
|
||||
deadline = time.time() + timeout
|
||||
while requests_processing and time.time() < deadline:
|
||||
while True:
|
||||
ret, cur_requests_processing = fetcher.perform()
|
||||
if ret != pycurl.E_CALL_MULTI_PERFORM:
|
||||
_, success, failed = fetcher.info_read()
|
||||
break
|
||||
if requests_processing > cur_requests_processing:
|
||||
deadline = time.time() + timeout
|
||||
requests_processing = cur_requests_processing
|
||||
|
||||
if fetcher.select(1) < 0:
|
||||
continue
|
||||
|
||||
# if there are downloads left to be done, repeat, and don't overwrite
|
||||
_, requests_processing = fetcher.perform()
|
||||
if requests_processing > 0:
|
||||
logging.warning("some requests stalled, retrying them")
|
||||
return http_download_files(url_base, folder_path, cacheDir, filenames)
|
||||
|
||||
return filepaths
|
||||
|
||||
|
||||
def https_download_file(url):
|
||||
crl = pycurl.Curl()
|
||||
crl.setopt(crl.CAINFO, certifi.where())
|
||||
crl.setopt(crl.URL, url)
|
||||
crl.setopt(crl.FOLLOWLOCATION, True)
|
||||
crl.setopt(crl.SSL_CIPHER_LIST, 'DEFAULT@SECLEVEL=1')
|
||||
crl.setopt(crl.COOKIEJAR, '/tmp/cddis_cookies')
|
||||
crl.setopt(pycurl.CONNECTTIMEOUT, 10)
|
||||
|
||||
buf = BytesIO()
|
||||
crl.setopt(crl.WRITEDATA, buf)
|
||||
crl.perform()
|
||||
response = crl.getinfo(pycurl.RESPONSE_CODE)
|
||||
crl.close()
|
||||
|
||||
if response != 200:
|
||||
raise DownloadFailed('HTTPS error ' + str(response))
|
||||
return buf.getvalue()
|
||||
|
||||
|
||||
def ftp_download_file(url):
|
||||
parsed = urlparse(url)
|
||||
is_sftp = parsed.scheme == "sftp"
|
||||
try:
|
||||
buf = BytesIO()
|
||||
with FTP_TLS(parsed.hostname) if is_sftp else FTP(parsed.hostname) as ftp:
|
||||
ftp.login(user='anonymous')
|
||||
if is_sftp:
|
||||
ftp.prot_p()
|
||||
ftp.retrbinary('RETR ' + parsed.path, buf.write)
|
||||
return buf.getvalue()
|
||||
except ftplib.all_errors as e:
|
||||
raise DownloadFailed(e)
|
||||
|
||||
|
||||
@retryable
|
||||
def download_files(url_base, folder_path, cacheDir, filenames):
|
||||
parsed = urlparse(url_base)
|
||||
if parsed.scheme == 'ftp':
|
||||
return ftp_download_files(url_base, folder_path, cacheDir, filenames)
|
||||
else:
|
||||
return http_download_files(url_base, folder_path, cacheDir, filenames)
|
||||
|
||||
|
||||
@retryable
|
||||
def download_file(url_base, folder_path, filename_zipped):
|
||||
url = url_base + folder_path + filename_zipped
|
||||
logging.debug('Downloading ' + url)
|
||||
if url.startswith('https://'):
|
||||
return https_download_file(url)
|
||||
elif url.startswith(('ftp://', 'sftp://')):
|
||||
return ftp_download_file(url)
|
||||
raise NotImplementedError('Did not find supported url scheme')
|
||||
|
||||
|
||||
def download_and_cache_file_return_first_success(url_bases, folder_and_file_names, cache_dir, compression='', overwrite=False, raise_error=False):
|
||||
last_error = None
|
||||
for folder_path, filename in folder_and_file_names:
|
||||
try:
|
||||
file = download_and_cache_file(url_bases, folder_path, cache_dir, filename, compression, overwrite)
|
||||
return file
|
||||
except DownloadFailed as e:
|
||||
last_error = e
|
||||
|
||||
if last_error and raise_error:
|
||||
raise last_error
|
||||
|
||||
|
||||
def download_and_cache_file(url_base, folder_path: str, cache_dir: str, filename: str, compression='', overwrite=False):
|
||||
filename_zipped = filename + compression
|
||||
folder_path_abs = os.path.join(cache_dir, folder_path)
|
||||
filepath = str(hatanaka.get_decompressed_path(os.path.join(folder_path_abs, filename)))
|
||||
|
||||
filepath_attempt = filepath + '.attempt_time'
|
||||
|
||||
if os.path.exists(filepath_attempt):
|
||||
with open(filepath_attempt, 'r') as rf:
|
||||
last_attempt_time = float(rf.read())
|
||||
if time.time() - last_attempt_time < SECS_IN_HR:
|
||||
raise DownloadFailed(f"Too soon to try downloading {folder_path + filename_zipped} from {url_base} again since last attempt")
|
||||
if not os.path.isfile(filepath) or overwrite:
|
||||
try:
|
||||
data_zipped = download_file(url_base, folder_path, filename_zipped)
|
||||
except (DownloadFailed, pycurl.error, socket.timeout):
|
||||
unix_time = time.time()
|
||||
os.makedirs(folder_path_abs, exist_ok=True)
|
||||
with atomic_write(filepath_attempt, mode='w', overwrite=True) as wf:
|
||||
wf.write(str(unix_time))
|
||||
raise DownloadFailed(f"Could not download {folder_path + filename_zipped} from {url_base} ")
|
||||
|
||||
os.makedirs(folder_path_abs, exist_ok=True)
|
||||
ephem_bytes = hatanaka.decompress(data_zipped)
|
||||
try:
|
||||
with atomic_write(filepath, mode='wb', overwrite=overwrite) as f:
|
||||
f.write(ephem_bytes)
|
||||
except FileExistsError:
|
||||
# Only happens when same file is downloaded in parallel by another process.
|
||||
pass
|
||||
return filepath
|
||||
|
||||
|
||||
# Currently, only GPS and Glonass are supported for daily and hourly data.
|
||||
CONSTELLATION_NASA_CHAR = {ConstellationId.GPS: 'n', ConstellationId.GLONASS: 'g'}
|
||||
|
||||
|
||||
def download_nav(time: GPSTime, cache_dir, constellation: ConstellationId):
|
||||
t = time.as_datetime()
|
||||
try:
|
||||
if constellation not in CONSTELLATION_NASA_CHAR:
|
||||
return None
|
||||
c = CONSTELLATION_NASA_CHAR[constellation]
|
||||
if GPSTime.from_datetime(datetime.utcnow()) - time > SECS_IN_DAY:
|
||||
url_bases = (
|
||||
'https://github.com/commaai/gnss-data/raw/master/gnss/data/daily/',
|
||||
'sftp://gdc.cddis.eosdis.nasa.gov/gnss/data/daily/',
|
||||
)
|
||||
filename = t.strftime(f"brdc%j0.%y{c}")
|
||||
folder_path = t.strftime(f'%Y/%j/%y{c}/')
|
||||
compression = '.gz' if folder_path >= '2020/335/' else '.Z'
|
||||
return download_and_cache_file(url_bases, folder_path, cache_dir+'daily_nav/', filename, compression)
|
||||
else:
|
||||
url_bases = (
|
||||
'https://github.com/commaai/gnss-data-hourly/raw/master/',
|
||||
'sftp://gdc.cddis.eosdis.nasa.gov/gnss/data/hourly/',
|
||||
)
|
||||
times = [t, (t - timedelta(hours=1))]
|
||||
folder_and_filenames = [(t.strftime('%Y/%j/'), t.strftime(f"hour%j0.%y{c}")) for t in times]
|
||||
compression = '.gz' if folder_and_filenames[0][0] >= '2020/336/' else '.Z'
|
||||
# always overwrite as this file is appended
|
||||
return download_and_cache_file_return_first_success(url_bases,
|
||||
folder_and_filenames, cache_dir+'hourly_nav/', compression, overwrite=True)
|
||||
except DownloadFailed:
|
||||
pass
|
||||
|
||||
|
||||
def download_orbits_gps_cod0(time, cache_dir, ephem_types):
|
||||
url_bases = (
|
||||
'https://github.com/commaai/gnss-data/raw/master/gnss/products/',
|
||||
'sftp://gdc.cddis.eosdis.nasa.gov/gnss/products/',
|
||||
)
|
||||
|
||||
if EphemerisType.ULTRA_RAPID_ORBIT not in ephem_types:
|
||||
# TODO: raise error here
|
||||
return None
|
||||
|
||||
tm = tow_to_datetime(time.tow, time.week).timetuple()
|
||||
doy = str(tm.tm_yday).zfill(3)
|
||||
filename = f"COD0OPSULT_{tm.tm_year}{doy}0000_02D_05M_ORB.SP3"
|
||||
# TODO: add hour management
|
||||
|
||||
folder_path = "%i/" % time.week
|
||||
folder_file_names = [(folder_path, filename)]
|
||||
return download_and_cache_file_return_first_success(url_bases, folder_file_names, cache_dir+'cddis_products/', compression='.gz')
|
||||
|
||||
|
||||
def download_orbits_gps(time, cache_dir, ephem_types):
|
||||
url_bases = (
|
||||
'https://github.com/commaai/gnss-data/raw/master/gnss/products/',
|
||||
'sftp://gdc.cddis.eosdis.nasa.gov/gnss/products/',
|
||||
'ftp://igs.ign.fr/pub/igs/products/',
|
||||
)
|
||||
folder_path = "%i/" % time.week
|
||||
filenames = []
|
||||
time_str = "%i%i" % (time.week, time.day)
|
||||
# Download filenames in order of quality. Final -> Rapid -> Ultra-Rapid(newest first)
|
||||
if EphemerisType.FINAL_ORBIT in ephem_types and GPSTime.from_datetime(datetime.utcnow()) - time > 3 * SECS_IN_WEEK:
|
||||
filenames.append(f"igs{time_str}.sp3")
|
||||
if EphemerisType.RAPID_ORBIT in ephem_types:
|
||||
filenames.append(f"igr{time_str}.sp3")
|
||||
if EphemerisType.ULTRA_RAPID_ORBIT in ephem_types:
|
||||
filenames.extend([f"igu{time_str}_18.sp3",
|
||||
f"igu{time_str}_12.sp3",
|
||||
f"igu{time_str}_06.sp3",
|
||||
f"igu{time_str}_00.sp3"])
|
||||
folder_file_names = [(folder_path, filename) for filename in filenames]
|
||||
ret = download_and_cache_file_return_first_success(url_bases, folder_file_names, cache_dir+'cddis_products/', compression='.Z')
|
||||
if ret is not None:
|
||||
return ret
|
||||
|
||||
# fallback to COD0 Ultra Rapid Orbits
|
||||
return download_orbits_gps_cod0(time, cache_dir, ephem_types)
|
||||
|
||||
|
||||
def download_prediction_orbits_russia_src(gps_time, cache_dir):
|
||||
# Download single file that contains Ultra_Rapid predictions for GPS, GLONASS and other constellations
|
||||
t = gps_time.as_datetime()
|
||||
# Files exist starting at 29-01-2022
|
||||
if t < datetime(2022, 1, 29):
|
||||
return None
|
||||
url_bases = 'https://github.com/commaai/gnss-data-alt/raw/master/MCC/PRODUCTS/'
|
||||
folder_path = t.strftime('%y%j/ultra/')
|
||||
file_prefix = "Stark_1D_" + t.strftime('%y%m%d')
|
||||
|
||||
# Predictions are 24H so previous day can also be used.
|
||||
prev_day = (t - timedelta(days=1))
|
||||
file_prefix_prev = "Stark_1D_" + prev_day.strftime('%y%m%d')
|
||||
folder_path_prev = prev_day.strftime('%y%j/ultra/')
|
||||
|
||||
current_day = GPSTime.from_datetime(datetime(t.year, t.month, t.day))
|
||||
# Ultra-Orbit is published in gnss-data-alt every 10th minute past the 5,11,17,23 hour.
|
||||
# Predictions published are delayed by around 10 hours.
|
||||
# Download latest file that includes gps_time with 20 minutes margin.:
|
||||
if gps_time > current_day + 23.5 * SECS_IN_HR:
|
||||
prev_day, current_day = [], [6, 12]
|
||||
elif gps_time > current_day + 17.5 * SECS_IN_HR:
|
||||
prev_day, current_day = [], [0, 6]
|
||||
elif gps_time > current_day + 11.5 * SECS_IN_HR:
|
||||
prev_day, current_day = [18], [0]
|
||||
elif gps_time > current_day + 5.5 * SECS_IN_HR:
|
||||
prev_day, current_day = [12, 18], []
|
||||
else:
|
||||
prev_day, current_day = [6, 12], []
|
||||
# Example: Stark_1D_22060100.sp3
|
||||
folder_and_file_names = [(folder_path, file_prefix + f"{h:02}.sp3") for h in reversed(current_day)] + \
|
||||
[(folder_path_prev, file_prefix_prev + f"{h:02}.sp3") for h in reversed(prev_day)]
|
||||
return download_and_cache_file_return_first_success(url_bases, folder_and_file_names, cache_dir+'russian_products/', raise_error=True)
|
||||
|
||||
|
||||
def download_orbits_russia_src(time, cache_dir, ephem_types):
|
||||
# Orbits from russian source. Contains GPS, GLONASS, GALILEO, BEIDOU
|
||||
url_bases = (
|
||||
'https://github.com/commaai/gnss-data-alt/raw/master/MCC/PRODUCTS/',
|
||||
'ftp://ftp.glonass-iac.ru/MCC/PRODUCTS/',
|
||||
)
|
||||
t = time.as_datetime()
|
||||
folder_paths = []
|
||||
current_gps_time = GPSTime.from_datetime(datetime.utcnow())
|
||||
filename = "Sta%i%i.sp3" % (time.week, time.day)
|
||||
if EphemerisType.FINAL_ORBIT in ephem_types and current_gps_time - time > 2 * SECS_IN_WEEK:
|
||||
folder_paths.append(t.strftime('%y%j/final/'))
|
||||
if EphemerisType.RAPID_ORBIT in ephem_types:
|
||||
folder_paths.append(t.strftime('%y%j/rapid/'))
|
||||
if EphemerisType.ULTRA_RAPID_ORBIT in ephem_types:
|
||||
folder_paths.append(t.strftime('%y%j/ultra/'))
|
||||
folder_file_names = [(folder_path, filename) for folder_path in folder_paths]
|
||||
return download_and_cache_file_return_first_success(url_bases, folder_file_names, cache_dir+'russian_products/')
|
||||
|
||||
|
||||
def download_ionex(time, cache_dir):
|
||||
t = time.as_datetime()
|
||||
url_bases = (
|
||||
'https://github.com/commaai/gnss-data/raw/master/gnss/products/ionex/',
|
||||
'sftp://gdc.cddis.eosdis.nasa.gov/gnss/products/ionex/',
|
||||
'ftp://igs.ensg.ign.fr/pub/igs/products/ionosphere/',
|
||||
'ftp://gssc.esa.int/gnss/products/ionex/',
|
||||
)
|
||||
folder_path = t.strftime('%Y/%j/')
|
||||
filenames = [t.strftime("codg%j0.%yi"), t.strftime("c1pg%j0.%yi"), t.strftime("c2pg%j0.%yi")]
|
||||
|
||||
folder_file_names = [(folder_path, f) for f in filenames]
|
||||
return download_and_cache_file_return_first_success(url_bases, folder_file_names, cache_dir+'ionex/', compression='.Z', raise_error=True)
|
||||
|
||||
|
||||
def download_dcb(time, cache_dir):
|
||||
filenames = []
|
||||
folder_paths = []
|
||||
url_bases = (
|
||||
'https://github.com/commaai/gnss-data/raw/master/gnss/products/bias/',
|
||||
'sftp://gdc.cddis.eosdis.nasa.gov/gnss/products/bias/',
|
||||
'ftp://igs.ign.fr/pub/igs/products/mgex/dcb/',
|
||||
)
|
||||
# seem to be a lot of data missing, so try many days
|
||||
for time_step in [time - i * SECS_IN_DAY for i in range(14)]:
|
||||
t = time_step.as_datetime()
|
||||
folder_paths.append(t.strftime('%Y/'))
|
||||
filenames.append(t.strftime("CAS0MGXRAP_%Y%j0000_01D_01D_DCB.BSX"))
|
||||
|
||||
return download_and_cache_file_return_first_success(url_bases, list(zip(folder_paths, filenames)), cache_dir+'dcb/', compression='.gz', raise_error=True)
|
||||
|
||||
|
||||
def download_cors_coords(cache_dir):
|
||||
cache_subdir = cache_dir + 'cors_coord/'
|
||||
url_bases = (
|
||||
'https://geodesy.noaa.gov/corsdata/coord/coord_14/',
|
||||
'https://alt.ngs.noaa.gov/corsdata/coord/coord_14/',
|
||||
)
|
||||
file_names = list_dir(url_bases)
|
||||
file_names = [file_name for file_name in file_names if file_name.endswith('coord.txt')]
|
||||
filepaths = download_files(url_bases, '', cache_subdir, file_names)
|
||||
return filepaths
|
||||
|
||||
|
||||
def download_cors_station(time, station_name, cache_dir):
|
||||
t = time.as_datetime()
|
||||
folder_path = t.strftime('%Y/%j/') + station_name + '/'
|
||||
filename = station_name + t.strftime("%j0.%yd")
|
||||
url_bases = (
|
||||
'https://geodesy.noaa.gov/corsdata/rinex/',
|
||||
'https://alt.ngs.noaa.gov/corsdata/rinex/',
|
||||
)
|
||||
try:
|
||||
filepath = download_and_cache_file(url_bases, folder_path, cache_dir+'cors_obs/', filename, compression='.gz')
|
||||
return filepath
|
||||
except DownloadFailed:
|
||||
logging.warning("File not downloaded, check availability on server.")
|
||||
return None
|
||||
@@ -1,106 +0,0 @@
|
||||
@0xb3ca6d2462778bb1;
|
||||
|
||||
struct Ephemeris {
|
||||
# This is according to the rinex (2?) format
|
||||
svId @0 :UInt16;
|
||||
year @1 :UInt16;
|
||||
month @2 :UInt16;
|
||||
day @3 :UInt16;
|
||||
hour @4 :UInt16;
|
||||
minute @5 :UInt16;
|
||||
second @6 :Float32;
|
||||
af0 @7 :Float64;
|
||||
af1 @8 :Float64;
|
||||
af2 @9 :Float64;
|
||||
|
||||
iode @10 :Float64;
|
||||
crs @11 :Float64;
|
||||
deltaN @12 :Float64;
|
||||
m0 @13 :Float64;
|
||||
|
||||
cuc @14 :Float64;
|
||||
ecc @15 :Float64;
|
||||
cus @16 :Float64;
|
||||
a @17 :Float64; # note that this is not the root!!
|
||||
|
||||
toe @18 :Float64;
|
||||
cic @19 :Float64;
|
||||
omega0 @20 :Float64;
|
||||
cis @21 :Float64;
|
||||
|
||||
i0 @22 :Float64;
|
||||
crc @23 :Float64;
|
||||
omega @24 :Float64;
|
||||
omegaDot @25 :Float64;
|
||||
|
||||
iDot @26 :Float64;
|
||||
codesL2 @27 :Float64;
|
||||
gpsWeekDEPRECATED @28 :Float64;
|
||||
l2 @29 :Float64;
|
||||
|
||||
svAcc @30 :Float64;
|
||||
svHealth @31 :Float64;
|
||||
tgd @32 :Float64;
|
||||
iodc @33 :Float64;
|
||||
|
||||
transmissionTime @34 :Float64;
|
||||
fitInterval @35 :Float64;
|
||||
|
||||
toc @36 :Float64;
|
||||
|
||||
ionoCoeffsValid @37 :Bool;
|
||||
ionoAlpha @38 :List(Float64);
|
||||
ionoBeta @39 :List(Float64);
|
||||
|
||||
towCount @40 :UInt32;
|
||||
toeWeek @41 :UInt16;
|
||||
tocWeek @42 :UInt16;
|
||||
}
|
||||
|
||||
struct GlonassEphemeris {
|
||||
svId @0 :UInt16;
|
||||
year @1 :UInt16;
|
||||
dayInYear @2 :UInt16;
|
||||
hour @3 :UInt16;
|
||||
minute @4 :UInt16;
|
||||
second @5 :Float32;
|
||||
|
||||
x @6 :Float64;
|
||||
xVel @7 :Float64;
|
||||
xAccel @8 :Float64;
|
||||
y @9 :Float64;
|
||||
yVel @10 :Float64;
|
||||
yAccel @11 :Float64;
|
||||
z @12 :Float64;
|
||||
zVel @13 :Float64;
|
||||
zAccel @14 :Float64;
|
||||
|
||||
svType @15 :UInt8;
|
||||
svURA @16 :Float32;
|
||||
age @17 :UInt8;
|
||||
|
||||
svHealth @18 :UInt8;
|
||||
tkDEPRECATED @19 :UInt16;
|
||||
tb @20 :UInt16;
|
||||
|
||||
tauN @21 :Float64;
|
||||
deltaTauN @22 :Float64;
|
||||
gammaN @23 :Float64;
|
||||
|
||||
p1 @24 :UInt8;
|
||||
p2 @25 :UInt8;
|
||||
p3 @26 :UInt8;
|
||||
p4 @27 :UInt8;
|
||||
|
||||
freqNumDEPRECATED @28 :UInt32;
|
||||
|
||||
n4 @29 :UInt8;
|
||||
nt @30 :UInt16;
|
||||
freqNum @31 :Int16;
|
||||
tkSeconds @32 :UInt32;
|
||||
}
|
||||
|
||||
struct EphemerisCache {
|
||||
gpsEphemerides @0 :List(Ephemeris);
|
||||
glonassEphemerides @1 :List(GlonassEphemeris);
|
||||
}
|
||||
@@ -1,498 +0,0 @@
|
||||
import warnings
|
||||
from abc import ABC, abstractmethod
|
||||
from collections import defaultdict
|
||||
from enum import IntEnum
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
import numpy as np
|
||||
import numpy.polynomial.polynomial as poly
|
||||
from datetime import datetime
|
||||
from math import sin, cos, sqrt, fabs, atan2
|
||||
|
||||
from .gps_time import GPSTime, utc_to_gpst
|
||||
from .constants import SPEED_OF_LIGHT, SECS_IN_MIN, SECS_IN_HR, SECS_IN_DAY, \
|
||||
EARTH_ROTATION_RATE, EARTH_GM
|
||||
from .helpers import get_constellation, get_prn_from_nmea_id
|
||||
|
||||
import capnp
|
||||
import os
|
||||
capnp.remove_import_hook()
|
||||
capnp_path = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), "ephemeris.capnp"))
|
||||
ephemeris_structs = capnp.load(capnp_path)
|
||||
|
||||
|
||||
def read4(f, rinex_ver):
|
||||
line = f.readline()[:-1]
|
||||
if rinex_ver == 2:
|
||||
line = ' ' + line # Shift 1 char to the right
|
||||
line = line.replace('D', 'E') # Handle bizarro float format
|
||||
return float(line[4:23]), float(line[23:42]), float(line[42:61]), float(line[61:80])
|
||||
|
||||
|
||||
class EphemerisType(IntEnum):
|
||||
# Matches the enum in log.capnp
|
||||
NAV = 0
|
||||
FINAL_ORBIT = 1
|
||||
RAPID_ORBIT = 2
|
||||
ULTRA_RAPID_ORBIT = 3
|
||||
QCOM_POLY = 4
|
||||
|
||||
@staticmethod
|
||||
def all_orbits():
|
||||
return EphemerisType.FINAL_ORBIT, EphemerisType.RAPID_ORBIT, EphemerisType.ULTRA_RAPID_ORBIT
|
||||
|
||||
@classmethod
|
||||
def from_file_name(cls, file_name: str):
|
||||
if "/final" in file_name or "/igs" in file_name:
|
||||
return EphemerisType.FINAL_ORBIT
|
||||
if "/rapid" in file_name or "/igr" in file_name:
|
||||
return EphemerisType.RAPID_ORBIT
|
||||
if "/ultra" in file_name or "/igu" in file_name or "COD0OPSULT" in file_name:
|
||||
return EphemerisType.ULTRA_RAPID_ORBIT
|
||||
raise RuntimeError(f"Ephemeris type not found in filename: {file_name}")
|
||||
|
||||
|
||||
class Ephemeris(ABC):
|
||||
|
||||
def __init__(self, prn: str, epoch: GPSTime, eph_type: EphemerisType, healthy: bool, max_time_diff: float,
|
||||
file_epoch: Optional[GPSTime] = None, file_name=None):
|
||||
self.prn = prn
|
||||
self.epoch = epoch
|
||||
self.eph_type = eph_type
|
||||
self.healthy = healthy
|
||||
self.max_time_diff = max_time_diff
|
||||
self.file_epoch = file_epoch
|
||||
self.file_name = file_name
|
||||
self.file_source = '' if file_name is None else file_name.split('/')[-1][:3] # File source for the ephemeris (e.g. igu, igr, Sta)
|
||||
|
||||
def valid(self, time):
|
||||
return abs(time - self.epoch) <= self.max_time_diff
|
||||
|
||||
def __repr__(self):
|
||||
time = self.epoch.as_datetime().strftime('%Y-%m-%dT%H:%M:%S.%f')
|
||||
return f"<{self.__class__.__name__} from {self.prn} at {time}>"
|
||||
|
||||
def get_sat_info(self, time: GPSTime):
|
||||
"""
|
||||
Returns: (pos, vel, clock_err, clock_rate_err, ephemeris)
|
||||
"""
|
||||
if not self.healthy:
|
||||
return None
|
||||
return list(self._get_sat_info(time)) + [self]
|
||||
|
||||
@abstractmethod
|
||||
def _get_sat_info(self, time):
|
||||
pass
|
||||
|
||||
|
||||
class GLONASSEphemeris(Ephemeris):
|
||||
def __init__(self, data, file_name=None):
|
||||
self.epoch = GPSTime.from_glonass(data.n4, data.nt, data.tb*15*SECS_IN_MIN)
|
||||
super().__init__('R%02i' % data.svId, self.epoch, EphemerisType.NAV, data.svHealth==0, max_time_diff=25*SECS_IN_MIN, file_name=file_name)
|
||||
self.data = data
|
||||
self.epoch = GPSTime.from_glonass(data.n4, data.nt, data.tb*15 * SECS_IN_MIN)
|
||||
self.channel = data.freqNum
|
||||
|
||||
def _get_sat_info(self, time: GPSTime):
|
||||
# see the russian doc for this:
|
||||
# http://gauss.gge.unb.ca/GLONASS.ICD.pdf
|
||||
|
||||
eph = self.data
|
||||
tdiff = time - self.epoch
|
||||
# Clock correction (except for general relativity which is applied later)
|
||||
clock_err = -eph.tauN + tdiff * eph.gammaN
|
||||
clock_rate_err = eph.gammaN
|
||||
|
||||
def glonass_diff_eq(state, acc):
|
||||
J2 = 1.0826257e-3
|
||||
mu = 3.9860044e14
|
||||
omega = 7.292115e-5
|
||||
ae = 6378136.0
|
||||
r = np.sqrt(state[0]**2 + state[1]**2 + state[2]**2)
|
||||
ders = np.zeros(6)
|
||||
if r**2 < 0:
|
||||
return ders
|
||||
a = 1.5 * J2 * mu * (ae**2)/ (r**5)
|
||||
b = 5 * (state[2]**2) / (r**2)
|
||||
c = -mu/(r**3) - a*(1-b)
|
||||
|
||||
ders[0:3] = state[3:6]
|
||||
ders[3] = (c + omega**2)*state[0] + 2*omega*state[4] + acc[0]
|
||||
ders[4] = (c + omega**2)*state[1] - 2*omega*state[3] + acc[1]
|
||||
ders[5] = (c - 2*a)*state[2] + acc[2]
|
||||
return ders
|
||||
|
||||
init_state = np.empty(6)
|
||||
init_state[0] = eph.x
|
||||
init_state[1] = eph.y
|
||||
init_state[2] = eph.z
|
||||
init_state[3] = eph.xVel
|
||||
init_state[4] = eph.yVel
|
||||
init_state[5] = eph.zVel
|
||||
init_state = 1000*init_state
|
||||
acc = 1000*np.array([eph.xAccel, eph.yAccel, eph.zAccel])
|
||||
state = init_state
|
||||
tstep = 90
|
||||
if tdiff < 0:
|
||||
tt = -tstep
|
||||
elif tdiff > 0:
|
||||
tt = tstep
|
||||
while abs(tdiff) > 1e-9:
|
||||
if abs(tdiff) < tstep:
|
||||
tt = tdiff
|
||||
k1 = glonass_diff_eq(state, acc)
|
||||
k2 = glonass_diff_eq(state + k1*tt/2, -acc)
|
||||
k3 = glonass_diff_eq(state + k2*tt/2, -acc)
|
||||
k4 = glonass_diff_eq(state + k3*tt, -acc)
|
||||
state += (k1 + 2*k2 + 2*k3 + k4)*tt/6.0
|
||||
tdiff -= tt
|
||||
|
||||
pos = state[0:3]
|
||||
vel = state[3:6]
|
||||
return pos, vel, clock_err, clock_rate_err
|
||||
|
||||
|
||||
class PolyEphemeris(Ephemeris):
|
||||
def __init__(self, prn: str, data, epoch: GPSTime, ephem_type: EphemerisType,
|
||||
file_epoch: Optional[GPSTime] = None, file_name: Optional[str] = None, healthy=True, tgd=0,
|
||||
max_time_diff: int=SECS_IN_HR):
|
||||
super().__init__(prn, epoch, ephem_type, healthy, max_time_diff=max_time_diff, file_epoch=file_epoch, file_name=file_name)
|
||||
self.data = data
|
||||
self.tgd = tgd
|
||||
|
||||
def _get_sat_info(self, time: GPSTime):
|
||||
dt = time - self.data['t0']
|
||||
deg = self.data['deg']
|
||||
deg_t = self.data['deg_t']
|
||||
indices = np.arange(deg+1)[:,np.newaxis]
|
||||
sat_pos = np.sum((dt**indices)*self.data['xyz'], axis=0)
|
||||
indices = indices[1:]
|
||||
sat_vel = np.sum(indices*(dt**(indices-1)*self.data['xyz'][1:]), axis=0)
|
||||
time_err = sum((dt**p)*self.data['clock'][deg_t-p] for p in range(deg_t+1))
|
||||
time_err_rate = sum(p*(dt**(p-1))*self.data['clock'][deg_t-p] for p in range(1,deg_t+1))
|
||||
time_err_with_rel = time_err - 2*np.inner(sat_pos, sat_vel)/SPEED_OF_LIGHT**2
|
||||
return sat_pos, sat_vel, time_err_with_rel, time_err_rate
|
||||
|
||||
|
||||
class GPSEphemeris(Ephemeris):
|
||||
def __init__(self, data, file_name=None):
|
||||
self.toe = GPSTime(data.toeWeek, data.toe)
|
||||
self.toc = GPSTime(data.tocWeek, data.toc)
|
||||
self.epoch = self.toc
|
||||
|
||||
super().__init__('G%02i' % data.svId, self.epoch, EphemerisType.NAV, data.svHealth==0, max_time_diff=2*SECS_IN_HR, file_name=file_name)
|
||||
self.max_time_diff_tgd = SECS_IN_DAY
|
||||
self.data = data
|
||||
self.sqrta = np.sqrt(data.a)
|
||||
|
||||
def get_tgd(self):
|
||||
return self.datatgd
|
||||
|
||||
def _get_sat_info(self, time: GPSTime):
|
||||
eph = self.data
|
||||
tdiff = time - self.toc # Time of clock
|
||||
clock_err = eph.af0 + tdiff * (eph.af1 + tdiff * eph.af2)
|
||||
clock_rate_err = eph.af1 + 2 * tdiff * eph.af2\
|
||||
|
||||
# Orbit propagation
|
||||
tdiff = time - self.toe # Time of ephemeris (might be different from time of clock)
|
||||
|
||||
# Calculate position per IS-GPS-200D p 97 Table 20-IV
|
||||
a = self.sqrta * self.sqrta # [m] Semi-major axis
|
||||
ma_dot = sqrt(EARTH_GM / (a * a * a)) + eph.deltaN # [rad/sec] Corrected mean motion
|
||||
ma = eph.m0 + ma_dot * tdiff # [rad] Corrected mean anomaly
|
||||
|
||||
# Iteratively solve for the Eccentric Anomaly (from Keith Alter and David Johnston)
|
||||
ea = ma # Starting value for E
|
||||
|
||||
ea_old = 2222
|
||||
while fabs(ea - ea_old) > 1.0E-14:
|
||||
ea_old = ea
|
||||
tempd1 = 1.0 - eph.ecc * cos(ea_old)
|
||||
ea = ea + (ma - ea_old + eph.ecc * sin(ea_old)) / tempd1
|
||||
ea_dot = ma_dot / tempd1
|
||||
|
||||
# Relativistic correction term
|
||||
einstein = -4.442807633E-10 * eph.ecc * self.sqrta * sin(ea)
|
||||
|
||||
# Begin calc for True Anomaly and Argument of Latitude
|
||||
tempd2 = sqrt(1.0 - eph.ecc * eph.ecc)
|
||||
# [rad] Argument of Latitude = True Anomaly + Argument of Perigee
|
||||
al = atan2(tempd2 * sin(ea), cos(ea) - eph.ecc) + eph.omega
|
||||
al_dot = tempd2 * ea_dot / tempd1
|
||||
|
||||
# Calculate corrected argument of latitude based on position
|
||||
cal = al + eph.cus * sin(2.0 * al) + eph.cuc * cos(2.0 * al)
|
||||
cal_dot = al_dot * (1.0 + 2.0 * (eph.cus * cos(2.0 * al) -
|
||||
eph.cuc * sin(2.0 * al)))
|
||||
|
||||
# Calculate corrected radius based on argument of latitude
|
||||
r = a * tempd1 + eph.crc * cos(2.0 * al) + eph.crs * sin(2.0 * al)
|
||||
r_dot = (a * eph.ecc * sin(ea) * ea_dot +
|
||||
2.0 * al_dot * (eph.crs * cos(2.0 * al) -
|
||||
eph.crc * sin(2.0 * al)))
|
||||
|
||||
# Calculate inclination based on argument of latitude
|
||||
inc = (eph.i0 + eph.iDot * tdiff +
|
||||
eph.cic * cos(2.0 * al) +
|
||||
eph.cis * sin(2.0 * al))
|
||||
inc_dot = (eph.iDot +
|
||||
2.0 * al_dot * (eph.cis * cos(2.0 * al) -
|
||||
eph.cic * sin(2.0 * al)))
|
||||
|
||||
# Calculate position and velocity in orbital plane
|
||||
x = r * cos(cal)
|
||||
y = r * sin(cal)
|
||||
x_dot = r_dot * cos(cal) - y * cal_dot
|
||||
y_dot = r_dot * sin(cal) + x * cal_dot
|
||||
|
||||
# Corrected longitude of ascending node
|
||||
om_dot = eph.omegaDot - EARTH_ROTATION_RATE
|
||||
om = eph.omega0 + tdiff * om_dot - EARTH_ROTATION_RATE * self.toe.tow
|
||||
|
||||
# Compute the satellite's position in Earth-Centered Earth-Fixed coordinates
|
||||
pos = np.empty(3)
|
||||
pos[0] = x * cos(om) - y * cos(inc) * sin(om)
|
||||
pos[1] = x * sin(om) + y * cos(inc) * cos(om)
|
||||
pos[2] = y * sin(inc)
|
||||
|
||||
tempd3 = y_dot * cos(inc) - y * sin(inc) * inc_dot
|
||||
|
||||
# Compute the satellite's velocity in Earth-Centered Earth-Fixed coordinates
|
||||
vel = np.empty(3)
|
||||
vel[0] = -om_dot * pos[1] + x_dot * cos(om) - tempd3 * sin(om)
|
||||
vel[1] = om_dot * pos[0] + x_dot * sin(om) + tempd3 * cos(om)
|
||||
vel[2] = y * cos(inc) * inc_dot + y_dot * sin(inc)
|
||||
|
||||
clock_err += einstein
|
||||
|
||||
return pos, vel, clock_err, clock_rate_err
|
||||
|
||||
|
||||
def parse_sp3_orbits(file_names, supported_constellations, skip_until_epoch: Optional[GPSTime] = None) -> Dict[str, List[PolyEphemeris]]:
|
||||
if skip_until_epoch is None:
|
||||
skip_until_epoch = GPSTime(0, 0)
|
||||
data: Dict[str, List] = {}
|
||||
for file_name in file_names:
|
||||
if file_name is None:
|
||||
continue
|
||||
with open(file_name) as f:
|
||||
ephem_type = EphemerisType.from_file_name(file_name)
|
||||
file_epoch = None
|
||||
while True:
|
||||
line = f.readline()[:-1]
|
||||
if not line:
|
||||
break
|
||||
# epoch header
|
||||
if line[0:2] == '* ':
|
||||
year = int(line[3:7])
|
||||
month = int(line[8:10])
|
||||
day = int(line[11:13])
|
||||
hour = int(line[14:16])
|
||||
minute = int(line[17:19])
|
||||
second = int(float(line[20:31]))
|
||||
epoch = GPSTime.from_datetime(datetime(year, month, day, hour, minute, second))
|
||||
if file_epoch is None:
|
||||
file_epoch = epoch
|
||||
# pos line
|
||||
elif line[0] == 'P':
|
||||
# Skipping data can reduce the time significantly when parsing the ephemeris
|
||||
if epoch < skip_until_epoch:
|
||||
continue
|
||||
prn = line[1:4].replace(' ', '0')
|
||||
# In old SP3 files vehicle ID doesn't contain constellation
|
||||
# identifier. We assume that constellation is GPS when missing.
|
||||
if prn[0] == '0':
|
||||
prn = 'G' + prn[1:]
|
||||
if get_constellation(prn) not in supported_constellations:
|
||||
continue
|
||||
if prn not in data:
|
||||
data[prn] = []
|
||||
#TODO this is a crappy way to deal with overlapping ultra rapid
|
||||
if len(data[prn]) < 1 or epoch - data[prn][-1][1] > 0:
|
||||
parsed = [(ephem_type, file_epoch, file_name),
|
||||
epoch,
|
||||
1e3 * float(line[4:18]),
|
||||
1e3 * float(line[18:32]),
|
||||
1e3 * float(line[32:46]),
|
||||
1e-6 * float(line[46:60])]
|
||||
if (np.array(parsed[2:]) != 0).all():
|
||||
data[prn].append(parsed)
|
||||
ephems = {}
|
||||
for prn in data:
|
||||
ephems[prn] = read_prn_data(data, prn)
|
||||
return ephems
|
||||
|
||||
|
||||
def read_prn_data(data, prn, deg=16, deg_t=1):
|
||||
np_data_prn = np.array(data[prn], dtype=object)
|
||||
# Currently, don't even bother with satellites that have unhealthy times
|
||||
if len(np_data_prn) == 0 or (np_data_prn[:, 5] > .99).any():
|
||||
return []
|
||||
ephems = []
|
||||
for i in range(len(np_data_prn) - deg):
|
||||
epoch_index = i + deg // 2
|
||||
epoch = np_data_prn[epoch_index][1]
|
||||
measurements = np_data_prn[i:i + deg + 1, 1:5]
|
||||
|
||||
times = (measurements[:, 0] - epoch).astype(float)
|
||||
if not (np.diff(times) != 900).any() and not (np.diff(times) != 300).any():
|
||||
continue
|
||||
|
||||
poly_data = {}
|
||||
poly_data['t0'] = epoch
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore") # Ignores: UserWarning: The value of the smallest subnormal for <class 'numpy.float64'> type is zero.
|
||||
poly_data['xyz'] = poly.polyfit(times, measurements[:, 1:].astype(float), deg)
|
||||
poly_data['clock'] = [(np_data_prn[epoch_index + 1][5] - np_data_prn[epoch_index - 1][5]) / 1800, np_data_prn[epoch_index][5]]
|
||||
poly_data['deg'] = deg
|
||||
poly_data['deg_t'] = deg_t
|
||||
# It can happen that a mix of orbit ephemeris types are used in the polyfit.
|
||||
ephem_type, file_epoch, file_name = np_data_prn[epoch_index][0]
|
||||
ephems.append(PolyEphemeris(prn, poly_data, epoch, ephem_type, file_epoch, file_name, healthy=True))
|
||||
return ephems
|
||||
|
||||
|
||||
def parse_rinex_nav_msg_gps(file_name):
|
||||
ephems = defaultdict(list)
|
||||
got_header = False
|
||||
rinex_ver = None
|
||||
#ion_alpha = None
|
||||
#ion_beta = None
|
||||
f = open(file_name)
|
||||
while True:
|
||||
line = f.readline()[:-1]
|
||||
if not line:
|
||||
break
|
||||
if not got_header:
|
||||
if rinex_ver is None:
|
||||
if line[60:80] != "RINEX VERSION / TYPE":
|
||||
raise RuntimeError("Doesn't appear to be a RINEX file")
|
||||
rinex_ver = int(float(line[0:9]))
|
||||
if line[20] != "N":
|
||||
raise RuntimeError("Doesn't appear to be a Navigation Message file")
|
||||
#if line[60:69] == "ION ALPHA":
|
||||
# line = line.replace('D', 'E') # Handle bizarro float format
|
||||
# ion_alpha= [float(line[3:14]), float(line[15:26]), float(line[27:38]), float(line[39:50])]
|
||||
#if line[60:68] == "ION BETA":
|
||||
# line = line.replace('D', 'E') # Handle bizarro float format
|
||||
# ion_beta= [float(line[3:14]), float(line[15:26]), float(line[27:38]), float(line[39:50])]
|
||||
if line[60:73] == "END OF HEADER":
|
||||
#ion = ion_alpha + ion_beta
|
||||
got_header = True
|
||||
continue
|
||||
if rinex_ver == 3:
|
||||
if line[0] != 'G':
|
||||
continue
|
||||
if rinex_ver == 3:
|
||||
sv_id = int(line[1:3])
|
||||
epoch = GPSTime.from_datetime(datetime.strptime(line[4:23], "%y %m %d %H %M %S"))
|
||||
elif rinex_ver == 2:
|
||||
sv_id = int(line[0:2])
|
||||
# 2000 year is in RINEX file as 0, but Python requires two digit year: 00
|
||||
epoch_str = line[3:20]
|
||||
if epoch_str[0] == ' ':
|
||||
epoch_str = '0' + epoch_str[1:]
|
||||
epoch = GPSTime.from_datetime(datetime.strptime(epoch_str, "%y %m %d %H %M %S"))
|
||||
line = ' ' + line # Shift 1 char to the right
|
||||
|
||||
line = line.replace('D', 'E') # Handle bizarro float format
|
||||
e = {'svId': sv_id}
|
||||
# TODO are TOC and TOE the same?
|
||||
e['toc'] = epoch.tow
|
||||
e['tocWeek'] = epoch.week
|
||||
e['af0'] = float(line[23:42])
|
||||
e['af1'] = float(line[42:61])
|
||||
e['af2'] = float(line[61:80])
|
||||
|
||||
e['iode'], e['crs'], e['deltaN'], e['m0'] = read4(f, rinex_ver)
|
||||
e['cuc'], e['ecc'], e['cus'], sqrta = read4(f, rinex_ver)
|
||||
e['a'] = sqrta ** 2
|
||||
e['toe'], e['cic'], e['omega0'], e['cis'] = read4(f, rinex_ver)
|
||||
e['i0'], e['crc'], e['omega'], e['omegaDot'] = read4(f, rinex_ver)
|
||||
e['iDot'], e['codesL2'], e['toeWeek'], l2_pflag = read4(f, rinex_ver)
|
||||
e['svAcc'], e['svHealth'], e['tgd'], e['iodc'] = read4(f, rinex_ver)
|
||||
f.readline() # Discard last row
|
||||
|
||||
data_struct = ephemeris_structs.Ephemeris.new_message(**e)
|
||||
|
||||
ephem = GPSEphemeris(data_struct, file_name=file_name)
|
||||
ephems[ephem.prn].append(ephem)
|
||||
f.close()
|
||||
return ephems
|
||||
|
||||
|
||||
def parse_rinex_nav_msg_glonass(file_name):
|
||||
ephems = defaultdict(list)
|
||||
f = open(file_name)
|
||||
got_header = False
|
||||
rinex_ver = None
|
||||
while True:
|
||||
line = f.readline()[:-1]
|
||||
if not line:
|
||||
break
|
||||
if not got_header:
|
||||
if rinex_ver is None:
|
||||
if line[60:80] != "RINEX VERSION / TYPE":
|
||||
raise RuntimeError("Doesn't appear to be a RINEX file")
|
||||
rinex_ver = int(float(line[0:9]))
|
||||
if line[20] != "G":
|
||||
raise RuntimeError("Doesn't appear to be a Navigation Message file")
|
||||
if line[60:73] == "END OF HEADER":
|
||||
got_header = True
|
||||
continue
|
||||
if rinex_ver == 3:
|
||||
sv_id = int(line[1:3])
|
||||
|
||||
epoch = utc_to_gpst(GPSTime.from_datetime(datetime.strptime(line[4:23], "%y %m %d %H %M %S")))
|
||||
elif rinex_ver == 2:
|
||||
sv_id = int(line[0:2])
|
||||
epoch = utc_to_gpst(GPSTime.from_datetime(datetime.strptime(line[3:20], "%y %m %d %H %M %S")))
|
||||
line = ' ' + line # Shift 1 char to the right
|
||||
|
||||
line = line.replace('D', 'E') # Handle bizarro float format
|
||||
e = {'svId': sv_id}
|
||||
e['n4'], e['nt'], toe_seconds = epoch.as_glonass()
|
||||
tb = toe_seconds / (15 * SECS_IN_MIN)
|
||||
|
||||
|
||||
e['tb'] = tb
|
||||
|
||||
e['tauN'] = -float(line[23:42])
|
||||
e['gammaN'] = float(line[42:61])
|
||||
e['tkSeconds'] = float(line[61:80])
|
||||
|
||||
e['x'], e['xVel'], e['xAccel'], e['svHealth'] = read4(f, rinex_ver)
|
||||
e['y'], e['yVel'], e['yAccel'], e['freqNum'] = read4(f, rinex_ver)
|
||||
e['z'], e['zVel'], e['zAccel'], e['age'] = read4(f, rinex_ver)
|
||||
|
||||
# TODO unclear why glonass sometimes has nav messages 3s after correct one
|
||||
if abs(tb - int(tb)) > 1e-3:
|
||||
continue
|
||||
|
||||
|
||||
data_struct = ephemeris_structs.GlonassEphemeris.new_message(**e)
|
||||
ephem = GLONASSEphemeris(data_struct, file_name=file_name)
|
||||
|
||||
ephems[ephem.prn].append(ephem)
|
||||
f.close()
|
||||
return ephems
|
||||
|
||||
|
||||
def parse_qcom_ephem(qcom_poly):
|
||||
svId = qcom_poly.svId
|
||||
prn = get_prn_from_nmea_id(svId)
|
||||
epoch = GPSTime(qcom_poly.gpsWeek, qcom_poly.gpsTow)
|
||||
|
||||
data = qcom_poly
|
||||
poly_data = {}
|
||||
poly_data['t0'] = epoch
|
||||
poly_data['xyz'] = np.array([
|
||||
[data.xyz0[0], data.xyzN[0], data.xyzN[1], data.xyzN[2]],
|
||||
[data.xyz0[1], data.xyzN[3], data.xyzN[4], data.xyzN[5]],
|
||||
[data.xyz0[2], data.xyzN[6], data.xyzN[7], data.xyzN[8]] ]).T
|
||||
|
||||
poly_data['clock'] = [1e-3*data.other[3], 1e-3*data.other[2], 1e-3*data.other[1], 1e-3*data.other[0]]
|
||||
poly_data['deg'] = 3
|
||||
poly_data['deg_t'] = 3
|
||||
return PolyEphemeris(prn, poly_data, epoch, ephem_type=EphemerisType.QCOM_POLY, max_time_diff=300, file_name='qcom')
|
||||
@@ -1,203 +0,0 @@
|
||||
import datetime
|
||||
|
||||
|
||||
def datetime_to_tow(t):
|
||||
"""
|
||||
Convert a Python datetime object to GPS Week and Time Of Week.
|
||||
Does *not* convert from UTC to GPST.
|
||||
Fractional seconds are supported.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
t : datetime
|
||||
A time to be converted, on the GPST timescale.
|
||||
mod1024 : bool, optional
|
||||
If True (default), the week number will be output in 10-bit form.
|
||||
|
||||
Returns
|
||||
-------
|
||||
week, tow : tuple (int, float)
|
||||
The GPS week number and time-of-week.
|
||||
"""
|
||||
# DateTime to GPS week and TOW
|
||||
wk_ref = datetime.datetime(2014, 2, 16, 0, 0, 0, 0, None)
|
||||
refwk = 1780
|
||||
wk = (t - wk_ref).days // 7 + refwk
|
||||
tow = ((t - wk_ref) - datetime.timedelta((wk - refwk) * 7.0)).total_seconds()
|
||||
return wk, tow
|
||||
|
||||
|
||||
def tow_to_datetime(tow, week):
|
||||
"""
|
||||
Convert a GPS Week and Time Of Week to Python datetime object.
|
||||
Does *not* convert from GPST to UTC.
|
||||
Fractional seconds are supported.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
tow : time of week in seconds
|
||||
|
||||
weeks : gps week
|
||||
|
||||
|
||||
Returns
|
||||
-------
|
||||
t : datetime
|
||||
Python datetime
|
||||
"""
|
||||
# GPS week and TOW to DateTime
|
||||
t = datetime.datetime(1980, 1, 6, 0, 0, 0, 0, None)
|
||||
t += datetime.timedelta(seconds=tow)
|
||||
t += datetime.timedelta(weeks=week)
|
||||
return t
|
||||
|
||||
|
||||
def get_leap_seconds(time):
|
||||
# TODO use library for this
|
||||
if time <= GPSTime.from_datetime(datetime.datetime(2006, 1, 1)):
|
||||
raise ValueError("Don't know how many leap seconds to use before 2006")
|
||||
elif time <= GPSTime.from_datetime(datetime.datetime(2009, 1, 1)):
|
||||
return 14
|
||||
elif time <= GPSTime.from_datetime(datetime.datetime(2012, 7, 1)):
|
||||
return 15
|
||||
elif time <= GPSTime.from_datetime(datetime.datetime(2015, 7, 1)):
|
||||
return 16
|
||||
elif time <= GPSTime.from_datetime(datetime.datetime(2017, 1, 1)):
|
||||
return 17
|
||||
else:
|
||||
return 18
|
||||
|
||||
|
||||
def gpst_to_utc(t_gpst):
|
||||
t_utc = t_gpst - get_leap_seconds(t_gpst)
|
||||
if utc_to_gpst(t_utc) - t_gpst != 0:
|
||||
return t_utc + 1
|
||||
else:
|
||||
return t_utc
|
||||
|
||||
|
||||
def utc_to_gpst(t_utc):
|
||||
t_gpst = t_utc + get_leap_seconds(t_utc)
|
||||
return t_gpst
|
||||
|
||||
|
||||
class GPSTime:
|
||||
"""
|
||||
GPS time class to add and subtract [week, tow]
|
||||
"""
|
||||
def __init__(self, week, tow):
|
||||
self.week = week
|
||||
self.tow = tow
|
||||
self.seconds_in_week = 604800
|
||||
|
||||
@classmethod
|
||||
def from_datetime(cls, datetime):
|
||||
week, tow = datetime_to_tow(datetime)
|
||||
return cls(week, tow)
|
||||
|
||||
@classmethod
|
||||
def from_glonass(cls, cycle, days, tow):
|
||||
# https://en.wikipedia.org/wiki/GLONASS
|
||||
# Day number (1 to 1461) within a four-year interval
|
||||
# starting on 1 January of the last leap year
|
||||
t = datetime.datetime(1992, 1, 1, 0, 0, 0, 0, None)
|
||||
t += datetime.timedelta(days=cycle*(365*4+1)+(days-1))
|
||||
# according to Moscow decree time.
|
||||
t -= datetime.timedelta(hours=3)
|
||||
t += datetime.timedelta(seconds=tow)
|
||||
ret = cls.from_datetime(t)
|
||||
return utc_to_gpst(ret)
|
||||
|
||||
@classmethod
|
||||
def from_meas(cls, meas):
|
||||
return cls(meas[1], meas[2])
|
||||
|
||||
def __sub__(self, other):
|
||||
if isinstance(other, type(self)):
|
||||
return (self.week - other.week)*self.seconds_in_week + self.tow - other.tow
|
||||
elif isinstance(other, float) or isinstance(other, int):
|
||||
new_week = self.week
|
||||
new_tow = self.tow - other
|
||||
while new_tow < 0:
|
||||
new_tow += self.seconds_in_week
|
||||
new_week -= 1
|
||||
return GPSTime(new_week, new_tow)
|
||||
raise NotImplementedError(f"subtracting {other} from {self}")
|
||||
|
||||
def __add__(self, other):
|
||||
if isinstance(other, float) or isinstance(other, int):
|
||||
new_week = self.week
|
||||
new_tow = self.tow + other
|
||||
while new_tow >= self.seconds_in_week:
|
||||
new_tow -= self.seconds_in_week
|
||||
new_week += 1
|
||||
return GPSTime(new_week, new_tow)
|
||||
raise NotImplementedError(f"adding {other} from {self}")
|
||||
|
||||
def __lt__(self, other):
|
||||
return self - other < 0
|
||||
|
||||
def __gt__(self, other):
|
||||
return self - other > 0
|
||||
|
||||
def __le__(self, other):
|
||||
return self - other <= 0
|
||||
|
||||
def __ge__(self, other):
|
||||
return self - other >= 0
|
||||
|
||||
def __eq__(self, other):
|
||||
return self - other == 0
|
||||
|
||||
def as_datetime(self):
|
||||
return tow_to_datetime(self.tow, self.week)
|
||||
|
||||
def as_glonass(self):
|
||||
time_utc = gpst_to_utc(self)
|
||||
datetime_utc = time_utc.as_datetime()
|
||||
datetime_glonass = datetime_utc + datetime.timedelta(hours=3)
|
||||
|
||||
year = datetime_glonass.year
|
||||
cycle = (year - 1992) // 4
|
||||
days = (datetime_glonass - datetime.datetime(1992 + cycle*4, 1, 1)).days + 1
|
||||
tod = (datetime_glonass - datetime_glonass.replace(hour=0, minute=0, second=0, microsecond=0)).total_seconds()
|
||||
return cycle, days, tod
|
||||
|
||||
def as_unix_timestamp(self):
|
||||
return (gpst_to_utc(self).as_datetime() - datetime.datetime(1970, 1, 1)).total_seconds()
|
||||
|
||||
@property
|
||||
def day(self):
|
||||
return int(self.tow/(24*3600))
|
||||
|
||||
def __repr__(self):
|
||||
return f"GPSTime(week={self.week}, tow={self.tow})"
|
||||
|
||||
|
||||
class TimeSyncer:
|
||||
"""
|
||||
Converts logmonotime to gps_time and vice versa
|
||||
"""
|
||||
def __init__(self, mono_time, gps_time):
|
||||
self.ref_mono_time = mono_time
|
||||
self.ref_gps_time = gps_time
|
||||
|
||||
@classmethod
|
||||
def from_datetime(cls, datetime):
|
||||
week, tow = datetime_to_tow(datetime)
|
||||
return cls(week, tow)
|
||||
|
||||
@classmethod
|
||||
def from_logs(cls, raw_qcom_measurement_report, clocks):
|
||||
#TODO
|
||||
#return cls(week, mono_time, gps_time)
|
||||
return None
|
||||
|
||||
def mono2gps(self, mono_time):
|
||||
return self.ref_gps_time + mono_time - self.ref_mono_time
|
||||
|
||||
def gps2mono(self, gps_time):
|
||||
return gps_time - self.ref_gps_time + self.ref_mono_time
|
||||
|
||||
def __str__(self):
|
||||
return f"Reference mono time: {self.ref_mono_time} \n Reference gps time: {self.ref_gps_time}"
|
||||
@@ -1,221 +0,0 @@
|
||||
from enum import IntEnum
|
||||
from typing import Dict
|
||||
|
||||
import numpy as np
|
||||
from .lib.coordinates import LocalCoord
|
||||
|
||||
|
||||
class ConstellationId(IntEnum):
|
||||
# Int values match Ublox gnssid version 8
|
||||
GPS = 0
|
||||
SBAS = 1
|
||||
GALILEO = 2
|
||||
BEIDOU = 3
|
||||
IMES = 4
|
||||
QZNSS = 5
|
||||
GLONASS = 6
|
||||
# Not supported by Ublox:
|
||||
IRNSS = 7
|
||||
|
||||
def to_rinex_char(self) -> str:
|
||||
# returns single character id
|
||||
return RINEX_CONSTELLATION_TO_ID[self]
|
||||
|
||||
@classmethod
|
||||
def from_rinex_char(cls, c: str):
|
||||
if c in RINEX_ID_TO_CONSTELLATION:
|
||||
return RINEX_ID_TO_CONSTELLATION[c]
|
||||
else:
|
||||
raise ValueError("Unknown rinex constellation id: ", c)
|
||||
|
||||
@classmethod
|
||||
def from_qcom_source(cls, report_source: int):
|
||||
if report_source == 0:
|
||||
return ConstellationId.GPS
|
||||
if report_source == 1:
|
||||
return ConstellationId.GLONASS
|
||||
if report_source == 2:
|
||||
return ConstellationId.BEIDOU
|
||||
if report_source == 6:
|
||||
return ConstellationId.SBAS
|
||||
raise NotImplementedError('Only GPS (0), GLONASS (1), BEIDOU (2) and SBAS (6) are supported from qcom, not:', {report_source})
|
||||
|
||||
|
||||
# From https://gpsd.gitlab.io/gpsd/NMEA.html#_satellite_ids
|
||||
# NmeaId is the unique 3 digits id for every satellite globally. (Example: 001, 201)
|
||||
# SvId is the 2 digits satellite id that is unique within a constellation. (Get the unique satellite with the constellation id. Examples: G01, R01)
|
||||
CONSTELLATION_TO_NMEA_RANGES = {
|
||||
# NmeaId ranges for each constellation with its svId offset.
|
||||
# constellation: [(start, end, svIdOffset)]
|
||||
# svId = nmeaId + offset
|
||||
ConstellationId.GPS: [(1, 32, 0)], # svId [1,32]
|
||||
ConstellationId.SBAS: [(33, 64, -32), (120, 158, -87)], # svId [1,71]
|
||||
ConstellationId.GLONASS: [(65, 96, -64)], # svId [1,31]
|
||||
ConstellationId.IMES: [(173, 182, -172)], # svId [1,9]
|
||||
ConstellationId.QZNSS: [(193, 200, -192)], # svId [1,28] # todo should be QZSS
|
||||
ConstellationId.BEIDOU: [(201, 235, -200), (401, 437, -365)], # svId 1-72
|
||||
ConstellationId.GALILEO: [(301, 336, -300)] # svId 1-36
|
||||
}
|
||||
#
|
||||
# # Source: RINEX 3.04
|
||||
RINEX_CONSTELLATION_TO_ID: Dict[ConstellationId, str] = {
|
||||
ConstellationId.GPS: 'G',
|
||||
ConstellationId.GLONASS: 'R',
|
||||
ConstellationId.SBAS: 'S',
|
||||
ConstellationId.GALILEO: 'E',
|
||||
ConstellationId.BEIDOU: 'C',
|
||||
ConstellationId.QZNSS: 'J',
|
||||
ConstellationId.IRNSS: 'I'
|
||||
}
|
||||
|
||||
# Make above dictionary bidirectional map:
|
||||
# Now you can ask for constellation using:
|
||||
# >>> RINEX_CONSTELLATION_IDENTIFIERS['R']
|
||||
# "GLONASS"
|
||||
RINEX_ID_TO_CONSTELLATION: Dict[str, ConstellationId] = {con_id: con for con, con_id in RINEX_CONSTELLATION_TO_ID.items()}
|
||||
|
||||
|
||||
def get_el_az(pos, sat_pos):
|
||||
converter = LocalCoord.from_ecef(pos)
|
||||
sat_ned = converter.ecef2ned(sat_pos)
|
||||
sat_range = np.linalg.norm(sat_ned)
|
||||
|
||||
el = np.arcsin(-sat_ned[2] / sat_range) # pylint: disable=unsubscriptable-object
|
||||
az = np.arctan2(sat_ned[1], sat_ned[0]) # pylint: disable=unsubscriptable-object
|
||||
return el, az
|
||||
|
||||
|
||||
def get_closest(time, candidates, recv_pos=None):
|
||||
if recv_pos is None:
|
||||
# Takes a list of object that have an epoch(GPSTime) value
|
||||
# and return the one that is closest the given time (GPSTime)
|
||||
return min(candidates, key=lambda candidate: abs(time - candidate.epoch), default=None)
|
||||
|
||||
return min(
|
||||
(candidate for candidate in candidates if candidate.valid(time, recv_pos)),
|
||||
key=lambda candidate: np.linalg.norm(recv_pos - candidate.pos),
|
||||
default=None,
|
||||
)
|
||||
|
||||
def get_constellation(prn: str):
|
||||
identifier = prn[0]
|
||||
return ConstellationId.from_rinex_char(identifier)
|
||||
|
||||
def get_sv_id(prn: str):
|
||||
return int(prn[1:])
|
||||
|
||||
def get_constellation_and_sv_id(nmea_id):
|
||||
for c, ranges in CONSTELLATION_TO_NMEA_RANGES.items():
|
||||
for (start, end, sv_id_offset) in ranges:
|
||||
if start <= nmea_id <= end:
|
||||
sv_id = nmea_id + sv_id_offset
|
||||
return c, sv_id
|
||||
|
||||
raise ValueError(f"constellation not found for nmeaid {nmea_id}")
|
||||
|
||||
|
||||
def get_prn_from_nmea_id(nmea_id: int):
|
||||
c_id, sv_id = get_constellation_and_sv_id(nmea_id)
|
||||
return "%s%02d" % (c_id.to_rinex_char(), sv_id)
|
||||
|
||||
|
||||
def get_nmea_id_from_prn(prn: str):
|
||||
constellation = get_constellation(prn)
|
||||
sv_id = int(prn[1:]) # satellite id
|
||||
return get_nmea_id_from_constellation_and_svid(constellation, sv_id)
|
||||
|
||||
|
||||
def get_nmea_id_from_constellation_and_svid(constellation: ConstellationId, sv_id: int):
|
||||
ranges = CONSTELLATION_TO_NMEA_RANGES[constellation]
|
||||
for (start, end, sv_id_offset) in ranges:
|
||||
new_nmea_id = sv_id - sv_id_offset
|
||||
if start <= new_nmea_id <= end:
|
||||
return new_nmea_id
|
||||
|
||||
raise ValueError(f"NMEA ID not found for constellation {constellation.name} with satellite id {sv_id}")
|
||||
|
||||
|
||||
def rinex3_obs_from_rinex2_obs(observable):
|
||||
if observable == 'P2':
|
||||
return 'C2P'
|
||||
if len(observable) == 2:
|
||||
return observable + 'C'
|
||||
raise NotImplementedError("Don't know this: " + observable)
|
||||
|
||||
|
||||
class TimeRangeHolder:
|
||||
'''Class to support test if date is in any of the multiple, sparse ranges'''
|
||||
|
||||
def __init__(self):
|
||||
# Sorted list
|
||||
self._ranges = []
|
||||
|
||||
def _previous_and_contains_index(self, time):
|
||||
prev = None
|
||||
current = None
|
||||
|
||||
for idx, (start, end) in enumerate(self._ranges):
|
||||
# Time may be in next range
|
||||
if time > end:
|
||||
continue
|
||||
|
||||
# Time isn't in any next range
|
||||
if time < start:
|
||||
prev = idx - 1
|
||||
current = None
|
||||
# Time is in current range
|
||||
else:
|
||||
prev = idx - 1
|
||||
current = idx
|
||||
break
|
||||
|
||||
# Break in last loop
|
||||
if prev is None:
|
||||
prev = len(self._ranges) - 1
|
||||
|
||||
return prev, current
|
||||
|
||||
def add(self, start_time, end_time):
|
||||
prev_start, current_start = self._previous_and_contains_index(start_time)
|
||||
_, current_end = self._previous_and_contains_index(end_time)
|
||||
|
||||
# Merge ranges
|
||||
if current_start is not None and current_end is not None:
|
||||
# If ranges are different then merge
|
||||
if current_start != current_end:
|
||||
new_start, _ = self._ranges[current_start]
|
||||
_, new_end = self._ranges[current_end]
|
||||
new_range = (new_start, new_end)
|
||||
# Required reversed order to correct remove
|
||||
del self._ranges[current_end]
|
||||
del self._ranges[current_start]
|
||||
self._ranges.insert(current_start, new_range)
|
||||
# Extend range - left
|
||||
elif current_start is not None:
|
||||
new_start, _ = self._ranges[current_start]
|
||||
new_range = (new_start, end_time)
|
||||
del self._ranges[current_start]
|
||||
self._ranges.insert(current_start, new_range)
|
||||
# Extend range - right
|
||||
elif current_end is not None:
|
||||
_, new_end = self._ranges[current_end]
|
||||
new_range = (start_time, new_end)
|
||||
del self._ranges[current_end]
|
||||
self._ranges.insert(prev_start + 1, new_range)
|
||||
# Create new range
|
||||
else:
|
||||
new_range = (start_time, end_time)
|
||||
self._ranges.insert(prev_start + 1, new_range)
|
||||
|
||||
def __contains__(self, time):
|
||||
for start, end in self._ranges:
|
||||
# Time may be in next range
|
||||
if time > end:
|
||||
continue
|
||||
|
||||
# Time isn't in any next range
|
||||
if time < start:
|
||||
return False
|
||||
# Time is in current range
|
||||
return True
|
||||
return False
|
||||
-256
@@ -1,256 +0,0 @@
|
||||
import datetime as dt
|
||||
import numpy as np
|
||||
import re
|
||||
from math import cos, sin, pi, floor
|
||||
from .constants import SECS_IN_MIN, SECS_IN_HR, EARTH_RADIUS
|
||||
from .lib.coordinates import LocalCoord
|
||||
from .gps_time import GPSTime
|
||||
|
||||
# Altitude of Ionospheric-pierce-point
|
||||
IPP_ALT = 6821000
|
||||
|
||||
def get_alpha_beta(rcv_pos, el):
|
||||
geocentric_alt = np.linalg.norm(rcv_pos)
|
||||
alpha = np.pi/2 + el
|
||||
arcsin_arg = geocentric_alt*np.sin(alpha)/IPP_ALT
|
||||
beta = np.arcsin(np.clip(arcsin_arg, -1, 1))
|
||||
return alpha, beta
|
||||
|
||||
def get_slant_delay(rcv_pos, az, el, sat_pos, time, freq, vertical_delay):
|
||||
alpha, beta = get_alpha_beta(rcv_pos, el)
|
||||
slant_delay = vertical_delay * ((1 - ((EARTH_RADIUS * np.sin(beta)) /
|
||||
(EARTH_RADIUS + 3.5e5))**2)**(-0.5))
|
||||
return slant_delay
|
||||
|
||||
def closest_in_list(lst, val, num=2):
|
||||
"""
|
||||
Returns two (`num` in general) closest values of `val` in list `lst`
|
||||
"""
|
||||
idxs = sorted(lst, key=lambda x: abs(x - val))[:num]
|
||||
return sorted(list(lst).index(x) for x in idxs)
|
||||
|
||||
|
||||
def get_header_line(headr, proprty):
|
||||
"""
|
||||
:param headr: the header of the RINEX-file
|
||||
:param proprty: string-like property to search for (e.g. 'delta-utc')
|
||||
:return: the string of the ``headr`` containing ``property``
|
||||
"""
|
||||
pattern = re.compile(proprty, re.IGNORECASE)
|
||||
for d in headr:
|
||||
if pattern.search(d):
|
||||
return d
|
||||
|
||||
|
||||
def get_header_body(file_path):
|
||||
"""
|
||||
Opens `file_path`, reads file and returns header and body
|
||||
separated with "END OF HEADER"
|
||||
:param file_path: path to RINEX-like file
|
||||
:return: header, body (arrays of lines)
|
||||
"""
|
||||
with open(file_path) as fd:
|
||||
data = fd.readlines()
|
||||
for j, d in enumerate(data):
|
||||
if "END OF HEADER" in d:
|
||||
header_end = j
|
||||
break
|
||||
return data[:header_end], data[header_end + 1:]
|
||||
|
||||
|
||||
def get_int_from_header(hdr, seq):
|
||||
"""
|
||||
Returns the first int from the line that contains `seq` of lines `hdr`.
|
||||
In fact, _header_ here may not be header of RINEX/IONEX, just some set of lines.
|
||||
"""
|
||||
return int(get_header_line(hdr, seq).split()[0])
|
||||
|
||||
def compute_grid_lats_lons(data):
|
||||
grid = np.array([], dtype='uint16')
|
||||
lats = np.array([])
|
||||
for j, line in enumerate(data[1:]):
|
||||
if "LAT" in line:
|
||||
lat, lon1, lon2, dlon, h = (float(line[x:x + 6]) for x in range(2, 32, 6))
|
||||
lats = np.append(lats, lat)
|
||||
row_length = (lon2 - lon1) / dlon + 1 # total number of values of longitudes
|
||||
next_lines_with_numbers = int(np.ceil(row_length / 16))
|
||||
elems_in_row = [
|
||||
min(16, int(row_length - i * 16)) for i in range(next_lines_with_numbers)
|
||||
]
|
||||
row = np.array([], dtype='int16')
|
||||
for i, elem in enumerate(elems_in_row):
|
||||
row = np.append(
|
||||
row,
|
||||
np.array(
|
||||
[int(data[j + 2 + i][5 * x:5 * x + 5]) for x in range(elem)],
|
||||
dtype='int16',
|
||||
),
|
||||
)
|
||||
if len(grid) > 0:
|
||||
grid = np.vstack((grid, row))
|
||||
else:
|
||||
grid = np.append(grid, row)
|
||||
lons = np.linspace(lon1, lon2, int(row_length))
|
||||
return (grid, lats, lons)
|
||||
|
||||
|
||||
class IonexMap:
|
||||
def __init__(self, exp, data1, data2):
|
||||
self.exp = exp
|
||||
self.t1 = GPSTime.from_datetime(dt.datetime(*[int(d) for d in data1[0].split()[:6]]))
|
||||
self.t2 = GPSTime.from_datetime(dt.datetime(*[int(d) for d in data2[0].split()[:6]]))
|
||||
assert self.t2 - self.t1 == SECS_IN_HR
|
||||
assert len(data1) == len(data2)
|
||||
|
||||
self.max_time_diff = SECS_IN_MIN*30
|
||||
self.epoch = self.t1 + self.max_time_diff
|
||||
|
||||
self.grid_TEC1, self.lats, self.lons = compute_grid_lats_lons(data1)
|
||||
self.grid_TEC2, self.lats, self.lons = compute_grid_lats_lons(data2)
|
||||
|
||||
def valid(self, time):
|
||||
return abs(time - self.epoch) <= self.max_time_diff
|
||||
|
||||
@staticmethod
|
||||
def find_nearest(lst, val):
|
||||
return (np.abs(lst - val)).argmin()
|
||||
|
||||
def get_TEC(self, pos, time):
|
||||
"""
|
||||
Returns TEC in a position `pos` of ionosphere
|
||||
:param pos: (lat, lon) [deg, deg]
|
||||
:return:
|
||||
"""
|
||||
if pos[0] in self.lats and pos[1] in self.lons:
|
||||
lat = self.find_nearest(self.lats, pos[0])
|
||||
lon = self.find_nearest(self.lons, pos[1])
|
||||
E = self.grid_TEC1[lat][lon] + self.grid_TEC2[lat][lon]
|
||||
return E
|
||||
lat_idxs = closest_in_list(self.lats, pos[0])
|
||||
lon_idxs = closest_in_list(self.lons, pos[1])
|
||||
lat0, lat1 = self.lats[lat_idxs[0]], self.lats[lat_idxs[1]]
|
||||
lon0, lon1 = self.lons[lon_idxs[0]], self.lons[lon_idxs[1]]
|
||||
dlat = lat1 - lat0
|
||||
dlon = lon1 - lon0
|
||||
p = float(pos[0] - lat0) / dlat
|
||||
q = float(pos[1] - lon0) / dlon
|
||||
|
||||
(E00, E10), (E01, E11) = self.grid_TEC1[lat_idxs[0]:lat_idxs[1] + 1, lon_idxs[0]:lon_idxs[1] + 1]
|
||||
TEC_1 = ((1 - p) * (1 - q) * E00 + p * (1 - q) * E01 + (1 - p) * q * E10 + p * q * E11)
|
||||
(E00, E10), (E01, E11) = self.grid_TEC2[lat_idxs[0]:lat_idxs[1] + 1, lon_idxs[0]:lon_idxs[1] + 1]
|
||||
TEC_2 = ((1 - p) * (1 - q) * E00 + p * (1 - q) * E01 + (1 - p) * q * E10 + p * q * E11)
|
||||
|
||||
return (1 - (time - self.t1)/SECS_IN_HR)*TEC_1 + ((time - self.t1)/SECS_IN_HR)*TEC_2
|
||||
|
||||
def get_delay(self, rcv_pos, az, el, sat_pos, time, freq):
|
||||
# To get a delay from a TEC map, we need to calculate
|
||||
# the ionospheric pierce point, geometry described here
|
||||
# https://en.wikipedia.org/wiki/Ionospheric_pierce_point
|
||||
alpha, beta = get_alpha_beta(rcv_pos, el)
|
||||
conv = LocalCoord.from_ecef(rcv_pos)
|
||||
gamma = np.pi - alpha - beta
|
||||
geocentric_alt = np.linalg.norm(rcv_pos)
|
||||
ipp_dist = geocentric_alt*np.sin(gamma)/np.sin(beta)
|
||||
ipp_ned = conv.ecef2ned(sat_pos)*(ipp_dist)/np.linalg.norm(sat_pos)
|
||||
ipp_geo = conv.ned2geodetic(ipp_ned)
|
||||
factor = 40.30E16 / (freq**2) * 10**(self.exp)
|
||||
vertical_delay = self.get_TEC(ipp_geo, time) * factor
|
||||
slant_delay = get_slant_delay(rcv_pos, az, el, sat_pos, time, freq, vertical_delay)
|
||||
return slant_delay
|
||||
|
||||
@staticmethod
|
||||
def round_to_grid(number, base):
|
||||
return int(base * round(float(number) / base))
|
||||
|
||||
|
||||
def parse_ionex(ionex_file):
|
||||
"""
|
||||
:param ionex_file: path to the IONEX file
|
||||
:return: TEC interpolation function `f( (lat,lon), datetime )`
|
||||
"""
|
||||
header, body = get_header_body(ionex_file)
|
||||
|
||||
exponent = get_int_from_header(header, "EXPONENT")
|
||||
maps_count = get_int_from_header(header, "MAPS IN FILE")
|
||||
# =============
|
||||
# Separate maps
|
||||
# =============
|
||||
map_start_idx = []
|
||||
map_end_idx = []
|
||||
|
||||
for j, line in enumerate(body):
|
||||
if "START OF TEC MAP" in line:
|
||||
map_start_idx += [j]
|
||||
elif "END OF TEC MAP" in line:
|
||||
map_end_idx += [j]
|
||||
if maps_count != len(map_start_idx):
|
||||
raise LookupError("Parsing error: the number of maps in the header " +
|
||||
"is not equal to the number of maps in the body.")
|
||||
if len(map_start_idx) != len(map_end_idx):
|
||||
raise IndexError("Starts end ends numbers are not equal.")
|
||||
map_dates = []
|
||||
for i in range(maps_count):
|
||||
date_components = body[map_start_idx[i] + 1].split()[:6]
|
||||
map_dates.append(dt.datetime(*[int(d) for d in date_components]))
|
||||
|
||||
maps = []
|
||||
iono_map = iono_map_prev = None
|
||||
for m in range(maps_count):
|
||||
iono_map_prev = iono_map
|
||||
iono_map = body[map_start_idx[m] + 1:map_end_idx[m]]
|
||||
if iono_map and iono_map_prev:
|
||||
maps += [IonexMap(exponent, iono_map_prev, iono_map)]
|
||||
return maps
|
||||
|
||||
|
||||
def klobuchar(pos, az, el, time, iono_coeffs):
|
||||
"""
|
||||
Details are taken from [5]: IS-GPS-200H, Fig. 20-4
|
||||
Note: result is referred to the GPS L₁ frequency;
|
||||
if the user is operating on the GPS L₂ frequency, the correction term must
|
||||
be multiplied by γ = f₂²/f₁¹ = 0.6071850227694382
|
||||
:param pos: [lat, lon, alt] in radians and meters
|
||||
"""
|
||||
|
||||
tow = time.tow
|
||||
if pos[2] < -1E3 or el < 0:
|
||||
return 0.0
|
||||
if len(iono_coeffs) < 8:
|
||||
return None
|
||||
|
||||
# earth centered angle (semi-circle)
|
||||
psi = 0.0137 / (el / pi + 0.11) - 0.022
|
||||
|
||||
# subionospheric latitude/longitude (semi-circle)
|
||||
phi = pos[0] / pi + psi * cos(az)
|
||||
if phi > 0.416:
|
||||
phi = 0.416
|
||||
elif phi < -0.416:
|
||||
phi = -0.416
|
||||
lam = pos[1] / pi + psi * sin(az) / cos(phi * pi)
|
||||
|
||||
# geomagnetic latitude (semi-circle) */
|
||||
phi += 0.064 * cos((lam - 1.617) * pi)
|
||||
|
||||
# local time (s)
|
||||
tt = 43200.0 * lam + tow
|
||||
tt -= floor(tt / 86400.0) * 86400.0 # 0<=tt<86400
|
||||
|
||||
# slant factor
|
||||
f = 1.0 + 16.0 * pow(0.53 - el / pi, 3.0)
|
||||
|
||||
# ionospheric delay
|
||||
amp = iono_coeffs[0] + phi * (iono_coeffs[1] + phi *
|
||||
(iono_coeffs[2] + phi * iono_coeffs[3]))
|
||||
per = iono_coeffs[4] + phi * (iono_coeffs[5] + phi *
|
||||
(iono_coeffs[6] + phi * iono_coeffs[7]))
|
||||
if amp < 0.0:
|
||||
amp = 0.
|
||||
if per < 72000.0:
|
||||
per = 72000.0
|
||||
x = 2.0 * pi * (tt - 50400.0) / per
|
||||
|
||||
mul = 5E-9
|
||||
if abs(x) < 1.57:
|
||||
mul = (5E-9 + amp * (1.0 + x * x * (-0.5 + x * x / 24.0)))
|
||||
return 2.99792458E8 * f * mul
|
||||
@@ -1,106 +0,0 @@
|
||||
import numpy as np
|
||||
"""
|
||||
Coordinate transformation module. All methods accept arrays as input
|
||||
with each row as a position.
|
||||
"""
|
||||
|
||||
|
||||
a = 6378137
|
||||
b = 6356752.3142
|
||||
esq = 6.69437999014 * 0.001
|
||||
e1sq = 6.73949674228 * 0.001
|
||||
|
||||
|
||||
def geodetic2ecef(geodetic, radians=False):
|
||||
geodetic = np.array(geodetic)
|
||||
input_shape = geodetic.shape
|
||||
geodetic = np.atleast_2d(geodetic)
|
||||
|
||||
ratio = 1.0 if radians else (np.pi / 180.0)
|
||||
lat = ratio*geodetic[:,0]
|
||||
lon = ratio*geodetic[:,1]
|
||||
alt = geodetic[:,2]
|
||||
|
||||
xi = np.sqrt(1 - esq * np.sin(lat)**2)
|
||||
x = (a / xi + alt) * np.cos(lat) * np.cos(lon)
|
||||
y = (a / xi + alt) * np.cos(lat) * np.sin(lon)
|
||||
z = (a / xi * (1 - esq) + alt) * np.sin(lat)
|
||||
ecef = np.array([x, y, z]).T
|
||||
return ecef.reshape(input_shape)
|
||||
|
||||
|
||||
def ecef2geodetic(ecef, radians=False):
|
||||
"""
|
||||
Convert ECEF coordinates to geodetic using ferrari's method
|
||||
"""
|
||||
# Save shape and export column
|
||||
ecef = np.atleast_1d(ecef)
|
||||
input_shape = ecef.shape
|
||||
ecef = np.atleast_2d(ecef)
|
||||
x, y, z = ecef[:, 0], ecef[:, 1], ecef[:, 2]
|
||||
|
||||
ratio = 1.0 if radians else (180.0 / np.pi)
|
||||
|
||||
# Conver from ECEF to geodetic using Ferrari's methods
|
||||
# https://en.wikipedia.org/wiki/Geographic_coordinate_conversion#Ferrari.27s_solution
|
||||
r = np.sqrt(x * x + y * y)
|
||||
Esq = a * a - b * b
|
||||
F = 54 * b * b * z * z
|
||||
G = r * r + (1 - esq) * z * z - esq * Esq
|
||||
C = (esq * esq * F * r * r) / (pow(G, 3))
|
||||
S = np.cbrt(1 + C + np.sqrt(C * C + 2 * C))
|
||||
P = F / (3 * pow((S + 1 / S + 1), 2) * G * G)
|
||||
Q = np.sqrt(1 + 2 * esq * esq * P)
|
||||
r_0 = -(P * esq * r) / (1 + Q) + np.sqrt(0.5 * a * a*(1 + 1.0 / Q) -
|
||||
P * (1 - esq) * z * z / (Q * (1 + Q)) - 0.5 * P * r * r)
|
||||
U = np.sqrt(pow((r - esq * r_0), 2) + z * z)
|
||||
V = np.sqrt(pow((r - esq * r_0), 2) + (1 - esq) * z * z)
|
||||
Z_0 = b * b * z / (a * V)
|
||||
h = U * (1 - b * b / (a * V))
|
||||
lat = ratio*np.arctan((z + e1sq * Z_0) / r)
|
||||
lon = ratio*np.arctan2(y, x)
|
||||
|
||||
# stack the new columns and return to the original shape
|
||||
geodetic = np.column_stack((lat, lon, h))
|
||||
return geodetic.reshape(input_shape)
|
||||
|
||||
class LocalCoord:
|
||||
"""
|
||||
Allows conversions to local frames. In this case NED.
|
||||
That is: North East Down from the start position in
|
||||
meters.
|
||||
"""
|
||||
def __init__(self, init_geodetic, init_ecef):
|
||||
self.init_ecef = init_ecef
|
||||
lat, lon, _ = (np.pi/180)*np.array(init_geodetic)
|
||||
self.ned2ecef_matrix = np.array([[-np.sin(lat)*np.cos(lon), -np.sin(lon), -np.cos(lat)*np.cos(lon)],
|
||||
[-np.sin(lat)*np.sin(lon), np.cos(lon), -np.cos(lat)*np.sin(lon)],
|
||||
[np.cos(lat), 0, -np.sin(lat)]])
|
||||
self.ecef2ned_matrix = self.ned2ecef_matrix.T
|
||||
|
||||
@classmethod
|
||||
def from_geodetic(cls, init_geodetic):
|
||||
init_ecef = geodetic2ecef(init_geodetic)
|
||||
return LocalCoord(init_geodetic, init_ecef)
|
||||
|
||||
@classmethod
|
||||
def from_ecef(cls, init_ecef):
|
||||
init_geodetic = ecef2geodetic(init_ecef)
|
||||
return LocalCoord(init_geodetic, init_ecef)
|
||||
|
||||
def ecef2ned(self, ecef):
|
||||
ecef = np.array(ecef)
|
||||
return np.dot(self.ecef2ned_matrix, (ecef - self.init_ecef).T).T
|
||||
|
||||
def ned2ecef(self, ned):
|
||||
ned = np.array(ned)
|
||||
# Transpose so that init_ecef will broadcast correctly for 1d or 2d ned.
|
||||
return (np.dot(self.ned2ecef_matrix, ned.T).T + self.init_ecef)
|
||||
|
||||
def geodetic2ned(self, geodetic):
|
||||
ecef = geodetic2ecef(geodetic)
|
||||
return self.ecef2ned(ecef)
|
||||
|
||||
def ned2geodetic(self, ned):
|
||||
ecef = self.ned2ecef(ned)
|
||||
return ecef2geodetic(ecef)
|
||||
@@ -1,291 +0,0 @@
|
||||
import numpy as np
|
||||
from numpy import dot, inner, array, linalg
|
||||
from .coordinates import LocalCoord
|
||||
|
||||
|
||||
'''
|
||||
Vectorized functions that transform between
|
||||
rotation matrices, euler angles and quaternions.
|
||||
All support lists, array or array of arrays as inputs.
|
||||
Supports both x2y and y_from_x format (y_from_x preferred!).
|
||||
'''
|
||||
|
||||
def euler2quat(eulers):
|
||||
eulers = array(eulers)
|
||||
if len(eulers.shape) > 1:
|
||||
output_shape = (-1,4)
|
||||
else:
|
||||
output_shape = (4,)
|
||||
eulers = np.atleast_2d(eulers)
|
||||
gamma, theta, psi = eulers[:,0], eulers[:,1], eulers[:,2]
|
||||
|
||||
cos_half_gamma = np.cos(gamma / 2)
|
||||
cos_half_theta = np.cos(theta / 2)
|
||||
cos_half_psi = np.cos(psi / 2)
|
||||
sin_half_gamma = np.sin(gamma / 2)
|
||||
sin_half_theta = np.sin(theta / 2)
|
||||
sin_half_psi = np.sin(psi / 2)
|
||||
q0 = cos_half_gamma * cos_half_theta * cos_half_psi + sin_half_gamma * sin_half_theta * sin_half_psi
|
||||
q1 = sin_half_gamma * cos_half_theta * cos_half_psi - cos_half_gamma * sin_half_theta * sin_half_psi
|
||||
q2 = cos_half_gamma * sin_half_theta * cos_half_psi + sin_half_gamma * cos_half_theta * sin_half_psi
|
||||
q3 = cos_half_gamma * cos_half_theta * sin_half_psi - sin_half_gamma * sin_half_theta * cos_half_psi
|
||||
|
||||
quats = array([q0, q1, q2, q3]).T
|
||||
for i in range(len(quats)):
|
||||
if quats[i,0] < 0:
|
||||
quats[i] = -quats[i]
|
||||
return quats.reshape(output_shape)
|
||||
|
||||
|
||||
def quat2euler(quats):
|
||||
quats = array(quats)
|
||||
if len(quats.shape) > 1:
|
||||
output_shape = (-1,3)
|
||||
else:
|
||||
output_shape = (3,)
|
||||
quats = np.atleast_2d(quats)
|
||||
q0, q1, q2, q3 = quats[:,0], quats[:,1], quats[:,2], quats[:,3]
|
||||
|
||||
gamma = np.arctan2(2 * (q0 * q1 + q2 * q3), 1 - 2 * (q1**2 + q2**2))
|
||||
theta = np.arcsin(2 * (q0 * q2 - q3 * q1))
|
||||
psi = np.arctan2(2 * (q0 * q3 + q1 * q2), 1 - 2 * (q2**2 + q3**2))
|
||||
|
||||
eulers = array([gamma, theta, psi]).T
|
||||
return eulers.reshape(output_shape)
|
||||
|
||||
|
||||
def quat2rot(quats):
|
||||
quats = array(quats)
|
||||
input_shape = quats.shape
|
||||
quats = np.atleast_2d(quats)
|
||||
Rs = np.zeros((quats.shape[0], 3, 3))
|
||||
q0 = quats[:, 0]
|
||||
q1 = quats[:, 1]
|
||||
q2 = quats[:, 2]
|
||||
q3 = quats[:, 3]
|
||||
Rs[:, 0, 0] = q0 * q0 + q1 * q1 - q2 * q2 - q3 * q3
|
||||
Rs[:, 0, 1] = 2 * (q1 * q2 - q0 * q3)
|
||||
Rs[:, 0, 2] = 2 * (q0 * q2 + q1 * q3)
|
||||
Rs[:, 1, 0] = 2 * (q1 * q2 + q0 * q3)
|
||||
Rs[:, 1, 1] = q0 * q0 - q1 * q1 + q2 * q2 - q3 * q3
|
||||
Rs[:, 1, 2] = 2 * (q2 * q3 - q0 * q1)
|
||||
Rs[:, 2, 0] = 2 * (q1 * q3 - q0 * q2)
|
||||
Rs[:, 2, 1] = 2 * (q0 * q1 + q2 * q3)
|
||||
Rs[:, 2, 2] = q0 * q0 - q1 * q1 - q2 * q2 + q3 * q3
|
||||
|
||||
if len(input_shape) < 2:
|
||||
return Rs[0]
|
||||
return Rs
|
||||
|
||||
|
||||
def rot2quat(rots):
|
||||
input_shape = rots.shape
|
||||
if len(input_shape) < 3:
|
||||
rots = array([rots])
|
||||
K3 = np.empty((len(rots), 4, 4))
|
||||
K3[:, 0, 0] = (rots[:, 0, 0] - rots[:, 1, 1] - rots[:, 2, 2]) / 3.0
|
||||
K3[:, 0, 1] = (rots[:, 1, 0] + rots[:, 0, 1]) / 3.0
|
||||
K3[:, 0, 2] = (rots[:, 2, 0] + rots[:, 0, 2]) / 3.0
|
||||
K3[:, 0, 3] = (rots[:, 1, 2] - rots[:, 2, 1]) / 3.0
|
||||
K3[:, 1, 0] = K3[:, 0, 1]
|
||||
K3[:, 1, 1] = (rots[:, 1, 1] - rots[:, 0, 0] - rots[:, 2, 2]) / 3.0
|
||||
K3[:, 1, 2] = (rots[:, 2, 1] + rots[:, 1, 2]) / 3.0
|
||||
K3[:, 1, 3] = (rots[:, 2, 0] - rots[:, 0, 2]) / 3.0
|
||||
K3[:, 2, 0] = K3[:, 0, 2]
|
||||
K3[:, 2, 1] = K3[:, 1, 2]
|
||||
K3[:, 2, 2] = (rots[:, 2, 2] - rots[:, 0, 0] - rots[:, 1, 1]) / 3.0
|
||||
K3[:, 2, 3] = (rots[:, 0, 1] - rots[:, 1, 0]) / 3.0
|
||||
K3[:, 3, 0] = K3[:, 0, 3]
|
||||
K3[:, 3, 1] = K3[:, 1, 3]
|
||||
K3[:, 3, 2] = K3[:, 2, 3]
|
||||
K3[:, 3, 3] = (rots[:, 0, 0] + rots[:, 1, 1] + rots[:, 2, 2]) / 3.0
|
||||
q = np.empty((len(rots), 4))
|
||||
for i in range(len(rots)):
|
||||
_, eigvecs = linalg.eigh(K3[i].T)
|
||||
eigvecs = eigvecs[:,3:]
|
||||
q[i, 0] = eigvecs[-1]
|
||||
q[i, 1:] = -eigvecs[:-1].flatten()
|
||||
if q[i, 0] < 0:
|
||||
q[i] = -q[i]
|
||||
|
||||
if len(input_shape) < 3:
|
||||
return q[0]
|
||||
return q
|
||||
|
||||
|
||||
def euler2rot(eulers):
|
||||
return rotations_from_quats(euler2quat(eulers))
|
||||
|
||||
|
||||
def rot2euler(rots):
|
||||
return quat2euler(quats_from_rotations(rots))
|
||||
|
||||
|
||||
quats_from_rotations = rot2quat
|
||||
quat_from_rot = rot2quat
|
||||
rotations_from_quats = quat2rot
|
||||
rot_from_quat= quat2rot
|
||||
rot_from_quat= quat2rot
|
||||
euler_from_rot = rot2euler
|
||||
euler_from_quat = quat2euler
|
||||
rot_from_euler = euler2rot
|
||||
quat_from_euler = euler2quat
|
||||
|
||||
|
||||
'''
|
||||
Random helpers below
|
||||
'''
|
||||
|
||||
|
||||
def quat_product(q, r):
|
||||
t = np.zeros(4)
|
||||
t[0] = r[0] * q[0] - r[1] * q[1] - r[2] * q[2] - r[3] * q[3]
|
||||
t[1] = r[0] * q[1] + r[1] * q[0] - r[2] * q[3] + r[3] * q[2]
|
||||
t[2] = r[0] * q[2] + r[1] * q[3] + r[2] * q[0] - r[3] * q[1]
|
||||
t[3] = r[0] * q[3] - r[1] * q[2] + r[2] * q[1] + r[3] * q[0]
|
||||
return t
|
||||
|
||||
|
||||
def rot_matrix(roll, pitch, yaw):
|
||||
cr, sr = np.cos(roll), np.sin(roll)
|
||||
cp, sp = np.cos(pitch), np.sin(pitch)
|
||||
cy, sy = np.cos(yaw), np.sin(yaw)
|
||||
rr = array([[1,0,0],[0, cr,-sr],[0, sr, cr]])
|
||||
rp = array([[cp,0,sp],[0, 1,0],[-sp, 0, cp]])
|
||||
ry = array([[cy,-sy,0],[sy, cy,0],[0, 0, 1]])
|
||||
return ry.dot(rp.dot(rr))
|
||||
|
||||
|
||||
def rot(axis, angle):
|
||||
# Rotates around an arbitrary axis
|
||||
ret_1 = (1 - np.cos(angle)) * array([[axis[0]**2, axis[0] * axis[1], axis[0] * axis[2]], [
|
||||
axis[1] * axis[0], axis[1]**2, axis[1] * axis[2]
|
||||
], [axis[2] * axis[0], axis[2] * axis[1], axis[2]**2]])
|
||||
ret_2 = np.cos(angle) * np.eye(3)
|
||||
ret_3 = np.sin(angle) * array([[0, -axis[2], axis[1]], [axis[2], 0, -axis[0]],
|
||||
[-axis[1], axis[0], 0]])
|
||||
return ret_1 + ret_2 + ret_3
|
||||
|
||||
|
||||
def ecef_euler_from_ned(ned_ecef_init, ned_pose):
|
||||
'''
|
||||
Got it from here:
|
||||
Using Rotations to Build Aerospace Coordinate Systems
|
||||
-Don Koks
|
||||
'''
|
||||
converter = LocalCoord.from_ecef(ned_ecef_init)
|
||||
x0 = converter.ned2ecef([1, 0, 0]) - converter.ned2ecef([0, 0, 0])
|
||||
y0 = converter.ned2ecef([0, 1, 0]) - converter.ned2ecef([0, 0, 0])
|
||||
z0 = converter.ned2ecef([0, 0, 1]) - converter.ned2ecef([0, 0, 0])
|
||||
|
||||
x1 = rot(z0, ned_pose[2]).dot(x0)
|
||||
y1 = rot(z0, ned_pose[2]).dot(y0)
|
||||
z1 = rot(z0, ned_pose[2]).dot(z0)
|
||||
|
||||
x2 = rot(y1, ned_pose[1]).dot(x1)
|
||||
y2 = rot(y1, ned_pose[1]).dot(y1)
|
||||
z2 = rot(y1, ned_pose[1]).dot(z1)
|
||||
|
||||
x3 = rot(x2, ned_pose[0]).dot(x2)
|
||||
y3 = rot(x2, ned_pose[0]).dot(y2)
|
||||
#z3 = rot(x2, ned_pose[0]).dot(z2)
|
||||
|
||||
x0 = array([1, 0, 0])
|
||||
y0 = array([0, 1, 0])
|
||||
z0 = array([0, 0, 1])
|
||||
|
||||
psi = np.arctan2(inner(x3, y0), inner(x3, x0))
|
||||
theta = np.arctan2(-inner(x3, z0), np.sqrt(inner(x3, x0)**2 + inner(x3, y0)**2))
|
||||
y2 = rot(z0, psi).dot(y0)
|
||||
z2 = rot(y2, theta).dot(z0)
|
||||
phi = np.arctan2(inner(y3, z2), inner(y3, y2))
|
||||
|
||||
ret = array([phi, theta, psi])
|
||||
return ret
|
||||
|
||||
|
||||
def ned_euler_from_ecef(ned_ecef_init, ecef_poses):
|
||||
'''
|
||||
Got the math from here:
|
||||
Using Rotations to Build Aerospace Coordinate Systems
|
||||
-Don Koks
|
||||
|
||||
Also accepts array of ecef_poses and array of ned_ecef_inits.
|
||||
Where each row is a pose and an ecef_init.
|
||||
'''
|
||||
ned_ecef_init = array(ned_ecef_init)
|
||||
ecef_poses = array(ecef_poses)
|
||||
output_shape = ecef_poses.shape
|
||||
ned_ecef_init = np.atleast_2d(ned_ecef_init)
|
||||
if ned_ecef_init.shape[0] == 1:
|
||||
ned_ecef_init = np.tile(ned_ecef_init[0], (output_shape[0], 1))
|
||||
ecef_poses = np.atleast_2d(ecef_poses)
|
||||
|
||||
ned_poses = np.zeros(ecef_poses.shape)
|
||||
for i, ecef_pose in enumerate(ecef_poses):
|
||||
converter = LocalCoord.from_ecef(ned_ecef_init[i])
|
||||
x0 = array([1, 0, 0])
|
||||
y0 = array([0, 1, 0])
|
||||
z0 = array([0, 0, 1])
|
||||
|
||||
x1 = rot(z0, ecef_pose[2]).dot(x0)
|
||||
y1 = rot(z0, ecef_pose[2]).dot(y0)
|
||||
z1 = rot(z0, ecef_pose[2]).dot(z0)
|
||||
|
||||
x2 = rot(y1, ecef_pose[1]).dot(x1)
|
||||
y2 = rot(y1, ecef_pose[1]).dot(y1)
|
||||
z2 = rot(y1, ecef_pose[1]).dot(z1)
|
||||
|
||||
x3 = rot(x2, ecef_pose[0]).dot(x2)
|
||||
y3 = rot(x2, ecef_pose[0]).dot(y2)
|
||||
#z3 = rot(x2, ecef_pose[0]).dot(z2)
|
||||
|
||||
x0 = converter.ned2ecef([1, 0, 0]) - converter.ned2ecef([0, 0, 0])
|
||||
y0 = converter.ned2ecef([0, 1, 0]) - converter.ned2ecef([0, 0, 0])
|
||||
z0 = converter.ned2ecef([0, 0, 1]) - converter.ned2ecef([0, 0, 0])
|
||||
|
||||
psi = np.arctan2(inner(x3, y0), inner(x3, x0))
|
||||
theta = np.arctan2(-inner(x3, z0), np.sqrt(inner(x3, x0)**2 + inner(x3, y0)**2))
|
||||
y2 = rot(z0, psi).dot(y0)
|
||||
z2 = rot(y2, theta).dot(z0)
|
||||
phi = np.arctan2(inner(y3, z2), inner(y3, y2))
|
||||
ned_poses[i] = array([phi, theta, psi])
|
||||
|
||||
return ned_poses.reshape(output_shape)
|
||||
|
||||
|
||||
def ecef2car(car_ecef, psi, theta, points_ecef, ned_converter):
|
||||
"""
|
||||
TODO: add roll rotation
|
||||
Converts an array of points in ecef coordinates into
|
||||
x-forward, y-left, z-up coordinates
|
||||
Parameters
|
||||
----------
|
||||
psi: yaw, radian
|
||||
theta: pitch, radian
|
||||
Returns
|
||||
-------
|
||||
[x, y, z] coordinates in car frame
|
||||
"""
|
||||
|
||||
# input is an array of points in ecef cocrdinates
|
||||
# output is an array of points in car's coordinate (x-front, y-left, z-up)
|
||||
|
||||
# convert points to NED
|
||||
points_ned = []
|
||||
for p in points_ecef:
|
||||
points_ned.append(ned_converter.ecef2ned_matrix.dot(array(p) - car_ecef))
|
||||
|
||||
points_ned = np.vstack(points_ned).T
|
||||
|
||||
# n, e, d -> x, y, z
|
||||
# Calculate relative positions and rotate wrt to heading and pitch of car
|
||||
invert_R = array([[1., 0., 0.], [0., -1., 0.], [0., 0., -1.]])
|
||||
|
||||
c, s = np.cos(psi), np.sin(psi)
|
||||
yaw_R = array([[c, s, 0.], [-s, c, 0.], [0., 0., 1.]])
|
||||
|
||||
c, s = np.cos(theta), np.sin(theta)
|
||||
pitch_R = array([[c, 0., -s], [0., 1., 0.], [s, 0., c]])
|
||||
|
||||
return dot(pitch_R, dot(yaw_R, dot(invert_R, points_ned)))
|
||||
-192
@@ -1,192 +0,0 @@
|
||||
import sympy
|
||||
import numpy as np
|
||||
from typing import List
|
||||
|
||||
from .constants import EARTH_ROTATION_RATE, SPEED_OF_LIGHT
|
||||
from .helpers import ConstellationId
|
||||
from .raw_gnss import GNSSMeasurement
|
||||
|
||||
|
||||
def gauss_newton(fun, b, M, xtol=1e-8, max_n=25):
|
||||
|
||||
W = np.linalg.inv(M)
|
||||
for _ in range(max_n):
|
||||
# Compute function and jacobian on current estimate
|
||||
r, J = fun(b)
|
||||
|
||||
# Update estimate, WLS https://en.wikipedia.org/wiki/Weighted_least_squares
|
||||
delta = np.linalg.pinv(J.T.dot(W).dot(J)).dot(J.T).dot(W) @ r
|
||||
b -= delta
|
||||
|
||||
# Check step size for stopping condition
|
||||
if np.linalg.norm(delta) < xtol:
|
||||
break
|
||||
|
||||
r, J = fun(b)
|
||||
Mb = np.linalg.pinv(J.T.dot(W).dot(J))
|
||||
x_std = np.sqrt(np.diagonal(Mb))
|
||||
return b, r, x_std
|
||||
|
||||
|
||||
def calc_pos_fix(measurements, posfix_functions=None, x0=None, signal='C1C', min_measurements=5):
|
||||
'''
|
||||
Calculates gps fix using gauss newton method
|
||||
To solve the problem a minimal of 4 measurements are required.
|
||||
If Glonass is included 5 are required to solve for the additional free variable.
|
||||
returns:
|
||||
0 -> list with positions
|
||||
1 -> pseudorange errs
|
||||
'''
|
||||
if x0 is None:
|
||||
x0 = [0, 0, 0, 0, 0]
|
||||
|
||||
if len(measurements) < min_measurements:
|
||||
return [],[],[]
|
||||
|
||||
Fx_pos = pr_residual(measurements, posfix_functions, signal=signal, no_nans=True)
|
||||
meas_cov = np.diag([meas.observables_std[signal]**2 for meas in measurements])
|
||||
|
||||
x, residual, x_std = gauss_newton(Fx_pos, x0, meas_cov)
|
||||
return x.tolist(), residual.tolist(), x_std
|
||||
|
||||
|
||||
def calc_vel_fix(measurements, est_pos, velfix_function=None, v0=None, signal='D1C', min_measurements=5):
|
||||
'''
|
||||
Calculates gps velocity fix using gauss newton method
|
||||
returns:
|
||||
0 -> list with velocities
|
||||
1 -> pseudorange_rate errs
|
||||
'''
|
||||
if v0 is None:
|
||||
v0 = [0, 0, 0, 0]
|
||||
|
||||
if len(measurements) < min_measurements:
|
||||
return [], [], []
|
||||
|
||||
Fx_vel = prr_residual(measurements, est_pos, velfix_function, signal=signal, no_nans=True)
|
||||
meas_cov = np.diag([meas.observables_std[signal]**2 for meas in measurements])
|
||||
|
||||
v, residual, x_std = gauss_newton(Fx_vel, v0, meas_cov)
|
||||
return v.tolist(), residual.tolist(), x_std
|
||||
|
||||
|
||||
def get_posfix_sympy_fun(constellation):
|
||||
# Unknowns
|
||||
x, y, z = sympy.Symbol('x'), sympy.Symbol('y'), sympy.Symbol('z')
|
||||
bc = sympy.Symbol('bc')
|
||||
bg = sympy.Symbol('bg')
|
||||
zero_theta = sympy.Symbol('zero_theta')
|
||||
var = [x, y, z, bc, bg]
|
||||
|
||||
# Knowns
|
||||
pr = sympy.Symbol('pr')
|
||||
sat_x, sat_y, sat_z = sympy.Symbol('sat_x'), sympy.Symbol('sat_y'), sympy.Symbol('sat_z')
|
||||
|
||||
theta = (EARTH_ROTATION_RATE * (pr - bc) / SPEED_OF_LIGHT)*zero_theta
|
||||
val = sympy.sqrt(
|
||||
(sat_x * sympy.cos(theta) + sat_y * sympy.sin(theta) - x) ** 2 +
|
||||
(sat_y * sympy.cos(theta) - sat_x * sympy.sin(theta) - y) ** 2 +
|
||||
(sat_z - z) ** 2
|
||||
)
|
||||
|
||||
if constellation == ConstellationId.GLONASS:
|
||||
res = val - (pr - bc - bg)
|
||||
elif constellation == ConstellationId.GPS:
|
||||
res = val - (pr - bc)
|
||||
else:
|
||||
raise NotImplementedError(f"Constellation {constellation} not supported")
|
||||
|
||||
res = [res] + [sympy.diff(res, v) for v in var]
|
||||
|
||||
return sympy.lambdify([x, y, z, bc, bg, pr, zero_theta, sat_x, sat_y, sat_z], res, modules=["numpy"])
|
||||
|
||||
|
||||
def get_velfix_sympy_func():
|
||||
# implementing this without sympy.Matrix gives a 2x speedup at generation
|
||||
|
||||
# knowns, receiver position, satellite position, satellite velocity
|
||||
ep_x, ep_y, ep_z = sympy.Symbol('ep_x'), sympy.Symbol('ep_y'), sympy.Symbol('ep_z')
|
||||
est_pos = np.array([ep_x, ep_y, ep_z])
|
||||
sp_x, sp_y, sp_z = sympy.Symbol('sp_x'), sympy.Symbol('sp_y'), sympy.Symbol('sp_z')
|
||||
sat_pos = np.array([sp_x, sp_y, sp_z])
|
||||
sv_x, sv_y, sv_z = sympy.Symbol('sv_x'), sympy.Symbol('sv_y'), sympy.Symbol('sv_z')
|
||||
sat_vel = np.array([sv_x, sv_y, sv_z])
|
||||
observables = sympy.Symbol('observables')
|
||||
|
||||
# unknown, receiver velocity
|
||||
v_x, v_y, v_z = sympy.Symbol('v_x'), sympy.Symbol('v_y'), sympy.Symbol('v_z')
|
||||
vel = np.array([v_x, v_y, v_z])
|
||||
vel_o = sympy.Symbol('vel_o')
|
||||
|
||||
loss = sat_pos - est_pos
|
||||
loss /= sympy.sqrt(loss.dot(loss))
|
||||
res = loss.dot(sat_vel - vel) - (observables - vel_o)
|
||||
|
||||
res = [res] + [sympy.diff(res, v) for v in [v_x, v_y, v_z, vel_o]]
|
||||
|
||||
return sympy.lambdify([
|
||||
ep_x, ep_y, ep_z, sp_x, sp_y, sp_z,
|
||||
sv_x, sv_y, sv_z, observables,
|
||||
v_x, v_y, v_z, vel_o
|
||||
],
|
||||
res, modules=["numpy"])
|
||||
|
||||
|
||||
def pr_residual(measurements: List[GNSSMeasurement], posfix_functions=None, signal='C1C', no_nans=False):
|
||||
|
||||
if posfix_functions is None:
|
||||
posfix_functions = {constellation: get_posfix_sympy_fun(constellation) for constellation in (ConstellationId.GPS, ConstellationId.GLONASS)}
|
||||
|
||||
def Fx_pos(inp):
|
||||
vals, gradients = [], []
|
||||
|
||||
for meas in measurements:
|
||||
if signal in meas.observables_final and np.isfinite(meas.observables_final[signal]):
|
||||
pr = meas.observables_final[signal]
|
||||
sat_pos = meas.sat_pos_final
|
||||
zero_theta = 0
|
||||
elif signal in meas.observables and np.isfinite(meas.observables[signal]) and meas.processed:
|
||||
pr = meas.observables[signal]
|
||||
pr += meas.sat_clock_err * SPEED_OF_LIGHT
|
||||
sat_pos = meas.sat_pos
|
||||
zero_theta = 1
|
||||
else:
|
||||
if not no_nans:
|
||||
vals.append(np.nan)
|
||||
gradients.append(np.nan)
|
||||
continue
|
||||
|
||||
val, *gradient = posfix_functions[meas.constellation_id](*inp, pr, zero_theta, *sat_pos)
|
||||
vals.append(val)
|
||||
gradients.append(gradient)
|
||||
return np.asarray(vals), np.asarray(gradients)
|
||||
return Fx_pos
|
||||
|
||||
|
||||
def prr_residual(measurements: List[GNSSMeasurement], est_pos, velfix_function=None, signal='D1C', no_nans=False):
|
||||
|
||||
if velfix_function is None:
|
||||
velfix_function = get_velfix_sympy_func()
|
||||
|
||||
def Fx_vel(vel):
|
||||
vals, gradients = [], []
|
||||
|
||||
for meas in measurements:
|
||||
if signal not in meas.observables or not np.isfinite(meas.observables[signal]):
|
||||
if not no_nans:
|
||||
vals.append(np.nan)
|
||||
gradients.append(np.nan)
|
||||
continue
|
||||
|
||||
sat_pos = meas.sat_pos_final if meas.corrected else meas.sat_pos
|
||||
|
||||
val, *gradient = velfix_function(est_pos[0], est_pos[1], est_pos[2],
|
||||
sat_pos[0], sat_pos[1], sat_pos[2],
|
||||
meas.sat_vel[0], meas.sat_vel[1], meas.sat_vel[2],
|
||||
meas.observables[signal],
|
||||
vel[0], vel[1], vel[2], vel[3])
|
||||
vals.append(val)
|
||||
gradients.append(gradient)
|
||||
|
||||
return np.asarray(vals), np.asarray(gradients)
|
||||
return Fx_vel
|
||||
@@ -1,381 +0,0 @@
|
||||
from math import sqrt
|
||||
from typing import Dict, List, Optional, Union
|
||||
|
||||
import numpy as np
|
||||
import datetime
|
||||
import struct
|
||||
|
||||
from . import constants
|
||||
from .ephemeris import Ephemeris
|
||||
from .lib.coordinates import LocalCoord
|
||||
from .gps_time import GPSTime
|
||||
from .helpers import ConstellationId, get_constellation_and_sv_id, get_nmea_id_from_constellation_and_svid, \
|
||||
rinex3_obs_from_rinex2_obs
|
||||
|
||||
|
||||
def array_from_normal_meas(meas):
|
||||
return np.concatenate(([meas.get_nmea_id()],
|
||||
[meas.recv_time_week],
|
||||
[meas.recv_time_sec],
|
||||
[meas.glonass_freq],
|
||||
[meas.observables['C1C']],
|
||||
[meas.observables_std['C1C']],
|
||||
[meas.observables['D1C']],
|
||||
[meas.observables_std['D1C']],
|
||||
[meas.observables['S1C']],
|
||||
[meas.observables['L1C']]))
|
||||
|
||||
|
||||
def normal_meas_from_array(arr):
|
||||
observables, observables_std = {}, {}
|
||||
observables['C1C'] = arr[4]
|
||||
observables_std['C1C'] = arr[5]
|
||||
observables['D1C'] = arr[6]
|
||||
observables_std['D1C'] = arr[7]
|
||||
observables['S1C'] = arr[8]
|
||||
observables['L1C'] = arr[9]
|
||||
constellation_id, sv_id = get_constellation_and_sv_id(nmea_id=arr[0])
|
||||
return GNSSMeasurement(constellation_id, sv_id, arr[1], arr[2],
|
||||
observables, observables_std, arr[3])
|
||||
|
||||
|
||||
class GNSSMeasurement:
|
||||
PRN = 0
|
||||
RECV_TIME_WEEK = 1
|
||||
RECV_TIME_SEC = 2
|
||||
GLONASS_FREQ = 3
|
||||
|
||||
PR = 4
|
||||
PR_STD = 5
|
||||
PRR = 6
|
||||
PRR_STD = 7
|
||||
|
||||
SAT_POS = slice(8, 11)
|
||||
SAT_VEL = slice(11, 14)
|
||||
|
||||
def __init__(self, constellation_id: ConstellationId, sv_id: int, recv_time_week: int, recv_time_sec: float, observables: Dict[str, float],
|
||||
observables_std: Dict[str, float], glonass_freq: Union[int, float, None] = None):
|
||||
# Metadata
|
||||
# prn: unique satellite id
|
||||
self.prn = "%s%02d" % (constellation_id.to_rinex_char(), sv_id) # satellite ID in rinex convention
|
||||
self.constellation_id = constellation_id
|
||||
self.sv_id = sv_id # satellite id per constellation
|
||||
|
||||
self.recv_time_week = recv_time_week
|
||||
self.recv_time_sec = recv_time_sec
|
||||
self.recv_time = GPSTime(recv_time_week, recv_time_sec)
|
||||
self.glonass_freq = glonass_freq # glonass channel
|
||||
|
||||
# Measurements
|
||||
self.observables = observables
|
||||
self.observables_std = observables_std
|
||||
|
||||
# flags
|
||||
self.processed = False
|
||||
self.corrected = False
|
||||
|
||||
# sat info
|
||||
self.sat_pos = np.array([np.nan, np.nan, np.nan])
|
||||
self.sat_vel = np.array([np.nan, np.nan, np.nan])
|
||||
self.sat_clock_err = np.nan
|
||||
self.sat_ephemeris: Optional[Ephemeris] = None
|
||||
|
||||
self.sat_pos_final = np.array([np.nan, np.nan, np.nan]) # sat_pos in receiver time's ECEF frame instead of satellite time's ECEF frame
|
||||
self.observables_final: Dict[str, float] = {}
|
||||
|
||||
def process(self, dog):
|
||||
sat_time = self.recv_time - self.observables['C1C']/constants.SPEED_OF_LIGHT
|
||||
sat_info = dog.get_sat_info(self.prn, sat_time)
|
||||
if sat_info is None:
|
||||
return False
|
||||
self.sat_pos, self.sat_vel, self.sat_clock_err, _, self.sat_ephemeris = sat_info
|
||||
self.processed = True
|
||||
return True
|
||||
|
||||
def correct(self, est_pos, dog, correct_delay=True):
|
||||
for obs in self.observables:
|
||||
if obs[0] == 'C': # or obs[0] == 'L':
|
||||
if correct_delay:
|
||||
delay = dog.get_delay(self.prn, self.recv_time, est_pos, signal=obs)
|
||||
else:
|
||||
delay = 0.0
|
||||
if delay is not None:
|
||||
self.observables_final[obs] = (self.observables[obs] +
|
||||
self.sat_clock_err*constants.SPEED_OF_LIGHT -
|
||||
delay)
|
||||
else:
|
||||
self.observables_final[obs] = self.observables[obs]
|
||||
if 'C1C' in self.observables_final and 'C2P' in self.observables_final:
|
||||
self.observables_final['IOF'] = (((constants.GPS_L1**2)*self.observables_final['C1C'] -
|
||||
(constants.GPS_L2**2)*self.observables_final['C2P'])/
|
||||
(constants.GPS_L1**2 - constants.GPS_L2**2))
|
||||
|
||||
geometric_range = np.linalg.norm(self.sat_pos - est_pos)
|
||||
theta_1 = constants.EARTH_ROTATION_RATE * geometric_range / constants.SPEED_OF_LIGHT
|
||||
self.sat_pos_final = np.array([self.sat_pos[0] * np.cos(theta_1) + self.sat_pos[1] * np.sin(theta_1),
|
||||
self.sat_pos[1] * np.cos(theta_1) - self.sat_pos[0] * np.sin(theta_1),
|
||||
self.sat_pos[2]])
|
||||
if 'C1C' in self.observables_final and np.isfinite(self.observables_final['C1C']):
|
||||
self.corrected = True
|
||||
return True
|
||||
return False
|
||||
|
||||
def as_array(self, only_corrected=True):
|
||||
observables = self.observables_final
|
||||
sat_pos = self.sat_pos_final
|
||||
if not self.corrected:
|
||||
if only_corrected:
|
||||
raise NotImplementedError('Only corrected measurements can be put into arrays')
|
||||
else:
|
||||
observables = self.observables
|
||||
sat_pos = self.sat_pos
|
||||
ret = np.array([self.get_nmea_id(), self.recv_time_week, self.recv_time_sec, self.glonass_freq,
|
||||
observables['C1C'], self.observables_std['C1C'],
|
||||
observables['D1C'], self.observables_std['D1C']])
|
||||
return np.concatenate((ret, sat_pos, self.sat_vel))
|
||||
|
||||
def __repr__(self):
|
||||
time = self.recv_time.as_datetime().strftime('%Y-%m-%dT%H:%M:%S.%f')
|
||||
return f"<GNSSMeasurement from {self.prn} at {time}>"
|
||||
|
||||
def get_nmea_id(self):
|
||||
return get_nmea_id_from_constellation_and_svid(self.constellation_id, self.sv_id)
|
||||
|
||||
|
||||
def process_measurements(measurements: List[GNSSMeasurement], dog) -> List[GNSSMeasurement]:
|
||||
proc_measurements = []
|
||||
for meas in measurements:
|
||||
if meas.process(dog):
|
||||
proc_measurements.append(meas)
|
||||
return proc_measurements
|
||||
|
||||
|
||||
def correct_measurements(measurements: List[GNSSMeasurement], est_pos, dog, correct_delay=True) -> List[GNSSMeasurement]:
|
||||
corrected_measurements = []
|
||||
for meas in measurements:
|
||||
if meas.correct(est_pos, dog, correct_delay=correct_delay):
|
||||
corrected_measurements.append(meas)
|
||||
return corrected_measurements
|
||||
|
||||
|
||||
def group_measurements_by_epoch(measurements):
|
||||
meas_filt_by_t = [[measurements[0]]]
|
||||
for m in measurements[1:]:
|
||||
if abs(m.recv_time - meas_filt_by_t[-1][-1].recv_time) > 1e-9:
|
||||
meas_filt_by_t.append([])
|
||||
meas_filt_by_t[-1].append(m)
|
||||
return meas_filt_by_t
|
||||
|
||||
|
||||
def group_measurements_by_sat(measurements):
|
||||
measurements_by_sat = {}
|
||||
sats = {m.prn for m in measurements}
|
||||
for sat in sats:
|
||||
measurements_by_sat[sat] = [m for m in measurements if m.prn == sat]
|
||||
return measurements_by_sat
|
||||
|
||||
def gps_time_from_qcom_report(gnss_msg):
|
||||
if gnss_msg.which() == 'measurementReport':
|
||||
report = gnss_msg.measurementReport
|
||||
constellation = ConstellationId.from_qcom_source(report.source)
|
||||
if constellation in [ConstellationId.GPS, ConstellationId.SBAS]:
|
||||
report_time = GPSTime(report.gpsWeek, report.milliseconds / 1000.0)
|
||||
elif constellation == ConstellationId.GLONASS:
|
||||
report_time = GPSTime.from_glonass(report.glonassCycleNumber,
|
||||
report.glonassNumberOfDays,
|
||||
report.milliseconds / 1000.0)
|
||||
else:
|
||||
raise NotImplementedError(f'Unknownconstellation {report.source}')
|
||||
else:
|
||||
report = gnss_msg.drMeasurementReport
|
||||
constellation = ConstellationId.from_qcom_source(report.source)
|
||||
if ConstellationId.from_qcom_source(report.source) in [ConstellationId.GPS, ConstellationId.SBAS]:
|
||||
report_time = GPSTime(report.gpsWeek, report.gpsMilliseconds / 1000.0)
|
||||
elif constellation == ConstellationId.GLONASS:
|
||||
report_time = GPSTime.from_glonass(report.glonassYear,
|
||||
report.glonassDay,
|
||||
report.glonassMilliseconds / 1000.0)
|
||||
else:
|
||||
raise NotImplementedError(f'Unknownconstellation {report.source}')
|
||||
return report_time
|
||||
|
||||
def get_measurements_from_qcom_reports(reports):
|
||||
new_meas_dr = []
|
||||
new_meas = []
|
||||
for gnss_msg in reports:
|
||||
if gnss_msg.which() == 'drMeasurementReport':
|
||||
new_meas_dr.extend(read_raw_qcom(gnss_msg.drMeasurementReport))
|
||||
else:
|
||||
new_meas.extend(read_raw_qcom(gnss_msg.measurementReport))
|
||||
sat_dict_dr = {meas.prn: meas for meas in new_meas_dr}
|
||||
out_meas = []
|
||||
for meas in new_meas:
|
||||
if meas.prn in sat_dict_dr:
|
||||
# Sometimes DR measurements are complete garbage, in those cases non-DR measurements are still sane, so cross-check
|
||||
if abs(meas.observables['C1C'] - sat_dict_dr[meas.prn].observables['C1C']) < 1000:
|
||||
meas.observables['C1C'] = sat_dict_dr[meas.prn].observables['C1C']
|
||||
meas.observables_std['C1C'] = sat_dict_dr[meas.prn].observables_std['C1C']
|
||||
out_meas.append(meas)
|
||||
return out_meas
|
||||
|
||||
def read_raw_qcom(report):
|
||||
dr = 'DrMeasurementReport' in str(report.schema)
|
||||
# Only gps/sbas and glonass are supported
|
||||
constellation_id = ConstellationId.from_qcom_source(report.source)
|
||||
if constellation_id in [ConstellationId.GPS, ConstellationId.SBAS]: # gps/sbas
|
||||
if dr:
|
||||
recv_tow = report.gpsMilliseconds / 1000.0 # seconds
|
||||
time_bias_ms = struct.unpack("f", struct.pack("I", report.gpsTimeBiasMs))[0]
|
||||
else:
|
||||
recv_tow = report.milliseconds / 1000.0 # seconds
|
||||
time_bias_ms = report.timeBias
|
||||
recv_time = GPSTime(report.gpsWeek, recv_tow)
|
||||
elif constellation_id == ConstellationId.GLONASS:
|
||||
if dr:
|
||||
recv_tow = report.glonassMilliseconds / 1000.0 # seconds
|
||||
recv_time = GPSTime.from_glonass(report.glonassYear, report.glonassDay, recv_tow)
|
||||
time_bias_ms = report.glonassTimeBias
|
||||
else:
|
||||
recv_tow = report.milliseconds / 1000.0 # seconds
|
||||
recv_time = GPSTime.from_glonass(report.glonassCycleNumber, report.glonassNumberOfDays, recv_tow)
|
||||
time_bias_ms = report.timeBias
|
||||
else:
|
||||
raise NotImplementedError('Only GPS (0), SBAS (1) and GLONASS (6) are supported from qcom, not:', {report.source})
|
||||
# logging.debug(recv_time, report.source, time_bias_ms, dr)
|
||||
measurements = []
|
||||
for i in report.sv:
|
||||
# todo change svId to nmea_id in cereal message. Or better: change the publisher to publish correct svId's, since constellation id is also given
|
||||
nmea_id = i.svId
|
||||
if nmea_id == 255:
|
||||
# TODO nmea_id is not valid. Fix publisher
|
||||
continue
|
||||
_, sv_id = get_constellation_and_sv_id(nmea_id)
|
||||
if not i.measurementStatus.measurementNotUsable and i.measurementStatus.satelliteTimeIsKnown and i.measurementStatus.freshMeasurementIndicator:
|
||||
observables, observables_std = {}, {}
|
||||
if dr:
|
||||
sat_tow = (i.filteredMeasurementIntegral + i.filteredMeasurementFraction + i.latency + time_bias_ms) / 1000
|
||||
else:
|
||||
sat_tow = (i.unfilteredMeasurementIntegral + i.unfilteredMeasurementFraction + i.latency + time_bias_ms) / 1000
|
||||
observables['C1C'] = (recv_tow - sat_tow)*constants.SPEED_OF_LIGHT
|
||||
observables_std['C1C'] = i.unfilteredTimeUncertainty * 1e-3 * constants.SPEED_OF_LIGHT # always use unfiltered std, filtered std is bigger?
|
||||
if i.measurementStatus.fineOrCoarseVelocity:
|
||||
# about 10x better, perhaps filtered with carrier phase?
|
||||
observables['D1C'] = i.fineSpeed
|
||||
observables_std['D1C'] = sqrt(i.fineSpeedUncertainty) # sqrt empirically makes performance much better, might be wrong
|
||||
else:
|
||||
observables['D1C'] = i.unfilteredSpeed
|
||||
observables_std['D1C'] = i.unfilteredSpeedUncertainty
|
||||
observables['S1C'] = (i.carrierNoise/100.) if i.carrierNoise != 0 else np.nan
|
||||
observables['L1C'] = np.nan
|
||||
# logging.debug(" %.5f %3d %10.2f %7.2f %7.2f %.2f %d" % (recv_time.tow, nmea_id,
|
||||
# observables['C1C'], observables_std['C1C'],
|
||||
# observables_std['D1C'], observables['S1C'], i.latency), i.observationState, i.measurementStatus.fineOrCoarseVelocity)
|
||||
glonass_freq = (i.glonassFrequencyIndex - 7) if constellation_id == ConstellationId.GLONASS else np.nan
|
||||
measurements.append(GNSSMeasurement(constellation_id, sv_id,
|
||||
recv_time.week,
|
||||
recv_time.tow,
|
||||
observables,
|
||||
observables_std,
|
||||
glonass_freq))
|
||||
return measurements
|
||||
|
||||
|
||||
def read_raw_ublox(report) -> List[GNSSMeasurement]:
|
||||
recv_tow = report.rcvTow # seconds
|
||||
recv_week = report.gpsWeek
|
||||
measurements = []
|
||||
for i in report.measurements:
|
||||
# only add Gps and Glonass fixes
|
||||
if i.gnssId in [ConstellationId.GPS, ConstellationId.GLONASS]:
|
||||
if i.svId > 32 or i.pseudorange > 2**32:
|
||||
continue
|
||||
observables = {}
|
||||
observables_std = {}
|
||||
if i.trackingStatus.pseudorangeValid and i.sigId == 0:
|
||||
observables['C1C'] = i.pseudorange
|
||||
# Empirically it seems obvious ublox's std is
|
||||
# actually a variation
|
||||
observables_std['C1C'] = sqrt(i.pseudorangeStdev)*10
|
||||
if i.gnssId == ConstellationId.GLONASS:
|
||||
glonass_freq = i.glonassFrequencyIndex - 7
|
||||
observables['D1C'] = -(constants.SPEED_OF_LIGHT / (constants.GLONASS_L1 + glonass_freq * constants.GLONASS_L1_DELTA)) * i.doppler
|
||||
else: # GPS
|
||||
glonass_freq = np.nan
|
||||
observables['D1C'] = -(constants.SPEED_OF_LIGHT / constants.GPS_L1) * i.doppler
|
||||
observables_std['D1C'] = (constants.SPEED_OF_LIGHT / constants.GPS_L1) * i.dopplerStdev
|
||||
observables['S1C'] = i.cno
|
||||
if i.trackingStatus.carrierPhaseValid:
|
||||
observables['L1C'] = i.carrierCycles
|
||||
else:
|
||||
observables['L1C'] = np.nan
|
||||
|
||||
measurements.append(GNSSMeasurement(ConstellationId(i.gnssId), i.svId, recv_week, recv_tow,
|
||||
observables, observables_std, glonass_freq))
|
||||
return measurements
|
||||
|
||||
|
||||
def read_rinex_obs(obsdata) -> List[List[GNSSMeasurement]]:
|
||||
measurements: List[List[GNSSMeasurement]] = []
|
||||
obsdata_keys = list(obsdata.data.keys())
|
||||
first_sat = obsdata_keys[0]
|
||||
n = len(obsdata.data[first_sat]['Epochs'])
|
||||
for i in range(n):
|
||||
recv_time_datetime = obsdata.data[first_sat]['Epochs'][i]
|
||||
recv_time_datetime = recv_time_datetime.astype(datetime.datetime)
|
||||
recv_time = GPSTime.from_datetime(recv_time_datetime)
|
||||
measurements.append([])
|
||||
for sat_str in obsdata_keys:
|
||||
if np.isnan(obsdata.data[sat_str]['C1'][i]):
|
||||
continue
|
||||
observables, observables_std = {}, {}
|
||||
for obs in obsdata.data[sat_str]:
|
||||
if obs == 'Epochs':
|
||||
continue
|
||||
rinex3_obs_key = rinex3_obs_from_rinex2_obs(obs)
|
||||
observables[rinex3_obs_key] = obsdata.data[sat_str][obs][i]
|
||||
observables_std[rinex3_obs_key] = 1.
|
||||
|
||||
constellation_id, sv_id = get_constellation_and_sv_id(int(sat_str))
|
||||
measurements[-1].append(GNSSMeasurement(constellation_id, sv_id,
|
||||
recv_time.week, recv_time.tow,
|
||||
observables, observables_std))
|
||||
return measurements
|
||||
|
||||
|
||||
def get_Q(recv_pos, sat_positions):
|
||||
local = LocalCoord.from_ecef(recv_pos)
|
||||
sat_positions_rel = local.ecef2ned(sat_positions)
|
||||
sat_distances = np.linalg.norm(sat_positions_rel, axis=1)
|
||||
A = np.column_stack((sat_positions_rel[:,0]/sat_distances, # pylint: disable=unsubscriptable-object
|
||||
sat_positions_rel[:,1]/sat_distances, # pylint: disable=unsubscriptable-object
|
||||
sat_positions_rel[:,2]/sat_distances, # pylint: disable=unsubscriptable-object
|
||||
-np.ones(len(sat_distances))))
|
||||
if A.shape[0] < 4 or np.linalg.matrix_rank(A) < 4:
|
||||
return np.inf*np.ones((4,4))
|
||||
Q = np.linalg.inv(A.T.dot(A))
|
||||
return Q
|
||||
|
||||
|
||||
def get_DOP(recv_pos, sat_positions):
|
||||
Q = get_Q(recv_pos, sat_positions)
|
||||
return np.sqrt(np.trace(Q))
|
||||
|
||||
|
||||
def get_HDOP(recv_pos, sat_positions):
|
||||
Q = get_Q(recv_pos, sat_positions)
|
||||
return np.sqrt(np.trace(Q[:2,:2]))
|
||||
|
||||
|
||||
def get_VDOP(recv_pos, sat_positions):
|
||||
Q = get_Q(recv_pos, sat_positions)
|
||||
return np.sqrt(Q[2,2])
|
||||
|
||||
|
||||
def get_TDOP(recv_pos, sat_positions):
|
||||
Q = get_Q(recv_pos, sat_positions)
|
||||
return np.sqrt(Q[3,3])
|
||||
|
||||
|
||||
def get_PDOP(recv_pos, sat_positions):
|
||||
Q = get_Q(recv_pos, sat_positions)
|
||||
return np.sqrt(np.trace(Q[:3,:3]))
|
||||
@@ -1,251 +0,0 @@
|
||||
|
||||
# Copyright (C) 2014 Swift Navigation Inc.
|
||||
#
|
||||
# This source is subject to the license found in the file 'LICENSE' which must
|
||||
# be be distributed together with this source. All other rights reserved.
|
||||
#
|
||||
# THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
||||
# EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
import datetime
|
||||
import numpy as np
|
||||
import logging
|
||||
|
||||
def floatornan(x):
|
||||
if x == '' or x[-1] == ' ':
|
||||
return np.NaN
|
||||
return float(x)
|
||||
|
||||
|
||||
def digitorzero(x):
|
||||
if x == ' ' or x == '':
|
||||
return 0
|
||||
return int(x)
|
||||
|
||||
|
||||
def padline(l, n=16):
|
||||
x = len(l)
|
||||
x_ = n * ((x + n - 1) // n)
|
||||
padded = l + ' ' * (x_ - x)
|
||||
while len(padded) < 70:
|
||||
padded += ' ' * 16
|
||||
return padded
|
||||
|
||||
|
||||
TOTAL_SATS = 132 # Increased to support Galileo
|
||||
|
||||
|
||||
class DownloadError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class RINEXFile:
|
||||
def __init__(self, filename, rate=None):
|
||||
self.rate = rate
|
||||
try:
|
||||
with open(filename) as f:
|
||||
self._read_header(f)
|
||||
self._read_data(f)
|
||||
except TypeError:
|
||||
logging.exception("TypeError, file likely not downloaded.")
|
||||
raise DownloadError("file download failure")
|
||||
except FileNotFoundError:
|
||||
logging.exception("File not found in directory.")
|
||||
raise DownloadError("file missing in download cache")
|
||||
def _read_header(self, f):
|
||||
version_line = padline(f.readline(), 80)
|
||||
|
||||
self.version = float(version_line[0:9])
|
||||
if (self.version > 2.11):
|
||||
raise ValueError(
|
||||
f"RINEX file versions > 2.11 not supported (file version {self.version:f})")
|
||||
|
||||
self.filetype = version_line[20]
|
||||
if self.filetype not in "ONGM": # Check valid file type
|
||||
raise ValueError(f"RINEX file type '{self.filetype}' not supported")
|
||||
if self.filetype != 'O':
|
||||
raise ValueError("Only 'OBSERVATION DATA' RINEX files are currently supported")
|
||||
|
||||
self.gnss = version_line[40]
|
||||
if self.gnss not in " GRSEM": # Check valid satellite system
|
||||
raise ValueError(f"Satellite system '{self.filetype}' not supported")
|
||||
if self.gnss == ' ':
|
||||
self.gnss = 'G'
|
||||
if self.gnss != 'G':
|
||||
#raise ValueError("Only GPS data currently supported")
|
||||
pass
|
||||
|
||||
self.comment = ""
|
||||
while True: # Read the rest of the header
|
||||
line = padline(f.readline(), 80)
|
||||
label = line[60:80].rstrip()
|
||||
if label == "END OF HEADER":
|
||||
break
|
||||
if label == "COMMENT":
|
||||
self.comment += line[:60] + '\n'
|
||||
if label == "MARKER NAME":
|
||||
self.marker_name = line[:60].rstrip()
|
||||
if self.marker_name == '':
|
||||
self.marker_name = 'UNKNOWN'
|
||||
if label == "# / TYPES OF OBSERV":
|
||||
# RINEX files can have multiple line headers
|
||||
# This code handles the case
|
||||
try:
|
||||
n_obs = int(line[0:6])
|
||||
self.obs_types = []
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
if n_obs <= 9:
|
||||
for i in range(0, n_obs):
|
||||
self.obs_types.append(line[10 + 6 * i:12 + 6 * i])
|
||||
if n_obs > 9:
|
||||
for i in range(0, 9):
|
||||
self.obs_types.append(line[10 + 6 * i:12 + 6 * i])
|
||||
n_obs -= 9
|
||||
|
||||
def _read_next_non_comment(self, f):
|
||||
line = f.readline()
|
||||
while line and line.find('COMMENT') != -1:
|
||||
line = f.readline()
|
||||
return line
|
||||
|
||||
def _read_epoch_header(self, f):
|
||||
epoch_hdr = self._read_next_non_comment(f)
|
||||
if epoch_hdr == '':
|
||||
return None
|
||||
# ignore any line with these three strings
|
||||
skippable = ('0.0000000 4 5', 'MARKER NUMBER', ' 4 1')
|
||||
while any(skip in epoch_hdr for skip in skippable):
|
||||
epoch_hdr = self._read_next_non_comment(f)
|
||||
|
||||
if epoch_hdr == '':
|
||||
return None
|
||||
|
||||
year = int(epoch_hdr[1:3])
|
||||
if year >= 80:
|
||||
year += 1900
|
||||
else:
|
||||
year += 2000
|
||||
month = int(epoch_hdr[4:6])
|
||||
day = int(epoch_hdr[7:9])
|
||||
hour = int(epoch_hdr[10:12])
|
||||
minute = int(epoch_hdr[13:15])
|
||||
second = int(epoch_hdr[15:18])
|
||||
microsecond = int(
|
||||
epoch_hdr[19:25]) # Discard the least sig. fig. (use microseconds only).
|
||||
epoch = datetime.datetime(year, month, day, hour, minute, second, microsecond)
|
||||
|
||||
flag = int(epoch_hdr[28])
|
||||
allowed_flags = {0, 3, 4}
|
||||
if flag not in allowed_flags:
|
||||
raise ValueError("Don't know how to handle epoch flag %d in epoch header:\n%s" %
|
||||
(flag, epoch_hdr))
|
||||
|
||||
n_sats = int(epoch_hdr[29:32])
|
||||
if flag > 1: # event flag: nsats is number of records
|
||||
for i in range(n_sats):
|
||||
f.readline()
|
||||
return None
|
||||
|
||||
sats = []
|
||||
for i in range(0, n_sats):
|
||||
if ((i % 12) == 0) and (i > 0):
|
||||
epoch_hdr = f.readline()
|
||||
sats.append(epoch_hdr[(32 + (i % 12) * 3):(35 + (i % 12) * 3)])
|
||||
|
||||
return epoch, flag, sats
|
||||
|
||||
def _read_obs(self, f, n_sat, sat_map):
|
||||
obs = np.empty((TOTAL_SATS, len(self.obs_types)), dtype=np.float64) * np.NaN
|
||||
lli = np.zeros((TOTAL_SATS, len(self.obs_types)), dtype=np.uint8)
|
||||
signal_strength = np.zeros((TOTAL_SATS, len(self.obs_types)), dtype=np.uint8)
|
||||
|
||||
for i in range(n_sat):
|
||||
# Join together observations for a single satellite if split across lines.
|
||||
obs_line = ''.join(
|
||||
padline(f.readline()[:-1], 16) for _ in range((len(self.obs_types) + 4) // 5))
|
||||
for j in range(len(self.obs_types)):
|
||||
obs_record = obs_line[16 * j:16 * (j + 1)]
|
||||
obs[int(sat_map[i]), j] = floatornan(obs_record[0:14])
|
||||
lli[int(sat_map[i]), j] = digitorzero(obs_record[14:15])
|
||||
signal_strength[int(sat_map[i]), j] = digitorzero(obs_record[15:16])
|
||||
|
||||
return obs, lli, signal_strength
|
||||
|
||||
def _skip_obs(self, f, n_sat):
|
||||
for i in range(n_sat):
|
||||
for _ in range((len(self.obs_types) + 4) // 5):
|
||||
f.readline()
|
||||
|
||||
def _read_data_chunk(self, f, CHUNK_SIZE=10000):
|
||||
obss = np.empty(
|
||||
(CHUNK_SIZE, TOTAL_SATS, len(self.obs_types)), dtype=np.float64) * np.NaN
|
||||
llis = np.zeros((CHUNK_SIZE, TOTAL_SATS, len(self.obs_types)), dtype=np.uint8)
|
||||
signal_strengths = np.zeros(
|
||||
(CHUNK_SIZE, TOTAL_SATS, len(self.obs_types)), dtype=np.uint8)
|
||||
epochs = np.zeros(CHUNK_SIZE, dtype='datetime64[us]')
|
||||
flags = np.zeros(CHUNK_SIZE, dtype=np.uint8)
|
||||
|
||||
i = 0
|
||||
while True:
|
||||
hdr = self._read_epoch_header(f)
|
||||
if hdr is None:
|
||||
break
|
||||
# data faster than desired rate: ignore it
|
||||
if self.rate and (hdr[0].microsecond or hdr[0].second % self.rate != 0):
|
||||
self._skip_obs(f, len(hdr[2]))
|
||||
continue
|
||||
epoch, flags[i], sats = hdr
|
||||
epochs[i] = np.datetime64(epoch)
|
||||
sat_map = np.ones(len(sats)) * -1
|
||||
for n, sat in enumerate(sats):
|
||||
if sat[0] == 'G':
|
||||
sat_map[n] = int(sat[1:]) - 1
|
||||
if sat[0] == 'R':
|
||||
sat_map[n] = int(sat[1:]) - 1 + 64
|
||||
obss[i], llis[i], signal_strengths[i] = self._read_obs(f, len(sats), sat_map)
|
||||
i += 1
|
||||
if i >= CHUNK_SIZE:
|
||||
break
|
||||
|
||||
return obss[:i], llis[:i], signal_strengths[:i], epochs[:i], flags[:i]
|
||||
|
||||
def _read_data(self, f):
|
||||
self.data = {}
|
||||
while True:
|
||||
obss, llis, signal_strengths, epochs, flags = self._read_data_chunk(f)
|
||||
if obss.shape[0] == 0:
|
||||
break
|
||||
|
||||
for i, sv in enumerate(['%02d' % d for d in range(1, TOTAL_SATS+1)]):
|
||||
if sv not in self.data:
|
||||
self.data[sv] = {}
|
||||
for j, obs_type in enumerate(self.obs_types):
|
||||
if obs_type in self.data[sv]:
|
||||
self.data[sv][obs_type] = np.append(self.data[sv][obs_type], obss[:, i, j])
|
||||
else:
|
||||
self.data[sv][obs_type] = obss[:, i, j]
|
||||
if 'Epochs' in self.data[sv]:
|
||||
self.data[sv]['Epochs'] = np.append(self.data[sv]['Epochs'], epochs)
|
||||
else:
|
||||
self.data[sv]['Epochs'] = epochs
|
||||
for sat in list(self.data.keys()):
|
||||
if np.all(np.isnan(self.data[sat]['C1'])):
|
||||
del self.data[sat]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
from numpy import cos, exp, pi
|
||||
from .lib.coordinates import ecef2geodetic
|
||||
|
||||
|
||||
def saast(pos, el, humi=0.75, temp0=15.0):
|
||||
"""
|
||||
Function from RTKlib: https://github.com/tomojitakasu/RTKLIB/blob/master/src/rtkcmn.c#L3362-3362
|
||||
with no changes
|
||||
:param time: time
|
||||
:param pos: receiver position {ecef} m)
|
||||
:param el: azimuth/elevation angle {az,el} (rad) -- we do not use az
|
||||
:param humi: relative humidity
|
||||
:param temp0: temperature (Celsius)
|
||||
:return: tropospheric delay (m)
|
||||
"""
|
||||
pos_rad = ecef2geodetic(pos, radians=True)
|
||||
if pos_rad[2] < -1E3 or 1E4 < pos_rad[2] or el <= 0:
|
||||
return 0.0
|
||||
|
||||
# /* standard atmosphere */
|
||||
hgt = 0.0 if pos_rad[2] < 0.0 else pos_rad[2]
|
||||
|
||||
pres = 1013.25 * pow(1.0 - 2.2557E-5 * hgt, 5.2568)
|
||||
temp = temp0 - 6.5E-3 * hgt + 273.16
|
||||
e = 6.108 * humi * exp((17.15 * temp - 4684.0) / (temp - 38.45))
|
||||
|
||||
# /* saastamoninen model */
|
||||
z = pi / 2.0 - el
|
||||
trph = 0.0022768 * pres / (
|
||||
1.0 - 0.00266 * cos(2.0 * pos_rad[0]) - 0.00028 * hgt / 1E3) / cos(z)
|
||||
trpw = 0.002277 * (1255.0 / temp + 0.05) * e / cos(z)
|
||||
return trph + trpw
|
||||
+13
-10
@@ -9,17 +9,17 @@ source "$BASEDIR/launch_env.sh"
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
|
||||
|
||||
function agnos_init {
|
||||
# wait longer for weston to come up
|
||||
if [ -f "$BASEDIR/prebuilt" ]; then
|
||||
sleep 3
|
||||
fi
|
||||
|
||||
# TODO: move this to agnos
|
||||
sudo rm -f /data/etc/NetworkManager/system-connections/*.nmmeta
|
||||
|
||||
# set success flag for current boot slot
|
||||
sudo abctl --set_success
|
||||
|
||||
# TODO: do this without udev in AGNOS
|
||||
# udev does this, but sometimes we startup faster
|
||||
sudo chgrp gpu /dev/adsprpc-smd /dev/ion /dev/kgsl-3d0
|
||||
sudo chmod 660 /dev/adsprpc-smd /dev/ion /dev/kgsl-3d0
|
||||
|
||||
# Check if AGNOS update is required
|
||||
if [ $(< /VERSION) != "$AGNOS_VERSION" ]; then
|
||||
AGNOS_PY="$DIR/system/hardware/tici/agnos.py"
|
||||
@@ -35,9 +35,6 @@ function launch {
|
||||
# Remove orphaned git lock if it exists on boot
|
||||
[ -f "$DIR/.git/index.lock" ] && rm -f $DIR/.git/index.lock
|
||||
|
||||
# Pull time from panda
|
||||
$DIR/selfdrive/boardd/set_time.py
|
||||
|
||||
# Check to see if there's a valid overlay-based update available. Conditions
|
||||
# are as follows:
|
||||
#
|
||||
@@ -77,14 +74,20 @@ function launch {
|
||||
export PYTHONPATH="$PWD"
|
||||
|
||||
# hardware specific init
|
||||
agnos_init
|
||||
if [ -f /AGNOS ]; then
|
||||
agnos_init
|
||||
fi
|
||||
|
||||
# write tmux scrollback to a file
|
||||
tmux capture-pane -pq -S-1000 > /tmp/launch_log
|
||||
|
||||
# start manager
|
||||
cd selfdrive/manager
|
||||
./build.py && ./mapd_installer.py && ./manager.py
|
||||
if [ ! -f $DIR/prebuilt ]; then
|
||||
./build.py
|
||||
fi
|
||||
./mapd_installer.py && ./manager.py
|
||||
|
||||
# if broken, keep on screen error
|
||||
while true; do sleep 1; done
|
||||
}
|
||||
|
||||
+1
-5
@@ -7,11 +7,7 @@ export OPENBLAS_NUM_THREADS=1
|
||||
export VECLIB_MAXIMUM_THREADS=1
|
||||
|
||||
if [ -z "$AGNOS_VERSION" ]; then
|
||||
export AGNOS_VERSION="8.2"
|
||||
fi
|
||||
|
||||
if [ -z "$PASSIVE" ]; then
|
||||
export PASSIVE="1"
|
||||
export AGNOS_VERSION="9.6"
|
||||
fi
|
||||
|
||||
export STAGING_ROOT="/data/safe_staging"
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
export PASSIVE="0"
|
||||
exec ./launch_chffrplus.sh
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ public:
|
||||
bool ignore_checksum = false;
|
||||
bool ignore_counter = false;
|
||||
|
||||
bool parse(uint64_t sec, const std::vector<uint8_t> &dat);
|
||||
bool parse(uint64_t nanos, const std::vector<uint8_t> &dat);
|
||||
bool update_counter_generic(int64_t v, int cnt_size);
|
||||
};
|
||||
|
||||
@@ -69,9 +69,9 @@ private:
|
||||
public:
|
||||
bool can_valid = false;
|
||||
bool bus_timeout = false;
|
||||
uint64_t first_sec = 0;
|
||||
uint64_t last_sec = 0;
|
||||
uint64_t last_nonempty_sec = 0;
|
||||
uint64_t first_nanos = 0;
|
||||
uint64_t last_nanos = 0;
|
||||
uint64_t last_nonempty_nanos = 0;
|
||||
uint64_t bus_timeout_threshold = 0;
|
||||
uint64_t can_invalid_cnt = CAN_INVALID_CNT;
|
||||
|
||||
@@ -81,10 +81,10 @@ public:
|
||||
#ifndef DYNAMIC_CAPNP
|
||||
void update_string(const std::string &data, bool sendcan);
|
||||
void update_strings(const std::vector<std::string> &data, std::vector<SignalValue> &vals, bool sendcan);
|
||||
void UpdateCans(uint64_t sec, const capnp::List<cereal::CanData>::Reader& cans);
|
||||
void UpdateCans(uint64_t nanos, const capnp::List<cereal::CanData>::Reader& cans);
|
||||
#endif
|
||||
void UpdateCans(uint64_t sec, const capnp::DynamicStruct::Reader& cans);
|
||||
void UpdateValid(uint64_t sec);
|
||||
void UpdateCans(uint64_t nanos, const capnp::DynamicStruct::Reader& cans);
|
||||
void UpdateValid(uint64_t nanos);
|
||||
void query_latest(std::vector<SignalValue> &vals, uint64_t last_ts = 0);
|
||||
};
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ cdef extern from "common_dbc.h":
|
||||
|
||||
|
||||
cdef extern from "common.h":
|
||||
cdef const DBC* dbc_lookup(const string)
|
||||
cdef const DBC* dbc_lookup(const string) except +
|
||||
|
||||
cdef cppclass CANParser:
|
||||
bool can_valid
|
||||
|
||||
Binary file not shown.
+1075
-318
File diff suppressed because it is too large
Load Diff
@@ -26,6 +26,10 @@ cdef class CANPacker:
|
||||
msg = self.dbc[0].msgs[i]
|
||||
self.name_to_address[string(msg.name)] = msg.address
|
||||
|
||||
def __dealloc__(self):
|
||||
if self.packer:
|
||||
del self.packer
|
||||
|
||||
cdef vector[uint8_t] pack(self, addr, values):
|
||||
cdef vector[SignalPackValue] values_thing
|
||||
values_thing.reserve(len(values))
|
||||
|
||||
Binary file not shown.
+1689
-801
File diff suppressed because it is too large
Load Diff
@@ -66,6 +66,10 @@ cdef class CANParser:
|
||||
self.can = new cpp_CANParser(bus, dbc_name, message_v)
|
||||
self.update_strings([])
|
||||
|
||||
def __dealloc__(self):
|
||||
if self.can:
|
||||
del self.can
|
||||
|
||||
def update_strings(self, strings, sendcan=False):
|
||||
for v in self.vl_all.values():
|
||||
for l in v.values(): # no-cython-lint
|
||||
|
||||
Binary file not shown.
@@ -22,18 +22,47 @@ BO_ 280 ECM_TRQ: 8 XXX
|
||||
|
||||
BO_ 284 ESP_8: 8 XXX
|
||||
SG_ BRK_PRESSURE : 3|12@0+ (1,0) [0|1] "" XXX
|
||||
SG_ Vehicle_Stopped : 7|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ BRAKE_PEDAL : 19|12@0+ (1,0) [0|1] "" XXX
|
||||
SG_ Vehicle_Speed : 39|16@0+ (0.0078125,0) [0|511.984375] "km/h" XXX
|
||||
SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 288 ECM_2: 7 XXX
|
||||
SG_ ACC_TORQUE_REQ_ENABLE : 5|1@1+ (1,0) [0|0] "" XXX
|
||||
SG_ ESC_TORQUE_REQ_ENABLE : 6|1@1+ (1,0) [0|0] "" XXX
|
||||
SG_ TCM_TORQUE_REQ_ENABLE : 7|1@1+ (1,0) [0|0] "" XXX
|
||||
SG_ Accelerator_Position : 16|8@1+ (0.4,0) [0|100] "%" XXX
|
||||
SG_ CRUISE_OVERRIDE : 31|1@1+ (1,0) [0|0] "" XXX
|
||||
SG_ COUNTER : 47|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ CHECKSUM : 55|8@0+ (1,0) [0|0] "" XXX
|
||||
|
||||
BO_ 320 ESP_1: 8 XXX
|
||||
SG_ Brake_State : 0|2@1+ (1,0) [0|0] "" XXX
|
||||
SG_ Brake_Pedal_State : 2|2@1+ (1,0) [0|0] "" XXX
|
||||
SG_ ACC_Engaged : 15|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ ACC_Enabled : 23|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ Vehicle_Speed : 33|10@0+ (0.5,0) [0|511] "km/h" XXX
|
||||
SG_ ACC_OFF_REQ : 39|2@0+ (1,0) [0|0] "" XXX
|
||||
SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ BRAKE_PRESSED_ACC : 6|1@0+ (1,0) [0|3] "" XXX
|
||||
|
||||
BO_ 268 ESP_2: 8 ESC
|
||||
SG_ ESC_TORQUE_REQ : 4|13@0+ (0.25,-500) [-500|1547.5] "Nm" XXX
|
||||
SG_ ACC_TORQUE_REQ_ENABLE : 5|1@1+ (1,0) [0|0] "" XXX
|
||||
SG_ ESC_TORQUE_REQ_MAX : 6|1@1+ (1,0) [0|0] "" XXX
|
||||
SG_ ESC_TORQUE_REQ_MIN : 7|1@1+ (1,0) [0|0] "" XXX
|
||||
SG_ ACC_TORQUE_REQ : 20|13@0+ (0.25,-500) [-500|1547.5] "Nm" XXX
|
||||
SG_ TCS_ACTIVE : 21|1@1+ (1,0) [0|0] "" XXX
|
||||
SG_ ACC_TORQUE_REQ_MAX : 22|1@1+ (1,0) [0|0] "" XXX
|
||||
SG_ ACC_BRK_PREP : 40|1@1+ (1,0) [0|0] "" XXX
|
||||
SG_ DISABLE_FUEL_SHUTOFF : 47|1@1+ (1,0) [0|0] "" XXX
|
||||
SG_ DAS_REQ_ACTIVE : 48|3@1+ (1,0) [0|0] "" XXX
|
||||
SG_ COLLISION_BRK_PREP : 51|1@1+ (1,0) [0|0] "" XXX
|
||||
SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ CHECKSUM : 63|8@0+ (1,0) [0|0] "" XXX
|
||||
|
||||
BO_ 344 ESP_6: 8 XXX
|
||||
SG_ WHEEL_SPEED_FL : 5|14@0+ (0.5,0) [0|8191] "rpm" XXX
|
||||
SG_ WHEEL_SPEED_FR : 21|14@0+ (0.5,0) [0|8191] "rpm" XXX
|
||||
@@ -59,11 +88,9 @@ BO_ 500 DAS_3: 8 XXX
|
||||
SG_ DISABLE_FUEL_SHUTOFF : 23|1@1+ (1,0) [0|0] "" XXX
|
||||
SG_ GR_MAX_REQ : 32|4@1+ (1,0) [0|0] "" XXX
|
||||
SG_ ACC_DECEL_REQ : 36|3@1+ (1,0) [0|0] "" XXX
|
||||
SG_ STS : 46|2@1+ (1,0) [0|0] "" XXX
|
||||
SG_ ACC_FAULTED : 47|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ ACC_FAULTED : 46|2@1+ (1,0) [0|0] "" XXX
|
||||
SG_ COLLISION_BRK_PREP : 48|1@1+ (1,0) [0|0] "" XXX
|
||||
SG_ ACC_BRK_PREP : 49|1@1+ (1,0) [0|0] "" XXX
|
||||
SG_ BRAKE_BOOL_1 : 36|1@0+ (1,0) [0|3] "" XXX
|
||||
SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
@@ -74,6 +101,11 @@ BO_ 501 DAS_4: 8 XXX
|
||||
SG_ ACC_DISTANCE_CONFIG_2 : 41|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ SPEED_DIGITAL : 63|8@0+ (1,0) [0|255] "mph" XXX
|
||||
SG_ ACC_STATE : 38|3@0+ (1,0) [0|7] "" XXX
|
||||
SG_ FCW_OFF : 25|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ FCW_ERROR : 27|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ FCW_BRAKE_ENABLED : 29|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ FCW_BRAKE_DISABLED : 47|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ ACC_FAULTED : 50|1@0+ (1,0) [0|1] "" XXX
|
||||
|
||||
BO_ 544 EPS_2: 8 XXX
|
||||
SG_ LKAS_STATE : 23|4@0+ (1,0) [0|15] "" XXX
|
||||
@@ -103,12 +135,28 @@ BO_ 571 CRUISE_BUTTONS: 3 XXX
|
||||
SG_ COUNTER : 15|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ CHECKSUM : 23|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 625 DAS_5: 8 XXX
|
||||
SG_ FCW_STATE : 2|1@1+ (1,0) [0|0] "" XXX
|
||||
SG_ FCW_DISTANCE : 3|2@1+ (1,0) [0|0] "" XXX
|
||||
SG_ ACCFCW_MESSAGE : 12|4@1+ (1,0) [0|0] "" XXX
|
||||
SG_ SET_SPEED_KPH : 24|8@1+ (1,0) [0|250] "km/h" XXX
|
||||
SG_ WHEEL_TORQUE_REQUEST : 38|15@0+ (1,-7767) [-7767|24999] "Nm" XXX
|
||||
SG_ WHEEL_TORQUE_REQUEST_ACTIVE : 39|1@1+ (1,0) [0|0] "" XXX
|
||||
SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 669 EPB_1: 3 XXX
|
||||
SG_ PARKING_BRAKE_STATUS : 11|3@0+ (1,0) [0|7] "" XXX
|
||||
SG_ COUNTER : 15|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ CHECKSUM : 23|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 678 DAS_6: 8 XXX
|
||||
SG_ LKAS_ICON_COLOR : 1|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ LKAS_LANE_LINES : 19|4@0+ (1,0) [0|1] "" XXX
|
||||
SG_ LKAS_ALERTS : 27|4@0+ (1,0) [0|1] "" XXX
|
||||
SG_ CAR_MODEL : 15|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ AUTO_HIGH_BEAM_ON : 47|1@1+ (1,0) [0|0] "" XXX
|
||||
SG_ LKAS_DISABLED : 56|1@1+ (1,0) [0|0] "" XXX
|
||||
|
||||
BO_ 720 BSM_1: 6 XXX
|
||||
SG_ RIGHT_STATUS : 5|1@0+ (1,0) [0|1] "" XXX
|
||||
@@ -124,11 +172,14 @@ BO_ 820 BCM_1: 8 XXX
|
||||
SG_ DOOR_OPEN_RL : 19|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ DOOR_OPEN_RR : 20|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ DOOR_OPEN_TRUNK : 22|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ PARKING_BRAKE_SWITCH : 23|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ TURN_LIGHT_LEFT : 31|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ TURN_LIGHT_RIGHT : 30|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ HIGH_BEAM_DISPLAY : 58|1@0+ (1,0) [0|1] "" XXX
|
||||
|
||||
VAL_ 320 ACC_OFF_REQ 2 "PERMANENT" 1 "TEMPORARY" 0 "NONE"
|
||||
VAL_ 368 Gear_State 4 "D" 2 "N" 1 "R" 0 "P" ;
|
||||
VAL_ 669 PARKING_BRAKE_STATUS 3 "RELEASING" 2 "APPLYING" 1 "APPLIED" 0 "OFF" ;
|
||||
|
||||
CM_ SG_ 258 STEERING_ANGLE_HP "Steering angle high precision";
|
||||
CM_ SG_ 264 ENGINE_TORQUE "Effective engine torque";
|
||||
@@ -213,12 +264,6 @@ BO_ 729 LKAS_HEARTBIT: 5 XXX
|
||||
SG_ FORWARD_2 : 30|6@0+ (1,0) [0|127] "" XXX
|
||||
SG_ FORWARD_3 : 39|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 288 ACCEL_RELATED_120: 7 XXX
|
||||
SG_ COUNTER : 47|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ CHECKSUM : 55|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ ACCEL : 23|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ GAS_ENGINE_RPM_MAYBE : 31|16@0+ (1,0) [0|65535] "" XXX
|
||||
|
||||
BO_ 257 ACCEL_RELATED_101: 5 XXX
|
||||
SG_ ENERGY_OR_RPM : 31|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
@@ -283,17 +328,6 @@ BO_ 324 SPEED_2: 8 XXX
|
||||
BO_ 832 UNKNOWN_340: 8 XXX
|
||||
SG_ SPEED_DIGITAL : 63|8@0+ (1,0) [0|255] "mph" XXX
|
||||
|
||||
BO_ 625 ACC_1: 8 XXX
|
||||
SG_ SPEED : 31|8@0+ (1,0) [0|255] "km/h" XXX
|
||||
SG_ ACCEL_PERHAPS : 39|16@0+ (1,0) [0|255] "" XXX
|
||||
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
|
||||
BO_ 268 ACC_10c: 8 XXX
|
||||
SG_ BRAKE_PERHAPS : 48|1@0+ (1,0) [0|3] "" XXX
|
||||
SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
CM_ SG_ 653 BRAKE_PRESSURE "max seems to be 148";
|
||||
CM_ SG_ 746 PRNDL "5=L, 4=D, 3=N, 2=R, 1=P";
|
||||
CM_ SG_ 320 BRAKE_PRESSED_2 "Value is 5 when brake is pressed by human, 1 when ACC brake";
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user