diff --git a/.gitignore b/.gitignore index 06c6117b1..83ccbb478 100644 --- a/.gitignore +++ b/.gitignore @@ -56,6 +56,7 @@ selfdrive/modeld/_dmonitoringmodeld /src/ one +/body/ openpilot notebooks xx @@ -76,7 +77,7 @@ cppcheck_report.txt comma*.sh selfdrive/modeld/thneed/compile -models/*.thneed +selfdrive/modeld/models/*.thneed *.bz2 diff --git a/Jenkinsfile b/Jenkinsfile index d12c8e494..3b134d7c0 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -18,13 +18,6 @@ fi ln -snf ${env.TEST_DIR} /data/pythonpath -if [ -f /EON ]; then - echo \$\$ > /dev/cpuset/app/tasks || true - echo \$PPID > /dev/cpuset/app/tasks || true - mkdir -p /dev/shm - chmod 777 /dev/shm -fi - cd ${env.TEST_DIR} || true ${cmd} exit 0 @@ -37,7 +30,7 @@ END""" def phone_steps(String device_type, steps) { lock(resource: "", label: device_type, inversePrecedence: true, variable: 'device_ip', quantity: 1) { - timeout(time: 60, unit: 'MINUTES') { + timeout(time: 20, unit: 'MINUTES') { phone(device_ip, "git checkout", readFile("selfdrive/test/setup_device_ci.sh"),) steps.each { item -> phone(device_ip, item[0], item[1]) @@ -53,33 +46,19 @@ pipeline { SOURCE_DIR = "/data/openpilot_source/" } options { - timeout(time: 4, unit: 'HOURS') + timeout(time: 4, unit: 'HOURS') } stages { - stage('build releases') { + stage('build release3') { + agent { docker { image 'ghcr.io/commaai/alpine-ssh'; args '--user=root' } } when { branch 'devel-staging' } - - parallel { - stage('release2') { - agent { docker { image 'ghcr.io/commaai/alpine-ssh'; args '--user=root' } } - steps { - phone_steps("eon-build", [ - ["build release2-staging & dashcam-staging", "PUSH=1 $SOURCE_DIR/release/build_release.sh"], - ]) - } - } - - stage('release3') { - agent { docker { image 'ghcr.io/commaai/alpine-ssh'; args '--user=root' } } - steps { - phone_steps("tici", [ - ["build release3-staging & dashcam3-staging", "PUSH=1 $SOURCE_DIR/release/build_release.sh"], - ]) - } - } + steps { + phone_steps("tici", [ + ["build release3-staging & dashcam3-staging", "PUSH=1 $SOURCE_DIR/release/build_release.sh"], + ]) } } @@ -101,69 +80,13 @@ pipeline { stages { stage('parallel tests') { parallel { - stage('C2: build') { - steps { - phone_steps("eon-build", [ - ["build master-ci", "cd $SOURCE_DIR/release && EXTRA_FILES='tools/' ./build_devel.sh"], - ["build openpilot", "cd selfdrive/manager && ./build.py"], - ["test manager", "python selfdrive/manager/test/test_manager.py"], - ["onroad tests", "cd selfdrive/test/ && ./test_onroad.py"], - ["test car interfaces", "cd selfdrive/car/tests/ && ./test_car_interfaces.py"], - ]) - } - } - - stage('C2: replay') { - steps { - phone_steps("eon2", [ - ["build", "cd selfdrive/manager && ./build.py"], - ["model replay", "cd selfdrive/test/process_replay && ./model_replay.py"], - ]) - } - } - - stage('C2: HW + Unit Tests') { - steps { - phone_steps("eon", [ - ["build", "cd selfdrive/manager && ./build.py"], - ["test sounds", "python selfdrive/ui/tests/test_soundd.py"], - ["test boardd loopback", "python selfdrive/boardd/tests/test_boardd_loopback.py"], - ["test loggerd", "python selfdrive/loggerd/tests/test_loggerd.py"], - ["test encoder", "python selfdrive/loggerd/tests/test_encoder.py"], - ["test logcatd", "python selfdrive/logcatd/tests/test_logcatd_android.py"], - ["test updater", "python selfdrive/hardware/eon/test_neos_updater.py"], - ]) - } - } - - /* - stage('Power Consumption Tests') { - steps { - lock(resource: "", label: "c2-zookeeper", inversePrecedence: true, variable: 'device_ip', quantity: 1) { - timeout(time: 90, unit: 'MINUTES') { - sh script: "/home/batman/tools/zookeeper/enable_and_wait.py $device_ip 120", label: "turn on device" - phone(device_ip, "git checkout", readFile("selfdrive/test/setup_device_ci.sh"),) - phone(device_ip, "build", "scons -j4 && sync") - sh script: "/home/batman/tools/zookeeper/disable.py $device_ip", label: "turn off device" - sh script: "/home/batman/tools/zookeeper/enable_and_wait.py $device_ip 120", label: "turn on device" - sh script: "/home/batman/tools/zookeeper/check_consumption.py 60 3", label: "idle power consumption after boot" - sh script: "/home/batman/tools/zookeeper/ignition.py 1", label: "go onroad" - sh script: "/home/batman/tools/zookeeper/check_consumption.py 60 10", label: "onroad power consumption" - sh script: "/home/batman/tools/zookeeper/ignition.py 0", label: "go offroad" - sh script: "/home/batman/tools/zookeeper/check_consumption.py 60 2", label: "idle power consumption offroad" - } - } - } - } - */ - - stage('C3: build') { + stage('build') { environment { R3_PUSH = "${env.BRANCH_NAME == 'master' ? '1' : ' '}" } steps { phone_steps("tici", [ - ["build master-ci", "cd $SOURCE_DIR/release && EXTRA_FILES='tools/' ./build_devel.sh"], + ["build master-ci", "cd $SOURCE_DIR/release && TARGET_DIR=$TEST_DIR EXTRA_FILES='tools/' ./build_devel.sh"], ["build openpilot", "cd selfdrive/manager && ./build.py"], ["test manager", "python selfdrive/manager/test/test_manager.py"], ["onroad tests", "cd selfdrive/test/ && ./test_onroad.py"], @@ -172,28 +95,20 @@ pipeline { } } - stage('C3: HW + Unit Tests') { + stage('HW + Unit Tests') { steps { phone_steps("tici2", [ ["build", "cd selfdrive/manager && ./build.py"], + ["test power draw", "python selfdrive/hardware/tici/test_power_draw.py"], ["test boardd loopback", "python selfdrive/boardd/tests/test_boardd_loopback.py"], ["test loggerd", "python selfdrive/loggerd/tests/test_loggerd.py"], ["test encoder", "LD_LIBRARY_PATH=/usr/local/lib python selfdrive/loggerd/tests/test_encoder.py"], + ["test sensord", "python selfdrive/sensord/test/test_sensord.py"], ]) } } - stage('C2: camerad') { - steps { - phone_steps("eon-party", [ - ["build", "cd selfdrive/manager && ./build.py"], - ["test camerad", "python selfdrive/camerad/test/test_camerad.py"], - ["test exposure", "python selfdrive/camerad/test/test_exposure.py"], - ]) - } - } - - stage('C3: camerad') { + stage('camerad') { steps { phone_steps("tici-party", [ ["build", "cd selfdrive/manager && ./build.py"], @@ -203,9 +118,9 @@ pipeline { } } - stage('C3: replay') { + stage('replay') { steps { - phone_steps("tici-party", [ + phone_steps("tici3", [ ["build", "cd selfdrive/manager && ./build.py"], ["model replay", "cd selfdrive/test/process_replay && ./model_replay.py"], ]) @@ -214,18 +129,6 @@ pipeline { } } - - stage('Push master-ci') { - when { - branch 'master' - } - steps { - phone_steps("eon-build", [ - ["push devel", "cd $SOURCE_DIR/release && PUSH='master-ci' ./build_devel.sh"], - ]) - } - } - } post { @@ -240,4 +143,3 @@ pipeline { } } } - diff --git a/README.md b/README.md index b012883d7..5af02de8d 100755 --- a/README.md +++ b/README.md @@ -41,8 +41,8 @@ Running in a car To use openpilot in a car, you need four things * This software. It's free and available right here. * One of [the 150+ supported cars](docs/CARS.md). We support Honda, Toyota, Hyundai, Nissan, Kia, Chrysler, Lexus, Acura, Audi, VW, and more. If your car is not supported, but has adaptive cruise control and lane keeping assist, it's likely able to run openpilot. -* A supported device to run this software. This can be a [comma two](https://comma.ai/shop/products/two), [comma three](https://comma.ai/shop/products/three), or if you like to experiment, a [Ubuntu computer with webcams](https://github.com/commaai/openpilot/tree/master/tools/webcam). -* A way to connect to your car. With a comma two or three, you need only a [car harness](https://comma.ai/shop/products/car-harness). With an EON Gold or PC, you also need a [black panda](https://comma.ai/shop/products/panda). +* A supported device to run this software: a [comma three](https://comma.ai/shop/products/three), or if you like to experiment, a [Ubuntu computer with webcams](https://github.com/commaai/openpilot/tree/master/tools/webcam). +* A way to connect to your car. With a comma three, you need only a [car harness](https://comma.ai/shop/products/car-harness). With a PC, you also need a [black panda](https://comma.ai/shop/products/panda). We have detailed instructions for [how to install the device in a car](https://comma.ai/setup). diff --git a/RELEASES.md b/RELEASES.md index 8564975f4..2c7ff17de 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,22 @@ +Version 0.8.14 (2022-06-01) +======================== + * New driving model + * Bigger model, using both of comma three's road-facing cameras + * Better at cut-in detection and tight turns + * New driver monitoring model + * Tweaked network structure to improve output resolution for DSP + * Fixed bug in quantization aware training to reduce quantizing errors + * Resulted in 7x less MSE and no more random biases at runtime + * Added toggle to disable disengaging on the accelerator pedal + * comma body support + * Audi RS3 support thanks to jyoung8607! + * Hyundai Ioniq Plug-in Hybrid 2019 support thanks to sunnyhaibin! + * Hyundai Tucson Diesel 2019 support thanks to sunnyhaibin! + * Toyota Alphard Hybrid 2021 support + * Toyota Avalon Hybrid 2022 support + * Toyota RAV4 2022 support + * Toyota RAV4 Hybrid 2022 support + Version 0.8.13 (2022-02-18) ======================== * Improved driver monitoring diff --git a/SConstruct b/SConstruct index 832550b14..d9d05f794 100644 --- a/SConstruct +++ b/SConstruct @@ -73,14 +73,9 @@ lenv = { rpath = lenv["LD_LIBRARY_PATH"].copy() -if arch == "aarch64" or arch == "larch64": +if arch == "larch64": lenv["LD_LIBRARY_PATH"] += ['/data/data/com.termux/files/usr/lib'] - if arch == "aarch64": - # android - lenv["ANDROID_DATA"] = os.environ['ANDROID_DATA'] - lenv["ANDROID_ROOT"] = os.environ['ANDROID_ROOT'] - cpppath = [ "#third_party/opencl/include", ] @@ -89,57 +84,45 @@ if arch == "aarch64" or arch == "larch64": "/usr/local/lib", "/usr/lib", "/system/vendor/lib64", - "/system/comma/usr/lib", f"#third_party/acados/{arch}/lib", ] - if arch == "larch64": - libpath += [ - "#third_party/snpe/larch64", - "#third_party/libyuv/larch64/lib", - "/usr/lib/aarch64-linux-gnu" - ] - cpppath += [ - "#selfdrive/camerad/include", - ] - cflags = ["-DQCOM2", "-mcpu=cortex-a57"] - cxxflags = ["-DQCOM2", "-mcpu=cortex-a57"] - rpath += ["/usr/local/lib"] - else: - rpath = [] - libpath += [ - "#third_party/snpe/aarch64", - "#third_party/libyuv/lib", - "/system/vendor/lib64" - ] - cflags = ["-DQCOM", "-D_USING_LIBCXX", "-mcpu=cortex-a57"] - cxxflags = ["-DQCOM", "-D_USING_LIBCXX", "-mcpu=cortex-a57"] + libpath += [ + "#third_party/snpe/larch64", + "#third_party/libyuv/larch64/lib", + "/usr/lib/aarch64-linux-gnu" + ] + cpppath += [ + "#selfdrive/camerad/include", + ] + cflags = ["-DQCOM2", "-mcpu=cortex-a57"] + cxxflags = ["-DQCOM2", "-mcpu=cortex-a57"] + rpath += ["/usr/local/lib"] else: cflags = [] cxxflags = [] cpppath = [] + # MacOS if arch == "Darwin": + brew_prefix = subprocess.check_output(['brew', '--prefix'], encoding='utf8').strip() yuv_dir = "mac" if real_arch != "arm64" else "mac_arm64" libpath = [ f"#third_party/libyuv/{yuv_dir}/lib", - "/usr/local/lib", - "/opt/homebrew/lib", - "/usr/local/Homebrew/Library", - "/usr/local/opt/openssl/lib", - "/opt/homebrew/opt/openssl/lib", - "/usr/local/Cellar", + f"{brew_prefix}/lib", + f"{brew_prefix}/Library", + f"{brew_prefix}/opt/openssl/lib", + f"{brew_prefix}/Cellar", f"#third_party/acados/{arch}/lib", "/System/Library/Frameworks/OpenGL.framework/Libraries", ] cflags += ["-DGL_SILENCE_DEPRECATION"] cxxflags += ["-DGL_SILENCE_DEPRECATION"] cpppath += [ - "/opt/homebrew/include", - "/usr/local/include", - "/usr/local/opt/openssl/include", - "/opt/homebrew/opt/openssl/include" + f"{brew_prefix}/include", + f"{brew_prefix}/opt/openssl/include", ] + # Linux 86_64 else: libpath = [ "#third_party/acados/x86_64/lib", @@ -147,7 +130,7 @@ else: "#third_party/libyuv/x64/lib", "#third_party/mapbox-gl-native-qt/x86_64", "#cereal", - "#selfdrive/common", + "#common", "/usr/lib", "/usr/local/lib", ] @@ -155,7 +138,7 @@ else: rpath += [ Dir("#third_party/snpe/x86_64-linux-clang").abspath, Dir("#cereal").abspath, - Dir("#selfdrive/common").abspath + Dir("#common").abspath ] if GetOption('asan'): @@ -173,8 +156,8 @@ if arch != "Darwin": ldflags += ["-Wl,--as-needed", "-Wl,--no-undefined"] # Enable swaglog include in submodules -cflags += ["-DSWAGLOG"] -cxxflags += ["-DSWAGLOG"] +cflags += ['-DSWAGLOG="\\"common/swaglog.h\\""'] +cxxflags += ['-DSWAGLOG="\\"common/swaglog.h\\""'] env = Environment( ENV=lenv, @@ -200,9 +183,7 @@ env = Environment( "#third_party/acados/include/blasfeo/include", "#third_party/acados/include/hpipm/include", "#third_party/catch2/include", - "#third_party/bzip2", "#third_party/libyuv/include", - "#third_party/openmax/include", "#third_party/json11", "#third_party/curl/include", "#third_party/libgralloc/include", @@ -231,7 +212,7 @@ env = Environment( "#third_party", "#opendbc/can", "#selfdrive/boardd", - "#selfdrive/common", + "#common", ], CYTHONCFILESUFFIX=".cpp", COMPILATIONDB_USE_ABSPATH=True, @@ -261,6 +242,7 @@ if os.environ.get('SCONS_PROGRESS'): SHARED = False +# TODO: this can probably be removed def abspath(x): if arch == 'aarch64': pth = os.path.join("/data/pythonpath", x[0].path) @@ -289,9 +271,7 @@ Export('envCython') # Qt build environment qt_env = env.Clone() -qt_modules = ["Widgets", "Gui", "Core", "Network", "Concurrent", "Multimedia", "Quick", "Qml", "QuickWidgets", "Location", "Positioning"] -if arch != "aarch64": - qt_modules += ["DBus"] +qt_modules = ["Widgets", "Gui", "Core", "Network", "Concurrent", "Multimedia", "Quick", "Qml", "QuickWidgets", "Location", "Positioning", "DBus"] qt_libs = [] if arch == "Darwin": @@ -306,15 +286,6 @@ if arch == "Darwin": qt_env["LINKFLAGS"] += ["-F" + os.path.join(qt_env['QTDIR'], "lib")] qt_env["FRAMEWORKS"] += [f"Qt{m}" for m in qt_modules] + ["OpenGL"] qt_env.AppendENVPath('PATH', os.path.join(qt_env['QTDIR'], "bin")) -elif arch == "aarch64": - qt_env['QTDIR'] = "/system/comma/usr" - qt_dirs = [ - f"/system/comma/usr/include/qt", - ] - qt_dirs += [f"/system/comma/usr/include/qt/Qt{m}" for m in qt_modules] - - qt_libs = [f"Qt5{m}" for m in qt_modules] - qt_libs += ['EGL', 'GLESv3', 'c++_shared'] else: qt_env['QTDIR'] = "/usr" qt_dirs = [ @@ -359,14 +330,14 @@ if GetOption("clazy"): Export('env', 'qt_env', 'arch', 'real_arch', 'SHARED', 'USE_WEBCAM') -SConscript(['selfdrive/common/SConscript']) -Import('_common', '_gpucommon', '_gpu_libs') +SConscript(['common/SConscript']) +Import('_common', '_gpucommon') if SHARED: common, gpucommon = abspath(common), abspath(gpucommon) else: common = [_common, 'json11'] - gpucommon = [_gpucommon] + _gpu_libs + gpucommon = [_gpucommon] Export('common', 'gpucommon') @@ -392,7 +363,7 @@ rednose_config = { }, } -if arch not in ["aarch64", "larch64"]: +if arch != "larch64": rednose_config['to_build'].update({ 'gnss': ('#selfdrive/locationd/models/gnss_kf.py', True, []), 'loc_4': ('#selfdrive/locationd/models/loc_kf.py', True, []), @@ -413,7 +384,6 @@ SConscript(['opendbc/can/SConscript']) SConscript(['third_party/SConscript']) -SConscript(['common/SConscript']) SConscript(['common/kalman/SConscript']) SConscript(['common/transformations/SConscript']) diff --git a/cereal/SConscript b/cereal/SConscript index df066dc51..e40d3ba1a 100644 --- a/cereal/SConscript +++ b/cereal/SConscript @@ -49,7 +49,7 @@ vipc_sources = [ 'visionipc/visionbuf.cc', ] -if arch in ["aarch64", "larch64"]: +if arch == "larch64": vipc_sources += ['visionipc/visionbuf_ion.cc'] else: vipc_sources += ['visionipc/visionbuf_cl.cc'] @@ -58,15 +58,17 @@ vipc_objects = env.SharedObject(vipc_sources) vipc = env.Library('visionipc', vipc_objects) -libs = envCython["LIBS"]+["OpenCL", "zmq", vipc, messaging_lib, common] -if arch == "aarch64": - libs += ["adreno_utils"] +vipc_frameworks = [] +vipc_libs = envCython["LIBS"] + [vipc, messaging_lib, common, "zmq"] if arch == "Darwin": - del libs[libs.index('OpenCL')] - envCython['FRAMEWORKS'] += ['OpenCL'] -envCython.Program('visionipc/visionipc_pyx.so', 'visionipc/visionipc_pyx.pyx', LIBS=libs) - + vipc_frameworks.append('OpenCL') +else: + vipc_libs.append('OpenCL') +envCython.Program('visionipc/visionipc_pyx.so', 'visionipc/visionipc_pyx.pyx', + LIBS=vipc_libs, FRAMEWORKS=vipc_frameworks) if GetOption('test'): env.Program('messaging/test_runner', ['messaging/test_runner.cc', 'messaging/msgq_tests.cc'], LIBS=[messaging_lib, common]) - env.Program('visionipc/test_runner', ['visionipc/test_runner.cc', 'visionipc/visionipc_tests.cc'], LIBS=[vipc, messaging_lib, 'zmq', 'pthread', 'OpenCL', common]) + + env.Program('visionipc/test_runner', ['visionipc/test_runner.cc', 'visionipc/visionipc_tests.cc'], + LIBS=['pthread'] + vipc_libs, FRAMEWORKS=vipc_frameworks) diff --git a/cereal/car.capnp b/cereal/car.capnp index 10f8578b4..5a4e256ad 100644 --- a/cereal/car.capnp +++ b/cereal/car.capnp @@ -17,6 +17,7 @@ struct CarEvent @0x9b1657f34caf3ad3 { immediateDisable @6 :Bool; preEnable @7 :Bool; permanent @8 :Bool; # alerts presented regardless of openpilot state + override @9 :Bool; enum EventName @0xbaa8c5d505f727de { canError @0; @@ -31,7 +32,9 @@ struct CarEvent @0x9b1657f34caf3ad3 { reverseGear @10; buttonCancel @11; buttonEnable @12; - pedalPressed @13; + pedalPressed @13; # exits active state + pedalPressedPreEnable @73; # added during pre-enable state for either pedal + gasPressedOverride @108; # added when user is pressing gas with no disengage on gas cruiseDisabled @14; speedTooLow @17; outOfSpace @18; @@ -63,6 +66,7 @@ struct CarEvent @0x9b1657f34caf3ad3 { accFaulted @51; sensorDataInvalid @52; commIssue @53; + commIssueAvgFreq @109; tooDistracted @54; posenetInvalid @55; soundsUnavailable @56; @@ -77,7 +81,6 @@ struct CarEvent @0x9b1657f34caf3ad3 { speedTooHigh @70; laneChangeBlocked @71; relayMalfunction @72; - gasPressed @73; stockFcw @74; startup @75; startupNoCar @76; @@ -93,6 +96,7 @@ struct CarEvent @0x9b1657f34caf3ad3 { deviceFalling @90; fanMalfunction @91; cameraMalfunction @92; + cameraFrameRate @110; gpsMalfunction @94; processNotRunning @95; dashcamMode @96; @@ -105,6 +109,8 @@ struct CarEvent @0x9b1657f34caf3ad3 { highCpuUsage @105; cruiseMismatch @106; lkasDisabled @107; + canBusMissing @111; + controlsdLagging @112; radarCanErrorDEPRECATED @15; communityFeatureDisallowedDEPRECATED @62; @@ -137,6 +143,10 @@ struct CarEvent @0x9b1657f34caf3ad3 { struct CarState { events @13 :List(CarEvent); + # CAN health + canValid @26 :Bool; # invalid counter/checksums + canTimeout @40 :Bool; # CAN bus dropped out + # car speed vEgo @1 :Float32; # best estimate of speed aEgo @16 :Float32; # best estimate of acceleration @@ -152,6 +162,7 @@ struct CarState { # brake pedal, 0.0-1.0 brake @5 :Float32; # this is user pedal only brakePressed @6 :Bool; # this is user pedal only + parkingBrake @39 :Bool; brakeHoldActive @38 :Bool; # steering wheel @@ -162,11 +173,12 @@ struct CarState { steeringTorqueEps @27 :Float32; # TODO: standardize units steeringPressed @9 :Bool; # if the user is using the steering wheel steeringRateLimited @29 :Bool; # if the torque is limited by the rate limiter - steerWarning @35 :Bool; # temporary steer unavailble - steerError @36 :Bool; # permanent steer error + steerFaultTemporary @35 :Bool; # temporary EPS fault + steerFaultPermanent @36 :Bool; # permanent EPS fault stockAeb @30 :Bool; stockFcw @31 :Bool; espDisabled @32 :Bool; + accFaulted @42 :Bool; # cruise state cruiseState @10 :CruiseState; @@ -183,7 +195,6 @@ struct CarState { # lock info doorOpen @24 :Bool; seatbeltUnlatched @25 :Bool; - canValid @26 :Bool; # clutch (manual transmission only) clutchPressed @28 :Bool; @@ -195,6 +206,9 @@ struct CarState { leftBlindspot @33 :Bool; # Is there something blocking the left lane change rightBlindspot @34 :Bool; # Is there something blocking the right lane change + fuelGauge @41 :Float32; # battery or fuel tank level from 0.0 to 1.0 + charging @43 :Bool; + struct WheelSpeeds { # optional wheel speeds fl @0 :Float32; @@ -289,7 +303,8 @@ struct RadarData @0x888ad6581cf0aacb { struct CarControl { # must be true for any actuator commands to work enabled @0 :Bool; - active @7 :Bool; + latActive @11: Bool; + longActive @12: Bool; # Actuator commands as computed by controlsd actuators @6 :Actuators; @@ -299,8 +314,8 @@ struct CarControl { # and matches what is sent to the car actuatorsOutput @10 :Actuators; - roll @8 :Float32; - pitch @9 :Float32; + orientationNED @13 :List(Float32); + angularVelocity @14 :List(Float32); cruiseControl @4 :CruiseControl; hudControl @5 :HUDControl; @@ -378,6 +393,9 @@ struct CarControl { gasDEPRECATED @1 :Float32; brakeDEPRECATED @2 :Float32; steeringTorqueDEPRECATED @3 :Float32; + activeDEPRECATED @7 :Bool; + rollDEPRECATED @8 :Float32; + pitchDEPRECATED @9 :Float32; } # ****** car param ****** @@ -387,6 +405,8 @@ struct CarParams { carFingerprint @1 :Text; fuzzyFingerprint @55 :Bool; + notCar @66 :Bool; # flag for non-car robotics platforms + enableGasInterceptor @2 :Bool; pcmCruise @3 :Bool; # is openpilot's state tied to the PCM's cruise state? enableDsu @5 :Bool; # driving support unit @@ -398,10 +418,10 @@ struct CarParams { minSteerSpeed @8 :Float32; maxSteeringAngleDeg @54 :Float32; safetyConfigs @62 :List(SafetyConfig); - unsafeMode @65 :Int16; + alternativeExperience @65 :Int16; # panda flag for features like no disengage on gas - steerMaxBP @11 :List(Float32); - steerMaxV @12 :List(Float32); + steerMaxBPDEPRECATED @11 :List(Float32); + steerMaxVDEPRECATED @12 :List(Float32); gasMaxBPDEPRECATED @13 :List(Float32); gasMaxVDEPRECATED @14 :List(Float32); brakeMaxBPDEPRECATED @15 :List(Float32); @@ -425,6 +445,7 @@ struct CarParams { pid @26 :LateralPIDTuning; indi @27 :LateralINDITuning; lqr @40 :LateralLQRTuning; + torque @67 :LateralTorqueTuning; } steerLimitAlert @28 :Bool; @@ -457,7 +478,9 @@ struct CarParams { struct SafetyConfig { safetyModel @0 :SafetyModel; - safetyParam @1 :Int16; + safetyParam @3 :UInt16; + safetyParamDEPRECATED @1 :Int16; + safetyParam2DEPRECATED @2 :UInt32; } struct LateralParams { @@ -473,11 +496,20 @@ struct CarParams { kf @4 :Float32; } + struct LateralTorqueTuning { + useSteeringAngle @0 :Bool; + kp @1 :Float32; + ki @2 :Float32; + friction @3 :Float32; + kf @4 :Float32; + } + struct LongitudinalPIDTuning { kpBP @0 :List(Float32); kpV @1 :List(Float32); kiBP @2 :List(Float32); kiV @3 :List(Float32); + kf @6 :Float32; deadzoneBP @4 :List(Float32); deadzoneV @5 :List(Float32); } @@ -539,6 +571,9 @@ struct CarParams { hyundaiLegacy @23; hyundaiCommunity @24; stellantis @25; + faw @26; + body @27; + hyundaiHDA2 @28; } enum SteerControlType { @@ -583,6 +618,8 @@ struct CarParams { programmedFuelInjection @14; electricBrakeBooster @15; shiftByWire @16; + + debug @17; } enum FingerprintSource { diff --git a/cereal/legacy.capnp b/cereal/legacy.capnp index 9a4891681..a8fa5e4a1 100644 --- a/cereal/legacy.capnp +++ b/cereal/legacy.capnp @@ -559,293 +559,6 @@ struct AndroidGnss @0xdfdf30d03fc485bd { } } -struct QcomGnss @0xde94674b07ae51c1 { - logTs @0 :UInt64; - union { - measurementReport @1 :MeasurementReport; - clockReport @2 :ClockReport; - drMeasurementReport @3 :DrMeasurementReport; - drSvPoly @4 :DrSvPolyReport; - rawLog @5 :Data; - } - - enum MeasurementSource @0xd71a12b6faada7ee { - gps @0; - glonass @1; - beidou @2; - } - - enum SVObservationState @0xe81e829a0d6c83e9 { - idle @0; - search @1; - searchVerify @2; - bitEdge @3; - trackVerify @4; - track @5; - restart @6; - dpo @7; - glo10msBe @8; - glo10msAt @9; - } - - struct MeasurementStatus @0xe501010e1bcae83b { - subMillisecondIsValid @0 :Bool; - subBitTimeIsKnown @1 :Bool; - satelliteTimeIsKnown @2 :Bool; - bitEdgeConfirmedFromSignal @3 :Bool; - measuredVelocity @4 :Bool; - fineOrCoarseVelocity @5 :Bool; - lockPointValid @6 :Bool; - lockPointPositive @7 :Bool; - lastUpdateFromDifference @8 :Bool; - lastUpdateFromVelocityDifference @9 :Bool; - strongIndicationOfCrossCorelation @10 :Bool; - tentativeMeasurement @11 :Bool; - measurementNotUsable @12 :Bool; - sirCheckIsNeeded @13 :Bool; - probationMode @14 :Bool; - - glonassMeanderBitEdgeValid @15 :Bool; - glonassTimeMarkValid @16 :Bool; - - gpsRoundRobinRxDiversity @17 :Bool; - gpsRxDiversity @18 :Bool; - gpsLowBandwidthRxDiversityCombined @19 :Bool; - gpsHighBandwidthNu4 @20 :Bool; - gpsHighBandwidthNu8 @21 :Bool; - gpsHighBandwidthUniform @22 :Bool; - multipathIndicator @23 :Bool; - - imdJammingIndicator @24 :Bool; - lteB13TxJammingIndicator @25 :Bool; - freshMeasurementIndicator @26 :Bool; - - multipathEstimateIsValid @27 :Bool; - directionIsValid @28 :Bool; - } - - struct MeasurementReport @0xf580d7d86b7b8692 { - source @0 :MeasurementSource; - - fCount @1 :UInt32; - - gpsWeek @2 :UInt16; - glonassCycleNumber @3 :UInt8; - glonassNumberOfDays @4 :UInt16; - - milliseconds @5 :UInt32; - timeBias @6 :Float32; - clockTimeUncertainty @7 :Float32; - clockFrequencyBias @8 :Float32; - clockFrequencyUncertainty @9 :Float32; - - sv @10 :List(SV); - - struct SV @0xf10c595ae7bb2c27 { - svId @0 :UInt8; - observationState @2 :SVObservationState; - observations @3 :UInt8; - goodObservations @4 :UInt8; - gpsParityErrorCount @5 :UInt16; - glonassFrequencyIndex @1 :Int8; - glonassHemmingErrorCount @6 :UInt8; - filterStages @7 :UInt8; - carrierNoise @8 :UInt16; - latency @9 :Int16; - predetectInterval @10 :UInt8; - postdetections @11 :UInt16; - - unfilteredMeasurementIntegral @12 :UInt32; - unfilteredMeasurementFraction @13 :Float32; - unfilteredTimeUncertainty @14 :Float32; - unfilteredSpeed @15 :Float32; - unfilteredSpeedUncertainty @16 :Float32; - measurementStatus @17 :MeasurementStatus; - multipathEstimate @18 :UInt32; - azimuth @19 :Float32; - elevation @20 :Float32; - carrierPhaseCyclesIntegral @21 :Int32; - carrierPhaseCyclesFraction @22 :UInt16; - fineSpeed @23 :Float32; - fineSpeedUncertainty @24 :Float32; - cycleSlipCount @25 :UInt8; - } - - } - - struct ClockReport @0xca965e4add8f4f0b { - hasFCount @0 :Bool; - fCount @1 :UInt32; - - hasGpsWeek @2 :Bool; - gpsWeek @3 :UInt16; - hasGpsMilliseconds @4 :Bool; - gpsMilliseconds @5 :UInt32; - gpsTimeBias @6 :Float32; - gpsClockTimeUncertainty @7 :Float32; - gpsClockSource @8 :UInt8; - - hasGlonassYear @9 :Bool; - glonassYear @10 :UInt8; - hasGlonassDay @11 :Bool; - glonassDay @12 :UInt16; - hasGlonassMilliseconds @13 :Bool; - glonassMilliseconds @14 :UInt32; - glonassTimeBias @15 :Float32; - glonassClockTimeUncertainty @16 :Float32; - glonassClockSource @17 :UInt8; - - bdsWeek @18 :UInt16; - bdsMilliseconds @19 :UInt32; - bdsTimeBias @20 :Float32; - bdsClockTimeUncertainty @21 :Float32; - bdsClockSource @22 :UInt8; - - galWeek @23 :UInt16; - galMilliseconds @24 :UInt32; - galTimeBias @25 :Float32; - galClockTimeUncertainty @26 :Float32; - galClockSource @27 :UInt8; - - clockFrequencyBias @28 :Float32; - clockFrequencyUncertainty @29 :Float32; - frequencySource @30 :UInt8; - gpsLeapSeconds @31 :UInt8; - gpsLeapSecondsUncertainty @32 :UInt8; - gpsLeapSecondsSource @33 :UInt8; - - gpsToGlonassTimeBiasMilliseconds @34 :Float32; - gpsToGlonassTimeBiasMillisecondsUncertainty @35 :Float32; - gpsToBdsTimeBiasMilliseconds @36 :Float32; - gpsToBdsTimeBiasMillisecondsUncertainty @37 :Float32; - bdsToGloTimeBiasMilliseconds @38 :Float32; - bdsToGloTimeBiasMillisecondsUncertainty @39 :Float32; - gpsToGalTimeBiasMilliseconds @40 :Float32; - gpsToGalTimeBiasMillisecondsUncertainty @41 :Float32; - galToGloTimeBiasMilliseconds @42 :Float32; - galToGloTimeBiasMillisecondsUncertainty @43 :Float32; - galToBdsTimeBiasMilliseconds @44 :Float32; - galToBdsTimeBiasMillisecondsUncertainty @45 :Float32; - - hasRtcTime @46 :Bool; - systemRtcTime @47 :UInt32; - fCountOffset @48 :UInt32; - lpmRtcCount @49 :UInt32; - clockResets @50 :UInt32; - } - - struct DrMeasurementReport @0x8053c39445c6c75c { - - reason @0 :UInt8; - seqNum @1 :UInt8; - seqMax @2 :UInt8; - rfLoss @3 :UInt16; - - systemRtcValid @4 :Bool; - fCount @5 :UInt32; - clockResets @6 :UInt32; - systemRtcTime @7 :UInt64; - - gpsLeapSeconds @8 :UInt8; - gpsLeapSecondsUncertainty @9 :UInt8; - gpsToGlonassTimeBiasMilliseconds @10 :Float32; - gpsToGlonassTimeBiasMillisecondsUncertainty @11 :Float32; - - gpsWeek @12 :UInt16; - gpsMilliseconds @13 :UInt32; - gpsTimeBiasMs @14 :UInt32; - gpsClockTimeUncertaintyMs @15 :UInt32; - gpsClockSource @16 :UInt8; - - glonassClockSource @17 :UInt8; - glonassYear @18 :UInt8; - glonassDay @19 :UInt16; - glonassMilliseconds @20 :UInt32; - glonassTimeBias @21 :Float32; - glonassClockTimeUncertainty @22 :Float32; - - clockFrequencyBias @23 :Float32; - clockFrequencyUncertainty @24 :Float32; - frequencySource @25 :UInt8; - - source @26 :MeasurementSource; - - sv @27 :List(SV); - - struct SV @0xf08b81df8cbf459c { - svId @0 :UInt8; - glonassFrequencyIndex @1 :Int8; - observationState @2 :SVObservationState; - observations @3 :UInt8; - goodObservations @4 :UInt8; - filterStages @5 :UInt8; - predetectInterval @6 :UInt8; - cycleSlipCount @7 :UInt8; - postdetections @8 :UInt16; - - measurementStatus @9 :MeasurementStatus; - - carrierNoise @10 :UInt16; - rfLoss @11 :UInt16; - latency @12 :Int16; - - filteredMeasurementFraction @13 :Float32; - filteredMeasurementIntegral @14 :UInt32; - filteredTimeUncertainty @15 :Float32; - filteredSpeed @16 :Float32; - filteredSpeedUncertainty @17 :Float32; - - unfilteredMeasurementFraction @18 :Float32; - unfilteredMeasurementIntegral @19 :UInt32; - unfilteredTimeUncertainty @20 :Float32; - unfilteredSpeed @21 :Float32; - unfilteredSpeedUncertainty @22 :Float32; - - multipathEstimate @23 :UInt32; - azimuth @24 :Float32; - elevation @25 :Float32; - dopplerAcceleration @26 :Float32; - fineSpeed @27 :Float32; - fineSpeedUncertainty @28 :Float32; - - carrierPhase @29 :Float64; - fCount @30 :UInt32; - - parityErrorCount @31 :UInt16; - goodParity @32 :Bool; - } - } - - struct DrSvPolyReport @0xb1fb80811a673270 { - svId @0 :UInt16; - frequencyIndex @1 :Int8; - - hasPosition @2 :Bool; - hasIono @3 :Bool; - hasTropo @4 :Bool; - hasElevation @5 :Bool; - polyFromXtra @6 :Bool; - hasSbasIono @7 :Bool; - - iode @8 :UInt16; - t0 @9 :Float64; - xyz0 @10 :List(Float64); - xyzN @11 :List(Float64); - other @12 :List(Float32); - - positionUncertainty @13 :Float32; - ionoDelay @14 :Float32; - ionoDot @15 :Float32; - sbasIonoDelay @16 :Float32; - sbasIonoDot @17 :Float32; - tropoDelay @18 :Float32; - elevation @19 :Float32; - elevationDot @20 :Float32; - elevationUncertainty @21 :Float32; - velocityCoeff @22 :List(Float64); - } -} - struct LidarPts @0xe3d6685d4e9d8f7a { r @0 :List(UInt16); # uint16 m*500.0 theta @1 :List(UInt16); # uint16 deg*100.0 diff --git a/cereal/log.capnp b/cereal/log.capnp index 6f4f43939..3b53c01e5 100644 --- a/cereal/log.capnp +++ b/cereal/log.capnp @@ -119,6 +119,7 @@ struct InitData { struct FrameData { frameId @0 :UInt32; encodeId @1 :UInt32; # DEPRECATED + frameIdSensor @25 :UInt32; frameType @7 :FrameType; frameLength @3 :Int32; @@ -126,6 +127,7 @@ struct FrameData { # Timestamps timestampEof @2 :UInt64; timestampSof @8 :UInt64; + processingTime @23 :Float32; # Exposure integLines @4 :Int32; @@ -151,6 +153,8 @@ struct FrameData { image @6 :Data; globalGainDEPRECATED @5 :Int32; + temperaturesC @24 :List(Float32); + enum FrameType { unknown @0; neo @1; @@ -274,6 +278,7 @@ struct GpsLocationData { external @5; ublox @6; trimble @7; + qcomdiag @8; } } @@ -289,6 +294,7 @@ struct DeviceState @0xa4d8b5af2aa492eb { networkType @22 :NetworkType; networkInfo @31 :NetworkInfo; networkStrength @24 :NetworkStrength; + networkMetered @41 :Bool; lastAthenaPingTime @32 :UInt64; started @11 :Bool; @@ -388,8 +394,8 @@ struct PandaState @0xa7649e2575e4591e { pandaType @10 :PandaType; ignitionCan @13 :Bool; safetyModel @14 :Car.CarParams.SafetyModel; - safetyParam @20 :Int16; - unsafeMode @23 :Int16; + safetyParam @27 :UInt16; + alternativeExperience @23 :Int16; faultStatus @15 :FaultStatus; powerSaveEnabled @16 :Bool; uptime @17 :UInt32; @@ -397,6 +403,7 @@ struct PandaState @0xa7649e2575e4591e { harnessStatus @21 :HarnessStatus; heartbeatLost @22 :Bool; blockedCnt @24 :UInt32; + interruptLoad @25 :Float32; enum FaultStatus { none @0; @@ -427,6 +434,7 @@ struct PandaState @0xa7649e2575e4591e { interruptRateKlineInit @19; interruptRateClockSource @20; interruptRateTick @21; + interruptRateExti @22; # Update max fault type in boardd when adding faults } @@ -453,6 +461,8 @@ struct PandaState @0xa7649e2575e4591e { hasGpsDEPRECATED @6 :Bool; fanSpeedRpmDEPRECATED @11 :UInt16; usbPowerModeDEPRECATED @12 :PeripheralState.UsbPowerMode; + safetyParamDEPRECATED @20 :Int16; + safetyParam2DEPRECATED @26 :UInt32; } struct PeripheralState { @@ -558,6 +568,8 @@ struct ControlsState @0x97ff69c53601abf1 { ufAccelCmd @33 :Float32; 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 @@ -579,6 +591,7 @@ struct ControlsState @0x97ff69c53601abf1 { lqrState @55 :LateralLQRState; angleState @58 :LateralAngleState; debugState @59 :LateralDebugState; + torqueState @60 :LateralTorqueState; } enum OpenpilotState @0xdbe58b96d2d1ac61 { @@ -586,6 +599,7 @@ struct ControlsState @0x97ff69c53601abf1 { preEnabled @1; enabled @2; softDisabling @3; + overriding @4; } enum AlertStatus { @@ -630,6 +644,20 @@ struct ControlsState @0x97ff69c53601abf1 { steeringAngleDesiredDeg @9 :Float32; } + struct LateralTorqueState { + active @0 :Bool; + error @1 :Float32; + errorRate @8 :Float32; + p @2 :Float32; + i @3 :Float32; + d @4 :Float32; + f @5 :Float32; + output @6 :Float32; + saturated @7 :Bool; + actualLateralAccel @9 :Float32; + desiredLateralAccel @10 :Float32; + } + struct LateralLQRState { active @0 :Bool; steeringAngleDeg @1 :Float32; @@ -688,6 +716,7 @@ struct ControlsState @0x97ff69c53601abf1 { struct ModelDataV2 { frameId @0 :UInt32; + frameIdExtra @20 :UInt32; frameAge @1 :UInt32; frameDropPerc @2 :Float32; timestampEof @3 :UInt64; @@ -795,6 +824,10 @@ struct EncodeIndex { timestampSof @6 :UInt64; timestampEof @7 :UInt64; + # encoder metadata + flags @8 :UInt32; + len @9 :UInt32; + enum Type { bigBoxLossless @0; # rcamera.mkv fullHEVC @1; # fcamera.hevc @@ -802,6 +835,7 @@ struct EncodeIndex { chffrAndroidH264 @3; # acamera fullLosslessClip @4; # prcamera.mkv front @5; # dcamera.hevc + qcameraH264 @6; # qcamera.ts } } @@ -873,6 +907,7 @@ struct LongitudinalPlan @0xe00b5b3eba12876c { } struct LateralPlan @0xe1e9318e2ae8b51e { + modelMonoTime @31 :UInt64; laneWidth @0 :Float32; lProb @5 :Float32; rProb @7 :Float32; @@ -1041,6 +1076,49 @@ struct ProcLog { } } +struct GnssMeasurements { + ubloxMonoTime @0 :UInt64; + correctedMeasurements @1 :List(CorrectedMeasurement); + + positionECEF @2 :Measurement; + velocityECEF @3 :Measurement; + # todo add accuracy of position? + # Represents heading in degrees. + bearingDeg @4 :Measurement; + # Todo sync this with timing pulse of ublox + + struct CorrectedMeasurement { + constellationId @0 :ConstellationId; + svId @1 :UInt8; + # Is 0 when not Glonass constellation. + glonassFrequency @2 :Int8; + pseudorange @3 :Float64; + pseudorangeStd @4 :Float64; + pseudorangeRate @5 :Float64; + pseudorangeRateStd @6 :Float64; + # Satellite position and velocity [x,y,z] + satPos @7 :List(Float64); + satVel @8 :List(Float64); + } + + enum ConstellationId { + # Satellite Constellation using the Ublox gnssid as index + gps @0; + sbas @1; + galileo @2; + beidou @3; + imes @4; + qznss @5; + glonass @6; + } + + struct Measurement { + value @0 : List(Float64); + std @1 : Float64; + valid @2 : Bool; + } +} + struct UbloxGnss { union { measurementReport @0 :MeasurementReport; @@ -1214,6 +1292,297 @@ struct UbloxGnss { } } +struct QcomGnss @0xde94674b07ae51c1 { + logTs @0 :UInt64; + union { + measurementReport @1 :MeasurementReport; + clockReport @2 :ClockReport; + drMeasurementReport @3 :DrMeasurementReport; + drSvPoly @4 :DrSvPolyReport; + rawLog @5 :Data; + } + + enum MeasurementSource @0xd71a12b6faada7ee { + gps @0; + glonass @1; + beidou @2; + unknown3 @3; + unknown4 @4; + unknown5 @5; + unknown6 @6; + } + + enum SVObservationState @0xe81e829a0d6c83e9 { + idle @0; + search @1; + searchVerify @2; + bitEdge @3; + trackVerify @4; + track @5; + restart @6; + dpo @7; + glo10msBe @8; + glo10msAt @9; + } + + struct MeasurementStatus @0xe501010e1bcae83b { + subMillisecondIsValid @0 :Bool; + subBitTimeIsKnown @1 :Bool; + satelliteTimeIsKnown @2 :Bool; + bitEdgeConfirmedFromSignal @3 :Bool; + measuredVelocity @4 :Bool; + fineOrCoarseVelocity @5 :Bool; + lockPointValid @6 :Bool; + lockPointPositive @7 :Bool; + lastUpdateFromDifference @8 :Bool; + lastUpdateFromVelocityDifference @9 :Bool; + strongIndicationOfCrossCorelation @10 :Bool; + tentativeMeasurement @11 :Bool; + measurementNotUsable @12 :Bool; + sirCheckIsNeeded @13 :Bool; + probationMode @14 :Bool; + + glonassMeanderBitEdgeValid @15 :Bool; + glonassTimeMarkValid @16 :Bool; + + gpsRoundRobinRxDiversity @17 :Bool; + gpsRxDiversity @18 :Bool; + gpsLowBandwidthRxDiversityCombined @19 :Bool; + gpsHighBandwidthNu4 @20 :Bool; + gpsHighBandwidthNu8 @21 :Bool; + gpsHighBandwidthUniform @22 :Bool; + multipathIndicator @23 :Bool; + + imdJammingIndicator @24 :Bool; + lteB13TxJammingIndicator @25 :Bool; + freshMeasurementIndicator @26 :Bool; + + multipathEstimateIsValid @27 :Bool; + directionIsValid @28 :Bool; + } + + struct MeasurementReport @0xf580d7d86b7b8692 { + source @0 :MeasurementSource; + + fCount @1 :UInt32; + + gpsWeek @2 :UInt16; + glonassCycleNumber @3 :UInt8; + glonassNumberOfDays @4 :UInt16; + + milliseconds @5 :UInt32; + timeBias @6 :Float32; + clockTimeUncertainty @7 :Float32; + clockFrequencyBias @8 :Float32; + clockFrequencyUncertainty @9 :Float32; + + sv @10 :List(SV); + + struct SV @0xf10c595ae7bb2c27 { + svId @0 :UInt8; + observationState @2 :SVObservationState; + observations @3 :UInt8; + goodObservations @4 :UInt8; + gpsParityErrorCount @5 :UInt16; + glonassFrequencyIndex @1 :Int8; + glonassHemmingErrorCount @6 :UInt8; + filterStages @7 :UInt8; + carrierNoise @8 :UInt16; + latency @9 :Int16; + predetectInterval @10 :UInt8; + postdetections @11 :UInt16; + + unfilteredMeasurementIntegral @12 :UInt32; + unfilteredMeasurementFraction @13 :Float32; + unfilteredTimeUncertainty @14 :Float32; + unfilteredSpeed @15 :Float32; + unfilteredSpeedUncertainty @16 :Float32; + measurementStatus @17 :MeasurementStatus; + multipathEstimate @18 :UInt32; + azimuth @19 :Float32; + elevation @20 :Float32; + carrierPhaseCyclesIntegral @21 :Int32; + carrierPhaseCyclesFraction @22 :UInt16; + fineSpeed @23 :Float32; + fineSpeedUncertainty @24 :Float32; + cycleSlipCount @25 :UInt8; + } + + } + + struct ClockReport @0xca965e4add8f4f0b { + hasFCount @0 :Bool; + fCount @1 :UInt32; + + hasGpsWeek @2 :Bool; + gpsWeek @3 :UInt16; + hasGpsMilliseconds @4 :Bool; + gpsMilliseconds @5 :UInt32; + gpsTimeBias @6 :Float32; + gpsClockTimeUncertainty @7 :Float32; + gpsClockSource @8 :UInt8; + + hasGlonassYear @9 :Bool; + glonassYear @10 :UInt8; + hasGlonassDay @11 :Bool; + glonassDay @12 :UInt16; + hasGlonassMilliseconds @13 :Bool; + glonassMilliseconds @14 :UInt32; + glonassTimeBias @15 :Float32; + glonassClockTimeUncertainty @16 :Float32; + glonassClockSource @17 :UInt8; + + bdsWeek @18 :UInt16; + bdsMilliseconds @19 :UInt32; + bdsTimeBias @20 :Float32; + bdsClockTimeUncertainty @21 :Float32; + bdsClockSource @22 :UInt8; + + galWeek @23 :UInt16; + galMilliseconds @24 :UInt32; + galTimeBias @25 :Float32; + galClockTimeUncertainty @26 :Float32; + galClockSource @27 :UInt8; + + clockFrequencyBias @28 :Float32; + clockFrequencyUncertainty @29 :Float32; + frequencySource @30 :UInt8; + gpsLeapSeconds @31 :UInt8; + gpsLeapSecondsUncertainty @32 :UInt8; + gpsLeapSecondsSource @33 :UInt8; + + gpsToGlonassTimeBiasMilliseconds @34 :Float32; + gpsToGlonassTimeBiasMillisecondsUncertainty @35 :Float32; + gpsToBdsTimeBiasMilliseconds @36 :Float32; + gpsToBdsTimeBiasMillisecondsUncertainty @37 :Float32; + bdsToGloTimeBiasMilliseconds @38 :Float32; + bdsToGloTimeBiasMillisecondsUncertainty @39 :Float32; + gpsToGalTimeBiasMilliseconds @40 :Float32; + gpsToGalTimeBiasMillisecondsUncertainty @41 :Float32; + galToGloTimeBiasMilliseconds @42 :Float32; + galToGloTimeBiasMillisecondsUncertainty @43 :Float32; + galToBdsTimeBiasMilliseconds @44 :Float32; + galToBdsTimeBiasMillisecondsUncertainty @45 :Float32; + + hasRtcTime @46 :Bool; + systemRtcTime @47 :UInt32; + fCountOffset @48 :UInt32; + lpmRtcCount @49 :UInt32; + clockResets @50 :UInt32; + } + + struct DrMeasurementReport @0x8053c39445c6c75c { + + reason @0 :UInt8; + seqNum @1 :UInt8; + seqMax @2 :UInt8; + rfLoss @3 :UInt16; + + systemRtcValid @4 :Bool; + fCount @5 :UInt32; + clockResets @6 :UInt32; + systemRtcTime @7 :UInt64; + + gpsLeapSeconds @8 :UInt8; + gpsLeapSecondsUncertainty @9 :UInt8; + gpsToGlonassTimeBiasMilliseconds @10 :Float32; + gpsToGlonassTimeBiasMillisecondsUncertainty @11 :Float32; + + gpsWeek @12 :UInt16; + gpsMilliseconds @13 :UInt32; + gpsTimeBiasMs @14 :UInt32; + gpsClockTimeUncertaintyMs @15 :UInt32; + gpsClockSource @16 :UInt8; + + glonassClockSource @17 :UInt8; + glonassYear @18 :UInt8; + glonassDay @19 :UInt16; + glonassMilliseconds @20 :UInt32; + glonassTimeBias @21 :Float32; + glonassClockTimeUncertainty @22 :Float32; + + clockFrequencyBias @23 :Float32; + clockFrequencyUncertainty @24 :Float32; + frequencySource @25 :UInt8; + + source @26 :MeasurementSource; + + sv @27 :List(SV); + + struct SV @0xf08b81df8cbf459c { + svId @0 :UInt8; + glonassFrequencyIndex @1 :Int8; + observationState @2 :SVObservationState; + observations @3 :UInt8; + goodObservations @4 :UInt8; + filterStages @5 :UInt8; + predetectInterval @6 :UInt8; + cycleSlipCount @7 :UInt8; + postdetections @8 :UInt16; + + measurementStatus @9 :MeasurementStatus; + + carrierNoise @10 :UInt16; + rfLoss @11 :UInt16; + latency @12 :Int16; + + filteredMeasurementFraction @13 :Float32; + filteredMeasurementIntegral @14 :UInt32; + filteredTimeUncertainty @15 :Float32; + filteredSpeed @16 :Float32; + filteredSpeedUncertainty @17 :Float32; + + unfilteredMeasurementFraction @18 :Float32; + unfilteredMeasurementIntegral @19 :UInt32; + unfilteredTimeUncertainty @20 :Float32; + unfilteredSpeed @21 :Float32; + unfilteredSpeedUncertainty @22 :Float32; + + multipathEstimate @23 :UInt32; + azimuth @24 :Float32; + elevation @25 :Float32; + dopplerAcceleration @26 :Float32; + fineSpeed @27 :Float32; + fineSpeedUncertainty @28 :Float32; + + carrierPhase @29 :Float64; + fCount @30 :UInt32; + + parityErrorCount @31 :UInt16; + goodParity @32 :Bool; + } + } + + struct DrSvPolyReport @0xb1fb80811a673270 { + svId @0 :UInt16; + frequencyIndex @1 :Int8; + + hasPosition @2 :Bool; + hasIono @3 :Bool; + hasTropo @4 :Bool; + hasElevation @5 :Bool; + polyFromXtra @6 :Bool; + hasSbasIono @7 :Bool; + + iode @8 :UInt16; + t0 @9 :Float64; + xyz0 @10 :List(Float64); + xyzN @11 :List(Float64); + other @12 :List(Float32); + + positionUncertainty @13 :Float32; + ionoDelay @14 :Float32; + ionoDot @15 :Float32; + sbasIonoDelay @16 :Float32; + sbasIonoDot @17 :Float32; + tropoDelay @18 :Float32; + elevation @19 :Float32; + elevationDot @20 :Float32; + elevationUncertainty @21 :Float32; + velocityCoeff @22 :List(Float64); + } +} + struct Clocks { bootTimeNanos @0 :UInt64; monotonicNanos @1 :UInt64; @@ -1276,6 +1645,9 @@ struct DriverState { phoneUse @22 :Float32; occludedProb @23 :Float32; + readyProb @24 :List(Float32); + notReadyProb @25 :List(Float32); + irPwrDEPRECATED @10 :Float32; descriptorDEPRECATED @1 :List(Float32); stdDEPRECATED @2 :Float32; @@ -1285,6 +1657,7 @@ struct DriverMonitoringState @0xb83cda094a1da284 { events @0 :List(Car.CarEvent); faceDetected @1 :Bool; isDistracted @2 :Bool; + distractedType @17 :UInt32; awarenessStatus @3 :Float32; posePitchOffset @6 :Float32; posePitchValidCount @7 :UInt32; @@ -1432,6 +1805,13 @@ struct NavRoute { } } +struct EncodeData { + idx @0 :EncodeIndex; + data @1 :Data; + header @2 :Data; + unixTimestampNanos @3 :UInt64; +} + struct Event { logMonoTime @0 :UInt64; # nanoseconds valid @67 :Bool = true; @@ -1461,7 +1841,9 @@ struct Event { lateralPlan @64 :LateralPlan; ubloxGnss @34 :UbloxGnss; ubloxRaw @39 :Data; + qcomGnss @31 :QcomGnss; gpsLocationExternal @48 :GpsLocationData; + gnssMeasurements @91 :GnssMeasurements; driverState @59 :DriverState; liveParameters @61 :LiveParametersData; cameraOdometry @63 :CameraOdometry; @@ -1479,6 +1861,7 @@ struct Event { roadEncodeIdx @15 :EncodeIndex; driverEncodeIdx @76 :EncodeIndex; wideRoadEncodeIdx @77 :EncodeIndex; + qRoadEncodeIdx @90 :EncodeIndex; # systems stuff androidLog @20 :AndroidLogEntry; @@ -1497,6 +1880,10 @@ struct Event { # *********** debug *********** testJoystick @52 :Joystick; + roadEncodeData @86 :EncodeData; + driverEncodeData @87 :EncodeData; + wideRoadEncodeData @88 :EncodeData; + qRoadEncodeData @89 :EncodeData; # *********** legacy + deprecated *********** model @9 :Legacy.ModelData; # TODO: rename modelV2 and mark this as deprecated @@ -1517,7 +1904,6 @@ struct Event { gpsPlannerPlanDEPRECATED @41 :Legacy.GPSPlannerPlan; applanixRawDEPRECATED @42 :Data; androidGnssDEPRECATED @30 :Legacy.AndroidGnss; - qcomGnssDEPRECATD @31 :Legacy.QcomGnss; lidarPtsDEPRECATED @32 :Legacy.LidarPts; navStatusDEPRECATED @38 :Legacy.NavStatus; trafficEventsDEPRECATED @43 :List(Legacy.TrafficEvent); diff --git a/cereal/logger/logger.h b/cereal/logger/logger.h index e21509352..03336f8ff 100644 --- a/cereal/logger/logger.h +++ b/cereal/logger/logger.h @@ -1,7 +1,8 @@ #pragma once #ifdef SWAGLOG -#include "selfdrive/common/swaglog.h" +// cppcheck-suppress preprocessorErrorDirective +#include SWAGLOG #else #define CLOUDLOG_DEBUG 10 diff --git a/cereal/messaging/__init__.py b/cereal/messaging/__init__.py index 0440104eb..c695769e6 100644 --- a/cereal/messaging/__init__.py +++ b/cereal/messaging/__init__.py @@ -94,7 +94,7 @@ def drain_sock(sock: SubSocket, wait_for_one: bool = False) -> List[capnp.lib.ca # TODO: print when we drop packets? -def recv_sock(sock: SubSocket, wait: bool = False) -> Union[None, capnp.lib.capnp._DynamicStructReader]: +def recv_sock(sock: SubSocket, wait: bool = False) -> Optional[capnp.lib.capnp._DynamicStructReader]: """Same as drain sock, but only returns latest message. Consider using conflate instead.""" dat = None @@ -114,13 +114,13 @@ def recv_sock(sock: SubSocket, wait: bool = False) -> Union[None, capnp.lib.capn return dat -def recv_one(sock: SubSocket) -> Union[None, capnp.lib.capnp._DynamicStructReader]: +def recv_one(sock: SubSocket) -> Optional[capnp.lib.capnp._DynamicStructReader]: dat = sock.receive() if dat is not None: dat = log_from_bytes(dat) return dat -def recv_one_or_none(sock: SubSocket) -> Union[None, capnp.lib.capnp._DynamicStructReader]: +def recv_one_or_none(sock: SubSocket) -> Optional[capnp.lib.capnp._DynamicStructReader]: dat = sock.receive(non_blocking=True) if dat is not None: dat = log_from_bytes(dat) @@ -133,7 +133,7 @@ def recv_one_retry(sock: SubSocket) -> capnp.lib.capnp._DynamicStructReader: if dat is not None: return log_from_bytes(dat) -class SubMaster(): +class SubMaster: def __init__(self, services: List[str], poll: Optional[List[str]] = None, ignore_alive: Optional[List[str]] = None, ignore_avg_freq: Optional[List[str]] = None, addr: str = "127.0.0.1"): @@ -142,6 +142,7 @@ class SubMaster(): self.rcv_time = {s: 0. for s in services} self.rcv_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 = {s: deque([0.0] * AVG_FREQ_HISTORY, maxlen=AVG_FREQ_HISTORY) for s in services} self.sock = {} self.freq = {} @@ -205,6 +206,7 @@ class SubMaster(): self.valid[s] = msg.valid if SIMULATION: + self.freq_ok[s] = True self.alive[s] = True if not SIMULATION: @@ -214,11 +216,13 @@ class SubMaster(): # alive if delay is within 10x the expected frequency self.alive[s] = (cur_time - self.rcv_time[s]) < (10. / self.freq[s]) - # alive if average frequency is higher than 90% of expected frequency + # TODO: check if update frequency is high enough to not drop messages + # freq_ok if average frequency is higher than 90% of expected frequency avg_dt = sum(self.recv_dts[s]) / AVG_FREQ_HISTORY expected_dt = 1 / (self.freq[s] * 0.90) - self.alive[s] = self.alive[s] and (avg_dt < expected_dt) + self.freq_ok[s] = (avg_dt < expected_dt) else: + self.freq_ok[s] = True self.alive[s] = True def all_alive(self, service_list=None) -> bool: @@ -226,17 +230,24 @@ class SubMaster(): service_list = self.alive.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_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_alive_and_valid(self, service_list=None) -> bool: + 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_valid(service_list=service_list) + 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) -class PubMaster(): +class PubMaster: def __init__(self, services: List[str]): self.sock = {} for s in services: @@ -248,4 +259,4 @@ class PubMaster(): self.sock[s].send(dat) def all_readers_updated(self, s: str) -> bool: - return self.sock[s].all_readers_updated() + return self.sock[s].all_readers_updated() # type: ignore diff --git a/cereal/messaging/bridge.cc b/cereal/messaging/bridge.cc index d4bdfcea7..844f6d10e 100644 --- a/cereal/messaging/bridge.cc +++ b/cereal/messaging/bridge.cc @@ -11,6 +11,11 @@ typedef void (*sighandler_t)(int sig); #include "impl_zmq.h" #include "services.h" +std::atomic do_exit = false; +static void set_do_exit(int sig) { + do_exit = true; +} + void sigpipe_handler(int sig) { assert(sig == SIGPIPE); std::cout << "SIGPIPE received" << std::endl; @@ -31,6 +36,8 @@ static std::vector get_services(std::string whitelist_str, bool zmq int main(int argc, char** argv) { signal(SIGPIPE, (sighandler_t)sigpipe_handler); + signal(SIGINT, (sighandler_t)set_do_exit); + signal(SIGTERM, (sighandler_t)set_do_exit); bool zmq_to_msgq = argc > 2; std::string ip = zmq_to_msgq ? argv[1] : "127.0.0.1"; @@ -67,11 +74,13 @@ int main(int argc, char** argv) { sub2pub[sub_sock] = pub_sock; } - while (true) { + while (!do_exit) { for (auto sub_sock : poller->poll(100)) { Message * msg = sub_sock->receive(); if (msg == NULL) continue; - sub2pub[sub_sock]->sendMessage(msg); + int ret; + do { ret = sub2pub[sub_sock]->sendMessage(msg); } while (ret == -1 && errno == EINTR); + assert(ret >= 0); delete msg; } } diff --git a/cereal/messaging/messaging.cc b/cereal/messaging/messaging.cc index bfa634e61..69c0e80c2 100644 --- a/cereal/messaging/messaging.cc +++ b/cereal/messaging/messaging.cc @@ -1,3 +1,6 @@ +#include +#include + #include "messaging.h" #include "impl_zmq.h" #include "impl_msgq.h" @@ -9,7 +12,14 @@ const bool MUST_USE_ZMQ = false; #endif bool messaging_use_zmq(){ - return std::getenv("ZMQ") || MUST_USE_ZMQ; + if (std::getenv("ZMQ") || MUST_USE_ZMQ) { + if (std::getenv("OPENPILOT_PREFIX")) { + std::cerr << "OPENPILOT_PREFIX not supported with ZMQ backend\n"; + assert(false); + } + return true; + } + return false; } Context * Context::create(){ diff --git a/cereal/messaging/messaging.h b/cereal/messaging/messaging.h index 4a184ff70..51ddb7af2 100644 --- a/cereal/messaging/messaging.h +++ b/cereal/messaging/messaging.h @@ -66,7 +66,7 @@ public: class SubMaster { public: - SubMaster(const std::vector &service_list, + SubMaster(const std::vector &service_list, const std::vector &poll = {}, const char *address = nullptr, const std::vector &ignore_alive = {}); void update(int timeout = 1000); void update_msgs(uint64_t current_time, const std::vector> &messages); diff --git a/cereal/messaging/msgq.cc b/cereal/messaging/msgq.cc index cabf8aaba..f527a5656 100644 --- a/cereal/messaging/msgq.cc +++ b/cereal/messaging/msgq.cc @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -81,23 +82,22 @@ void msgq_wait_for_subscriber(msgq_queue_t *q){ return; } - int msgq_new_queue(msgq_queue_t * q, const char * path, size_t size){ assert(size < 0xFFFFFFFF); // Buffer must be smaller than 2^32 bytes std::signal(SIGUSR2, sigusr2_handler); - const char * prefix = "/dev/shm/"; - char * full_path = new char[strlen(path) + strlen(prefix) + 1]; - strcpy(full_path, prefix); - strcat(full_path, path); + std::string full_path = "/dev/shm/"; + const char* prefix = std::getenv("OPENPILOT_PREFIX"); + if (prefix) { + full_path += std::string(prefix) + "/"; + } + full_path += path; - auto fd = open(full_path, O_RDWR | O_CREAT, 0664); + auto fd = open(full_path.c_str(), O_RDWR | O_CREAT, 0664); if (fd < 0) { std::cout << "Warning, could not open: " << full_path << std::endl; - delete[] full_path; return -1; } - delete[] full_path; int rc = ftruncate(fd, size + sizeof(msgq_header_t)); if (rc < 0){ @@ -179,7 +179,7 @@ void msgq_init_subscriber(msgq_queue_t * q) { // No more slots available. Reset all subscribers to kick out inactive ones if (new_num_readers > NUM_READERS){ - std::cout << "Warning, evicting all subscribers!" << std::endl; + //std::cout << "Warning, evicting all subscribers!" << std::endl; *q->num_readers = 0; for (size_t i = 0; i < NUM_READERS; i++){ @@ -307,7 +307,7 @@ int msgq_msg_ready(msgq_queue_t * q){ assert(id >= 0); // Make sure subscriber is initialized if (q->read_uid_local != *q->read_uids[id]){ - std::cout << q->endpoint << ": Reader was evicted, reconnecting" << std::endl; + //std::cout << q->endpoint << ": Reader was evicted, reconnecting" << std::endl; msgq_init_subscriber(q); goto start; } @@ -334,7 +334,7 @@ int msgq_msg_recv(msgq_msg_t * msg, msgq_queue_t * q){ assert(id >= 0); // Make sure subscriber is initialized if (q->read_uid_local != *q->read_uids[id]){ - std::cout << q->endpoint << ": Reader was evicted, reconnecting" << std::endl; + //std::cout << q->endpoint << ": Reader was evicted, reconnecting" << std::endl; msgq_init_subscriber(q); goto start; } diff --git a/cereal/messaging/socketmaster.cc b/cereal/messaging/socketmaster.cc index 56698dc2e..2066559dd 100644 --- a/cereal/messaging/socketmaster.cc +++ b/cereal/messaging/socketmaster.cc @@ -51,26 +51,29 @@ struct SubMaster::SubMessage { bool updated = false, alive = false, valid = true, ignore_alive; uint64_t rcv_time = 0, rcv_frame = 0; void *allocated_msg_reader = nullptr; + bool is_polled = false; capnp::FlatArrayMessageReader *msg_reader = nullptr; AlignedBuffer aligned_buf; cereal::Event::Reader event; }; -SubMaster::SubMaster(const std::vector &service_list, const char *address, - const std::vector &ignore_alive) { +SubMaster::SubMaster(const std::vector &service_list, const std::vector &poll, + const char *address, const std::vector &ignore_alive) { poller_ = Poller::create(); for (auto name : service_list) { const service *serv = get_service(name); assert(serv != nullptr); SubSocket *socket = SubSocket::create(message_context.context(), name, address ? address : "127.0.0.1", true); assert(socket != 0); - poller_->registerSocket(socket); + bool is_polled = inList(poll, name) || poll.empty(); + if (is_polled) poller_->registerSocket(socket); SubMessage *m = new SubMessage{ .name = name, .socket = socket, .freq = serv->frequency, .ignore_alive = inList(ignore_alive, name), - .allocated_msg_reader = malloc(sizeof(capnp::FlatArrayMessageReader))}; + .allocated_msg_reader = malloc(sizeof(capnp::FlatArrayMessageReader)), + .is_polled = is_polled}; m->msg_reader = new (m->allocated_msg_reader) capnp::FlatArrayMessageReader({}); messages_[socket] = m; services_[name] = m; @@ -81,6 +84,14 @@ void SubMaster::update(int timeout) { for (auto &kv : messages_) kv.second->updated = false; auto sockets = poller_->poll(timeout); + + // add non-polled sockets for non-blocking receive + for (auto &kv : messages_) { + SubMessage *m = kv.second; + SubSocket *s = kv.first; + if (!m->is_polled) sockets.push_back(s); + } + uint64_t current_time = nanos_since_boot(); std::vector> messages; diff --git a/cereal/services.py b/cereal/services.py index c8fc3d5cc..f895d883d 100755 --- a/cereal/services.py +++ b/cereal/services.py @@ -23,6 +23,7 @@ DCAM_FREQ = 10. if not TICI else 20. services = { # service: (should_log, frequency, qlog decimation (optional)) + # note: the "EncodeIdx" packets will still be in the log "sensorEvents": (True, 100., 100), "gpsNMEA": (True, 9.), "deviceState": (True, 2., 1), @@ -31,7 +32,7 @@ services = { "pandaStates": (True, 2., 1), "peripheralState": (True, 2., 1), "radarState": (True, 20., 5), - "roadEncodeIdx": (True, 20., 1), + "roadEncodeIdx": (False, 20., 1), "liveTracks": (True, 20.), "sendcan": (True, 100., 139), "logMessage": (True, 0.), @@ -44,6 +45,8 @@ services = { "procLog": (True, 0.5), "gpsLocationExternal": (True, 10., 10), "ubloxGnss": (True, 10.), + "qcomGnss": (True, 2.), + "gnssMeasurements": (True, 10.), "clocks": (True, 1., 1), "ubloxRaw": (True, 20.), "liveLocationKalman": (True, 20., 5), @@ -55,20 +58,25 @@ services = { "carParams": (True, 0.02, 1), "roadCameraState": (True, 20., 20), "driverCameraState": (True, DCAM_FREQ, DCAM_FREQ), - "driverEncodeIdx": (True, DCAM_FREQ, 1), + "driverEncodeIdx": (False, DCAM_FREQ, 1), "driverState": (True, DCAM_FREQ, DCAM_FREQ / 2), "driverMonitoringState": (True, DCAM_FREQ, DCAM_FREQ / 2), - "wideRoadEncodeIdx": (True, 20., 1), + "wideRoadEncodeIdx": (False, 20., 1), "wideRoadCameraState": (True, 20., 20), "modelV2": (True, 20., 40), "managerState": (True, 2., 1), "uploaderState": (True, 0., 1), - "navInstruction": (True, 0.), + "navInstruction": (True, 0., 10), "navRoute": (True, 0.), "navThumbnail": (True, 0.), + "qRoadEncodeIdx": (False, 20.), # debug - "testJoystick": (False, 0.), + "testJoystick": (True, 0.), + "roadEncodeData": (False, 20.), + "driverEncodeData": (False, DCAM_FREQ), + "wideRoadEncodeData": (False, 20.), + "qRoadEncodeData": (False, 20.), } service_list = {name: Service(new_port(idx), *vals) for # type: ignore idx, (name, vals) in enumerate(services.items())} diff --git a/cereal/visionipc/visionbuf.cc b/cereal/visionipc/visionbuf.cc index e94a8bbc0..276b4fb4f 100644 --- a/cereal/visionipc/visionbuf.cc +++ b/cereal/visionipc/visionbuf.cc @@ -2,24 +2,9 @@ #define ALIGN(x, align) (((x) + (align)-1) & ~((align)-1)) -#ifdef QCOM -// from libadreno_utils.so -extern "C" void compute_aligned_width_and_height(int width, - int height, - int bpp, - int tile_mode, - int raster_mode, - int padding_threshold, - int *aligned_w, - int *aligned_h); -#endif - void visionbuf_compute_aligned_width_and_height(int width, int height, int *aligned_w, int *aligned_h) { -#ifdef QCOM - compute_aligned_width_and_height(ALIGN(width, 32), ALIGN(height, 32), 3, 0, 0, 512, aligned_w, aligned_h); -#else - *aligned_w = width; *aligned_h = height; -#endif + *aligned_w = width; + *aligned_h = height; } void VisionBuf::init_rgb(size_t init_width, size_t init_height, size_t init_stride) { diff --git a/cereal/visionipc/visionbuf.h b/cereal/visionipc/visionbuf.h index b27a08b26..864fac97d 100644 --- a/cereal/visionipc/visionbuf.h +++ b/cereal/visionipc/visionbuf.h @@ -12,12 +12,14 @@ #define VISIONBUF_SYNC_TO_DEVICE 1 enum VisionStreamType { - VISION_STREAM_RGB_BACK, - VISION_STREAM_RGB_FRONT, - VISION_STREAM_RGB_WIDE, + VISION_STREAM_RGB_ROAD, + VISION_STREAM_RGB_DRIVER, + VISION_STREAM_RGB_WIDE_ROAD, + VISION_STREAM_ROAD, VISION_STREAM_DRIVER, VISION_STREAM_WIDE_ROAD, + VISION_STREAM_RGB_MAP, VISION_STREAM_MAX, }; diff --git a/cereal/visionipc/visionipc.pxd b/cereal/visionipc/visionipc.pxd index 5cb729f7e..db45aee80 100644 --- a/cereal/visionipc/visionipc.pxd +++ b/cereal/visionipc/visionipc.pxd @@ -16,6 +16,7 @@ cdef extern from "visionbuf.h": size_t width size_t height size_t stride + void set_frame_id(uint64_t id) cdef extern from "visionipc.h": struct VisionIpcBufExtra: diff --git a/cereal/visionipc/visionipc_pyx.pyx b/cereal/visionipc/visionipc_pyx.pyx index 3168f1e66..9db6e1f7b 100644 --- a/cereal/visionipc/visionipc_pyx.pyx +++ b/cereal/visionipc/visionipc_pyx.pyx @@ -16,12 +16,13 @@ from .visionipc cimport VisionBuf as cppVisionBuf from .visionipc cimport VisionIpcBufExtra cpdef enum VisionStreamType: - VISION_STREAM_RGB_BACK - VISION_STREAM_RGB_FRONT - VISION_STREAM_RGB_WIDE + VISION_STREAM_RGB_ROAD + VISION_STREAM_RGB_DRIVER + VISION_STREAM_RGB_WIDE_ROAD VISION_STREAM_ROAD VISION_STREAM_DRIVER VISION_STREAM_WIDE_ROAD + VISION_STREAM_RGB_MAP cdef class VisionIpcServer: @@ -33,12 +34,13 @@ cdef class VisionIpcServer: def create_buffers(self, VisionStreamType tp, size_t num_buffers, bool rgb, size_t width, size_t height): self.server.create_buffers(tp, num_buffers, rgb, width, height) - def send(self, VisionStreamType tp, bytes data, uint32_t frame_id=0, uint64_t timestamp_sof=0, uint64_t timestamp_eof=0): + def send(self, VisionStreamType tp, const unsigned char[:] data, uint32_t frame_id=0, uint64_t timestamp_sof=0, uint64_t timestamp_eof=0): cdef cppVisionBuf * buf = self.server.get_buffer(tp) # Populate buffer assert buf.len == len(data) - memcpy(buf.addr, data, len(data)) + memcpy(buf.addr, &data[0], len(data)) + buf.set_frame_id(frame_id) cdef VisionIpcBufExtra extra extra.frame_id = frame_id diff --git a/cereal/visionipc/visionipc_server.cc b/cereal/visionipc/visionipc_server.cc index e15c1aee4..aa424709c 100644 --- a/cereal/visionipc/visionipc_server.cc +++ b/cereal/visionipc/visionipc_server.cc @@ -14,7 +14,7 @@ std::string get_endpoint_name(std::string name, VisionStreamType type){ if (messaging_use_zmq()){ - assert(name == "camerad"); + assert(name == "camerad" || name == "navd"); return std::to_string(9000 + static_cast(type)); } else { return "visionipc_" + name + "_" + std::to_string(type); diff --git a/cereal/visionipc/visionipc_tests.cc b/cereal/visionipc/visionipc_tests.cc index 4d1df05f5..811cc69d8 100644 --- a/cereal/visionipc/visionipc_tests.cc +++ b/cereal/visionipc/visionipc_tests.cc @@ -40,11 +40,11 @@ TEST_CASE("Check buffers"){ TEST_CASE("Check yuv/rgb"){ VisionIpcServer server("camerad"); server.create_buffers(VISION_STREAM_ROAD, 1, false, 100, 100); - server.create_buffers(VISION_STREAM_RGB_BACK, 1, true, 100, 100); + server.create_buffers(VISION_STREAM_RGB_ROAD, 1, true, 100, 100); server.start_listener(); VisionIpcClient client_yuv = VisionIpcClient("camerad", VISION_STREAM_ROAD, false); - VisionIpcClient client_rgb = VisionIpcClient("camerad", VISION_STREAM_RGB_BACK, false); + VisionIpcClient client_rgb = VisionIpcClient("camerad", VISION_STREAM_RGB_ROAD, false); client_yuv.connect(); client_rgb.connect(); diff --git a/common/SConscript b/common/SConscript index a41fc8b7e..ebc0ec79e 100644 --- a/common/SConscript +++ b/common/SConscript @@ -1,4 +1,34 @@ -Import('envCython', 'common') +Import('env', 'envCython', 'arch', 'SHARED') +if SHARED: + fxn = env.SharedLibrary +else: + fxn = env.Library + +common_libs = [ + 'params.cc', + 'statlog.cc', + 'swaglog.cc', + 'util.cc', + 'gpio.cc', + 'i2c.cc', + 'watchdog.cc', +] + +_common = fxn('common', common_libs, LIBS="json11") + +files = [ + 'clutil.cc', + 'visionimg.cc', +] + +_gpucommon = fxn('gpucommon', files) +Export('_common', '_gpucommon') + +if GetOption('test'): + env.Program('tests/test_util', ['tests/test_util.cc'], LIBS=[_common]) + env.Program('tests/test_swaglog', ['tests/test_swaglog.cc'], LIBS=[_common, 'json11', 'zmq', 'pthread']) + +# Cython envCython.Program('clock.so', 'clock.pyx') -envCython.Program('params_pyx.so', 'params_pyx.pyx', LIBS=envCython['LIBS'] + [common, 'zmq']) +envCython.Program('params_pyx.so', 'params_pyx.pyx', LIBS=envCython['LIBS'] + [_common, 'zmq', 'json11']) diff --git a/selfdrive/common/clutil.cc b/common/clutil.cc similarity index 99% rename from selfdrive/common/clutil.cc rename to common/clutil.cc index 4e952a2a8..b8f9fde4c 100644 --- a/selfdrive/common/clutil.cc +++ b/common/clutil.cc @@ -1,10 +1,10 @@ -#include "selfdrive/common/clutil.h" +#include "common/clutil.h" #include #include #include -#include "selfdrive/common/util.h" +#include "common/util.h" namespace { // helper functions diff --git a/selfdrive/common/clutil.h b/common/clutil.h similarity index 100% rename from selfdrive/common/clutil.h rename to common/clutil.h diff --git a/common/conversions.py b/common/conversions.py new file mode 100644 index 000000000..b02b33c62 --- /dev/null +++ b/common/conversions.py @@ -0,0 +1,19 @@ +import numpy as np + +class Conversions: + # Speed + MPH_TO_KPH = 1.609344 + KPH_TO_MPH = 1. / MPH_TO_KPH + MS_TO_KPH = 3.6 + KPH_TO_MS = 1. / MS_TO_KPH + MS_TO_MPH = MS_TO_KPH * KPH_TO_MPH + MPH_TO_MS = MPH_TO_KPH * KPH_TO_MS + MS_TO_KNOTS = 1.9438 + KNOTS_TO_MS = 1. / MS_TO_KNOTS + + # Angle + DEG_TO_RAD = np.pi / 180. + RAD_TO_DEG = 1. / DEG_TO_RAD + + # Mass + LB_TO_KG = 0.453592 diff --git a/common/file_helpers.py b/common/file_helpers.py index 592b2a199..8a45fa313 100644 --- a/common/file_helpers.py +++ b/common/file_helpers.py @@ -81,25 +81,12 @@ def _get_fileobject_func(writer, temp_dir): return writer.get_fileobject(dir=temp_dir) return _get_fileobject -def monkeypatch_os_link(): - # This is neccesary on EON/C2, where os.link is patched out of python - if not hasattr(os, 'link'): - from cffi import FFI - ffi = FFI() - ffi.cdef("int link(const char *oldpath, const char *newpath);") - libc = ffi.dlopen(None) - - def link(src, dest): - return libc.link(src.encode(), dest.encode()) - os.link = link - 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. - monkeypatch_os_link() writer = AtomicWriter(path, **kwargs) return writer._open(_get_fileobject_func(writer, get_tmpdir_on_same_filesystem(path))) @@ -108,6 +95,5 @@ def atomic_write_in_dir(path, **kwargs): """Creates an atomic writer using a temporary file in the same directory as the destination file. """ - monkeypatch_os_link() writer = AtomicWriter(path, **kwargs) return writer._open(_get_fileobject_func(writer, os.path.dirname(path))) diff --git a/selfdrive/common/gpio.cc b/common/gpio.cc similarity index 92% rename from selfdrive/common/gpio.cc rename to common/gpio.cc index 033d6da4f..73ff1b3f5 100644 --- a/selfdrive/common/gpio.cc +++ b/common/gpio.cc @@ -1,11 +1,11 @@ -#include "selfdrive/common/gpio.h" +#include "common/gpio.h" #include #include #include -#include "selfdrive/common/util.h" +#include "common/util.h" // We assume that all pins have already been exported on boot, // and that we have permission to write to them. diff --git a/selfdrive/common/gpio.h b/common/gpio.h similarity index 100% rename from selfdrive/common/gpio.h rename to common/gpio.h diff --git a/common/gpio.py b/common/gpio.py index cb0322146..32e5ca86c 100644 --- a/common/gpio.py +++ b/common/gpio.py @@ -1,4 +1,4 @@ -def gpio_init(pin, output): +def gpio_init(pin: int, output: bool) -> None: try: with open(f"/sys/class/gpio/gpio{pin}/direction", 'wb') as f: f.write(b"out" if output else b"in") @@ -6,7 +6,7 @@ def gpio_init(pin, output): print(f"Failed to set gpio {pin} direction: {e}") -def gpio_set(pin, high): +def gpio_set(pin: int, high: bool) -> None: try: with open(f"/sys/class/gpio/gpio{pin}/value", 'wb') as f: f.write(b"1" if high else b"0") diff --git a/selfdrive/common/i2c.cc b/common/i2c.cc similarity index 92% rename from selfdrive/common/i2c.cc rename to common/i2c.cc index 5e6488fab..eb10cd64b 100644 --- a/selfdrive/common/i2c.cc +++ b/common/i2c.cc @@ -1,4 +1,4 @@ -#include "selfdrive/common/i2c.h" +#include "common/i2c.h" #include #include @@ -8,9 +8,9 @@ #include #include -#include "selfdrive/common/util.h" -#include "selfdrive/common/swaglog.h" -#include "selfdrive/common/util.h" +#include "common/util.h" +#include "common/swaglog.h" +#include "common/util.h" #define UNUSED(x) (void)(x) diff --git a/selfdrive/common/i2c.h b/common/i2c.h similarity index 100% rename from selfdrive/common/i2c.h rename to common/i2c.h diff --git a/common/kalman/tests/test_simple_kalman.py b/common/kalman/tests/test_simple_kalman.py index 7b327918a..96b252765 100644 --- a/common/kalman/tests/test_simple_kalman.py +++ b/common/kalman/tests/test_simple_kalman.py @@ -36,8 +36,8 @@ class TestSimpleKalman(unittest.TestCase): 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) + x = self.kf.update(100) + self.assertEqual(x, self.kf.x) def test_old_equal_new(self): for _ in range(1000): diff --git a/common/logging_extra.py b/common/logging_extra.py index d3a75d0f4..5baaac1f9 100644 --- a/common/logging_extra.py +++ b/common/logging_extra.py @@ -3,6 +3,7 @@ import os import sys import copy import json +import time import uuid import socket import logging @@ -11,6 +12,8 @@ from threading import local from collections import OrderedDict from contextlib import contextmanager +LOG_TIMESTAMPS = "LOG_TIMESTAMPS" in os.environ + def json_handler(obj): # if isinstance(obj, (datetime.date, datetime.time)): # return obj.isoformat() @@ -163,6 +166,15 @@ class SwagLogger(logging.Logger): else: self.info(evt) + def timestamp(self, event_name): + if LOG_TIMESTAMPS: + t = time.monotonic() + tstp = NiceOrderedDict() + tstp['timestamp'] = NiceOrderedDict() + tstp['timestamp']["event"] = event_name + tstp['timestamp']["time"] = t*1e9 + self.debug(tstp) + def findCaller(self, stack_info=False, stacklevel=1): """ Find the stack frame of the caller so that we can note the source @@ -172,33 +184,33 @@ class SwagLogger(logging.Logger): #On some versions of IronPython, currentframe() returns None if #IronPython isn't run with -X:Frames. if f is not None: - f = f.f_back + f = f.f_back orig_f = f while f and stacklevel > 1: - f = f.f_back - stacklevel -= 1 + f = f.f_back + stacklevel -= 1 if not f: - f = orig_f + f = orig_f rv = "(unknown file)", 0, "(unknown function)", None while hasattr(f, "f_code"): - co = f.f_code - filename = os.path.normcase(co.co_filename) + co = f.f_code + filename = os.path.normcase(co.co_filename) - # TODO: is this pylint exception correct? - if filename == _srcfile: # pylint: disable=comparison-with-callable - f = f.f_back - continue - sinfo = None - if stack_info: - sio = io.StringIO() - sio.write('Stack (most recent call last):\n') - traceback.print_stack(f, file=sio) - sinfo = sio.getvalue() - if sinfo[-1] == '\n': - sinfo = sinfo[:-1] - sio.close() - rv = (co.co_filename, f.f_lineno, co.co_name, sinfo) - break + # TODO: is this pylint exception correct? + if filename == _srcfile: # pylint: disable=comparison-with-callable + f = f.f_back + continue + sinfo = None + if stack_info: + sio = io.StringIO() + sio.write('Stack (most recent call last):\n') + traceback.print_stack(f, file=sio) + sinfo = sio.getvalue() + if sinfo[-1] == '\n': + sinfo = sinfo[:-1] + sio.close() + rv = (co.co_filename, f.f_lineno, co.co_name, sinfo) + break return rv if __name__ == "__main__": diff --git a/common/markdown.py b/common/markdown.py deleted file mode 100755 index 30c5bc2c0..000000000 --- a/common/markdown.py +++ /dev/null @@ -1,48 +0,0 @@ -from typing import List - -HTML_REPLACEMENTS = [ - (r'&', r'&'), - (r'"', r'"'), -] - - -def parse_markdown(text: str, tab_length: int = 2) -> str: - lines = text.split("\n") - output: List[str] = [] - list_level = 0 - - def end_outstanding_lists(level: int, end_level: int) -> int: - while level > end_level: - level -= 1 - output.append("") - if level > 0: - output.append("") - return end_level - - for i, line in enumerate(lines): - if i + 1 < len(lines) and lines[i + 1].startswith("==="): # heading - output.append(f"

{line}

") - elif line.startswith("==="): - pass - elif line.lstrip().startswith("* "): # list - line_level = 1 + line.count(" " * tab_length, 0, line.index("*")) - if list_level >= line_level: - list_level = end_outstanding_lists(list_level, line_level) - else: - list_level += 1 - if list_level > 1: - output[-1] = output[-1].replace("", "") - output.append("