diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000000000..433b370d93d9b1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,25 @@ +--- +name: Bug report +about: Create a report to help us improve openpilot +title: '' +labels: 'bug' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**How to reproduce or log data** +Steps to reproduce the behavior, or a explorer/cabana link to the exact drive and timestamp of when the bug occurred. + +**Expected behavior** +A clear and concise description of what you expected to happen. + +** Device/Version information (please complete the following information):** + - Device: [e.g. EON/EON Gold] + - Version: [e.g. 0.6.4], or commit hash when on devel + - Car make/model [e.g. Toyota Prius 2016] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000000000..72e1845d7e124f --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,21 @@ +Choose one of the templates below: + +# Fingerprint +This pull requests adds a fingerprint for . + +This is an explorer link to a drive with the stock system enabled: ... + +# Car support +This pull requests adds support for . + +This is an explorer link to a drive with the stock system enabled: ... +This is an explorer link to a drive with openpilot system enabled: ... + +# Feature +This pull requests adds feature X + +## Description +Explain what the feature does + +## Testing +Explain how the feature was tested. Either by the added unit tests, or what tests were performed while driving. diff --git a/.gitignore b/.gitignore index 44294dde727e39..5877ee1169af20 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ venv/ .ipynb_checkpoints .idea .sconsign.dblite +.vscode model2.png a.out @@ -30,7 +31,7 @@ selfdrive/logcatd/logcatd selfdrive/mapd/default_speeds_by_region.json selfdrive/proclogd/proclogd selfdrive/ui/ui -selfdrive/test/tests/plant/out +selfdrive/test/longitudinal_maneuvers/out selfdrive/visiond/visiond selfdrive/loggerd/loggerd selfdrive/sensord/gpsd diff --git a/Dockerfile.openpilot b/Dockerfile.openpilot index 6be64c13118aaa..c49bd576b18433 100644 --- a/Dockerfile.openpilot +++ b/Dockerfile.openpilot @@ -6,43 +6,66 @@ RUN apt-get update && apt-get install -y \ build-essential \ bzip2 \ clang \ + cmake \ + curl \ + ffmpeg \ git \ libarchive-dev \ - libavcodec-dev \ - libavdevice-dev \ - libavfilter-dev \ - libavresample-dev \ - libavutil-dev \ + libbz2-dev \ + libcurl4-openssl-dev \ + libeigen3-dev \ libffi-dev \ + libglew-dev \ libglib2.0-0 \ + liblzma-dev \ + libmysqlclient-dev \ + libomp-dev \ + libopencv-dev \ libssl-dev \ - libswscale-dev \ libtool \ libusb-1.0-0 \ libzmq5-dev \ + locales \ ocl-icd-libopencl1 \ ocl-icd-opencl-dev \ opencl-headers \ - pkg-config \ + python-dev \ python-pip \ + screen \ + sudo \ + vim \ wget -COPY phonelibs/install_capnp.sh /tmp/install_capnp.sh -RUN /tmp/install_capnp.sh -RUN pip install --upgrade pip==18.0 +RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 + +RUN curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash + +ENV PATH="/root/.pyenv/bin:/root/.pyenv/shims:${PATH}" +RUN pyenv install 3.7.3 +RUN pyenv global 3.7.3 +RUN pyenv rehash + RUN pip install pipenv==2018.11.26 COPY Pipfile /tmp/ COPY Pipfile.lock /tmp/ -RUN cd /tmp && pipenv install --deploy --system -ENV PYTHONPATH /tmp/openpilot:$PYTHONPATH +RUN python --version +RUN cd /tmp && pipenv install --system --deploy + +# Install subset of dev dependencies needed for CI +RUN pip install matplotlib==3.1.1 dictdiffer==0.8.0 fastcluster==1.1.25 aenum==2.2.1 scipy==1.3.1 lru-dict==1.1.6 tenacity==5.1.1 azure-common==1.1.23 azure-nspkg==3.0.2 azure-storage-blob==2.1.0 azure-storage-common==2.1.0 azure-storage-nspkg==3.1.0 pycurl==7.43.0.3 + +COPY phonelibs/install_capnp.sh /tmp/install_capnp.sh +RUN /tmp/install_capnp.sh -RUN git clone --branch v0.6.2 https://github.com/commaai/openpilot-tools.git /tmp/openpilot/tools -RUN pip install -r /tmp/openpilot/tools/requirements.txt -RUN pip install fastcluster==1.1.20 scipy==0.19.1 dictdiffer==0.8.0 azure-batch==4.1.3 azure-common==1.1.16 azure-nspkg==3.0.0 azure-storage-blob==1.3.1 azure-storage-common==1.3.0 azure-storage-nspkg==3.0.0 +RUN git clone --branch v0.6.5 https://github.com/commaai/openpilot-tools.git /tmp/openpilot/tools +ENV PYTHONPATH /tmp/openpilot:${PYTHONPATH} COPY ./.pylintrc /tmp/openpilot/.pylintrc COPY ./common /tmp/openpilot/common COPY ./cereal /tmp/openpilot/cereal diff --git a/Pipfile b/Pipfile index 7afffb1e940942..4519727b9ae18a 100644 --- a/Pipfile +++ b/Pipfile @@ -4,16 +4,16 @@ url = "https://pypi.org/simple" verify_ssl = true [dev-packages] -ipython = "<6.0" -aenum = "*" -azure-batch = "==4.1.3" -azure-common = "==1.1.16" -azure-nspkg = "==3.0.1" -azure-storage-blob = "==1.3.1" -azure-storage-common = "==1.3.0" -azure-storage-nspkg = "==3.0.0" +opencv-python= "==3.4.2.17" +PyQt5 = "*" +ipython = "*" +azure-common = "*" +azure-nspkg = "*" +azure-storage-blob = "*" +azure-storage-common = "*" +azure-storage-nspkg = "*" bincopy = "*" -bleach = "==1.5.0" +bleach = "*" boto = "*" "boto3" = "*" celery = "*" @@ -23,7 +23,6 @@ decorator = "*" dlib = "*" dominate = "*" elasticsearch = "*" -entium = "==0.1.4" fasteners = "*" future = "*" futures = "*" @@ -32,32 +31,31 @@ pycocotools = {git = "https://github.com/cocodataset/cocoapi.git",subdirectory = gunicorn = "*" "h5py" = "*" hexdump = "*" -"html5lib" = "==0.9999999" +"html5lib" = "*" imageio = "*" intervaltree = "*" -ipykernel = "<5.0" +ipykernel = "*" joblib = "*" json-logging-py = "*" jupyter = "*" libarchive = "*" lru-dict = "*" lxml = "*" -matplotlib = "==2.2.3" "mpld3" = "*" msgpack-python = "*" nbstripout = "*" nose-parameterized = "*" -numpy = "==1.14.5" -osmium = "==2.15.0" -pbr = "==5.1.3" +numpy = "*" +osmium = "*" +pbr = "*" percache = "*" pprofile = "*" psutil = "*" pycurl = "*" -git-pylint-commit-hook = "==2.5.1" +git-pylint-commit-hook = "*" pymongo = "*" "pynmea2" = "*" -pypolyline = "==0.1.17" +pypolyline = "*" pysendfile = "*" python-logstash = "*" pyvcd = "*" @@ -68,11 +66,9 @@ scikit-image = "*" "subprocess32" = "*" supervisor = "*" tenacity = "*" -tensorflow-gpu = "==1.13.0rc0" -"transforms3d" = "*" +tensorflow-gpu = "" utm = "*" "v4l2" = "*" -visdom = "*" PyJWT = "==1.4.1" PyMySQL = "==0.9.2" Theano = "*" @@ -81,26 +77,28 @@ Werkzeug = "*" Flask-Cors = "*" Flask-SocketIO = "*" "GeoAlchemy2" = "*" -Keras = ">=2.1.6" -keras-maskrcnn = "*" -keras-retinanet = "*" Pygments = "*" PyNaCl = "*" "PySDL2" = "*" reverse_geocoder = "*" Shapely = "*" -SQLAlchemy = "==1.2.7" +SQLAlchemy = "*" uWSGI = "*" scipy = "*" -fastcluster = "==1.1.25" +fastcluster = "*" backports-abc = "*" pygame = "*" simplejson = "*" python-logstash-async = "*" -pandas = "*" seaborn = "*" -tensorflow-estimator = "==1.10.12" +tensorflow-estimator = "*" pyproj = "*" +mock = "*" +blinker = "*" +gast = "==0.2.2" +matplotlib = "*" +dictdiffer = "*" +aenum = "*" [packages] overpy = {git = "https://github.com/commaai/python-overpy.git",ref = "f86529af402d4642e1faeb146671c40284007323"} @@ -126,7 +124,7 @@ tqdm = "*" Cython = "*" PyYAML = "*" websocket_client = "*" -Logentries = {git = "https://github.com/commaai/le_python.git",ref = "5eef8f5be5929d33973e1b10e686fa0cdcd6792f"} +Logentries = {git = "https://github.com/commaai/le_python.git",ref = "feaeacb48f7f4bdb02c0a8fc092326d4e101b7f2"} urllib3 = "*" chardet = "*" idna = "*" @@ -140,6 +138,7 @@ nose = "*" pyflakes = "*" pylint = "*" pycryptodome = "*" +pillow = "*" [requires] -python_version = "2.7" +python_version = "3.7.3" diff --git a/Pipfile.lock b/Pipfile.lock index 15416a7bf6acce..0d410dcaea9a6b 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,11 +1,11 @@ { "_meta": { "hash": { - "sha256": "43f96719ff9a1b7eae6c7a88f903c4f5a137c2b195e3ba148f32767827b98710" + "sha256": "b684c418bc2eb803f0d3e173e0c9b2776eedd27c51d80b6fe58cf7588f35563d" }, "pipfile-spec": 6, "requires": { - "python_version": "2.7" + "python_version": "3.7.3" }, "sources": [ { @@ -18,17 +18,18 @@ "default": { "asn1crypto": { "hashes": [ - "sha256:2f1adbb7546ed199e3c90ef23ec95c5cf3585bac7d11fb7eb562a3fe89c64e87", - "sha256:9d5c20441baf0cb60a4ac34cc447c6c189024b6b4c6cd7877034f4965c464e49" + "sha256:d02bf8ea1b964a5ff04ac7891fe3a39150045d1e5e4fe99273ba677d11b92a04", + "sha256:f822954b90c4c44f002e2cd46d636ab630f1fe4df22c816a82b66505c404eb2a" ], - "version": "==0.24.0" + "version": "==1.0.0" }, "astroid": { "hashes": [ - "sha256:87de48a92e29cedf7210ffa853d11441e7ad94cb47bacd91b023499b51cbc756", - "sha256:d25869fc7f44f1d9fb7d24fd7ea0639656f5355fc3089cd1f3d18c6ec6b124c7" + "sha256:98c665ad84d10b18318c5ab7c3d203fe11714cbad2a4aef4f44651f415392754", + "sha256:b7546ffdedbf7abcfbff93cd1de9e9980b1ef744852689decc5aeada324238c6" ], - "version": "==1.6.6" + "markers": "python_version >= '3.5'", + "version": "==2.3.1" }, "atomicwrites": { "hashes": [ @@ -38,20 +39,12 @@ "index": "pypi", "version": "==1.3.0" }, - "backports.functools-lru-cache": { - "hashes": [ - "sha256:9d98697f088eb1b0fa451391f91afb5e3ebde16bbdb272819fd091151fda4f1a", - "sha256:f0b0e4eba956de51238e17573b7087e852dfe9854afd2e9c873f73fc0ca0a6dd" - ], - "markers": "python_version == '2.7'", - "version": "==1.5" - }, "certifi": { "hashes": [ - "sha256:046832c04d4e752f37383b628bc601a7ea7211496b4638f6514d0e5b9acc4939", - "sha256:945e3ba63a0b9f577b1395204e13c3a231f9bc0223888be653286534e5873695" + "sha256:e4f3620cfea4f83eedc95b24abd9cd56f3c4b146dd0177e83a21b4eb49e21e50", + "sha256:fd7c7c74727ddcf00e9acd26bba8da604ffec95bf1c2144e67aff7a8b50e6cef" ], - "version": "==2019.6.16" + "version": "==2019.9.11" }, "cffi": { "hashes": [ @@ -100,26 +93,14 @@ "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==7.0" }, - "configparser": { - "hashes": [ - "sha256:8be81d89d6e7b4c0d4e44bcc525845f6da25821de80cb5e06e7e0238a2899e32", - "sha256:da60d0014fd8c55eb48c1c5354352e363e2d30bbf7057e5e171a468390184c75" - ], - "markers": "python_version == '2.7'", - "version": "==3.7.4" - }, - "contextlib2": { - "hashes": [ - "sha256:509f9419ee91cdd00ba34443217d5ca51f5a364a404e1dce9e8979cea969ca48", - "sha256:f5260a6e679d2ff42ec91ec5252f4eeffdcf21053db9113bd0a8e4d953769c00" - ], - "markers": "python_version < '3.2'", - "version": "==0.5.5" - }, "crcmod": { "hashes": [ + "sha256:50586ab48981f11e5b117523d97bb70864a2a1af246cf6e4f5c4a21ef4611cd1", + "sha256:69a2e5c6c36d0f096a7beb4cd34e5f882ec5fd232efb710cdb85d4ff196bd52e", + "sha256:737fb308fa2ce9aed2e29075f0d5980d4a89bfbec48a368c607c5c63b3efb90e", "sha256:dc7051a0db5f2bd48665a990d3ec1cc305a466a77358ca4492826f41f283601e" ], "index": "pypi", @@ -149,47 +130,37 @@ }, "cython": { "hashes": [ - "sha256:04ebf16df9406d3279a2489c3327803c782d9e17637d525bfb44ecf5ec65850f", - "sha256:1486ec88d1c73dea3846a5640054018b002608e04a791ccbd2082a47bce4440a", - "sha256:20da832a5e9a8e93d1e1eb64650258956723940968eb585506531719b55b804f", - "sha256:2464688b523d7a133b52cf1343c1c595b92fc6554af1015f74b9e49951e992d4", - "sha256:27827b68a8359e9ab6bf683c68d8ee79863a0c94a577acf56aa02cc302e16f51", - "sha256:27deeeeca0fd8933af07923e809c8fed0763d150a4fdd4082932a33b8c874ed6", - "sha256:31f4da785d5e09deb852ea59795a629c5befb6040929e7880c6f63e6668246ce", - "sha256:4828cf8fa638c35139e643f30201b240c0d156b1b9967a7321ae42d721d7224c", - "sha256:48b365e32cc5639ae2c239d7bd4f8a1d920a13a7ae92113c4c938903c9400147", - "sha256:4eb71856c1d1b33083df9318fd30143470ad6f0d1b9ad2ee61a120710842d28b", - "sha256:5b06ef8422d27d8128f8f80bdefa111eadcab246fba1d668720af4f0b97b7a0e", - "sha256:71c553640e1ddaaf143e38dbc6cd1863fa3c0738fb1830a9aaffba9a51838f30", - "sha256:73e2742ee1f923c5f213183bf493901f9630e395634fce5b739a53b7dc5d64be", - "sha256:82a632bc02063eff0b8e7ff3089aa3d912d1c7499709f51c8f04f57c8832cfe6", - "sha256:977ca1ac059e4d4a4bf5fe2224986baf42b69290453eda44822606f4deae6515", - "sha256:a7e6217d0dd864a7cc4f457172766864496efd64d24d4980df1521f75f992761", - "sha256:ad0ed7dd5dff76eb3aae8c18d95b1c9f885a91a92132728051a704fb8060d08c", - "sha256:b1b8eda9e931f0ca1aadb95a890811bdf530407e48c962643b85675329d99abf", - "sha256:cec99c79205131da3ee75becea1f3f55c57bf6a1c500431de9ae7a32ac8a5cc4", - "sha256:d4bbdaa6f61ce2ef26535a7d473d6ffa6e413013c5c580af999546bf1627ae11", - "sha256:d8bdb4208975b12048bdace46e9dd8e3dda3872432f95b53789700a1330e6060", - "sha256:dce0362ff9b61f8411d1efc9e16fc528dadbd3707a557561992457f5cb446297", - "sha256:defbbbf5653629ce5cc54091ce49c6830da8d3104de53ed2169c9efcb0720f27", - "sha256:e0c53a7e2b6d82ec3c26c009c937fc88eb8c7edf000c54334261beaf56bb08f2", - "sha256:e1065bacfe5303f107896e63263537dee90920d26050f2e23c4af12c37da2db6", - "sha256:e142837c4212c0b2c71e6773cb6740828922806b4c00ee4215be3ceb558671e6", - "sha256:f4cbbab28c93ffee6ec929cf0826f0b11d2488e53a708d51142a5e62f8cd9806", - "sha256:fa8f63b6551621eea9efea4db37ae401104352f0ebaee32f7d20be88cbe589c3" - ], - "index": "pypi", - "version": "==0.29.12" - }, - "enum34": { - "hashes": [ - "sha256:2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850", - "sha256:644837f692e5f550741432dd3f223bbb9852018674981b1664e5dc339387588a", - "sha256:6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79", - "sha256:8ad8c4783bf61ded74527bffb48ed9b54166685e4230386a9ed9b1279e2df5b1" - ], - "markers": "python_version < '3'", - "version": "==1.1.6" + "sha256:07efba7b32c082c519b75e3b03821c2f32848e2b3e9986c784bbd8ffaf0666d7", + "sha256:08db41daf18fabf7b7a85e39aa26954f6246994540043194af026c0df65a4942", + "sha256:19bbe3caf885a1d2e2c30eacc10d1e45dbbefb156493fe1d5d1adc1668cc1269", + "sha256:1c574f2f2ba760b82b2bcf6262e77e75589247dc5ef796a3ff1b2213e50ee452", + "sha256:1dfe672c686e34598bdbaa93c3b30acb3720ae9258232a4f68ba04ee9969063d", + "sha256:283faea84e6c4e54c3f5c8ff89aa2b6c1c3a813aad4f6d48ed3b9cc9043ef9f9", + "sha256:2a145888d0942e7c36e86a7b7c7e2923cb9f7055805a3b72dcb137e3efdb0979", + "sha256:3f75065936e16569d6e13dfd76de988f5eabeae460aa54770c9b961ab6f747fc", + "sha256:4d78124f5f281f1d5d5b7919cbbc65a7073ff93562def81ee78a8307e6e72494", + "sha256:5ba4d088b8e5d59b8a5911ca9c72952acf3c83296b57daf75af92fb2af1e8423", + "sha256:6b19daeda1d5d1dfc973b291246f6a63a663b20c33980724d6d073c562719536", + "sha256:790c7dc80fd1c3e38acefe06027e2f5a8466c128c7e47c6e140fd5316132574d", + "sha256:7f8c4e648881454ba3ba0bcf3b21a9e1878a67d20ea2b8d9ec1c4c628592ab6b", + "sha256:8bcd3f597290f9902548d6355898d7e376e7f3762f89db9cd50b2b58429df9e8", + "sha256:8ffb18f71972a5c718a8600d9f52e3507f0d6fb72a978e03270d34a7035c98fb", + "sha256:92f025df1cb391e09f65775598c7dfb7efad72d74713775db54e267f62ca94a1", + "sha256:93cf1c72472a2fd0ef4c52f6074dab08fc28d475b9c824ba73a52701f7a48ae1", + "sha256:9a7fa692cdc967fdbf6a053c1975137d01f6935dede2ef222c71840b290caf79", + "sha256:a68eb0c1375f2401de881692b30370a51e550052b8e346b2f71bbdbdc74a214f", + "sha256:ac3b7a12ddd52ea910ee3a041e6bc65df7a52f0ba7bd10fb7123502af482c152", + "sha256:b402b700edaf571a0bae18ec35d5b71c266873a6616412b672435c10b6d8f041", + "sha256:c29d069a4a30f472482343c866f7486731ad638ef9af92bfe5fca9c7323d638e", + "sha256:d822311498f185db449b687336b4e5db7638c8d8b03bdf10ae91d74e23c7cc0c", + "sha256:dccc8df9e1ac158b06777bbaaeb4516f245f9b147701ae25e6023960e4a0c2a3", + "sha256:e31f4b946c2765b2f35440fdb4b00c496dfc5babc53c7ae61966b41171d1d59f", + "sha256:eb43f9e582cc221ee2832e25ea6fe5c06f2acc9da6353c562e922f107db12af8", + "sha256:f07822248110fd6213db8bc2745fdbbccef6f2b3d18ac91a7fba29c6bc575da5", + "sha256:ff69854f123b959d4ae14bd5330714bb9ee4360052992dc0fbd0a3dee4261f95" + ], + "index": "pypi", + "version": "==0.29.13" }, "flask": { "hashes": [ @@ -199,14 +170,6 @@ "index": "pypi", "version": "==1.1.1" }, - "futures": { - "hashes": [ - "sha256:49b3f5b064b6e3afc3316421a3f25f66c137ae88f068abbf72830170033c5e16", - "sha256:7e033af76a5e35f58e56da7a91e687706faf4e7bdfb2cbc3f2cca6b9bcda9794" - ], - "markers": "python_version < '3.2'", - "version": "==3.3.0" - }, "gunicorn": { "hashes": [ "sha256:aa8e0b40b4157b36a5df5e599f45c9c76d6af43845ba3b3b0efe2c70473c2471", @@ -230,19 +193,12 @@ "index": "pypi", "version": "==2.8" }, - "ipaddress": { - "hashes": [ - "sha256:64b28eec5e78e7510698f6d4da08800a5c575caa4a286c93d651c5d3ff7b6794", - "sha256:b146c751ea45cad6188dd6cf2d9b757f6f4f8d6ffb96a023e6f2e26eea02a72c" - ], - "markers": "python_version < '3'", - "version": "==1.0.22" - }, "isort": { "hashes": [ "sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1", "sha256:6e811fcb295968434526407adb8796944f1988c5b65e8139058f2014cbe100fd" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==4.3.21" }, "itsdangerous": { @@ -250,6 +206,7 @@ "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19", "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.1.0" }, "jinja2": { @@ -270,26 +227,27 @@ }, "lazy-object-proxy": { "hashes": [ - "sha256:159a745e61422217881c4de71f9eafd9d703b93af95618635849fe469a283661", - "sha256:23f63c0821cc96a23332e45dfaa83266feff8adc72b9bcaef86c202af765244f", - "sha256:3b11be575475db2e8a6e11215f5aa95b9ec14de658628776e10d96fa0b4dac13", - "sha256:3f447aff8bc61ca8b42b73304f6a44fa0d915487de144652816f950a3f1ab821", - "sha256:4ba73f6089cd9b9478bc0a4fa807b47dbdb8fad1d8f31a0f0a5dbf26a4527a71", - "sha256:4f53eadd9932055eac465bd3ca1bd610e4d7141e1278012bd1f28646aebc1d0e", - "sha256:64483bd7154580158ea90de5b8e5e6fc29a16a9b4db24f10193f0c1ae3f9d1ea", - "sha256:6f72d42b0d04bfee2397aa1862262654b56922c20a9bb66bb76b6f0e5e4f9229", - "sha256:7c7f1ec07b227bdc561299fa2328e85000f90179a2f44ea30579d38e037cb3d4", - "sha256:7c8b1ba1e15c10b13cad4171cfa77f5bb5ec2580abc5a353907780805ebe158e", - "sha256:8559b94b823f85342e10d3d9ca4ba5478168e1ac5658a8a2f18c991ba9c52c20", - "sha256:a262c7dfb046f00e12a2bdd1bafaed2408114a89ac414b0af8755c696eb3fc16", - "sha256:acce4e3267610c4fdb6632b3886fe3f2f7dd641158a843cf6b6a68e4ce81477b", - "sha256:be089bb6b83fac7f29d357b2dc4cf2b8eb8d98fe9d9ff89f9ea6012970a853c7", - "sha256:bfab710d859c779f273cc48fb86af38d6e9210f38287df0069a63e40b45a2f5c", - "sha256:c10d29019927301d524a22ced72706380de7cfc50f767217485a912b4c8bd82a", - "sha256:dd6e2b598849b3d7aee2295ac765a578879830fb8966f70be8cd472e6069932e", - "sha256:e408f1eacc0a68fed0c08da45f31d0ebb38079f043328dce69ff133b95c29dc1" - ], - "version": "==1.4.1" + "sha256:02b260c8deb80db09325b99edf62ae344ce9bc64d68b7a634410b8e9a568edbf", + "sha256:18f9c401083a4ba6e162355873f906315332ea7035803d0fd8166051e3d402e3", + "sha256:1f2c6209a8917c525c1e2b55a716135ca4658a3042b5122d4e3413a4030c26ce", + "sha256:2f06d97f0ca0f414f6b707c974aaf8829c2292c1c497642f63824119d770226f", + "sha256:616c94f8176808f4018b39f9638080ed86f96b55370b5a9463b2ee5c926f6c5f", + "sha256:63b91e30ef47ef68a30f0c3c278fbfe9822319c15f34b7538a829515b84ca2a0", + "sha256:77b454f03860b844f758c5d5c6e5f18d27de899a3db367f4af06bec2e6013a8e", + "sha256:83fe27ba321e4cfac466178606147d3c0aa18e8087507caec78ed5a966a64905", + "sha256:84742532d39f72df959d237912344d8a1764c2d03fe58beba96a87bfa11a76d8", + "sha256:874ebf3caaf55a020aeb08acead813baf5a305927a71ce88c9377970fe7ad3c2", + "sha256:9f5caf2c7436d44f3cec97c2fa7791f8a675170badbfa86e1992ca1b84c37009", + "sha256:a0c8758d01fcdfe7ae8e4b4017b13552efa7f1197dd7358dc9da0576f9d0328a", + "sha256:a4def978d9d28cda2d960c279318d46b327632686d82b4917516c36d4c274512", + "sha256:ad4f4be843dace866af5fc142509e9b9817ca0c59342fdb176ab6ad552c927f5", + "sha256:ae33dd198f772f714420c5ab698ff05ff900150486c648d29951e9c70694338e", + "sha256:b4a2b782b8a8c5522ad35c93e04d60e2ba7f7dcb9271ec8e8c3e08239be6c7b4", + "sha256:c462eb33f6abca3b34cdedbe84d761f31a60b814e173b98ede3c81bb48967c4f", + "sha256:fd135b8d35dfdcdb984828c84d695937e58cc5f49e1c854eb311c4d6aa03f4f1" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.4.2" }, "libusb1": { "hashes": [ @@ -300,7 +258,8 @@ }, "logentries": { "git": "https://github.com/commaai/le_python.git", - "ref": "5eef8f5be5929d33973e1b10e686fa0cdcd6792f" + "ref": "feaeacb48f7f4bdb02c0a8fc092326d4e101b7f2", + "version": "==0.8" }, "markupsafe": { "hashes": [ @@ -333,6 +292,7 @@ "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.1.1" }, "mccabe": { @@ -359,36 +319,62 @@ }, "numpy": { "hashes": [ - "sha256:0778076e764e146d3078b17c24c4d89e0ecd4ac5401beff8e1c87879043a0633", - "sha256:141c7102f20abe6cf0d54c4ced8d565b86df4d3077ba2343b61a6db996cefec7", - "sha256:14270a1ee8917d11e7753fb54fc7ffd1934f4d529235beec0b275e2ccf00333b", - "sha256:27e11c7a8ec9d5838bc59f809bfa86efc8a4fd02e58960fa9c49d998e14332d5", - "sha256:2a04dda79606f3d2f760384c38ccd3d5b9bb79d4c8126b67aff5eb09a253763e", - "sha256:3c26010c1b51e1224a3ca6b8df807de6e95128b0908c7e34f190e7775455b0ca", - "sha256:52c40f1a4262c896420c6ea1c6fda62cf67070e3947e3307f5562bd783a90336", - "sha256:6e4f8d9e8aa79321657079b9ac03f3cf3fd067bf31c1cca4f56d49543f4356a5", - "sha256:7242be12a58fec245ee9734e625964b97cf7e3f2f7d016603f9e56660ce479c7", - "sha256:7dc253b542bfd4b4eb88d9dbae4ca079e7bf2e2afd819ee18891a43db66c60c7", - "sha256:94f5bd885f67bbb25c82d80184abbf7ce4f6c3c3a41fbaa4182f034bba803e69", - "sha256:a89e188daa119ffa0d03ce5123dee3f8ffd5115c896c2a9d4f0dbb3d8b95bfa3", - "sha256:ad3399da9b0ca36e2f24de72f67ab2854a62e623274607e37e0ce5f5d5fa9166", - "sha256:b0348be89275fd1d4c44ffa39530c41a21062f52299b1e3ee7d1c61f060044b8", - "sha256:b5554368e4ede1856121b0dfa35ce71768102e4aa55e526cb8de7f374ff78722", - "sha256:cbddc56b2502d3f87fda4f98d948eb5b11f36ff3902e17cb6cc44727f2200525", - "sha256:d79f18f41751725c56eceab2a886f021d70fd70a6188fd386e29a045945ffc10", - "sha256:dc2ca26a19ab32dc475dbad9dfe723d3a64c835f4c23f625c2b6566ca32b9f29", - "sha256:dd9bcd4f294eb0633bb33d1a74febdd2b9018b8b8ed325f861fffcd2c7660bb8", - "sha256:e8baab1bc7c9152715844f1faca6744f2416929de10d7639ed49555a85549f52", - "sha256:ec31fe12668af687b99acf1567399632a7c47b0e17cfb9ae47c098644ef36797", - "sha256:f12b4f7e2d8f9da3141564e6737d79016fe5336cc92de6814eba579744f65b0a", - "sha256:f58ac38d5ca045a377b3b377c84df8175ab992c970a53332fa8ac2373df44ff7" - ], - "index": "pypi", - "version": "==1.16.4" + "sha256:05dbfe72684cc14b92568de1bc1f41e5f62b00f714afc9adee42f6311738091f", + "sha256:0d82cb7271a577529d07bbb05cb58675f2deb09772175fab96dc8de025d8ac05", + "sha256:10132aa1fef99adc85a905d82e8497a580f83739837d7cbd234649f2e9b9dc58", + "sha256:12322df2e21f033a60c80319c25011194cd2a21294cc66fee0908aeae2c27832", + "sha256:16f19b3aa775dddc9814e02a46b8e6ae6a54ed8cf143962b4e53f0471dbd7b16", + "sha256:3d0b0989dd2d066db006158de7220802899a1e5c8cf622abe2d0bd158fd01c2c", + "sha256:438a3f0e7b681642898fd7993d38e2bf140a2d1eafaf3e89bb626db7f50db355", + "sha256:5fd214f482ab53f2cea57414c5fb3e58895b17df6e6f5bca5be6a0bb6aea23bb", + "sha256:73615d3edc84dd7c4aeb212fa3748fb83217e00d201875a47327f55363cef2df", + "sha256:7bd355ad7496f4ce1d235e9814ec81ee3d28308d591c067ce92e49f745ba2c2f", + "sha256:7d077f2976b8f3de08a0dcf5d72083f4af5411e8fddacd662aae27baa2601196", + "sha256:a4092682778dc48093e8bda8d26ee8360153e2047826f95a3f5eae09f0ae3abf", + "sha256:b458de8624c9f6034af492372eb2fee41a8e605f03f4732f43fc099e227858b2", + "sha256:e70fc8ff03a961f13363c2c95ef8285e0cf6a720f8271836f852cc0fa64e97c8", + "sha256:ee8e9d7cad5fe6dde50ede0d2e978d81eafeaa6233fb0b8719f60214cf226578", + "sha256:f4a4f6aba148858a5a5d546a99280f71f5ee6ec8182a7d195af1a914195b21a2" + ], + "index": "pypi", + "version": "==1.17.2" }, "overpy": { "git": "https://github.com/commaai/python-overpy.git", - "ref": "f86529af402d4642e1faeb146671c40284007323" + "ref": "f86529af402d4642e1faeb146671c40284007323", + "version": "==0.4" + }, + "pillow": { + "hashes": [ + "sha256:00fdeb23820f30e43bba78eb9abb00b7a937a655de7760b2e09101d63708b64e", + "sha256:01f948e8220c85eae1aa1a7f8edddcec193918f933fb07aaebe0bfbbcffefbf1", + "sha256:08abf39948d4b5017a137be58f1a52b7101700431f0777bec3d897c3949f74e6", + "sha256:099a61618b145ecb50c6f279666bbc398e189b8bc97544ae32b8fcb49ad6b830", + "sha256:2c1c61546e73de62747e65807d2cc4980c395d4c5600ecb1f47a650c6fa78c79", + "sha256:2ed9c4f694861642401f27dc3cb99772be67cd190e84845c749dae0a06c3bfae", + "sha256:338581b30b908e111be578f0297255f6b57a51358cd16fa0e6f664c9a1f88bff", + "sha256:38c7d48a21cd06fdeee93987147b9b1c55b73b4cfcbf83240568bfbd5adee447", + "sha256:43fd026f613c8e48a25eba1a92f4d2ad7f3903c95d8c33a11611a7717d2ab654", + "sha256:4548236844327a718ce3bb182ab32a16fa2050c61e334e959f554cac052fb0df", + "sha256:5090857876c58885cfa388dc649e5db30aae98a068c26f3fd0ac9d7d9a4d9572", + "sha256:5bbba34f97a26a93f5e8dec469ca4ddd712451418add43da946dbaed7f7a98d2", + "sha256:65a28969a025a0eb4594637b6103201dc4ed2a9508bdab56ac33e43e3081c404", + "sha256:892bb52b70bd5ea9dbbc3ac44f38e84f5a04e9d8b1bff48159d96cb795b81159", + "sha256:8a9becd5cbd5062f973bcd2e7bc79483af310222de112b6541f8af1f93a3cc42", + "sha256:972a7aaeb7c4a2795b52eef52ee991ef040b31009f36deca6207a986607b55f3", + "sha256:97b119c436bfa96a92ac2ca525f7025836d4d4e64b1c9f9eff8dbaf3ff1d86f3", + "sha256:9ba37698e242223f8053cc158f130aee046a96feacbeab65893dbe94f5530118", + "sha256:b1b0e1f626a0f079c0d3696db70132fb1f29aa87c66aecb6501a9b8be64ce9f7", + "sha256:c14c1224fd1a5be2733530d648a316974dbbb3c946913562c6005a76f21ca042", + "sha256:c79a8546c48ae6465189e54e3245a97ddf21161e33ff7eaa42787353417bb2b6", + "sha256:ceb76935ac4ebdf6d7bc845482a4450b284c6ccfb281e34da51d510658ab34d8", + "sha256:e22bffaad04b4d16e1c091baed7f2733fc1ebb91e0c602abf1b6834d17158b1f", + "sha256:ec883b8e44d877bda6f94a36313a1c6063f8b1997aa091628ae2f34c7f97c8d5", + "sha256:f1baa54d50ec031d1a9beb89974108f8f2c0706f49798f4777df879df0e1adb6", + "sha256:f53a5385932cda1e2c862d89460992911a89768c65d176ff8c50cddca4d29bed" + ], + "index": "pypi", + "version": "==6.2.0" }, "psutil": { "hashes": [ @@ -420,37 +406,37 @@ }, "pycryptodome": { "hashes": [ - "sha256:0281dc6a65a4d0d9e439f54e0ad5faf27bfdc2ebe9ead36912bac74a0920fa2e", - "sha256:02af9b284f5c9a55f06f5e4532c16c9b7bd958e293e93969934d864ef7bd87ee", - "sha256:09da99372fb69762e4b9690291176a166cc351793e2e1c9405d29ca291503aa8", - "sha256:0c2400ccfc049c3f24e65d4f02bb4208d86e408011019e455fab7f50d2b226c9", - "sha256:2081dd6dce6b21bf3596427edaedd4f2561dce616893b162ed2c674f3a3ca70a", - "sha256:28b86ec9fdb005a2a18e4862a3a7277046738825ee8dc89cda5657e75a396089", - "sha256:2d790c0d4c0d5edcf5fbab4e2af7b03757e40c5ae8d217f0dfe9ddea37fe130f", - "sha256:2f24906153dca16528cf5515b1afa9ef635423d5a654904e861765f88ca667b6", - "sha256:30d283939896fa4bacbdb9fa86e6fd51e9a5b953a511e210b38481f697f289f5", - "sha256:31f78b67f97830d137f74813c0502a181a03b43a32ed124049bb20428176c307", - "sha256:33c1f3a380fd38ab4dd4372bef17e98002b360b52814bb1b077693b1bd06ec87", - "sha256:34091e9a6650c44e25339f22fc821396f19f152f65be2546edd823a093fb5a04", - "sha256:567fb73951ab6865a2eb1a0060b54be1e27302574f6c65879525bdf53fab49e1", - "sha256:5bc40f8aa7ba8ca7f833ad2477b9d84e1bfd2630b22a46d9bbd221982f8c3ac0", - "sha256:6b0a0ccf33c7a6100c569667c888335a4aaf0d22218cb97b4963a65d70f6c343", - "sha256:71b93157f1ce93fc7cfff9359b76def2b4826a7ef7a7f95e070161368e7f584a", - "sha256:7d939d511b7dac29b2d936706786771ecb8256e43fade5cdb0e8bc58f02b86cf", - "sha256:7fbc5a93d52e4c51487f4648b00dc41700adb144d10fc567b05f852e76c243ad", - "sha256:9cb94b8f9c915a5d2b273d612a25a8e5d67b49543f8eb6bcec0275ac46cda421", - "sha256:a585ea1722f9731e75881d5ffcc51d11c794d244ac57e7c2a9cbb8d5ac729302", - "sha256:a6458dd7a10ae51f6fce56bdfc79bf6d3b54556237045d09e77fbda9d6d37864", - "sha256:a9fb92e948128bce0239b87c6efcf2cb1c5a703d0b41dd6835211e6fafd1c5df", - "sha256:b0b6b4ca1c53e7d6ca9f2720919f63837f05e7a5f92912a2bc29bfd03ed3b54f", - "sha256:b7d22c8d648aaa3a7ec785eda544402141eb78ac5ffbba4cbe2c3a1f52276870", - "sha256:bc9560574a868cfa2ba781b7bb0b4685b08ea251697abfc49070ffc05e1cbee6", - "sha256:c0c5a576f3f7b7de3f86889cb47eb51b59dc11db9cf1e2a0f51eb4d988010ea4", - "sha256:e1c91c2fa942a71c98a7a1f462de6dbbe82f34b9267eb8131314d97bd13bf0d4", - "sha256:ec936361ad78aa95382c313df95777795b8185aac5dd3ec5463363ea94b556fc" - ], - "index": "pypi", - "version": "==3.8.2" + "sha256:023c294367d7189ae224fb61bc8d49a2347704087c1c78dbd5ab114dd5b97761", + "sha256:0f29e1238ad3b6b6e2acd7ea1d8e8b382978a56503f2c48b67d5dc144d143cb0", + "sha256:18f376698e3ddcb1d3b312512ca78c9eed132e68ac6d0bf2e72452dfe213e96f", + "sha256:1de815b847982f909dc2e5e2ca641b85cde80d95cc7e6a359c03d4b42cd21568", + "sha256:1ff619b8e4050799ca5ca0ffdf8eb0dbccba6997997866755f37e6aa7dde23fe", + "sha256:233a04bb7bdd4b07e14d61d5166150942d872802daa4f049d49a453fe0659e94", + "sha256:33c07e1e36ec84524b49f99f11804d5e4d2188c643e84d914cb1e0a277ed3c79", + "sha256:3701822a085dbebf678bfbdfbd6ebd92ffa80d5a544c9979984bf16a67c9790b", + "sha256:3f8e6851c0a45429f9b86c1597d3b831b0cff140b3e170a891fce55ef8dac2bb", + "sha256:4f6cdddf1fe72e7f173e9734aa19b94cbd046b61a8559d650ff222e36021d5c1", + "sha256:52d20b22c5b1fc952b4c686b99a6c55c3b0b0a673bec30570f156a72198f66ff", + "sha256:5452b534fecf8bf57cf9106d00877f5f4ab7264e7a5e1f5ea8d15b04517d1255", + "sha256:5a7a9a4a7f8f0990fa97fee71c7f7e0c412925c515cfc6d4996961e92c9be8e5", + "sha256:600bf9dd5fbed0feee83950e2a8baacaa1f38b56c237fff270d31e47f8da9e52", + "sha256:6840c9881e528224ebf72b3f73b3d11baf399e265106c9f4d9bae4f09615a93a", + "sha256:71b041d43fe13004abc36ca720ac64ea489ee8a3407a25116481d0faf9d62494", + "sha256:7252498b427c421e306473ed344e58235eedd95c15fec2e1b33d333aefa1ea10", + "sha256:8d2135c941d38f241e0e62dbdfc1ca5d9240527e61316126797f50b6f3e49825", + "sha256:a0962aea03933b99cf391c3e10dfef32f77915d5553464264cfbc6711f31d254", + "sha256:a117047a220b3911d425affcd1cbc97a1af7ea7eb5d985d9964d42b4f0558489", + "sha256:a35a5c588248ba00eb976a8554211e584a55de286783bc69b12bdd7954052b4a", + "sha256:c1a4f3f651471b9bf60b0d98fa8a994b8a73ff8ab4edc691e23243c853aaff9f", + "sha256:c419943306756ddd1a1997120bb073733bc223365909c68185106d5521cbc0ef", + "sha256:c453ad968b67d66448543420ec39770c30bd16d986058255f058ab87c4f6cc1f", + "sha256:d2d78644655629c7d1b9bf28e479d29facc0949d9ff095103ca9c2314b329ee0", + "sha256:d7be60dc2126ee350ac7191549f5ab05c2dd76a5d5a3022249f395a401c6ea37", + "sha256:dbeb08ad850056747aa7d5f33273b7ce0b9a77910604a1be7b7a6f2ef076213f", + "sha256:f02382dc1bf91fb7123f2a3851fb1b526c871fa9359f387f2bcc847efc74ae52" + ], + "index": "pypi", + "version": "==3.9.0" }, "pyflakes": { "hashes": [ @@ -470,11 +456,11 @@ }, "pylint": { "hashes": [ - "sha256:367e3d49813d349a905390ac27989eff82ab84958731c5ef0bef867452cfdc42", - "sha256:97a42df23d436c70132971d1dcb9efad2fe5c0c6add55b90161e773caf729300" + "sha256:7edbae11476c2182708063ac387a8f97c760d9cfe36a5ede0ca996f90cf346c8", + "sha256:844ce067788028c1a35086a5c66bc5e599ddd851841c41d6ee1623b36774d9f2" ], "index": "pypi", - "version": "==1.9.5" + "version": "==2.4.2" }, "pyserial": { "hashes": [ @@ -494,51 +480,53 @@ }, "pyyaml": { "hashes": [ - "sha256:57acc1d8533cbe51f6662a55434f0dbecfa2b9eaf115bede8f6fd00115a0c0d3", - "sha256:588c94b3d16b76cfed8e0be54932e5729cc185caffaa5a451e7ad2f7ed8b4043", - "sha256:68c8dd247f29f9a0d09375c9c6b8fdc64b60810ebf07ba4cdd64ceee3a58c7b7", - "sha256:70d9818f1c9cd5c48bb87804f2efc8692f1023dac7f1a1a5c61d454043c1d265", - "sha256:86a93cccd50f8c125286e637328ff4eef108400dd7089b46a7be3445eecfa391", - "sha256:a0f329125a926876f647c9fa0ef32801587a12328b4a3c741270464e3e4fa778", - "sha256:a3c252ab0fa1bb0d5a3f6449a4826732f3eb6c0270925548cac342bc9b22c225", - "sha256:b4bb4d3f5e232425e25dda21c070ce05168a786ac9eda43768ab7f3ac2770955", - "sha256:cd0618c5ba5bda5f4039b9398bb7fb6a317bb8298218c3de25c47c4740e4b95e", - "sha256:ceacb9e5f8474dcf45b940578591c7f3d960e82f926c707788a570b51ba59190", - "sha256:fe6a88094b64132c4bb3b631412e90032e8cfe9745a58370462240b8cb7553cd" + "sha256:0113bc0ec2ad727182326b61326afa3d1d8280ae1122493553fd6f4397f33df9", + "sha256:01adf0b6c6f61bd11af6e10ca52b7d4057dd0be0343eb9283c878cf3af56aee4", + "sha256:5124373960b0b3f4aa7df1707e63e9f109b5263eca5976c66e08b1c552d4eaf8", + "sha256:5ca4f10adbddae56d824b2c09668e91219bb178a1eee1faa56af6f99f11bf696", + "sha256:7907be34ffa3c5a32b60b95f4d95ea25361c951383a894fec31be7252b2b6f34", + "sha256:7ec9b2a4ed5cad025c2278a1e6a19c011c80a3caaac804fd2d329e9cc2c287c9", + "sha256:87ae4c829bb25b9fe99cf71fbb2140c448f534e24c998cc60f39ae4f94396a73", + "sha256:9de9919becc9cc2ff03637872a440195ac4241c80536632fffeb6a1e25a74299", + "sha256:a5a85b10e450c66b49f98846937e8cfca1db3127a9d5d1e31ca45c3d0bef4c5b", + "sha256:b0997827b4f6a7c286c01c5f60384d218dca4ed7d9efa945c3e1aa623d5709ae", + "sha256:b631ef96d3222e62861443cc89d6563ba3eeb816eeb96b2629345ab795e53681", + "sha256:bf47c0607522fdbca6c9e817a6e81b08491de50f3766a7a0e6a5be7905961b41", + "sha256:f81025eddd0327c7d4cfe9b62cf33190e1e736cc6e97502b3ec425f574b3e7a8" ], "index": "pypi", - "version": "==5.1.1" + "version": "==5.1.2" }, "pyzmq": { "hashes": [ - "sha256:00dd015159eaeb1c0731ad49310e1f5d839c9a35a15e4f3267f5052233fad99b", - "sha256:03913b6beb8e7b417b9910b0ee1fd5d62e9626d218faefbe879d70714ceab1a2", - "sha256:13f17386df81d5e6efb9a4faea341d8de22cdc82e49a326dded26e33f42a3112", - "sha256:16c6281d96885db1e15f7047ddc1a8f48ff4ea35d31ca709f4d2eb39f246d356", - "sha256:17efab4a804e31f58361631256d660214204046f9e2b962738b171b9ad674ea7", - "sha256:2b79919ddeff3d3c96aa6087c21d294c8db1c01f6bfeee73324944683685f419", - "sha256:2f832e4711657bb8d16ea1feba860f676ec5f14fb9fe3b449b5953a60e89edae", - "sha256:31a11d37ac73107363b47e14c94547dbfc6a550029c3fe0530be443199026fc2", - "sha256:33a3e928e6c3138c675e1d6702dd11f6b7050177d7aab3fc322db6e1d2274490", - "sha256:34a38195a6d3a9646cbcdaf8eb245b4d935c7a57f7e1b3af467814bc1a92467e", - "sha256:42900054f1500acef6df7428edf806abbf641bf92eb9ceded24aa863397c3bae", - "sha256:4ccc7f3c63aa9d744dadb62c49eda2d0e7de55649b80c45d7c684d70161a69af", - "sha256:5b220c37c346e6575db8c88a940c1fc234f99ce8e0068c408919bb8896c4b6d2", - "sha256:6074848da5c8b44a1ca40adf75cf65aa92bc80f635e8249aa8f37a69b2b9b6f5", - "sha256:61a4155964bd4a14ef95bf46cb1651bcf8dcbbed8c0108e9c974c1fcbb57788f", - "sha256:62b5774688326600c52f587f7a033ca6b6284bef4c8b1b5fda32480897759eac", - "sha256:65a9ffa4f9f085d696f16fd7541f34b3c357d25fe99c90e3bce2ea59c3b5b4b6", - "sha256:76a077d2c30f8adc5e919a55985a784b96aeca69b53c1ea6fd5723d3ae2e6f53", - "sha256:8e5b4c51557071d6379d6dc1f54f35e9f6a137f5e84e102efb869c8d3c13c8ff", - "sha256:917f73e07cc04f0678a96d93e7bb8b1adcccdde9ccfe202e622814f4d1d1ecfd", - "sha256:91c75d3c4c357f9643e739db9e79ab9681b2f6ae8ec5678d6ef2ea0d01532596", - "sha256:923dd91618b100bb4c92ab9ed7b65825a595b8524a094ce03c7cb2aaae7d353b", - "sha256:9849054e0355e2bc7f4668766a25517ba76095031c9ff5e39ae8949cee5bb024", - "sha256:c9d453933f0e3f44b9759189f2a18aa765f7f1a4345c727c18ebe8ad0d748d26", - "sha256:cb7514936277abce64c2f4c56883e5704d85ed04d98d2d432d1c6764003bb003" - ], - "index": "pypi", - "version": "==18.0.2" + "sha256:01636e95a88d60118479041c6aaaaf5419c6485b7b1d37c9c4dd424b7b9f1121", + "sha256:021dba0d1436516092c624359e5da51472b11ba8edffa334218912f7e8b65467", + "sha256:0463bd941b6aead494d4035f7eebd70035293dd6caf8425993e85ad41de13fa3", + "sha256:05fd51edd81eed798fccafdd49c936b6c166ffae7b32482e4d6d6a2e196af4e6", + "sha256:1fadc8fbdf3d22753c36d4172169d184ee6654f8d6539e7af25029643363c490", + "sha256:22efa0596cf245a78a99060fe5682c4cd00c58bb7614271129215c889062db80", + "sha256:260c70b7c018905ec3659d0f04db735ac830fe27236e43b9dc0532cf7c9873ef", + "sha256:2762c45e289732d4450406cedca35a9d4d71e449131ba2f491e0bf473e3d2ff2", + "sha256:2fc6cada8dc53521c1189596f1898d45c5f68603194d3a6453d6db4b27f4e12e", + "sha256:343b9710a61f2b167673bea1974e70b5dccfe64b5ed10626798f08c1f7227e72", + "sha256:41bf96d5f554598a0632c3ec28e3026f1d6591a50f580df38eff0b8067efb9e7", + "sha256:856b2cdf7a1e2cbb84928e1e8db0ea4018709b39804103d3a409e5584f553f57", + "sha256:85b869abc894672de9aecdf032158ea8ad01e2f0c3b09ef60e3687fb79418096", + "sha256:93f44739db69234c013a16990e43db1aa0af3cf5a4b8b377d028ff24515fbeb3", + "sha256:98fa3e75ccb22c0dc99654e3dd9ff693b956861459e8c8e8734dd6247b89eb29", + "sha256:9a22c94d2e93af8bebd4fcf5fa38830f5e3b1ff0d4424e2912b07651eb1bafb4", + "sha256:a7d3f4b4bbb5d7866ae727763268b5c15797cbd7b63ea17f3b0ec1067da8994b", + "sha256:b645a49376547b3816433a7e2d2a99135c8e651e50497e7ecac3bd126e4bea16", + "sha256:cf0765822e78cf9e45451647a346d443f66792aba906bc340f4e0ac7870c169c", + "sha256:dc398e1e047efb18bfab7a8989346c6921a847feae2cad69fedf6ca12fb99e2c", + "sha256:dd5995ae2e80044e33b5077fb4bc2b0c1788ac6feaf15a6b87a00c14b4bdd682", + "sha256:e03fe5e07e70f245dc9013a9d48ae8cc4b10c33a1968039c5a3b64b5d01d083d", + "sha256:ea09a306144dff2795e48439883349819bef2c53c0ee62a3c2fae429451843bb", + "sha256:f4e37f33da282c3c319849877e34f97f0a3acec09622ec61b7333205bdd13b52", + "sha256:fa4bad0d1d173dee3e8ef3c3eb6b2bb6c723fc7a661eeecc1ecb2fa99860dd45" + ], + "index": "pypi", + "version": "==18.1.0" }, "raven": { "hashes": [ @@ -564,14 +552,6 @@ "index": "pypi", "version": "==1.1.10" }, - "singledispatch": { - "hashes": [ - "sha256:5b06af87df13818d14f08a028e42f566640aef80805c3b50c5056b086e3c2b9c", - "sha256:833b46966687b3de7f438c761ac475213e53b306740f1abfaa86e1d1aae56aa8" - ], - "markers": "python_version < '3.4'", - "version": "==3.4.0.3" - }, "six": { "hashes": [ "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", @@ -582,10 +562,10 @@ }, "smbus2": { "hashes": [ - "sha256:4d5aae2f65d39056bb44e8906d5c503f8ee7e02fadb0a6433f1091a9ce528dde" + "sha256:210e66eebe4d0b1fe836b3ec2751841942e1c4918c0b429b20a0e20a222228b4" ], "index": "pypi", - "version": "==0.2.3" + "version": "==0.3.0" }, "sympy": { "hashes": [ @@ -597,19 +577,40 @@ }, "tqdm": { "hashes": [ - "sha256:14a285392c32b6f8222ecfbcd217838f88e11630affe9006cd0e94c7eff3cb61", - "sha256:25d4c0ea02a305a688e7e9c2cdc8f862f989ef2a4701ab28ee963295f5b109ab" + "sha256:abc25d0ce2397d070ef07d8c7e706aede7920da163c64997585d42d3537ece3d", + "sha256:dd3fcca8488bb1d416aa7469d2f277902f26260c45aa86b667b074cd44b3b115" ], "index": "pypi", - "version": "==4.32.2" + "version": "==4.36.1" + }, + "typed-ast": { + "hashes": [ + "sha256:18511a0b3e7922276346bcb47e2ef9f38fb90fd31cb9223eed42c85d1312344e", + "sha256:262c247a82d005e43b5b7f69aff746370538e176131c32dda9cb0f324d27141e", + "sha256:2b907eb046d049bcd9892e3076c7a6456c93a25bebfe554e931620c90e6a25b0", + "sha256:354c16e5babd09f5cb0ee000d54cfa38401d8b8891eefa878ac772f827181a3c", + "sha256:4e0b70c6fc4d010f8107726af5fd37921b666f5b31d9331f0bd24ad9a088e631", + "sha256:630968c5cdee51a11c05a30453f8cd65e0cc1d2ad0d9192819df9978984529f4", + "sha256:66480f95b8167c9c5c5c87f32cf437d585937970f3fc24386f313a4c97b44e34", + "sha256:71211d26ffd12d63a83e079ff258ac9d56a1376a25bc80b1cdcdf601b855b90b", + "sha256:95bd11af7eafc16e829af2d3df510cecfd4387f6453355188342c3e79a2ec87a", + "sha256:bc6c7d3fa1325a0c6613512a093bc2a2a15aeec350451cbdf9e1d4bffe3e3233", + "sha256:cc34a6f5b426748a507dd5d1de4c1978f2eb5626d51326e43280941206c209e1", + "sha256:d755f03c1e4a51e9b24d899561fec4ccaf51f210d52abdf8c07ee2849b212a36", + "sha256:d7c45933b1bdfaf9f36c579671fec15d25b06c8398f113dab64c18ed1adda01d", + "sha256:d896919306dd0aa22d0132f62a1b78d11aaf4c9fc5b3410d3c666b818191630a", + "sha256:ffde2fbfad571af120fcbfbbc61c72469e72f550d676c3342492a9dfdefb8f12" + ], + "markers": "python_version < '3.8' and implementation_name == 'cpython'", + "version": "==1.4.0" }, "urllib3": { "hashes": [ - "sha256:b246607a25ac80bedac05c6f282e3cdaf3afb65420fd024ac94435cabe6e18d1", - "sha256:dbe59173209418ae49d485b87d1681aefa36252ee85884c31346debd19463232" + "sha256:3de946ffbed6e6746608990594d08faac602528ac7015ac28d33cee6a45b7398", + "sha256:9a107b99a5393caf59c7aa3c1249c16e6879447533d0887f4336dde834c7be86" ], "index": "pypi", - "version": "==1.25.3" + "version": "==1.25.6" }, "utm": { "hashes": [ @@ -628,10 +629,11 @@ }, "werkzeug": { "hashes": [ - "sha256:87ae4e5b5366da2347eb3116c0e6c681a0e939a33b2805e2c0cbd282664932c4", - "sha256:a13b74dd3c45f758d4ebdb224be8f1ab8ef58b3c0ffc1783a8c7d9f4f50227e6" + "sha256:7280924747b5733b246fe23972186c6b348f9ae29724135a6dfc1e53cea433e7", + "sha256:e5f4a1f98b52b18a93da705a7458e55afb26f32bff83ff5d19189f92462d65c4" ], - "version": "==0.15.5" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.16.0" }, "wrapt": { "hashes": [ @@ -643,16 +645,9 @@ "develop": { "absl-py": { "hashes": [ - "sha256:b943d1c567743ed0455878fcd60bc28ac9fae38d129d1ccfad58079da00b8951" + "sha256:0ce45920056fbbb66f52fcee7408ba6311da19f55589b2b3aab9f8af92a0e1f2" ], - "version": "==0.7.1" - }, - "adal": { - "hashes": [ - "sha256:5a7f1e037c6290c6d7609cab33a9e5e988c2fbec5c51d1c4c649ee3faff37eaf", - "sha256:fd17e5661f60634ddf96a569b95d34ccb8a98de60593d729c28bdcfe360eaad1" - ], - "version": "==1.2.2" + "version": "==0.8.0" }, "aenum": { "hashes": [ @@ -665,87 +660,90 @@ }, "amqp": { "hashes": [ - "sha256:aa4409446139676943a2eaa27d5f58caf750f4ca5a89f888c452afd86be6a67d", - "sha256:cbb6f87d53cac612a594f982b717cc1c54c6a1e17943a0a0d32dc6cc9e2120c8" + "sha256:19a917e260178b8d410122712bac69cb3e6db010d68f6101e7307508aded5e68", + "sha256:19d851b879a471fcfdcf01df9936cff924f422baa77653289f7095dedd5fb26a" ], - "version": "==2.5.0" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.5.1" }, "asn1crypto": { "hashes": [ - "sha256:2f1adbb7546ed199e3c90ef23ec95c5cf3585bac7d11fb7eb562a3fe89c64e87", - "sha256:9d5c20441baf0cb60a4ac34cc447c6c189024b6b4c6cd7877034f4965c464e49" + "sha256:d02bf8ea1b964a5ff04ac7891fe3a39150045d1e5e4fe99273ba677d11b92a04", + "sha256:f822954b90c4c44f002e2cd46d636ab630f1fe4df22c816a82b66505c404eb2a" ], - "version": "==0.24.0" + "version": "==1.0.0" }, "astor": { "hashes": [ "sha256:0e41295809baf43ae8303350e031aff81ae52189b6f881f36d623fa8b2f1960e", "sha256:37a6eed8b371f1228db08234ed7f6cfdc7817a3ed3824797e20cbb11dc2a7862" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==0.8.0" }, "astroid": { "hashes": [ - "sha256:87de48a92e29cedf7210ffa853d11441e7ad94cb47bacd91b023499b51cbc756", - "sha256:d25869fc7f44f1d9fb7d24fd7ea0639656f5355fc3089cd1f3d18c6ec6b124c7" + "sha256:98c665ad84d10b18318c5ab7c3d203fe11714cbad2a4aef4f44651f415392754", + "sha256:b7546ffdedbf7abcfbff93cd1de9e9980b1ef744852689decc5aeada324238c6" ], - "version": "==1.6.6" + "markers": "python_version >= '3.5'", + "version": "==2.3.1" }, "attrs": { "hashes": [ - "sha256:69c0dbf2ed392de1cb5ec704444b08a5ef81680a61cb899dc08127123af36a79", - "sha256:f0b870f674851ecbfbbbd364d6b5cbdff9dcedbc7f3f5e18a6891057f21fe399" - ], - "version": "==19.1.0" - }, - "azure-batch": { - "hashes": [ - "sha256:017be21a9e6db92473d2e33170d5dd445596fc70d706f73552ac9c6b57a6ef1c", - "sha256:cd71c7ebb5beab174b6225bbf79ae18d6db0c8d63227a7e514da0a75f138364c" + "sha256:ec20e7a4825331c1b5ebf261d111e16fa9612c1f7a5e1f884f12bd53a664dfd2", + "sha256:f913492e1663d3c36f502e5e9ba6cd13cf19d7fab50aa13239e420fef95e1396" ], - "index": "pypi", - "version": "==4.1.3" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==19.2.0" }, "azure-common": { "hashes": [ - "sha256:2606ae77ff81c0036965b92ec2efe03eaec02a66714140ca0f7aa401b8b9bbb0", - "sha256:c908621a71eb4ee9fab0962e35d3c27a18f09a854d8359c2f32c15b3f4fc576e" + "sha256:53b1195b8f20943ccc0e71a17849258f7781bc6db1c72edc7d6c055f79bd54e3", + "sha256:99ef36e74b6395329aada288764ce80504da16ecc8206cb9a72f55fb02e8b484" ], "index": "pypi", - "version": "==1.1.16" + "version": "==1.1.23" }, "azure-nspkg": { "hashes": [ - "sha256:a908f96a695b12e31b6c56cda0bb8e6d2a054283c350881667f300b8563ece33", - "sha256:af81fd4512be5ad0834b8e82c43bbe80b016bd295a8794fac28d69bf243357e0", - "sha256:ce4173e06f2f423775c4ca8a635e9a89b5fe8e4ba9fefbbe2a1e0d525072392c" + "sha256:1d0bbb2157cf57b1bef6c8c8e5b41133957364456c43b0a43599890023cca0a8", + "sha256:31a060caca00ed1ebd369fc7fe01a56768c927e404ebc92268f4d9d636435e28", + "sha256:e7d3cea6af63e667d87ba1ca4f8cd7cb4dfca678e4c55fc1cedb320760e39dd0" ], "index": "pypi", - "version": "==3.0.1" + "version": "==3.0.2" }, "azure-storage-blob": { "hashes": [ - "sha256:308058abfd789f5830d91f6407eb00a7b04925b2b9af267aecfb46c335802cdc", - "sha256:8cab5420ba6646ead09fdb497646f735b12645cba8efed96a86f7b370e175ade" + "sha256:a8e91a51d4f62d11127c7fd8ba0077385c5b11022f0269f8a2a71b9fc36bef31", + "sha256:b90323aad60f207f9f90a0c4cf94c10acc313c20b39403398dfba51f25f7b454" ], "index": "pypi", - "version": "==1.3.1" + "version": "==2.1.0" }, "azure-storage-common": { "hashes": [ - "sha256:585658ebc784e843a285732a69aa69ef922e17c3063460c2c7b27c89f377004c", - "sha256:a412a78618e82bf99030ce56f1f2d5fc6c2c2eec7ee1beda86ce6ea5f2c9196b" + "sha256:b01a491a18839b9d05a4fe3421458a0ddb5ab9443c14e487f40d16f9a1dc2fbe", + "sha256:ccedef5c67227bc4d6670ffd37cec18fb529a1b7c3a5e53e4096eb0cf23dc73f" ], "index": "pypi", - "version": "==1.3.0" + "version": "==2.1.0" }, "azure-storage-nspkg": { "hashes": [ - "sha256:4fc4685aef941eab2f7fb53824254cca2e38f2a1bf33cda0c8ae654fe15827d6", - "sha256:855315c038c0e695868025127e1b3057a1f984af9ccfbaeac4fbfd6c5dd3b466" + "sha256:6f3bbe8652d5f542767d8433e7f96b8df7f518774055ac7c92ed7ca85f653811", + "sha256:7da3bd6c73b8c464a57f53ae9af8328490d2267c66430d8a7621997e52a9703e" ], "index": "pypi", - "version": "==3.0.0" + "version": "==3.1.0" + }, + "backcall": { + "hashes": [ + "sha256:38ecd85be2c1e78f77fd91700c76e14667dc21e2713b63876c0eb901196e01e4", + "sha256:bbbf4b1e5cd2bdb08f915895b51081c041bac22394fdfcfdfbe9f14b77c08bf2" + ], + "version": "==0.1.0" }, "backports-abc": { "hashes": [ @@ -755,57 +753,42 @@ "index": "pypi", "version": "==0.5" }, - "backports.functools-lru-cache": { - "hashes": [ - "sha256:9d98697f088eb1b0fa451391f91afb5e3ebde16bbdb272819fd091151fda4f1a", - "sha256:f0b0e4eba956de51238e17573b7087e852dfe9854afd2e9c873f73fc0ca0a6dd" - ], - "markers": "python_version == '2.7'", - "version": "==1.5" - }, "backports.lzma": { "hashes": [ - "sha256:50829db66f0445442f6c796bba0ca62d1f87f54760c4682b6d1489e729a43744" + "sha256:16d8b68e4d3cd4e6c9ddb059850452946da3914c8a8e197a7f2b0954559f2df4" ], "index": "pypi", - "version": "==0.0.13" - }, - "backports.shutil-get-terminal-size": { - "hashes": [ - "sha256:0975ba55054c15e346944b38956a4c9cbee9009391e41b86c68990effb8c1f64", - "sha256:713e7a8228ae80341c70586d1cc0a8caa5207346927e23d09dcbcaf18eadec80" - ], - "markers": "python_version == '2.7'", - "version": "==1.0.0" - }, - "backports.weakref": { - "hashes": [ - "sha256:81bc9b51c0abc58edc76aefbbc68c62a787918ffe943a37947e162c3f8e19e82", - "sha256:bc4170a29915f8b22c9e7c4939701859650f2eb84184aee80da329ac0b9825c2" - ], - "version": "==1.0.post1" + "version": "==0.0.14" }, "billiard": { "hashes": [ - "sha256:756bf323f250db8bf88462cd042c992ba60d8f5e07fc5636c24ba7d6f4261d84" + "sha256:01afcb4e7c4fd6480940cfbd4d9edc19d7a7509d6ada533984d0d0f49901ec82", + "sha256:b8809c74f648dfe69b973c8e660bcec00603758c9db8ba89d7719f88d5f01f26" ], - "version": "==3.6.0.0" + "version": "==3.6.1.0" }, "bincopy": { "hashes": [ - "sha256:61d02c09910635599127056d2707c22bfa310cb31f935fbfdda406639017717e", - "sha256:a0e31dc5de70bffaf717bb76b136857eb78ea138fb49dc5a1bf06303f103dff8" + "sha256:1b4c7219e01042cd8217fb6c12b66f6b0ff01d1986d27b0cb18fcdcf1ea3dcb7", + "sha256:3ba5fe82fc07cb1be40e5ff668a9869aabb5b264a9223b3ff4ded77273260c8c" ], "index": "pypi", - "version": "==16.0.0" + "version": "==16.1.3" }, "bleach": { "hashes": [ - "sha256:978e758599b54cd3caa2e160d74102879b230ea8dc93871d0783721eef58bc65", - "sha256:e67f46adcec78dbc3c04462f3aba3213a673d5652eba2609ed1ef15492a44b8d" + "sha256:213336e49e102af26d9cde77dd2d0397afabc5a6bf2fed985dc35b5d1e285a16", + "sha256:3fdf7f77adcf649c9911387df51254b813185e32b2c6619f690b593a617e19fa" ], "index": "pypi", - "version": "==1.5.0" + "version": "==3.1.0" + }, + "blinker": { + "hashes": [ + "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6" + ], + "index": "pypi", + "version": "==1.4" }, "boto": { "hashes": [ @@ -817,18 +800,18 @@ }, "boto3": { "hashes": [ - "sha256:6a950bf98b22812896ea0f833a26d448acfdf43179f41f389d501af7a9fae328", - "sha256:cfbc062a76a7781af8e6a4ea26ebcafa3866872a8cceb05fdbf588c36e7848f0" + "sha256:4189e1ffed768bd0efd754a0abedebce19495ba2aa6b2f5e20f29ba80f81f9cb", + "sha256:fa4e28166922feeb9b7b56134c1acc817a1bca36284a0035bc08a3dab1853a9f" ], "index": "pypi", - "version": "==1.9.195" + "version": "==1.9.242" }, "botocore": { "hashes": [ - "sha256:691627c2aeff0fcbd9237985717c28404a628181fd3e86b7be500bf2ee156007", - "sha256:c59e9981db9dfc54f0d22f731ca8de904760049a9c60d86dcedde84ae64ef4f0" + "sha256:7af52e0aabaf4ba045e1a5832308e70e1ea4b499b71624857f09aed2ba5e667c", + "sha256:dd62d63bcd3176c92775c52d3e879288f89bf0ac0039df14ea31f25d693acd6d" ], - "version": "==1.12.195" + "version": "==1.12.242" }, "celery": { "hashes": [ @@ -840,10 +823,10 @@ }, "certifi": { "hashes": [ - "sha256:046832c04d4e752f37383b628bc601a7ea7211496b4638f6514d0e5b9acc4939", - "sha256:945e3ba63a0b9f577b1395204e13c3a231f9bc0223888be653286534e5873695" + "sha256:e4f3620cfea4f83eedc95b24abd9cd56f3c4b146dd0177e83a21b4eb49e21e50", + "sha256:fd7c7c74727ddcf00e9acd26bba8da604ffec95bf1c2144e67aff7a8b50e6cef" ], - "version": "==2019.6.16" + "version": "==2019.9.11" }, "cffi": { "hashes": [ @@ -892,23 +875,9 @@ "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==7.0" }, - "cloudpickle": { - "hashes": [ - "sha256:603244e0f552b72a267d47a7d9b347b27a3430f58a0536037a290e7e0e212ecf", - "sha256:b8ba7e322f2394b9bbbdc1c976e6442c2c02acc784cb9e553cee9186166a6890" - ], - "version": "==1.2.1" - }, - "configparser": { - "hashes": [ - "sha256:8be81d89d6e7b4c0d4e44bcc525845f6da25821de80cb5e06e7e0238a2899e32", - "sha256:da60d0014fd8c55eb48c1c5354352e363e2d30bbf7057e5e171a468390184c75" - ], - "markers": "python_version == '2.7'", - "version": "==3.7.4" - }, "control": { "hashes": [ "sha256:726e8c36a253a54c8886df31f860d740d70de4f8b041421d5df078c3bff3aadb" @@ -945,47 +914,13 @@ ], "version": "==0.10.0" }, - "cython": { - "hashes": [ - "sha256:04ebf16df9406d3279a2489c3327803c782d9e17637d525bfb44ecf5ec65850f", - "sha256:1486ec88d1c73dea3846a5640054018b002608e04a791ccbd2082a47bce4440a", - "sha256:20da832a5e9a8e93d1e1eb64650258956723940968eb585506531719b55b804f", - "sha256:2464688b523d7a133b52cf1343c1c595b92fc6554af1015f74b9e49951e992d4", - "sha256:27827b68a8359e9ab6bf683c68d8ee79863a0c94a577acf56aa02cc302e16f51", - "sha256:27deeeeca0fd8933af07923e809c8fed0763d150a4fdd4082932a33b8c874ed6", - "sha256:31f4da785d5e09deb852ea59795a629c5befb6040929e7880c6f63e6668246ce", - "sha256:4828cf8fa638c35139e643f30201b240c0d156b1b9967a7321ae42d721d7224c", - "sha256:48b365e32cc5639ae2c239d7bd4f8a1d920a13a7ae92113c4c938903c9400147", - "sha256:4eb71856c1d1b33083df9318fd30143470ad6f0d1b9ad2ee61a120710842d28b", - "sha256:5b06ef8422d27d8128f8f80bdefa111eadcab246fba1d668720af4f0b97b7a0e", - "sha256:71c553640e1ddaaf143e38dbc6cd1863fa3c0738fb1830a9aaffba9a51838f30", - "sha256:73e2742ee1f923c5f213183bf493901f9630e395634fce5b739a53b7dc5d64be", - "sha256:82a632bc02063eff0b8e7ff3089aa3d912d1c7499709f51c8f04f57c8832cfe6", - "sha256:977ca1ac059e4d4a4bf5fe2224986baf42b69290453eda44822606f4deae6515", - "sha256:a7e6217d0dd864a7cc4f457172766864496efd64d24d4980df1521f75f992761", - "sha256:ad0ed7dd5dff76eb3aae8c18d95b1c9f885a91a92132728051a704fb8060d08c", - "sha256:b1b8eda9e931f0ca1aadb95a890811bdf530407e48c962643b85675329d99abf", - "sha256:cec99c79205131da3ee75becea1f3f55c57bf6a1c500431de9ae7a32ac8a5cc4", - "sha256:d4bbdaa6f61ce2ef26535a7d473d6ffa6e413013c5c580af999546bf1627ae11", - "sha256:d8bdb4208975b12048bdace46e9dd8e3dda3872432f95b53789700a1330e6060", - "sha256:dce0362ff9b61f8411d1efc9e16fc528dadbd3707a557561992457f5cb446297", - "sha256:defbbbf5653629ce5cc54091ce49c6830da8d3104de53ed2169c9efcb0720f27", - "sha256:e0c53a7e2b6d82ec3c26c009c937fc88eb8c7edf000c54334261beaf56bb08f2", - "sha256:e1065bacfe5303f107896e63263537dee90920d26050f2e23c4af12c37da2db6", - "sha256:e142837c4212c0b2c71e6773cb6740828922806b4c00ee4215be3ceb558671e6", - "sha256:f4cbbab28c93ffee6ec929cf0826f0b11d2488e53a708d51142a5e62f8cd9806", - "sha256:fa8f63b6551621eea9efea4db37ae401104352f0ebaee32f7d20be88cbe589c3" - ], - "index": "pypi", - "version": "==0.29.12" - }, "datadog": { "hashes": [ - "sha256:0e33727bd9ef0b8201359accdf12f61fb58ab541bf4062693aca16653f8e7a0a", - "sha256:995e51d142ae3624c86c78369b268f23386bb207df5345d718c241718387875c" + "sha256:07c053e39c6509023d69bc2f3b8e3d5d101b4e75baf2da2b9fc707391c3e773d", + "sha256:bbfd8c3a13e87b9c15fb982dff269b983ad9fb5ab610e7f17d92b0bc001fbe0f" ], "index": "pypi", - "version": "==0.29.3" + "version": "==0.30.0" }, "decorator": { "hashes": [ @@ -1000,64 +935,57 @@ "sha256:6687150770438374ab581bb7a1b327a847dd9c5749e396102de3fad4e8a3ef93", "sha256:f684034d135af4c6cbb949b8a4d2ed61634515257a67299e5f940fbaa34377f5" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==0.6.0" }, + "dictdiffer": { + "hashes": [ + "sha256:97cf4ef98ebc1acf737074aed41e379cf48ab5ff528c92109dfb8e2e619e6809", + "sha256:b3ad476fc9cca60302b52c50e1839342d2092aeaba586d69cbf9249f87f52463" + ], + "index": "pypi", + "version": "==0.8.0" + }, "dlib": { "hashes": [ - "sha256:92587c81b0165e933593f505fdf099dface0d0f8ec874b1d8655fc774598911f" + "sha256:8ca127253a0ca82a3d847148515f82ff2c504ed77a6385ec4f38c7f8e5360860" ], "index": "pypi", - "version": "==19.17.0" + "version": "==19.18.0" }, "docutils": { "hashes": [ - "sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6", - "sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274", - "sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6" + "sha256:6c4f696463b79f1fb8ba0c594b63840ebd41f059e92b31957c46b74a4599b6d0", + "sha256:9e4d7ecfc600058e07ba661411a2b7de2fd0fafa17d1a7f7361cd47b1175c827", + "sha256:a2aeea129088da402665e92e0b25b04b073c04b2dce4ab65caaa38b7ce2e1a99" ], - "version": "==0.14" + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.15.2" }, "dominate": { "hashes": [ - "sha256:4076735c0745fe771e57b2313dbb4bfeec42731816ee23cee509f66e8912aa51", - "sha256:4b9fd42d2824b79761799590697db45bf93daad511b130c50513af38da33df9b" + "sha256:6e833aea505f0236a9fc692326bac575f8bd38ae0f3a1bdc73d20ca606ac75d5", + "sha256:a92474b4312bd8b4c1789792f3ec8c571cd8afa8e7502a2b1c64dd48cd67e59c" ], "index": "pypi", - "version": "==2.3.5" + "version": "==2.4.0" }, "elasticsearch": { "hashes": [ - "sha256:cbc73831c63fa2824538df76fcb2c4be007b43dbd9e7788ae70ea6d24109925b", - "sha256:d1b176b87a7fb75dca82978c82a4023e8b21cbc98f4018cb51190fb0b8b43764" + "sha256:693935914d59a517dfffdaab547ff906712a386d9e25027517464960221cbd4c", + "sha256:7644fa0a9ae524344185bda561826a781a5c6bd4d3eb98a24515c567aab88327" ], "index": "pypi", - "version": "==7.0.2" - }, - "entium": { - "hashes": [ - "sha256:233f39c6b5477e0c6fffd8d5cb7fc9df9deab80c79c7fb77e91f6d046782b0ce", - "sha256:4b14b4810a97ab041b629a0b59d21a98f5e197ee623d7b14925755ec4fd6888a" - ], - "index": "pypi", - "version": "==0.1.4" + "version": "==7.0.5" }, "entrypoints": { "hashes": [ "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19", "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451" ], + "markers": "python_version >= '2.7'", "version": "==0.3" }, - "enum34": { - "hashes": [ - "sha256:2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850", - "sha256:644837f692e5f550741432dd3f223bbb9852018674981b1664e5dc339387588a", - "sha256:6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79", - "sha256:8ad8c4783bf61ded74527bffb48ed9b54166685e4230386a9ed9b1279e2df5b1" - ], - "markers": "python_version < '3'", - "version": "==1.1.6" - }, "fastcluster": { "hashes": [ "sha256:0024b1304d4618a32900473b809265694bc6d0a10bfbc272407443318644d405", @@ -1114,27 +1042,11 @@ }, "flask-socketio": { "hashes": [ - "sha256:aced332903522a52822fb1e21744549510ce8b26e074422d4cd9aff68e43be5b", - "sha256:f6f7e0205f0dd92d98a87e3f6d26d94ade29ca380ba383b505070674c804ae2e" + "sha256:2172dff1e42415ba480cee02c30c2fc833671ff326f1598ee3d69aa02cf768ec", + "sha256:7ff5b2f5edde23e875a8b0abf868584e5706e11741557449bc5147df2cd78268" ], "index": "pypi", - "version": "==4.1.0" - }, - "funcsigs": { - "hashes": [ - "sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca", - "sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50" - ], - "markers": "python_version < '3.3'", - "version": "==1.0.2" - }, - "functools32": { - "hashes": [ - "sha256:89d824aa6c358c421a234d7f9ee0bd75933a67c29588ce50aaa3acdf4d403fa0", - "sha256:f6253dfbe0538ad2e387bd8fdfd9293c925d63553f5813c4e587745416501e6d" - ], - "markers": "python_version < '3'", - "version": "==3.2.3.post2" + "version": "==4.2.1" }, "future": { "hashes": [ @@ -1145,16 +1057,18 @@ }, "futures": { "hashes": [ - "sha256:49b3f5b064b6e3afc3316421a3f25f66c137ae88f068abbf72830170033c5e16", - "sha256:7e033af76a5e35f58e56da7a91e687706faf4e7bdfb2cbc3f2cca6b9bcda9794" + "sha256:3a44f286998ae64f0cc083682fcfec16c406134a81a589a5de445d7bb7c2751b", + "sha256:51ecb45f0add83c806c68e4b06106f90db260585b25ef2abfcda0bd95c0132fd", + "sha256:c4884a65654a7c45435063e14ae85280eb1f111d94e542396717ba9828c4337f" ], - "markers": "python_version < '3.2'", - "version": "==3.3.0" + "index": "pypi", + "version": "==3.1.1" }, "gast": { "hashes": [ "sha256:fe939df4583692f0512161ec1c880e0a10e71e6a232da045ab8edd3756fbadf0" ], + "index": "pypi", "version": "==0.2.2" }, "geoalchemy2": { @@ -1201,6 +1115,14 @@ "index": "pypi", "version": "==2.5.1" }, + "google-pasta": { + "hashes": [ + "sha256:40b4f55ba7b44823eac96d055000572c84ce48cacb3e91c100869844064b2d07", + "sha256:79d1ce28b381d68e98ef7707d19909adb58912f8dae8734402454424fc76b8fe", + "sha256:7ca8afc4cfeebf4a079cdf586333d5447cecd19a997475136138fc83c3351bc4" + ], + "version": "==0.1.7" + }, "greenlet": { "hashes": [ "sha256:000546ad01e6389e98626c1367be58efa613fa82a1be98b0c6fc24b563acc6d0", @@ -1228,40 +1150,40 @@ }, "grpcio": { "hashes": [ - "sha256:03b78b4e7dcdfe3e257bb528cc93923f9cbbab6d5babf15a60d21e9a4a70b1a2", - "sha256:1ce0ccfbdfe84387dbcbf44adb4ae16ec7ae70e166ffab478993eb1ea1cba3ce", - "sha256:22e167a9406d73dd19ffe8ed6a485f17e6eac82505be8c108897f15e68badcbb", - "sha256:31d0aeca8d8ee2301c62c5c340e0889d653b1280d68f9fa203982cb6337b050e", - "sha256:44c7f99ca17ebbcc96fc54ed00b454d8313f1eac28c563098d8b901025aff941", - "sha256:5471444f53f9db6a1f1f11f5dbc173228881df8446380b6b98f90afb8fd8348e", - "sha256:561bca3b1bde6d6564306eb05848fd155136e9c3a25d2961129b1e2edba22fce", - "sha256:5bf58e1d2c2f55365c06e8cb5abe067b88ca2e5550fb62009c41df4b54505acf", - "sha256:6b7163d1e85d76b0815df63fcc310daec02b44532bb433f743142d4febcb181f", - "sha256:766d79cddad95f5f6020037fe60ea8b98578afdf0c59d5a60c106c1bdd886303", - "sha256:770b7372d5ca68308ff66d7baee53369fa5ce985f84bcb6aa1948c1f2f7b02f2", - "sha256:7ab178da777fc0f55b6aef5a755f99726e8e4b75e3903954df07b27059b54fcf", - "sha256:8078305e77c2f6649d36b24d8778096413e474d9d7892c6f92cfb589c9d71b2e", - "sha256:85600b63a386d860eeaa955e9335e18dd0d7e5477e9214825abf2c2884488369", - "sha256:857d9b939ae128be1c0c792eb885c7ff6a386b9dea899ac4b06f4d90a31f9d87", - "sha256:87a41630c90c179fa5c593400f30a467c498972c702f348d41e19dafeb1d319e", - "sha256:8805d486c6128cc0fcc8ecf16c4095d99a8693a541ef851429ab334e028a4a97", - "sha256:8d71b7a89c306a41ccc7741fc9409b14f5b86727455c2a1c0c7cfcb0f784e1f2", - "sha256:9e1b80bd65f8f160880cb4dad7f55697f6d37b2d7f251fc0c2128e811928f369", - "sha256:9e290c84a145ae2411ee0ec9913c41cd7500e2e7485fe93632434d84ef4fda67", - "sha256:9ec9f88b5bc94bd99372f27cdd53af1c92ba06717380b127733b953cfb181174", - "sha256:a0a02a8b4ba6deadf706d5f849539b3685b72b186a3c9ef5d43e8972ed60fb6f", - "sha256:a4059c59519f5940e01a071f74ae2a60ea8f6185b03d22a09d40c7959a36b16b", - "sha256:a6e028c2a6da2ebfa2365a5b32531d311fbfec0e3600fc27e901b64f0ff7e54e", - "sha256:adcdebf9f8463df4120c427cf6c9aed39258bccd03ed37b6939e7a145d64d6e0", - "sha256:bdec982610259d07156a58f80b8c3e69be7751a9208bc577b059c5193d087fad", - "sha256:cefc4d4251ffb73feb303d4b7e9d6c367cb60f2db16d259ea28b114045f965aa", - "sha256:d4145c8aa6afbac10ad27e408f7ce15992fe89ba5d0b4abca31c0c2729864c03", - "sha256:da76dc5ad719ee99de5ea28a5629ff92172cbb4a70d8a6ae3a5b7a53c7382ce1", - "sha256:dde2452c08ef8b6426ccab6b5b6de9f06d836d9937d6870e68153cbf8cb49348", - "sha256:e3d88091d2539a4868750914a6fe7b9ec50e42b913851fc1b77423b5bd918530", - "sha256:f9c67cfe6278499d7f83559dc6322a8bbb108e307817a3d7acbfea807b3603cc" - ], - "version": "==1.22.0" + "sha256:0302331e014fc4bac028b6ad480b33f7abfe20b9bdcca7be417124dda8f22115", + "sha256:0aa0cce9c5eb1261b32173a20ed42b51308d55ce28ecc2021e868b3cb90d9503", + "sha256:0c83947575300499adbc308e986d754e7f629be0bdd9bea1ffdd5cf76e1f1eff", + "sha256:0ca26ff968d45efd4ef73447c4d4b34322ea8c7d06fbb6907ce9e5db78f1bbcb", + "sha256:0cf80a7955760c2498f8821880242bb657d70998065ff0d2a082de5ffce230a7", + "sha256:0d40706e57d9833fe0e023a08b468f33940e8909affa12547874216d36bba208", + "sha256:11872069156de34c6f3f9a1deb46cc88bc35dfde88262c4c73eb22b39b16fc55", + "sha256:16065227faae0ab0abf1789bfb92a2cd2ab5da87630663f93f8178026da40e0d", + "sha256:1e33778277685f6fabb22539136269c87c029e39b6321ef1a639b756a1c0a408", + "sha256:2b16be15b1ae656bc7a36642b8c7045be2dde2048bb4b67478003e9d9db8022a", + "sha256:3701dfca3ada27ceef0d17f728ce9dfef155ed20c57979c2b05083082258c6c1", + "sha256:41912ecaf482abf2de74c69f509878f99223f5dd6b2de1a09c955afd4de3cf9b", + "sha256:4332cbd20544fe7406910137590f38b5b3a1f6170258e038652cf478c639430f", + "sha256:44068ecbdc6467c2bff4d8198816c8a2701b6dd1ec16078fceb6adc7c1f577d6", + "sha256:53115960e37059420e2d16a4b04b00dd2ab3b6c3c67babd01ffbfdcd7881a69b", + "sha256:6e7027bcd4070414751e2a5e60706facb98a1fc636497c9bac5442fe37b8ae6b", + "sha256:6ff57fb2f07b7226b5bec89e8e921ea9bd220f35f11e094f2ba38f09eecd49c6", + "sha256:73240e244d7644654bbda1f309f4911748b6a1804b7a8897ddbe8a04c90f7407", + "sha256:785234bbc469bc75e26c868789a2080ffb30bd6e93930167797729889ad06b0b", + "sha256:82f9d3c7f91d2d1885631335c003c5d45ae1cd69cc0bc4893f21fef50b8151bc", + "sha256:86bdc2a965510658407a1372eb61f0c92f763fdfb2795e4d038944da4320c950", + "sha256:95e925b56676a55e6282b3de80a1cbad5774072159779c61eac02791dface049", + "sha256:96673bb4f14bd3263613526d1e7e33fdb38a9130e3ce87bf52314965706e1900", + "sha256:970014205e76920484679035b6fb4b16e02fc977e5aac4d22025da849c79dab9", + "sha256:ace5e8bf11a1571f855f5dab38a9bd34109b6c9bc2864abf24a597598c7e3695", + "sha256:ad375f03eb3b9cb75a24d91eab8609e134d34605f199efc41e20dd642bdac855", + "sha256:b819c4c7dcf0de76788ce5f95daad6d4e753d6da2b6a5f84e5bb5b5ce95fddc4", + "sha256:c17943fd340cbd906db49f3f03c7545e5a66b617e8348b2c7a0d2c759d216af1", + "sha256:d21247150dea86dabd3b628d8bc4b563036db3d332b3f4db3c5b1b0b122cb4f6", + "sha256:d4d500a7221116de9767229ff5dd10db91f789448d85befb0adf5a37b0cd83b5", + "sha256:e2a942a3cfccbbca21a90c144867112698ef36486345c285da9e98c466f22b22", + "sha256:e983273dca91cb8a5043bc88322eb48e2b8d4e4998ff441a1ee79ced89db3909" + ], + "version": "==1.24.1" }, "gunicorn": { "hashes": [ @@ -1273,37 +1195,36 @@ }, "h5py": { "hashes": [ - "sha256:05750b91640273c69989c657eaac34b091abdd75efc8c4824c82aaf898a2da0a", - "sha256:082a27208aa3a2286e7272e998e7e225b2a7d4b7821bd840aebf96d50977abbb", - "sha256:08e2e8297195f9e813e894b6c63f79372582787795bba2014a2db6a2de95f713", - "sha256:0dd2adeb2e9de5081eb8dcec88874e7fd35dae9a21557be3a55a3c7d491842a4", - "sha256:0f94de7a10562b991967a66bbe6dda9808e18088676834c0a4dcec3fdd3bcc6f", - "sha256:106e42e2e01e486a3d32eeb9ba0e3a7f65c12fa8998d63625fa41fb8bdc44cdb", - "sha256:1606c66015f04719c41a9863c156fc0e6b992150de21c067444bcb82e7d75579", - "sha256:1854c4beff9961e477e133143c5e5e355dac0b3ebf19c52cf7cc1b1ef757703c", - "sha256:1e9fb6f1746500ea91a00193ce2361803c70c6b13f10aae9a33ad7b5bd28e800", - "sha256:2cca17e80ddb151894333377675db90cd0279fa454776e0a4f74308376afd050", - "sha256:30e365e8408759db3778c361f1e4e0fe8e98a875185ae46c795a85e9bafb9cdf", - "sha256:3206bac900e16eda81687d787086f4ffd4f3854980d798e191a9868a6510c3ae", - "sha256:3c23d72058647cee19b30452acc7895621e2de0a0bd5b8a1e34204b9ea9ed43c", - "sha256:407b5f911a83daa285bbf1ef78a9909ee5957f257d3524b8606be37e8643c5f0", - "sha256:4162953714a9212d373ac953c10e3329f1e830d3c7473f2a2e4f25dd6241eef0", - "sha256:5fc7aba72a51b2c80605eba1c50dbf84224dcd206279d30a75c154e5652e1fe4", - "sha256:713ac19307e11de4d9833af0c4bd6778bde0a3d967cafd2f0f347223711c1e31", - "sha256:71b946d80ef3c3f12db157d7778b1fe74a517ca85e94809358b15580983c2ce2", - "sha256:8cc4aed71e20d87e0a6f02094d718a95252f11f8ed143bc112d22167f08d4040", - "sha256:9d41ca62daf36d6b6515ab8765e4c8c4388ee18e2a665701fef2b41563821002", - "sha256:a744e13b000f234cd5a5b2a1f95816b819027c57f385da54ad2b7da1adace2f3", - "sha256:b087ee01396c4b34e9dc41e3a6a0442158206d383c19c7d0396d52067b17c1cb", - "sha256:b0f03af381d33306ce67d18275b61acb4ca111ced645381387a02c8a5ee1b796", - "sha256:b9e4b8dfd587365bdd719ae178fa1b6c1231f81280b1375eef8626dfd8761bf3", - "sha256:c5dd4ec75985b99166c045909e10f0534704d102848b1d9f0992720e908928e7", - "sha256:d2b82f23cd862a9d05108fe99967e9edfa95c136f532a71cb3d28dc252771f50", - "sha256:e58a25764472af07b7e1c4b10b0179c8ea726446c7141076286e41891bf3a563", - "sha256:f3b49107fbfc77333fc2b1ef4d5de2abcd57e7ea3a1482455229494cf2da56ce" - ], - "index": "pypi", - "version": "==2.9.0" + "sha256:063947eaed5f271679ed4ffa36bb96f57bc14f44dd4336a827d9a02702e6ce6b", + "sha256:13c87efa24768a5e24e360a40e0bc4c49bcb7ce1bb13a3a7f9902cec302ccd36", + "sha256:16ead3c57141101e3296ebeed79c9c143c32bdd0e82a61a2fc67e8e6d493e9d1", + "sha256:3dad1730b6470fad853ef56d755d06bb916ee68a3d8272b3bab0c1ddf83bb99e", + "sha256:51ae56894c6c93159086ffa2c94b5b3388c0400548ab26555c143e7cfa05b8e5", + "sha256:54817b696e87eb9e403e42643305f142cd8b940fe9b3b490bbf98c3b8a894cf4", + "sha256:549ad124df27c056b2e255ea1c44d30fb7a17d17676d03096ad5cd85edb32dc1", + "sha256:6998be619c695910cb0effe5eb15d3a511d3d1a5d217d4bd0bebad1151ec2262", + "sha256:6ef7ab1089e3ef53ca099038f3c0a94d03e3560e6aff0e9d6c64c55fb13fc681", + "sha256:769e141512b54dee14ec76ed354fcacfc7d97fea5a7646b709f7400cf1838630", + "sha256:79b23f47c6524d61f899254f5cd5e486e19868f1823298bc0c29d345c2447172", + "sha256:7be5754a159236e95bd196419485343e2b5875e806fe68919e087b6351f40a70", + "sha256:84412798925dc870ffd7107f045d7659e60f5d46d1c70c700375248bf6bf512d", + "sha256:86868dc07b9cc8cb7627372a2e6636cdc7a53b7e2854ad020c9e9d8a4d3fd0f5", + "sha256:8bb1d2de101f39743f91512a9750fb6c351c032e5cd3204b4487383e34da7f75", + "sha256:a5f82cd4938ff8761d9760af3274acf55afc3c91c649c50ab18fcff5510a14a5", + "sha256:aac4b57097ac29089f179bbc2a6e14102dd210618e94d77ee4831c65f82f17c0", + "sha256:bffbc48331b4a801d2f4b7dac8a72609f0b10e6e516e5c480a3e3241e091c878", + "sha256:c0d4b04bbf96c47b6d360cd06939e72def512b20a18a8547fa4af810258355d5", + "sha256:c54a2c0dd4957776ace7f95879d81582298c5daf89e77fb8bee7378f132951de", + "sha256:cbf28ae4b5af0f05aa6e7551cee304f1d317dbed1eb7ac1d827cee2f1ef97a99", + "sha256:d3c59549f90a891691991c17f8e58c8544060fdf3ccdea267100fa5f561ff62f", + "sha256:d7ae7a0576b06cb8e8a1c265a8bc4b73d05fdee6429bffc9a26a6eb531e79d72", + "sha256:ecf4d0b56ee394a0984de15bceeb97cbe1fe485f1ac205121293fc44dcf3f31f", + "sha256:f0e25bb91e7a02efccb50aba6591d3fe2c725479e34769802fcdd4076abfa917", + "sha256:f23951a53d18398ef1344c186fb04b26163ca6ce449ebd23404b153fd111ded9", + "sha256:ff7d241f866b718e4584fa95f520cb19405220c501bd3a53ee11871ba5166ea2" + ], + "index": "pypi", + "version": "==2.10.0" }, "hexdump": { "hashes": [ @@ -1314,10 +1235,11 @@ }, "html5lib": { "hashes": [ - "sha256:2612a191a8d5842bfa057e41ba50bbb9dcb722419d2408c78cff4758d0754868" + "sha256:20b159aa3badc9d5ee8f5c647e5efd02ed2a66ab8d354930bd9ff139fc1dc0a3", + "sha256:66cb0dcfdbbc4f9c3ba1a63fdb511ffdbd4f513b2b6d81b80cd26ce6b3fb3736" ], "index": "pypi", - "version": "==0.9999999" + "version": "==1.0.1" }, "humanfriendly": { "hashes": [ @@ -1342,6 +1264,14 @@ "index": "pypi", "version": "==2.5.0" }, + "importlib-metadata": { + "hashes": [ + "sha256:aa18d7378b00b40847790e7c27e11673d7fed219354109d0e7b9e5b25dc3ad26", + "sha256:d5f18a79777f3aa179c145737780282e27b508fc8fd688cb17c7a813e8bd39af" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.23" + }, "intervaltree": { "hashes": [ "sha256:cb4f61c81dcb4fea6c09903f3599015a83c9bdad1f0bbd232495e6681e19e273" @@ -1349,31 +1279,21 @@ "index": "pypi", "version": "==3.0.2" }, - "ipaddress": { - "hashes": [ - "sha256:64b28eec5e78e7510698f6d4da08800a5c575caa4a286c93d651c5d3ff7b6794", - "sha256:b146c751ea45cad6188dd6cf2d9b757f6f4f8d6ffb96a023e6f2e26eea02a72c" - ], - "markers": "python_version < '3'", - "version": "==1.0.22" - }, "ipykernel": { "hashes": [ - "sha256:56d82987472f4b14ab0214e4aef55def006671885d285cd8821f2600861215a6", - "sha256:59b0855082d021f533cff477e1bb619e663b6aab11309a05bf88eaec9f53faed", - "sha256:699103c8e64886e3ec7053f2a6aa83bb90426063526f63a818732ff385202bad" + "sha256:167c3ef08450f5e060b76c749905acb0e0fbef9365899377a4a1eae728864383", + "sha256:b503913e0b4cce7ed2de965457dfb2edd633e8234161a60e23f2fe2161345d12" ], "index": "pypi", - "version": "==4.10.0" + "version": "==5.1.2" }, "ipython": { "hashes": [ - "sha256:0371b7e4bd74954a35086eac949beeac5b1c9f5ce231e2e77df2286a293765e3", - "sha256:37101b8cbe072fe17bff100bc03d096404e4a9a0357097aeb5b61677c042cab1", - "sha256:4bac649857611baaaf76bc82c173aa542f7486446c335fe1a6c05d0d491c8906" + "sha256:c4ab005921641e40a68e405e286e7a1fcc464497e14d81b6914b4fd95e5dee9b", + "sha256:dd76831f065f17bddd7eaa5c781f5ea32de5ef217592cf019e34043b56895aa1" ], "index": "pypi", - "version": "==5.8.0" + "version": "==7.8.0" }, "ipython-genutils": { "hashes": [ @@ -1384,23 +1304,17 @@ }, "ipywidgets": { "hashes": [ - "sha256:cb263c6974aca902d00a435711823bb4aaf6614a5f997f517e15fa84151e8fa2", - "sha256:eab6060f20f7f10d91f6efc8d33f9fd22133406980fcaee2738d836a910402f4" + "sha256:13ffeca438e0c0f91ae583dc22f50379b9d6b28390ac7be8b757140e9a771516", + "sha256:e945f6e02854a74994c596d9db83444a1850c01648f1574adf144fbbabe05c97" ], - "version": "==7.5.0" - }, - "isodate": { - "hashes": [ - "sha256:2e364a3d5759479cdb2d37cce6b9376ea504db2ff90252a2e5b7cc89cc9ff2d8", - "sha256:aa4d33c06640f5352aca96e4b81afd8ab3b47337cc12089822d6f322ac772c81" - ], - "version": "==0.6.0" + "version": "==7.5.1" }, "isort": { "hashes": [ "sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1", "sha256:6e811fcb295968434526407adb8796944f1988c5b65e8139058f2014cbe100fd" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==4.3.21" }, "itsdangerous": { @@ -1408,8 +1322,17 @@ "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19", "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.1.0" }, + "jedi": { + "hashes": [ + "sha256:786b6c3d80e2f06fd77162a07fed81b8baa22dde5d62896a790a331d6ac21a27", + "sha256:ba859c74fa3c966a22f2aeebe1b74ee27e2a462f56d3f5f7ca4a59af61bfe42e" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.15.1" + }, "jinja2": { "hashes": [ "sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013", @@ -1427,11 +1350,11 @@ }, "joblib": { "hashes": [ - "sha256:21e0c34a69ad7fde4f2b1f3402290e9ec46f545f15f1541c582edfe05d87b63a", - "sha256:315d6b19643ec4afd4c41c671f9f2d65ea9d787da093487a81ead7b0bac94524" + "sha256:006108c7576b3eb6c5b27761ddbf188eb6e6347696325ab2027ea1ee9a4b922d", + "sha256:6fcc57aacb4e89451fd449e9412687c51817c3f48662c3d8f38ba3f8a0a193ff" ], "index": "pypi", - "version": "==0.13.2" + "version": "==0.14.0" }, "json-logging-py": { "hashes": [ @@ -1442,10 +1365,10 @@ }, "jsonschema": { "hashes": [ - "sha256:0c0a81564f181de3212efa2d17de1910f8732fa1b71c42266d983cd74304e20d", - "sha256:a5f6559964a3851f59040d3b961de5e68e70971afb88ba519d27e6a039efff1a" + "sha256:5f9c0a719ca2ce14c5de2fd350a64fd2d13e8539db29836a86adc990bb1a068f", + "sha256:8d4a2b7b6c2237e0199c8ea1a6d3e05bf118e289ae2b9d7ba444182a2959560d" ], - "version": "==3.0.1" + "version": "==3.0.2" }, "jupyter": { "hashes": [ @@ -1458,33 +1381,28 @@ }, "jupyter-client": { "hashes": [ - "sha256:73a809a2964afa07adcc1521537fddb58c2ffbb7e84d53dc5901cf80480465b3", - "sha256:98e8af5edff5d24e4d31e73bc21043130ae9d955a91aa93fc0bc3b1d0f7b5880" + "sha256:6a6d415c62179728f6d9295b37356d8f6833e9e01c2b6e1901dc555571f57b21", + "sha256:f406f214f9daa92be110d5b83d62f3451ffc73d3522db7350f0554683533ab18" ], - "version": "==5.3.1" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==5.3.3" }, "jupyter-console": { "hashes": [ - "sha256:3f928b817fc82cda95e431eb4c2b5eb21be5c483c2b43f424761a966bb808094", - "sha256:545dedd3aaaa355148093c5609f0229aeb121b4852995c2accfa64fe3e0e55cd" + "sha256:308ce876354924fb6c540b41d5d6d08acfc946984bf0c97777c1ddcb42e0b2f5", + "sha256:cc80a97a5c389cbd30252ffb5ce7cefd4b66bde98219edd16bf5cb6f84bb3568" ], - "version": "==5.2.0" + "markers": "python_version >= '3.5'", + "version": "==6.0.0" }, "jupyter-core": { "hashes": [ "sha256:2c6e7c1e9f2ac45b5c2ceea5730bc9008d92fe59d0725eac57b04c0edfba24f7", "sha256:f4fa22d6cf25f34807c995f22d2923693575c70f02557bcbfbe59bd5ec8d8b84" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==4.5.0" }, - "keras": { - "hashes": [ - "sha256:794d0c92c6c4122f1f0fcf3a7bc2f49054c6a54ddbef8d8ffafca62795d760b6", - "sha256:90b610a3dbbf6d257b20a079eba3fdf2eed2158f64066a7c6f7227023fd60bc9" - ], - "index": "pypi", - "version": "==2.2.4" - }, "keras-applications": { "hashes": [ "sha256:5579f9a12bcde9748f4a12233925a59b93b73ae6947409ff34aa2ba258189fe5", @@ -1492,13 +1410,6 @@ ], "version": "==1.0.8" }, - "keras-maskrcnn": { - "hashes": [ - "sha256:9e2258390d749986fe6dc05aabdd7198ae689e60696b6a5568929379457a2e98" - ], - "index": "pypi", - "version": "==0.2.2" - }, "keras-preprocessing": { "hashes": [ "sha256:44aee5f2c4d80c3b29f208359fcb336df80f293a0bb6b1c738da43ca206656fb", @@ -1506,19 +1417,6 @@ ], "version": "==1.1.0" }, - "keras-resnet": { - "hashes": [ - "sha256:8ce27ba782d1b45b127af51208aefdceb2de8d2c54646bac5fc786506ce558c0" - ], - "version": "==0.2.0" - }, - "keras-retinanet": { - "hashes": [ - "sha256:6d4da9d83a9a82cb025298a88256546bc625e9c78cd4f1bbec576d11295910b6" - ], - "index": "pypi", - "version": "==0.5.1" - }, "kiwisolver": { "hashes": [ "sha256:05b5b061e09f60f56244adc885c4a7867da25ca387376b02c1efc29cc16bcd0f", @@ -1550,37 +1448,40 @@ "sha256:f2b22153870ca5cf2ab9c940d7bc38e8e9089fa0f7e5856ea195e1cf4ff43d5a", "sha256:f790f8b3dff3d53453de6a7b7ddd173d2e020fb160baff578d578065b108a05f" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.1.0" }, "kombu": { "hashes": [ - "sha256:55b71d3785def3470a16217fe0780f9e6f95e61bf9ad39ef8dce0177224eab77", - "sha256:eb365ea795cd7e629ba2f1f398e0c3ba354b91ef4de225ffdf6ab45fdfc7d581" + "sha256:31edb84947996fdda065b6560c128d5673bb913ff34aa19e7b84755217a24deb", + "sha256:c9078124ce2616b29cf6607f0ac3db894c59154252dee6392cdbbe15e5c4b566" ], - "version": "==4.6.3" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==4.6.5" }, "lazy-object-proxy": { "hashes": [ - "sha256:159a745e61422217881c4de71f9eafd9d703b93af95618635849fe469a283661", - "sha256:23f63c0821cc96a23332e45dfaa83266feff8adc72b9bcaef86c202af765244f", - "sha256:3b11be575475db2e8a6e11215f5aa95b9ec14de658628776e10d96fa0b4dac13", - "sha256:3f447aff8bc61ca8b42b73304f6a44fa0d915487de144652816f950a3f1ab821", - "sha256:4ba73f6089cd9b9478bc0a4fa807b47dbdb8fad1d8f31a0f0a5dbf26a4527a71", - "sha256:4f53eadd9932055eac465bd3ca1bd610e4d7141e1278012bd1f28646aebc1d0e", - "sha256:64483bd7154580158ea90de5b8e5e6fc29a16a9b4db24f10193f0c1ae3f9d1ea", - "sha256:6f72d42b0d04bfee2397aa1862262654b56922c20a9bb66bb76b6f0e5e4f9229", - "sha256:7c7f1ec07b227bdc561299fa2328e85000f90179a2f44ea30579d38e037cb3d4", - "sha256:7c8b1ba1e15c10b13cad4171cfa77f5bb5ec2580abc5a353907780805ebe158e", - "sha256:8559b94b823f85342e10d3d9ca4ba5478168e1ac5658a8a2f18c991ba9c52c20", - "sha256:a262c7dfb046f00e12a2bdd1bafaed2408114a89ac414b0af8755c696eb3fc16", - "sha256:acce4e3267610c4fdb6632b3886fe3f2f7dd641158a843cf6b6a68e4ce81477b", - "sha256:be089bb6b83fac7f29d357b2dc4cf2b8eb8d98fe9d9ff89f9ea6012970a853c7", - "sha256:bfab710d859c779f273cc48fb86af38d6e9210f38287df0069a63e40b45a2f5c", - "sha256:c10d29019927301d524a22ced72706380de7cfc50f767217485a912b4c8bd82a", - "sha256:dd6e2b598849b3d7aee2295ac765a578879830fb8966f70be8cd472e6069932e", - "sha256:e408f1eacc0a68fed0c08da45f31d0ebb38079f043328dce69ff133b95c29dc1" - ], - "version": "==1.4.1" + "sha256:02b260c8deb80db09325b99edf62ae344ce9bc64d68b7a634410b8e9a568edbf", + "sha256:18f9c401083a4ba6e162355873f906315332ea7035803d0fd8166051e3d402e3", + "sha256:1f2c6209a8917c525c1e2b55a716135ca4658a3042b5122d4e3413a4030c26ce", + "sha256:2f06d97f0ca0f414f6b707c974aaf8829c2292c1c497642f63824119d770226f", + "sha256:616c94f8176808f4018b39f9638080ed86f96b55370b5a9463b2ee5c926f6c5f", + "sha256:63b91e30ef47ef68a30f0c3c278fbfe9822319c15f34b7538a829515b84ca2a0", + "sha256:77b454f03860b844f758c5d5c6e5f18d27de899a3db367f4af06bec2e6013a8e", + "sha256:83fe27ba321e4cfac466178606147d3c0aa18e8087507caec78ed5a966a64905", + "sha256:84742532d39f72df959d237912344d8a1764c2d03fe58beba96a87bfa11a76d8", + "sha256:874ebf3caaf55a020aeb08acead813baf5a305927a71ce88c9377970fe7ad3c2", + "sha256:9f5caf2c7436d44f3cec97c2fa7791f8a675170badbfa86e1992ca1b84c37009", + "sha256:a0c8758d01fcdfe7ae8e4b4017b13552efa7f1197dd7358dc9da0576f9d0328a", + "sha256:a4def978d9d28cda2d960c279318d46b327632686d82b4917516c36d4c274512", + "sha256:ad4f4be843dace866af5fc142509e9b9817ca0c59342fdb176ab6ad552c927f5", + "sha256:ae33dd198f772f714420c5ab698ff05ff900150486c648d29951e9c70694338e", + "sha256:b4a2b782b8a8c5522ad35c93e04d60e2ba7f7dcb9271ec8e8c3e08239be6c7b4", + "sha256:c462eb33f6abca3b34cdedbe84d761f31a60b814e173b98ede3c81bb48967c4f", + "sha256:fd135b8d35dfdcdb984828c84d695937e58cc5f49e1c854eb311c4d6aa03f4f1" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.4.2" }, "libarchive": { "hashes": [ @@ -1605,39 +1506,38 @@ }, "lxml": { "hashes": [ - "sha256:06c7616601430aa140a69f97e3116308fffe0848f543b639a5ec2e8920ae72fd", - "sha256:177202792f9842374a8077735c69c41a4282183f7851443d2beb8ee310720819", - "sha256:19317ad721ceb9e39847d11131903931e2794e447d4751ebb0d9236f1b349ff2", - "sha256:36d206e62f3e5dbaafd4ec692b67157e271f5da7fd925fda8515da675eace50d", - "sha256:387115b066c797c85f9861a9613abf50046a15aac16759bc92d04f94acfad082", - "sha256:3ce1c49d4b4a7bc75fb12acb3a6247bb7a91fe420542e6d671ba9187d12a12c2", - "sha256:4d2a5a7d6b0dbb8c37dab66a8ce09a8761409c044017721c21718659fa3365a1", - "sha256:58d0a1b33364d1253a88d18df6c0b2676a1746d27c969dc9e32d143a3701dda5", - "sha256:62a651c618b846b88fdcae0533ec23f185bb322d6c1845733f3123e8980c1d1b", - "sha256:69ff21064e7debc9b1b1e2eee8c2d686d042d4257186d70b338206a80c5bc5ea", - "sha256:7060453eba9ba59d821625c6af6a266bd68277dce6577f754d1eb9116c094266", - "sha256:7d26b36a9c4bce53b9cfe42e67849ae3c5c23558bc08363e53ffd6d94f4ff4d2", - "sha256:83b427ad2bfa0b9705e02a83d8d607d2c2f01889eb138168e462a3a052c42368", - "sha256:923d03c84534078386cf50193057aae98fa94cace8ea7580b74754493fda73ad", - "sha256:b773715609649a1a180025213f67ffdeb5a4878c784293ada300ee95a1f3257b", - "sha256:baff149c174e9108d4a2fee192c496711be85534eab63adb122f93e70aa35431", - "sha256:bca9d118b1014b4c2d19319b10a3ebed508ff649396ce1855e1c96528d9b2fa9", - "sha256:ce580c28845581535dc6000fc7c35fdadf8bea7ccb57d6321b044508e9ba0685", - "sha256:d34923a569e70224d88e6682490e24c842907ba2c948c5fd26185413cbe0cd96", - "sha256:dd9f0e531a049d8b35ec5e6c68a37f1ba6ec3a591415e6804cbdf652793d15d7", - "sha256:ecb805cbfe9102f3fd3d2ef16dfe5ae9e2d7a7dfbba92f4ff1e16ac9784dbfb0", - "sha256:ede9aad2197a0202caff35d417b671f5f91a3631477441076082a17c94edd846", - "sha256:ef2d1fc370400e0aa755aab0b20cf4f1d0e934e7fd5244f3dd4869078e4942b9", - "sha256:f2fec194a49bfaef42a548ee657362af5c7a640da757f6f452a35da7dd9f923c" - ], - "index": "pypi", - "version": "==4.3.4" + "sha256:02ca7bf899da57084041bb0f6095333e4d239948ad3169443f454add9f4e9cb4", + "sha256:096b82c5e0ea27ce9138bcbb205313343ee66a6e132f25c5ed67e2c8d960a1bc", + "sha256:0a920ff98cf1aac310470c644bc23b326402d3ef667ddafecb024e1713d485f1", + "sha256:17cae1730a782858a6e2758fd20dd0ef7567916c47757b694a06ffafdec20046", + "sha256:17e3950add54c882e032527795c625929613adbd2ce5162b94667334458b5a36", + "sha256:1f4f214337f6ee5825bf90a65d04d70aab05526c08191ab888cb5149501923c5", + "sha256:2e8f77db25b0a96af679e64ff9bf9dddb27d379c9900c3272f3041c4d1327c9d", + "sha256:4dffd405390a45ecb95ab5ab1c1b847553c18b0ef8ed01e10c1c8b1a76452916", + "sha256:6b899931a5648862c7b88c795eddff7588fb585e81cecce20f8d9da16eff96e0", + "sha256:726c17f3e0d7a7200718c9a890ccfeab391c9133e363a577a44717c85c71db27", + "sha256:760c12276fee05c36f95f8040180abc7fbebb9e5011447a97cdc289b5d6ab6fc", + "sha256:796685d3969815a633827c818863ee199440696b0961e200b011d79b9394bbe7", + "sha256:891fe897b49abb7db470c55664b198b1095e4943b9f82b7dcab317a19116cd38", + "sha256:a471628e20f03dcdfde00770eeaf9c77811f0c331c8805219ca7b87ac17576c5", + "sha256:a63b4fd3e2cabdcc9d918ed280bdde3e8e9641e04f3c59a2a3109644a07b9832", + "sha256:b0b84408d4eabc6de9dd1e1e0bc63e7731e890c0b378a62443e5741cfd0ae90a", + "sha256:be78485e5d5f3684e875dab60f40cddace2f5b2a8f7fede412358ab3214c3a6f", + "sha256:c27eaed872185f047bb7f7da2d21a7d8913457678c9a100a50db6da890bc28b9", + "sha256:c81cb40bff373ab7a7446d6bbca0190bccc5be3448b47b51d729e37799bb5692", + "sha256:d11874b3c33ee441059464711cd365b89fa1a9cf19ae75b0c189b01fbf735b84", + "sha256:e9c028b5897901361d81a4718d1db217b716424a0283afe9d6735fe0caf70f79", + "sha256:fe489d486cd00b739be826e8c1be188ddb74c7a1ca784d93d06fda882a6a1681" + ], + "index": "pypi", + "version": "==4.4.1" }, "markdown": { "hashes": [ "sha256:2e50876bcdd74517e7b71f3e7a76102050edec255b3983403f1a63e7c8a41e7a", "sha256:56a46ac655704b91e5b7e6326ce43d5ef72411376588afa1dd90e881b83c7e8c" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==3.1.1" }, "markupsafe": { @@ -1671,35 +1571,23 @@ "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.1.1" }, "matplotlib": { "hashes": [ - "sha256:0ba8e3ec1b0feddc6b068fe70dc38dcf2917e301ad8d2b3f848c14ad463a4157", - "sha256:10a48e33e64dbd95f0776ba162f379c5cc55301c2d155506e79ce0c26b52f2ce", - "sha256:1376535fe731adbba55ab9e48896de226b7e89dbb55390c5fbd8f7161b7ae3be", - "sha256:16f0f8ba22df1e2c9f06c87088de45742322fde282a93b5c744c0f969cf7932e", - "sha256:1c6c999f2212858021329537f8e0f98f3f29086ec3683511dd1ecec84409f51d", - "sha256:2316dc177fc7b3d8848b49365498de0c385b4c9bba511edddd24c34fbe3d37a4", - "sha256:3398bfb533482bf21974cecf28224dd23784ad4e4848be582903f7a2436ec12e", - "sha256:3477cb1e1061b34210acc43d20050be8444478ff50b8adfac5fe2b45fc97df01", - "sha256:3cc06333b8264428d02231804e2e726b902e9161dc16f573183dee6cb7ef621f", - "sha256:4259ea7cb2c238355ee13275eddd261d869cefbdeb18a65f35459589d6d17def", - "sha256:4addcf93234b6122f530f90f485fd3d00d158911fbc1ed24db3fa66cd49fe565", - "sha256:50c0e24bcbce9c54346f4a2f4e97b0ed111f0413ac3fe9954061ae1c8aa7021f", - "sha256:62ed7597d9e54db6e133420d779c642503c25eba390e1178d85dfb2ba0d05948", - "sha256:69f6d51e41a17f6a5f70c56bb10b8ded9f299609204495a7fa2782a3a755ffc5", - "sha256:6d232e49b74e3d2db22c63c25a9a0166d965e87e2b057f795487f1f244b61d9d", - "sha256:7355bf757ecacd5f0ac9dd9523c8e1a1103faadf8d33c22664178e17533f8ce5", - "sha256:886b1045c5105631f10c1cbc999f910e44d33af3e9c7efd68c2123efc06ab636", - "sha256:9e1f353edd7fc7e5e9101abd5bc0201946f77a1b59e0da49095086c03db856ed", - "sha256:b3a343dfcbe296dbe0f26c731beee72a792ff948407e6979524298ae7bc3234e", - "sha256:d93675af09ca497a25f4f8d62f3313cf0f21e45427a87487049fe84898b99909", - "sha256:e2409ef9d37804dfb566f39c962e6ed70f281ff516b8131b3e6b4e6442711ff1", - "sha256:f8b653b0f89938ba72e92ab080c2f3aa24c1b72e2f61add22880cd1b9a6e3cdd" - ], - "index": "pypi", - "version": "==2.2.3" + "sha256:1febd22afe1489b13c6749ea059d392c03261b2950d1d45c17e3aed812080c93", + "sha256:31a30d03f39528c79f3a592857be62a08595dec4ac034978ecd0f814fa0eec2d", + "sha256:4442ce720907f67a79d45de9ada47be81ce17e6c2f448b3c64765af93f6829c9", + "sha256:796edbd1182cbffa7e1e7a97f1e141f875a8501ba8dd834269ae3cd45a8c976f", + "sha256:934e6243df7165aad097572abf5b6003c77c9b6c480c3c4de6f2ef1b5fdd4ec0", + "sha256:bab9d848dbf1517bc58d1f486772e99919b19efef5dd8596d4b26f9f5ee08b6b", + "sha256:c1fe1e6cdaa53f11f088b7470c2056c0df7d80ee4858dadf6cbe433fcba4323b", + "sha256:e5b8aeca9276a3a988caebe9f08366ed519fff98f77c6df5b64d7603d0e42e36", + "sha256:ec6bd0a6a58df3628ff269978f4a4b924a0d371ad8ce1f8e2b635b99e482877a" + ], + "index": "pypi", + "version": "==3.1.1" }, "mccabe": { "hashes": [ @@ -1710,10 +1598,10 @@ }, "meld3": { "hashes": [ - "sha256:b28a9bfac342aadb4557aa144bea9f8e6208bfb0596190570d10a892d35ff7dc", - "sha256:f7b754a0fde7a4429b2ebe49409db240b5699385a572501bb0d5627d299f9558" + "sha256:1efda676264490db2e30bfb81b27a918cc6d9c2de6d609491aa43410b9537eb9", + "sha256:a78cdcb6c0342b7ac82d900b584bd918ef72f86b60cdbf04754f840c070eb20c" ], - "version": "==1.0.2" + "version": "==2.0.0" }, "mistune": { "hashes": [ @@ -1727,6 +1615,7 @@ "sha256:83657d894c90d5681d62155c82bda9c1187827525880eda8ff5df4ec813437c3", "sha256:d157e52d4e5b938c550f39eb2fd15610db062441a9c2747d3dbfa9298211d0f8" ], + "index": "pypi", "version": "==3.0.5" }, "monotonic": { @@ -1734,9 +1623,16 @@ "sha256:23953d55076df038541e648a53676fb24980f7a1be290cdda21300b3bc21dfb0", "sha256:552a91f381532e33cbd07c6a2655a21908088962bb8fa7239ecbcc6ad1140cc7" ], - "markers": "python_version == '2.6' or python_version == '2.7' or python_version == '3.0' or python_version == '3.1' or python_version == '3.2'", "version": "==1.5" }, + "more-itertools": { + "hashes": [ + "sha256:409cd48d4db7052af495b09dec721011634af3753ae1ef92d2b32f73a745f832", + "sha256:92b8c4b06dac4f0611c0729b2f2ede52b2e1bac1ab48f089c7ddc12e26bb60c4" + ], + "markers": "python_version >= '3.4'", + "version": "==7.2.0" + }, "mpld3": { "hashes": [ "sha256:4d455884a211bf99b37ecc760759435c7bb6a5955de47d8daf4967e301878ab7" @@ -1751,26 +1647,13 @@ "index": "pypi", "version": "==0.5.6" }, - "msrest": { - "hashes": [ - "sha256:2c0909570913785a4408a17286e151f3b28d39277113e5c63378572f7395c660", - "sha256:c9e9cbb0c47745f9f5c82cce60849d7c3ec9e33fc6fad9e2987b7657ad1ba479" - ], - "version": "==0.6.8" - }, - "msrestazure": { - "hashes": [ - "sha256:070220fa9c86b55026360435b655d1d67ff4306fd1412687c400dc549e9647b7", - "sha256:e9d525b11d88f1073744e128ae19a4e023e4085893cfcfd02483fdd4cee25091" - ], - "version": "==0.6.1" - }, "nbconvert": { "hashes": [ - "sha256:138381baa41d83584459b5cfecfc38c800ccf1f37d9ddd0bd440783346a4c39c", - "sha256:4a978548d8383f6b2cfca4a3b0543afb77bc7cb5a96e8b424337ab58c12da9bc" + "sha256:427a468ec26e7d68a529b95f578d5cbf018cb4c1f889e897681c2b6d11897695", + "sha256:48d3c342057a2cf21e8df820d49ff27ab9f25fc72b8f15606bd47967333b2709" ], - "version": "==5.5.0" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==5.6.0" }, "nbformat": { "hashes": [ @@ -1789,9 +1672,10 @@ }, "networkx": { "hashes": [ - "sha256:45e56f7ab6fe81652fb4bc9f44faddb0e9025f469f602df14e3b2551c2ea5c8b" + "sha256:8311ddef63cf5c5c5e7c1d0212dd141d9a1fe3f474915281b73597ed5f1d4e3d" ], - "version": "==2.2" + "markers": "python_version >= '3.5'", + "version": "==2.3" }, "nose": { "hashes": [ @@ -1812,131 +1696,122 @@ }, "notebook": { "hashes": [ - "sha256:573e0ae650c5d76b18b6e564ba6d21bf321d00847de1d215b418acb64f056eb8", - "sha256:f64fa6624d2323fbef6210a621817d6505a45d0d4a9367f1843b20a38a4666ee" + "sha256:660976fe4fe45c7aa55e04bf4bccb9f9566749ff637e9020af3422f9921f9a5d", + "sha256:b0a290f5cc7792d50a21bec62b3c221dd820bf00efa916ce9aeec4b5354bde20" ], - "version": "==5.7.8" + "markers": "python_version >= '3.5'", + "version": "==6.0.1" }, "numpy": { "hashes": [ - "sha256:0778076e764e146d3078b17c24c4d89e0ecd4ac5401beff8e1c87879043a0633", - "sha256:141c7102f20abe6cf0d54c4ced8d565b86df4d3077ba2343b61a6db996cefec7", - "sha256:14270a1ee8917d11e7753fb54fc7ffd1934f4d529235beec0b275e2ccf00333b", - "sha256:27e11c7a8ec9d5838bc59f809bfa86efc8a4fd02e58960fa9c49d998e14332d5", - "sha256:2a04dda79606f3d2f760384c38ccd3d5b9bb79d4c8126b67aff5eb09a253763e", - "sha256:3c26010c1b51e1224a3ca6b8df807de6e95128b0908c7e34f190e7775455b0ca", - "sha256:52c40f1a4262c896420c6ea1c6fda62cf67070e3947e3307f5562bd783a90336", - "sha256:6e4f8d9e8aa79321657079b9ac03f3cf3fd067bf31c1cca4f56d49543f4356a5", - "sha256:7242be12a58fec245ee9734e625964b97cf7e3f2f7d016603f9e56660ce479c7", - "sha256:7dc253b542bfd4b4eb88d9dbae4ca079e7bf2e2afd819ee18891a43db66c60c7", - "sha256:94f5bd885f67bbb25c82d80184abbf7ce4f6c3c3a41fbaa4182f034bba803e69", - "sha256:a89e188daa119ffa0d03ce5123dee3f8ffd5115c896c2a9d4f0dbb3d8b95bfa3", - "sha256:ad3399da9b0ca36e2f24de72f67ab2854a62e623274607e37e0ce5f5d5fa9166", - "sha256:b0348be89275fd1d4c44ffa39530c41a21062f52299b1e3ee7d1c61f060044b8", - "sha256:b5554368e4ede1856121b0dfa35ce71768102e4aa55e526cb8de7f374ff78722", - "sha256:cbddc56b2502d3f87fda4f98d948eb5b11f36ff3902e17cb6cc44727f2200525", - "sha256:d79f18f41751725c56eceab2a886f021d70fd70a6188fd386e29a045945ffc10", - "sha256:dc2ca26a19ab32dc475dbad9dfe723d3a64c835f4c23f625c2b6566ca32b9f29", - "sha256:dd9bcd4f294eb0633bb33d1a74febdd2b9018b8b8ed325f861fffcd2c7660bb8", - "sha256:e8baab1bc7c9152715844f1faca6744f2416929de10d7639ed49555a85549f52", - "sha256:ec31fe12668af687b99acf1567399632a7c47b0e17cfb9ae47c098644ef36797", - "sha256:f12b4f7e2d8f9da3141564e6737d79016fe5336cc92de6814eba579744f65b0a", - "sha256:f58ac38d5ca045a377b3b377c84df8175ab992c970a53332fa8ac2373df44ff7" - ], - "index": "pypi", - "version": "==1.16.4" - }, - "oauthlib": { - "hashes": [ - "sha256:40a63637707e9163eda62d0f5345120c65e001a790480b8256448543c1f78f66", - "sha256:b4d99ae8ccfb7d33ba9591b59355c64eef5241534aa3da2e4c0435346b84bc8e" - ], - "version": "==3.0.2" + "sha256:05dbfe72684cc14b92568de1bc1f41e5f62b00f714afc9adee42f6311738091f", + "sha256:0d82cb7271a577529d07bbb05cb58675f2deb09772175fab96dc8de025d8ac05", + "sha256:10132aa1fef99adc85a905d82e8497a580f83739837d7cbd234649f2e9b9dc58", + "sha256:12322df2e21f033a60c80319c25011194cd2a21294cc66fee0908aeae2c27832", + "sha256:16f19b3aa775dddc9814e02a46b8e6ae6a54ed8cf143962b4e53f0471dbd7b16", + "sha256:3d0b0989dd2d066db006158de7220802899a1e5c8cf622abe2d0bd158fd01c2c", + "sha256:438a3f0e7b681642898fd7993d38e2bf140a2d1eafaf3e89bb626db7f50db355", + "sha256:5fd214f482ab53f2cea57414c5fb3e58895b17df6e6f5bca5be6a0bb6aea23bb", + "sha256:73615d3edc84dd7c4aeb212fa3748fb83217e00d201875a47327f55363cef2df", + "sha256:7bd355ad7496f4ce1d235e9814ec81ee3d28308d591c067ce92e49f745ba2c2f", + "sha256:7d077f2976b8f3de08a0dcf5d72083f4af5411e8fddacd662aae27baa2601196", + "sha256:a4092682778dc48093e8bda8d26ee8360153e2047826f95a3f5eae09f0ae3abf", + "sha256:b458de8624c9f6034af492372eb2fee41a8e605f03f4732f43fc099e227858b2", + "sha256:e70fc8ff03a961f13363c2c95ef8285e0cf6a720f8271836f852cc0fa64e97c8", + "sha256:ee8e9d7cad5fe6dde50ede0d2e978d81eafeaa6233fb0b8719f60214cf226578", + "sha256:f4a4f6aba148858a5a5d546a99280f71f5ee6ec8182a7d195af1a914195b21a2" + ], + "index": "pypi", + "version": "==1.17.2" }, "opencv-python": { "hashes": [ - "sha256:1703a296a96d3d46615e5053f224867977accb4240bcaa0fcabcb0768bf5ac13", - "sha256:1777ce7535ee7a1995cae168a107a1320e9df13648b930e72a1a2c2eccd64cda", - "sha256:1e5520482fb18fbd64d079e7f17ac0018f195fd75f6360a53bb82d7903106b50", - "sha256:25522dcf2529614750a71112a6659759080b4bdc2323f19d47f4d895960fd796", - "sha256:2af5f2842ad44c65ae2647377e0ff198719e1a1cfc9c6a19bc0c525c035d4bd8", - "sha256:31ec48d7eca13fc25c287dea7cecab453976e372cad8f50d55c054a247efda21", - "sha256:47cf48ff5dbd554e9f58cc9e98cf0b5de3f6a971172612bffa06bc5fb79ce872", - "sha256:494f98366bb5d6c2ac7e50e6617139f353704fd97a6d12ec9d392e72817d5cb0", - "sha256:4a9845870739e640e3350a8d98d511c92c087fe3d66090e83be7bf94e0ac64f7", - "sha256:4ac29cc0847d948a6636899014e84e165c30cc8779d6218394d44363462a01ce", - "sha256:5857ace03b7854221abf8072462d306c2c2ce4e366190b21d90ee8ee8aaf5bb4", - "sha256:5b4a23d99d5a2874767034466f5a8fd37b9f93ac14955a01b1a208983c76b9ad", - "sha256:734d87a5021c037064beb62133e135e66c7128e401a63b8b842b809ae2093749", - "sha256:78005c1c5d15ef4e32e0f485557bd15b5b6d87f49c19db7fe3e9246a61ebe7e4", - "sha256:81ae2283225c5c52fc3d72debd4241c30ccff2bb922578bf7867f9851cce3acb", - "sha256:88dbf900f297fdae0f62b899d6a784d8868ec2135854c5f8a9abbad00a6f0c5b", - "sha256:8c98ea7b8d327a31cd6028782a06147d0e0329ae8e829e881fb5d02f7ed8aec9", - "sha256:937d4686fef6967921145290f5b50c01c00c5b5d3542a6519e8a85cd88448723", - "sha256:a057958c0e362b3c4f03b9af1cbdb6d5af035fd22ecd7fd794eba8fdeb049eb8", - "sha256:c41eab31fa2c641226c6187caa391a688d064c99f078d604574f1912296b771f", - "sha256:cf4f7e62d1f80d1fa85a1693a3500def5cde54b2b75212b3609e552e4c25acfb", - "sha256:d90d60143e18334330c149f293071c9f2f3c79c896f33dc4ec65099e58baaaa7", - "sha256:db3106b7ca86999a7bd1f2fcc93e49314e5e6e451356774e421a69428df5020b", - "sha256:dbaf264db56f4771dfac6624f438bc4dc670aa94f61a6138848fcab7e9e77380", - "sha256:e65206c4cf651dc9cf0829962fae8bec986767c9f123d6a1ad17f9356bf7257e", - "sha256:eac94ddc78c58e891cff7180274317dad2938a4ddfc6ced1c04846c7f50e77e9", - "sha256:f2e828711f044a965509c862b3a59b3181e9c56c145a950cb53d43fec54e66d2" - ], - "version": "==4.1.0.25" + "sha256:0495e9247fbbd5d88346bb4d480df27fb4000aa4799b5a15b1735968a94a5189", + "sha256:078e8ea34d06b3fa459c58a6ce966ef715cc2e913b7bd96a46beb345975aa5d6", + "sha256:0dbbd0348c8282d4e3cf472a8e2a17785f05c22a55647253fa00b539897f8fcc", + "sha256:1b302b4721ca2d55ae7e9e80acebd73499c16a82be9bebc563a7937dbd348b2d", + "sha256:1f035595ef2f296c234c2b8b9659162646b9312afd0cec7ab0217bad915ff068", + "sha256:1f7fa5433c26c637cf923c59025df12fcd56b2d205da178c7ad6954e6e50912e", + "sha256:20bd10b6f6f5de1a5e796900ab77ea57366139290f426d2039d3919d8ddf9f1c", + "sha256:2306ddd98aa52688c9667f8080349d653d465a2b838cbacb19561286046ba1e8", + "sha256:31945ea9e7324c41be925f2b21fcb523844b2399dc649010f3a3e97825dcfcd0", + "sha256:36680744ebdc66a9da0a65f1f33ec9cf5d26a98749c5701dc612b334b213997d", + "sha256:409e3a4c925accd68a5ab1cef21dd04b957c0ee2985db8f075a808dccd6e0f73", + "sha256:440a093dda50daf093d73aae2dd333c9e4a593cfe7df8cbc298b421d313e263f", + "sha256:4b0465c3df9dea074583b6b4f8cf22e5902c5c5ec213a479c6c834a8a0191cf7", + "sha256:4b5902b647e66addfa5218dbc75e7a4de2f46c253ea17b234408f5792cfc8d7f", + "sha256:4f0a5c098aad4df88ce7dc3828a857921368635e3a961e80431e60f3522a99be", + "sha256:6df586230f9146afde5b8e2f4511978f8fb6172bf0f47ba290423979baae974d", + "sha256:6e4fee2ee2bc4d911dad78e2b167da97796879aaade4be3ff42ff1993e250b15", + "sha256:70f3c6fe31af7c00c60cb91bb7351837ba6c7b3d173b855ca5dbe265b90a1606", + "sha256:78390d93834b6b7c9d9234dba68ba9c34a966f60e519efd2691e5c367dee7f8e", + "sha256:81519bba8560c68f587482c157a74cf04d5a2877d4367377d2671e66eb7a3961", + "sha256:87beeb6ad4ffcd6fbfbb464a8a75c7a1389a0642cc632ecceb504c86139567e3", + "sha256:a354096290dd57ddb2664e7b21ddb6c6c2f5297cc4d8a402ce3f6a82a24807e3", + "sha256:a4635e22637181b478d6ad337c94b596c98c16bdbae92ef90514bbf31e30ef3a", + "sha256:b23359c21c4eb84f28fbe1331723bbf1ebc34125f22480da4b16cfae989a3249", + "sha256:ba52829eafab59c5260bec012fad0e26bd05389828af0e316e278912c82dab32", + "sha256:c672596fa261766d6d0cc02377755558b92dee80a64ee8dd6f58f4e56bf7835d", + "sha256:fd6ac9a11faa5d1cbf014d059dd890ad6f0583f149e780ff7d0d3d47e68438d6" + ], + "index": "pypi", + "version": "==3.4.2.17" + }, + "opt-einsum": { + "hashes": [ + "sha256:edfada4b1d0b3b782ace8bc14e80618ff629abf53143e1e6bbf9bd00b11ece77" + ], + "markers": "python_version >= '3.5'", + "version": "==3.1.0" }, "osmium": { "hashes": [ - "sha256:008f89720d833a28ff875893bc90ca6314ed27f23dedbff6b8e7e0224c058076", - "sha256:0811d5453e9828f14dc14f7380570a71b2ac2e9fbfc849fb1485a198e1bc0825", - "sha256:08a427a7c3fe3dceb84e19bcef6edada0dde9a675f75189d89dd7f4b0cab3539", - "sha256:0a1e4200e678e18db9b291a6498385b4c8f66dc3898be8fc6d0c232fe7600360", - "sha256:2183610dfbd7831b819e5990ec47a9c25dec76084dbae1d55bdc092bfba9177c", - "sha256:227ab38197d45fced6e18a5000e27b7bc7ef2970f7adcb856370661340a03b8e", - "sha256:2928713aaadaeab38fa8d546d274c9545b20440f2019425b3a6bab9444bd935a", - "sha256:2a3a42252afcf7fd3558c582e6a38df63df038a027b6d5fe1eaf8dac66969d37", - "sha256:4617fc74d13e2373b239597c6a875b90f95f40ec0d0977f68ca4beb3383a6f63", - "sha256:4ea02b36332585b66fb52b49468fac7426a257d0ffeaf0e0aa7ef7205f0fc442", - "sha256:56f269587578fcdd406af43dc276f3a59c4763821f9e41ce7b777f6f97cdede4", - "sha256:62688a1a662bc2ef7f0b05908c9e68ba11926fc79f3d1df13cd62cee74a6ca66", - "sha256:72d1d43834610c3d802316b526c204ecf428d5bbd5dab189b0e469bc67858db1", - "sha256:8a316b6bba0f33250c232c8a10f550d8578b639857e286159e1e0767d5ac7107", - "sha256:8b4802472d974b4f05ee960c40ccd0c14881b73cd68a669f23ce9b35fe313157", - "sha256:8c6b5c489d78d398786547480f87a7d51ad51cf0044479f13ecb0c74fb5616c7", - "sha256:91baacc2b7ad28574ec8c204ba812c5bdd9b0fae79f8b6787bea450441cba52f", - "sha256:b0b2f925c45fdd1af4a79d3051359c3bc70e7e83939c6096ab91f80b3e2e8cf8", - "sha256:b96ab16db2537edf7fd36f5b819f4575b7be0dce6ac857a813822b85c790c8c3", - "sha256:ce9f170aa8cf03a497e3a42fff785e4ddd6937a0a074e480d03b2ae90b60f80d", - "sha256:d5ebe6bf0e2afc943125ab01980cd0762b3cae8bb47c50aa14ee1a934caf0c85" - ], - "index": "pypi", - "version": "==2.15.0" + "sha256:0178bc3dd46fd304b0a22a951df1a116d37bb0d4869bbe6c566ce1abf39be7e5", + "sha256:07f6315af25fb496125d140151e317de0486ddc20254616d2347cd5537091e07", + "sha256:090fbcf394b76c7a4e967f55977a1491efaf3276b4a27ec1262cfd13073eb497", + "sha256:0b798022ddb598ffa8c5baf979cc0fe275a9419dfdf3ca21a92ede596f99bae2", + "sha256:2170516d9c3c95432ea725ac4a0dca590fb263f80b6fc3f361a3d30eb9c41f28", + "sha256:35d9ea62e0016466eece390792644192d45dbf12c70637d293b8be408c2390cd", + "sha256:455dcd129819b1c47cfcb7c676e362c07b32dc5558bf16eddd0333f8899e331e", + "sha256:5545722ce2ead2c1e634ef23e26b694fe06f5768006195762f14ab6496fb72ed", + "sha256:68d8a9bab38657362d55ec0c2878acc40a74f4602e263c1c3b75bdfe8135c59c", + "sha256:69fd3f0da9ecb3a041075bd84702ef9237c67c09f1a0b6defb00bbb727249259", + "sha256:712910c5472726bb62a6e043179697e0a52ebb09b7e4e23dbf4a8d0e31c90e11", + "sha256:82d84dbfe437546aad4e427d9b667eb4575b35100e8ff60fd1f0752522126211", + "sha256:8475e8dc2186d0817b0254e35f502582592b8b44cd0a9478cbecd6602791ff50", + "sha256:851491cddb07e7cf25b74a29e7ceca9c0eac74c45d0a033e6085820e830e1f32", + "sha256:8ae2ce116bec61b2e51b181f61214fba06ec25ccd4d51cb42386b8b4b73ccd91", + "sha256:8ea713709267a461eaf2c6544f4fe358312558e7448480f5fd0c3fef023e996d", + "sha256:b7f774794fac9df16ad745035aa61e28a00c5a75bed3483fa77f67e34dc61920", + "sha256:bb40e3e468b47e01f759a1c5de9e5429224ca6b8fe09f690c169480afc7ea840", + "sha256:bc67305d09f391d735883efea870c37a3aa2dabf32530026a409eb506b52a2f0", + "sha256:bef1b37772b39a438c5b2e65dbc1f3417ef2a8ade829ef1f6f0179431c5bcb7c", + "sha256:df9bded041a099a72bc3bfb3732df93c36f96801c2706721d1d8623419e64321", + "sha256:e0d4a1049a5bf8445c6e8c6cbc8f247795322870a32ca63f5fdec24cbcc973c2" + ], + "index": "pypi", + "version": "==2.15.3" }, "pandas": { "hashes": [ - "sha256:071e42b89b57baa17031af8c6b6bbd2e9a5c68c595bc6bf9adabd7a9ed125d3b", - "sha256:17450e25ae69e2e6b303817bdf26b2cd57f69595d8550a77c308be0cd0fd58fa", - "sha256:17916d818592c9ec891cbef2e90f98cc85e0f1e89ed0924c9b5220dc3209c846", - "sha256:2538f099ab0e9f9c9d09bbcd94b47fd889bad06dc7ae96b1ed583f1dc1a7a822", - "sha256:366f30710172cb45a6b4f43b66c220653b1ea50303fbbd94e50571637ffb9167", - "sha256:42e5ad741a0d09232efbc7fc648226ed93306551772fc8aecc6dce9f0e676794", - "sha256:4e718e7f395ba5bfe8b6f6aaf2ff1c65a09bb77a36af6394621434e7cc813204", - "sha256:4f919f409c433577a501e023943e582c57355d50a724c589e78bc1d551a535a2", - "sha256:4fe0d7e6438212e839fc5010c78b822664f1a824c0d263fd858f44131d9166e2", - "sha256:5149a6db3e74f23dc3f5a216c2c9ae2e12920aa2d4a5b77e44e5b804a5f93248", - "sha256:627594338d6dd995cfc0bacd8e654cd9e1252d2a7c959449228df6740d737eb8", - "sha256:83c702615052f2a0a7fb1dd289726e29ec87a27272d775cb77affe749cca28f8", - "sha256:8c872f7fdf3018b7891e1e3e86c55b190e6c5cee70cab771e8f246c855001296", - "sha256:90f116086063934afd51e61a802a943826d2aac572b2f7d55caaac51c13db5b5", - "sha256:a3352bacac12e1fc646213b998bce586f965c9d431773d9e91db27c7c48a1f7d", - "sha256:bcdd06007cca02d51350f96debe51331dec429ac8f93930a43eb8fb5639e3eb5", - "sha256:c1bd07ebc15285535f61ddd8c0c75d0d6293e80e1ee6d9a8d73f3f36954342d0", - "sha256:c9a4b7c55115eb278c19aa14b34fcf5920c8fe7797a09b7b053ddd6195ea89b3", - "sha256:cc8fc0c7a8d5951dc738f1c1447f71c43734244453616f32b8aa0ef6013a5dfb", - "sha256:d7b460bc316064540ce0c41c1438c416a40746fd8a4fb2999668bf18f3c4acf1" - ], - "index": "pypi", - "version": "==0.24.2" + "sha256:18d91a9199d1dfaa01ad645f7540370ba630bdcef09daaf9edf45b4b1bca0232", + "sha256:3f26e5da310a0c0b83ea50da1fd397de2640b02b424aa69be7e0784228f656c9", + "sha256:4182e32f4456d2c64619e97c58571fa5ca0993d1e8c2d9ca44916185e1726e15", + "sha256:426e590e2eb0e60f765271d668a30cf38b582eaae5ec9b31229c8c3c10c5bc21", + "sha256:5eb934a8f0dc358f0e0cdf314072286bbac74e4c124b64371395e94644d5d919", + "sha256:717928808043d3ea55b9bcde636d4a52d2236c246f6df464163a66ff59980ad8", + "sha256:8145f97c5ed71827a6ec98ceaef35afed1377e2d19c4078f324d209ff253ecb5", + "sha256:8744c84c914dcc59cbbb2943b32b7664df1039d99e834e1034a3372acb89ea4d", + "sha256:c1ac1d9590d0c9314ebf01591bd40d4c03d710bfc84a3889e5263c97d7891dee", + "sha256:cb2e197b7b0687becb026b84d3c242482f20cbb29a9981e43604eb67576da9f6", + "sha256:d4001b71ad2c9b84ff18b182cea22b7b6cbf624216da3ea06fb7af28d1f93165", + "sha256:d8930772adccb2882989ab1493fa74bd87d47c8ac7417f5dd3dd834ba8c24dc9", + "sha256:dfbb0173ee2399bc4ed3caf2d236e5c0092f948aafd0a15fbe4a0e77ee61a958", + "sha256:eebfbba048f4fa8ac711b22c78516e16ff8117d05a580e7eeef6b0c2be554c18", + "sha256:f1b21bc5cf3dbea53d33615d1ead892dfdae9d7052fa8898083bec88be20dcd2" + ], + "markers": "python_version >= '3.5.3'", + "version": "==0.25.1" }, "pandocfilters": { "hashes": [ @@ -1944,21 +1819,20 @@ ], "version": "==1.4.2" }, - "pathlib2": { + "parso": { "hashes": [ - "sha256:2156525d6576d21c4dcaddfa427fae887ef89a7a9de5cbfe0728b3aafa78427e", - "sha256:446014523bb9be5c28128c4d2a10ad6bb60769e78bd85658fe44a450674e0ef8" + "sha256:63854233e1fadb5da97f2744b6b24346d2750b85965e7e399bec1620232797dc", + "sha256:666b0ee4a7a1220f65d367617f2cd3ffddff3e205f3f16a0284df30e774c2a9c" ], - "markers": "python_version in '2.6 2.7 3.2 3.3'", - "version": "==2.3.4" + "version": "==0.5.1" }, "pbr": { "hashes": [ - "sha256:8257baf496c8522437e8a6cfe0f15e00aedc6c0e0e7c9d55eeeeab31e0853843", - "sha256:8c361cc353d988e4f5b998555c88098b9d5964c2e11acf7b0d21925a66bb5824" + "sha256:2c8e420cd4ed4cec4e7999ee47409e876af575d4c35a45840d59e8b5f3155ab8", + "sha256:b32c8ccaac7b1a20c0ce00ce317642e6cf231cf038f9875e0280e28af5bf7ac9" ], "index": "pypi", - "version": "==5.1.3" + "version": "==5.4.3" }, "percache": { "hashes": [ @@ -1984,34 +1858,35 @@ }, "pillow": { "hashes": [ - "sha256:0804f77cb1e9b6dbd37601cee11283bba39a8d44b9ddb053400c58e0c0d7d9de", - "sha256:0ab7c5b5d04691bcbd570658667dd1e21ca311c62dcfd315ad2255b1cd37f64f", - "sha256:0b3e6cf3ea1f8cecd625f1420b931c83ce74f00c29a0ff1ce4385f99900ac7c4", - "sha256:365c06a45712cd723ec16fa4ceb32ce46ad201eb7bbf6d3c16b063c72b61a3ed", - "sha256:38301fbc0af865baa4752ddae1bb3cbb24b3d8f221bf2850aad96b243306fa03", - "sha256:3aef1af1a91798536bbab35d70d35750bd2884f0832c88aeb2499aa2d1ed4992", - "sha256:3fe0ab49537d9330c9bba7f16a5f8b02da615b5c809cdf7124f356a0f182eccd", - "sha256:45a619d5c1915957449264c81c008934452e3fd3604e36809212300b2a4dab68", - "sha256:49f90f147883a0c3778fd29d3eb169d56416f25758d0f66775db9184debc8010", - "sha256:571b5a758baf1cb6a04233fb23d6cf1ca60b31f9f641b1700bfaab1194020555", - "sha256:5ac381e8b1259925287ccc5a87d9cf6322a2dc88ae28a97fe3e196385288413f", - "sha256:6153db744a743c0c8c91b8e3b9d40e0b13a5d31dbf8a12748c6d9bfd3ddc01ad", - "sha256:6fd63afd14a16f5d6b408f623cc2142917a1f92855f0df997e09a49f0341be8a", - "sha256:70acbcaba2a638923c2d337e0edea210505708d7859b87c2bd81e8f9902ae826", - "sha256:70b1594d56ed32d56ed21a7fbb2a5c6fd7446cdb7b21e749c9791eac3a64d9e4", - "sha256:76638865c83b1bb33bcac2a61ce4d13c17dba2204969dedb9ab60ef62bede686", - "sha256:7b2ec162c87fc496aa568258ac88631a2ce0acfe681a9af40842fc55deaedc99", - "sha256:7cee2cef07c8d76894ebefc54e4bb707dfc7f258ad155bd61d87f6cd487a70ff", - "sha256:7d16d4498f8b374fc625c4037742fbdd7f9ac383fd50b06f4df00c81ef60e829", - "sha256:b50bc1780681b127e28f0075dfb81d6135c3a293e0c1d0211133c75e2179b6c0", - "sha256:bd0582f831ad5bcad6ca001deba4568573a4675437db17c4031939156ff339fa", - "sha256:cfd40d8a4b59f7567620410f966bb1f32dc555b2b19f82a91b147fac296f645c", - "sha256:e3ae410089de680e8f84c68b755b42bc42c0ceb8c03dbea88a5099747091d38e", - "sha256:e9046e559c299b395b39ac7dbf16005308821c2f24a63cae2ab173bd6aa11616", - "sha256:ef6be704ae2bc8ad0ebc5cb850ee9139493b0fc4e81abcc240fb392a63ebc808", - "sha256:f8dc19d92896558f9c4317ee365729ead9d7bbcf2052a9a19a3ef17abbb8ac5b" - ], - "version": "==6.1.0" + "sha256:00fdeb23820f30e43bba78eb9abb00b7a937a655de7760b2e09101d63708b64e", + "sha256:01f948e8220c85eae1aa1a7f8edddcec193918f933fb07aaebe0bfbbcffefbf1", + "sha256:08abf39948d4b5017a137be58f1a52b7101700431f0777bec3d897c3949f74e6", + "sha256:099a61618b145ecb50c6f279666bbc398e189b8bc97544ae32b8fcb49ad6b830", + "sha256:2c1c61546e73de62747e65807d2cc4980c395d4c5600ecb1f47a650c6fa78c79", + "sha256:2ed9c4f694861642401f27dc3cb99772be67cd190e84845c749dae0a06c3bfae", + "sha256:338581b30b908e111be578f0297255f6b57a51358cd16fa0e6f664c9a1f88bff", + "sha256:38c7d48a21cd06fdeee93987147b9b1c55b73b4cfcbf83240568bfbd5adee447", + "sha256:43fd026f613c8e48a25eba1a92f4d2ad7f3903c95d8c33a11611a7717d2ab654", + "sha256:4548236844327a718ce3bb182ab32a16fa2050c61e334e959f554cac052fb0df", + "sha256:5090857876c58885cfa388dc649e5db30aae98a068c26f3fd0ac9d7d9a4d9572", + "sha256:5bbba34f97a26a93f5e8dec469ca4ddd712451418add43da946dbaed7f7a98d2", + "sha256:65a28969a025a0eb4594637b6103201dc4ed2a9508bdab56ac33e43e3081c404", + "sha256:892bb52b70bd5ea9dbbc3ac44f38e84f5a04e9d8b1bff48159d96cb795b81159", + "sha256:8a9becd5cbd5062f973bcd2e7bc79483af310222de112b6541f8af1f93a3cc42", + "sha256:972a7aaeb7c4a2795b52eef52ee991ef040b31009f36deca6207a986607b55f3", + "sha256:97b119c436bfa96a92ac2ca525f7025836d4d4e64b1c9f9eff8dbaf3ff1d86f3", + "sha256:9ba37698e242223f8053cc158f130aee046a96feacbeab65893dbe94f5530118", + "sha256:b1b0e1f626a0f079c0d3696db70132fb1f29aa87c66aecb6501a9b8be64ce9f7", + "sha256:c14c1224fd1a5be2733530d648a316974dbbb3c946913562c6005a76f21ca042", + "sha256:c79a8546c48ae6465189e54e3245a97ddf21161e33ff7eaa42787353417bb2b6", + "sha256:ceb76935ac4ebdf6d7bc845482a4450b284c6ccfb281e34da51d510658ab34d8", + "sha256:e22bffaad04b4d16e1c091baed7f2733fc1ebb91e0c602abf1b6834d17158b1f", + "sha256:ec883b8e44d877bda6f94a36313a1c6063f8b1997aa091628ae2f34c7f97c8d5", + "sha256:f1baa54d50ec031d1a9beb89974108f8f2c0706f49798f4777df879df0e1adb6", + "sha256:f53a5385932cda1e2c862d89460992911a89768c65d176ff8c50cddca4d29bed" + ], + "index": "pypi", + "version": "==6.2.0" }, "pprofile": { "hashes": [ @@ -2020,13 +1895,6 @@ "index": "pypi", "version": "==2.0.2" }, - "progressbar2": { - "hashes": [ - "sha256:9ecb2d35edaa30ed86eb92fb0135eb19a6ef9b3657be4350cc3d0d3563e6af65", - "sha256:c086fc1f718839c0ec95caaeb7bd5a1d0268a8775960b8f9dee06f2a04c84628" - ], - "version": "==3.42.0" - }, "prometheus-client": { "hashes": [ "sha256:71cd24a2b3eb335cb800c7159f423df1bd4dcd5171b234be15e3f31ec9f622da" @@ -2035,34 +1903,33 @@ }, "prompt-toolkit": { "hashes": [ - "sha256:1e71341526efa4b11bb44d323e687a5d9cef204aabe2907e3f0dc1534cda0ecc", - "sha256:955d81315bb7a049f19cd17d1a73f1a40861483260f7dffd825e98303a8bd6b6", - "sha256:c1cedd626e08b8ee830ee65897de754113ff3f3035880030c08b01674d85c5b4" + "sha256:46642344ce457641f28fc9d1c9ca939b63dadf8df128b86f1b9860e59c73a5e4", + "sha256:e7f8af9e3d70f514373bf41aa51bc33af12a6db3f71461ea47fea985defb2c31", + "sha256:f15af68f66e664eaa559d4ac8a928111eebd5feda0c11738b5998045224829db" ], - "version": "==1.0.16" + "version": "==2.0.10" }, "protobuf": { "hashes": [ - "sha256:05c36022fef3c7d3562ac22402965c0c2b9fe8421f459bb377323598996e407f", - "sha256:139b7eadcca0a861d60b523cb37d9475505e0dfb07972436b15407c2b968d87e", - "sha256:15f683006cb77fb849b1f561e509b03dd2b7dcc749086b8dd1831090d0ba4740", - "sha256:2ad566b7b7cdd8717c7af1825e19f09e8fef2787b77fcb979588944657679604", - "sha256:35cfcf97642ef62108e10a9431c77733ec7eaab8e32fe4653de20403429907cb", - "sha256:387822859ecdd012fdc25ec879f7f487da6e1d5b1ae6115e227e6be208836f71", - "sha256:4df14cbe1e7134afcfdbb9f058949e31c466de27d9b2f7fb4da9e0b67231b538", - "sha256:586c4ca37a7146d4822c700059f150ac3445ce0aef6f3ea258640838bb892dc2", - "sha256:58b11e530e954d29ab3180c48dc558a409f705bf16739fd4e0d3e07924ad7add", - "sha256:63c8c98ccb8c95f41c18fb829aeeab21c6249adee4ed75354125bdc44488f30e", - "sha256:72edcbacd0c73eef507d2ff1af99a6c27df18e66a3ff4351e401182e4de62b03", - "sha256:83dc8a561b3b954fd7002c690bb83278b8d1742a1e28abba9aaef28b0c8b437d", - "sha256:913171ecc84c2726b86574e40549a0ea619d569657c5a5ff782a3be7d81401a5", - "sha256:aabb7c741d3416671c3e6fe7c52970a226e6a8274417a97d7d795f953fadef36", - "sha256:b3452bbda12b1cbe2187d416779de07b2ab4c497d83a050e43c344778763721d", - "sha256:c5d5b8d4a9212338297fa1fa44589f69b470c0ba1d38168b432d577176b386a8", - "sha256:d86ee389c2c4fc3cebabb8ce83a8e97b6b3b5dc727b7419c1ccdc7b6e545a233", - "sha256:f2db8c754de788ab8be5e108e1e967c774c0942342b4f8aaaf14063889a6cfdc" - ], - "version": "==3.9.0" + "sha256:125713564d8cfed7610e52444c9769b8dcb0b55e25cc7841f2290ee7bc86636f", + "sha256:1accdb7a47e51503be64d9a57543964ba674edac103215576399d2d0e34eac77", + "sha256:27003d12d4f68e3cbea9eb67427cab3bfddd47ff90670cb367fcd7a3a89b9657", + "sha256:3264f3c431a631b0b31e9db2ae8c927b79fc1a7b1b06b31e8e5bcf2af91fe896", + "sha256:3c5ab0f5c71ca5af27143e60613729e3488bb45f6d3f143dc918a20af8bab0bf", + "sha256:45dcf8758873e3f69feab075e5f3177270739f146255225474ee0b90429adef6", + "sha256:56a77d61a91186cc5676d8e11b36a5feb513873e4ae88d2ee5cf530d52bbcd3b", + "sha256:5984e4947bbcef5bd849d6244aec507d31786f2dd3344139adc1489fb403b300", + "sha256:6b0441da73796dd00821763bb4119674eaf252776beb50ae3883bed179a60b2a", + "sha256:6f6677c5ade94d4fe75a912926d6796d5c71a2a90c2aeefe0d6f211d75c74789", + "sha256:84a825a9418d7196e2acc48f8746cf1ee75877ed2f30433ab92a133f3eaf8fbe", + "sha256:b842c34fe043ccf78b4a6cf1019d7b80113707d68c88842d061fa2b8fb6ddedc", + "sha256:ca33d2f09dae149a1dcf942d2d825ebb06343b77b437198c9e2ef115cf5d5bc1", + "sha256:cc9af00df3fc9302f537a8335668c20be27916b2277e9a5eaed510266e2bb33b", + "sha256:db83b5c12c0cd30150bb568e6feb2435c49ce4e68fe2d7b903113f0e221e58fe", + "sha256:f50f3b1c5c1c1334ca7ce9cad5992f098f460ffd6388a3cabad10b66c2006b09", + "sha256:f99f127909731cafb841c52f9216e447d3e4afb99b17bebfad327a75aee206de" + ], + "version": "==3.10.0" }, "psutil": { "hashes": [ @@ -2089,8 +1956,9 @@ }, "pycocotools": { "git": "https://github.com/cocodataset/cocoapi.git", - "ref": "aca78bcd6b4345d25405a64fdba1120dfa5da1ab", - "subdirectory": "PythonAPI" + "ref": "636becdc73d54283b3aac6d4ec363cffbb6f9b20", + "subdirectory": "PythonAPI", + "version": "==2.0" }, "pycparser": { "hashes": [ @@ -2153,11 +2021,11 @@ }, "pylint": { "hashes": [ - "sha256:367e3d49813d349a905390ac27989eff82ab84958731c5ef0bef867452cfdc42", - "sha256:97a42df23d436c70132971d1dcb9efad2fe5c0c6add55b90161e773caf729300" + "sha256:7edbae11476c2182708063ac387a8f97c760d9cfe36a5ede0ca996f90cf346c8", + "sha256:844ce067788028c1a35086a5c66bc5e599ddd851841c41d6ee1623b36774d9f2" ], "index": "pypi", - "version": "==1.9.5" + "version": "==2.4.2" }, "pylogbeat": { "hashes": [ @@ -2168,37 +2036,40 @@ }, "pymongo": { "hashes": [ - "sha256:32421df60d06f479d71b6b539642e410ece3006e8910688e68df962c8eb40a21", - "sha256:324b22a8443e11faca44c96b20e7ec8a9e59a1e664457edeeb4f796080b31cde", - "sha256:4505ff8b7923dd7a8bed1bf25c9c4d0df5ab0b8b2821f2296533f2149a55f401", - "sha256:460b224681ea711e48e3638d15be2249024031b7dcb9622ba19c2e85bd5a26cc", - "sha256:47473b70c5f3cd5ddd2c49ab3b9ceafdafbbed5bc963f147df22a9343d7978f5", - "sha256:49375839af76834e9c5c3cc78c78386873fd0b2ad9a0860a7dc4ec9fe73af9dd", - "sha256:4a65f0f71ece86c860d30a1436b646db8ea32aec518845ef2903ca569faec32e", - "sha256:530621906c5dd6d27305b39c4e017701e5f4299aa68b93cde70eb985f94ca26f", - "sha256:54f4770b5810e8dc3cbeed675874195f02bb2bc4e95a9d665068edfb3baff4f7", - "sha256:5ed9382410e938b0ff76041c34018210504729a83bcf4f6a70c7092c28169f6f", - "sha256:61cad83637ae12c1c825130d7f9325cd6c162e3a64e8747a8144866020be3ff4", - "sha256:61e8e1c58b4fdf47ab79b7c7db8bb022c1e40b3b5fcbbaeea5fc94dc5c75638d", - "sha256:6e04e496af7d156b66cce70460011c621ecbadf5dcdce325c7acbb3cd6ea245d", - "sha256:7ef89ec435e89da902451dde6845066fe2770befaf0301fe2a1ac426b51fced3", - "sha256:854e8425e5eb775ccfffad04ecd094c99923d60a2c2d49babb5c435e836a91fa", - "sha256:9569796d48498e4db4e1d56284b626a8ed15f641ce3a8b2085f06bb03f4c2c88", - "sha256:9d50c99c6388863cbfdc5db9bad62e3a7c2e5fc151554a07c7f3c2530334a34f", - "sha256:9ea016c2c011df21f77c1f806ce45129a344ba2d414bd50f9e065b13a4a134be", - "sha256:a8421f0823174888fb12a5fa675322e756499d71e77ff712b4412d4b8f3c6503", - "sha256:aef7d88384ada699976350a285c7a333f96ebc959e98e7d2c98589f47bbf3b7f", - "sha256:b4d7ff9957ee770cf03bd7156a68a2f2e838e60712d9608eadc8741c15d01e72", - "sha256:c1db85c39e6a60588f855dbc7bd68fb0dab796096148ab5aa4abecaff19e1c6e", - "sha256:cee2fc0b94e66e7230da12fc4b3d34793c49957e16ee04f6468a94e264a1e41d", - "sha256:cf1dea28379a16b23e47db312883f07b3ba8d9d6abc1c59e51d4c8ae1820ab43", - "sha256:d1cd175df7c8b5fc976bade78bf4d9fb5aa7ab465c0f59931e380bbe188ef8fc", - "sha256:d48a94edf3cdd34524936a72ea01b352682b337f33a42db10ba29a96c37147d3", - "sha256:d9cc103a4e97f78bc77a1d72759ab3722f6cdf0374ad4fb4b0c53bd3238bdf98", - "sha256:fcb9ae8aa9158106c5d98a4349ec0d90b68f052d620b2d24622ba03b91e4d81d" - ], - "index": "pypi", - "version": "==3.8.0" + "sha256:09f8196e1cb081713aa3face08d1806dc0a5dd64cb9f67fefc568519253a7ff2", + "sha256:1be549c0ce2ba8242c149156ae2064b12a5d4704448d49f630b4910606efd474", + "sha256:1f9fe869e289210250cba4ea20fbd169905b1793e1cd2737f423e107061afa98", + "sha256:3653cea82d1e35edd0a2355150daf8a27ebf12cf55182d5ad1046bfa288f5140", + "sha256:4249c6ba45587b959292a727532826c5032d59171f923f7f823788f413c2a5a3", + "sha256:4ff8f5e7c0a78983c1ee07894fff1b21c0e0ad3a122d9786cc3745fd60e4a2ce", + "sha256:56b29c638ab924716b48a3e94e3d7ac00b04acec1daa8190c36d61fc714c3629", + "sha256:56ec9358bbfe5ae3b25e785f8a14619d6799c855a44734c9098bb457174019bf", + "sha256:5b59bbde4eb417f3f9379f7b1a9de3669894f2bae9de933a836e2bffea2bbfa1", + "sha256:5dca250cbf1183c3e7b7b18c882c2b2199bfb20c74c4c68dbf11596808a296da", + "sha256:61101d1cc92881fac1f9ac7e99b033062f4c210178dc33193c8f5567feecb069", + "sha256:7b4aea184e4868ebd4f9f786ffee14a1121bda5436ad04f6bcbacfa2147f8386", + "sha256:86624c0205a403fb4fbfedef79c5b4ab27e21fd018fdb6a27cf03b3c32a9e2b9", + "sha256:88ac09e1b197c3b4531e43054d49c022a3ea1281431b2f4980abafa35d2a5ce2", + "sha256:8b0339809b12ea292d468524dd1777f1a9637d9bdc0353a9261b88f82537d606", + "sha256:93dbf7388f6bf9af48dbb32f265b75b3dbc743a7a2ce98e44c88c049c58d85d3", + "sha256:9b705daec636c560dd2d63935f428a6b3cddfe903fffc0f349e0e91007c893d6", + "sha256:a090a819fe6fefadc2901d3911c07c76c0935ec5c790a50e9f3c3c47bacd5978", + "sha256:a102b346f1921237eaa9a31ee89eda57ad3c3973d79be3a456d92524e7df8fec", + "sha256:a13363869f2f36291d6367069c65d51d7b8d1b2fb410266b0b6b1f3c90d6deb0", + "sha256:a409a43c76da50881b70cc9ee70a1744f882848e8e93a68fb434254379777fa3", + "sha256:a76475834a978058425b0163f1bad35a5f70e45929a543075633c3fc1df564c5", + "sha256:ad474e93525baa6c58d75d63a73143af24c9f93c8e26e8d382f32c4da637901a", + "sha256:b268c7fa03ac77a8662fab3b2ab0be4beecb82f60f4c24b584e69565691a107f", + "sha256:b67ec339b180acdbebcd03807ae4b1764a43e7069340fe860a60ac310b9d38be", + "sha256:cca4e1ab5ba0cd7877d3938167ee8ae9c2986cc0e10d3dcc3243d664d3a83fec", + "sha256:cef61de3f0f4441ec40266ff2ab42e5c16eaba1dc1fc6e1036f274621c52adc1", + "sha256:e28153b5d5ca33d4ba0c3bbc0e1ff161b9016e5e5f3f8ca10d6fa49106eb9e04", + "sha256:f30d7b37804daf0bab1143abc71666c630d7e270f5c14c5a7c300a6699c21108", + "sha256:f70f0133301cccf9bfd68fd20f67184ef991be578b646e78441106f9e27cc44d", + "sha256:fa75c21c1d82f20cce62f6fc4a68c2b0f33572ab406df1b17cd77a947d0b2993" + ], + "index": "pypi", + "version": "==3.9.0" }, "pymysql": { "hashes": [ @@ -2243,10 +2114,11 @@ }, "pyparsing": { "hashes": [ - "sha256:1873c03321fc118f4e9746baf201ff990ceb915f433f23b395f5580d1840cb2a", - "sha256:9b6323ef4ab914af344ba97510e966d64ba91055d6b9afa6b30799340e89cc03" + "sha256:6f98a7b9397e206d78cc01df10131398f1c8b8510a2f4d97d9abd82e1aacdd80", + "sha256:d9338df12903bbf5d65a0e4e87c2161968b10d2e489652bb47001d82a9b028b4" ], - "version": "==2.4.0" + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.4.2" }, "pypolyline": { "hashes": [ @@ -2266,35 +2138,61 @@ }, "pyproj": { "hashes": [ - "sha256:1303b343a1c4d83d1ac17494571d958335c0a4597d4aa623cd64df1f36fb18bf", - "sha256:1fd2f756f43ba762f5a1ae769c6cc9ae6f919996bf80c621f331e4a5d89ae74f", - "sha256:2b3f59b16cde23c0d95b1d9ba3dd1c0be3937d877df3b47a522d3c9a74d31668", - "sha256:2e5d8b892782db22c3d6ffcb272c8ac0a18995e22d45db762a893ec64cc039d6", - "sha256:512a59bc20587f88df78a69872ed8cb4ec7905415ba85b4de0af35601770fba1", - "sha256:5aa89b04855e439e2b96caf1f49fa2ab60e6e7c407034284d31d808abed0618a", - "sha256:75b4c5eba36060a00867e16e81755a44e93a95b0bbaa4d6ee40f10c330b62108", - "sha256:860fde3429f364767c88a8e7f14f330e3fdace9f438e0ef1b112108a44c1eee8", - "sha256:86886f21af819553990f0da9ad7737d52cd32076dd277db34e40cf805919e839", - "sha256:9417d46f2b5e6ba79bd6adea0aae9659501c8a0350a5a98c0d9cb1442d45b0b4", - "sha256:9bb81141715832bb8682dda3c2f8f1ad0f43cf8aec5db52e0992c16c7664e227", - "sha256:afe150d8f0b351df7a357cfce50a8a5c0a44bdfeec5e08075f873cfeddf63004", - "sha256:cc2e21c09245c3eb47014c3d4c58888cc8d48a168a03533f9ed3f8b2ee82a352", - "sha256:cefb4a1a5d51cd04c9dd31bb18047c2dafcb86bc33a0347746b5a0ef82c071d8", - "sha256:cfa2cd0ee23bcfc9f165b4f8e9c5b7ba829c7b49175fb73420544619148d91af", - "sha256:d3a78ce50e6c50e701d65929dc04ab751edaeae660455a9fef3c2231d609f8c1", - "sha256:d772ee53c8d316de1b7f68244ab654f864553bca177357f8787a65dc09816ae3", - "sha256:ddd99d6f2c813e44721c22039ddf333e4b95e8d0794b03d9962c94c01c823934", - "sha256:ec89e68a0cf210af0cc2724b5f8601d4b6809ff0f556e16efc8c955e79672f7a", - "sha256:f118762ed0abe8e988a20020241fe1e6133edb960d2665a44d6f48acc6d8e7c7" + "sha256:0f3b3280ae59c74212841c38d1df055537b4e83cbfcda4072ba6b0eeefd0b98a", + "sha256:36ad4ff82f38cdc7738da81289ec4309263ad40f3d62cb75eeef22bb70178698", + "sha256:4a26485f09052722deaa1ddc6b3133d41bd982be5b0e64e296626e71b94ee5e6", + "sha256:4b41db92d689119b57ff6fcc3ae5a75072c86a7078cb0c25434b3ab4b79ad624", + "sha256:5d1f4f2645abd05128d29bd71eb378ff0fedb9f96147356e68b87a628863bf92", + "sha256:7c05ca74d7a3c822afd933e2efb5c599475c1cb22919500cb7df8ecb1c24d04e", + "sha256:8124fe43d81a7caca43df6930110e2bfd2bd3b82b86587eefd6f6d86a81a658e", + "sha256:8e2a8fab431bc6d16a417792198813fe6b8c53aafb51f54e1e6a52cdb377b576", + "sha256:9121e2ae3eb13d32cf2c49e456e052fe88cab200cfc07e3162cdb276427040fa", + "sha256:a8462505b4fa7e7e73ac5e69f1aa3d4a31b25e93dac80a41a2ff35d996c3f173", + "sha256:c22c52ea26d318d808bdde23e2b57b85c292747971ff79d0ea578b578ff791d6", + "sha256:d25638d48af3df03c6d3c713495d62d0b9a135032b0dddafbb7f0004d052b1f5", + "sha256:d851dd9245f60871306a49af92523a8ea8d8a60f3e522bbd8b9cd512d8b825ec", + "sha256:e27a5bec46c706a343db9b218bf13abd53f1e066668b194bd48511c1773f6c1c", + "sha256:fb151507b8793acc8c622164e3cc57d0c51f3d4790dabba1daf141a780bad68a" ], "index": "pypi", - "version": "==2.2.1" + "version": "==2.4.0" + }, + "pyqt5": { + "hashes": [ + "sha256:6420d8c9de8746917bd2afe24f29b3722aabde36d1e9f8c34354f5b7fb7b987d", + "sha256:73f982b60819cc6d7cb0007b8b0cd11073e2546d74e0463726149e6a9d087caa", + "sha256:8e6125f110133069e8f4a085022cfc6b4a0af5b3c9009999a749007c299e965d", + "sha256:f8e76070782e68ba200eb2b67babf89ac629df5e36d2f4c680ef34ae40c8f964" + ], + "index": "pypi", + "version": "==5.13.1" + }, + "pyqt5-sip": { + "hashes": [ + "sha256:304acf771b6033cb4bafc415939d227c91265d30664ed643b298d7e95f509f81", + "sha256:39d2677f4de46ed4d7aa3b612f31c74c881975efe51c6a23fbb1d9382e4cc850", + "sha256:54b99a3057e8f01b90d49cca9ca566b1ea23d8920038760f44e75b90c62b9d5f", + "sha256:59f5332f86f3ccd3ac94674fe91eae6e8aca26da7c6588917cabd0fe22af106d", + "sha256:72be07a21b0f379987c4ec59bc86834a9719a2f9cfb49606a4d4e34dae9aa549", + "sha256:7b3b8c015e545fa30e42205fc1115b7c6afcb6acec790ce3f330a06323730523", + "sha256:7fbb6389c20aff4c3257e89bb1787effffcaf05c32d937c00094ae45846bffd5", + "sha256:828d9911acc483672a2bae1cc1bf79f591eb3338faad1f2c798aa2f45459a318", + "sha256:a9460dac973deccc6ff2d90f18fd105cbaada147f84e5917ed79374dcb237758", + "sha256:aade50f9a1b9d20f6aabe88e8999b10db57218f5c31950160f3f7957dd64e07c", + "sha256:ac9e5b282d1f0771a8310ed974afe1961ec31e9ae787d052c0e504ea46ae323a", + "sha256:ba41bd21b89c6713f7077b5f7d4a1c452989190aad5704e215560a266a1ecbab", + "sha256:c309dbbd6c155e961bfd6893496afa5cd184cce6f7dffd87ea68ee048b6f97e1", + "sha256:cfc21b1f80d4655ffa776c505a2576b4d148bbc52bb3e33fedbf6cfbdbc09d1b", + "sha256:d7b26e0b6d81bf14c1239e6a891ac1303a7e882512d990ec330369c7269226d7", + "sha256:f8b7a3e05235ce58a38bf317f71a5cb4ab45d3b34dc57421dd8cea48e0e4023e" + ], + "version": "==4.19.19" }, "pyrsistent": { "hashes": [ - "sha256:50cffebc87ca91b9d4be2dcc2e479272bcb466b5a0487b6c271f7ddea6917e14" + "sha256:34b47fa169d6006b32e99d4b3c4031f155e6e68ebcc107d6454852e8e0ee6533" ], - "version": "==0.15.3" + "version": "==0.15.4" }, "pysdl2": { "hashes": [ @@ -2320,10 +2218,10 @@ }, "python-engineio": { "hashes": [ - "sha256:4850c3e04b2040e4fd262d1047797473d1815b37a073807e7b80304c1c5f4848", - "sha256:89b90ee3816ed440c68ac7b6143244ae7d56a46a49295fbac8e6696482e596d1" + "sha256:2a4c874aea686e79f8ea9efc30748110df581df6d577d18bb5eaa1a8f2199d12", + "sha256:eae09ef72bbb13e66ad0bbe2fbb87271e0ba5e2ec8c6693c6be1e14239564e32" ], - "version": "==3.8.2.post1" + "version": "==3.9.3" }, "python-logstash": { "hashes": [ @@ -2342,24 +2240,17 @@ }, "python-socketio": { "hashes": [ - "sha256:335bd0fab481d65edce4ab82c3bb5cac950afa843329ea7c38777cd56c8eba38", - "sha256:efec4844456791b7d702efefd543ed67a8e314ca45efb8f0bfca7ae18fdee60a" - ], - "version": "==4.2.0" - }, - "python-utils": { - "hashes": [ - "sha256:34aaf26b39b0b86628008f2ae0ac001b30e7986a8d303b61e1357dfcdad4f6d3", - "sha256:e25f840564554eaded56eaa395bca507b0b9e9f0ae5ecb13a8cb785305c56d25" + "sha256:506b2cf7a520b40ea0b3f25e1272eff8de134dce6f471c1f6bc0de8c90fe8c57", + "sha256:d4e2c23241afa0aae2a5bcc107523b2fcc71f5020df89a093f3634eb48955967" ], - "version": "==2.3.0" + "version": "==4.3.1" }, "pytz": { "hashes": [ - "sha256:303879e36b721603cc54604edcac9d20401bdbe31e1e4fdee5b9f98d5d31dfda", - "sha256:d747dd3d23d77ef44c6a3526e274af6efeb0a6f1afd5a69ba4d5be4098c8e141" + "sha256:26c0b32e437e54a18161324a2fca3c4b9846b74a8dccddd843113109e1116b32", + "sha256:c894d57500a4cd2d5c71114aaab77dbab5eabd9022308ce5ac9bb93a60a6f0c7" ], - "version": "==2019.1" + "version": "==2019.2" }, "pyvcd": { "hashes": [ @@ -2400,68 +2291,51 @@ ], "version": "==1.0.3" }, - "pyyaml": { - "hashes": [ - "sha256:57acc1d8533cbe51f6662a55434f0dbecfa2b9eaf115bede8f6fd00115a0c0d3", - "sha256:588c94b3d16b76cfed8e0be54932e5729cc185caffaa5a451e7ad2f7ed8b4043", - "sha256:68c8dd247f29f9a0d09375c9c6b8fdc64b60810ebf07ba4cdd64ceee3a58c7b7", - "sha256:70d9818f1c9cd5c48bb87804f2efc8692f1023dac7f1a1a5c61d454043c1d265", - "sha256:86a93cccd50f8c125286e637328ff4eef108400dd7089b46a7be3445eecfa391", - "sha256:a0f329125a926876f647c9fa0ef32801587a12328b4a3c741270464e3e4fa778", - "sha256:a3c252ab0fa1bb0d5a3f6449a4826732f3eb6c0270925548cac342bc9b22c225", - "sha256:b4bb4d3f5e232425e25dda21c070ce05168a786ac9eda43768ab7f3ac2770955", - "sha256:cd0618c5ba5bda5f4039b9398bb7fb6a317bb8298218c3de25c47c4740e4b95e", - "sha256:ceacb9e5f8474dcf45b940578591c7f3d960e82f926c707788a570b51ba59190", - "sha256:fe6a88094b64132c4bb3b631412e90032e8cfe9745a58370462240b8cb7553cd" - ], - "index": "pypi", - "version": "==5.1.1" - }, "pyzmq": { "hashes": [ - "sha256:00dd015159eaeb1c0731ad49310e1f5d839c9a35a15e4f3267f5052233fad99b", - "sha256:03913b6beb8e7b417b9910b0ee1fd5d62e9626d218faefbe879d70714ceab1a2", - "sha256:13f17386df81d5e6efb9a4faea341d8de22cdc82e49a326dded26e33f42a3112", - "sha256:16c6281d96885db1e15f7047ddc1a8f48ff4ea35d31ca709f4d2eb39f246d356", - "sha256:17efab4a804e31f58361631256d660214204046f9e2b962738b171b9ad674ea7", - "sha256:2b79919ddeff3d3c96aa6087c21d294c8db1c01f6bfeee73324944683685f419", - "sha256:2f832e4711657bb8d16ea1feba860f676ec5f14fb9fe3b449b5953a60e89edae", - "sha256:31a11d37ac73107363b47e14c94547dbfc6a550029c3fe0530be443199026fc2", - "sha256:33a3e928e6c3138c675e1d6702dd11f6b7050177d7aab3fc322db6e1d2274490", - "sha256:34a38195a6d3a9646cbcdaf8eb245b4d935c7a57f7e1b3af467814bc1a92467e", - "sha256:42900054f1500acef6df7428edf806abbf641bf92eb9ceded24aa863397c3bae", - "sha256:4ccc7f3c63aa9d744dadb62c49eda2d0e7de55649b80c45d7c684d70161a69af", - "sha256:5b220c37c346e6575db8c88a940c1fc234f99ce8e0068c408919bb8896c4b6d2", - "sha256:6074848da5c8b44a1ca40adf75cf65aa92bc80f635e8249aa8f37a69b2b9b6f5", - "sha256:61a4155964bd4a14ef95bf46cb1651bcf8dcbbed8c0108e9c974c1fcbb57788f", - "sha256:62b5774688326600c52f587f7a033ca6b6284bef4c8b1b5fda32480897759eac", - "sha256:65a9ffa4f9f085d696f16fd7541f34b3c357d25fe99c90e3bce2ea59c3b5b4b6", - "sha256:76a077d2c30f8adc5e919a55985a784b96aeca69b53c1ea6fd5723d3ae2e6f53", - "sha256:8e5b4c51557071d6379d6dc1f54f35e9f6a137f5e84e102efb869c8d3c13c8ff", - "sha256:917f73e07cc04f0678a96d93e7bb8b1adcccdde9ccfe202e622814f4d1d1ecfd", - "sha256:91c75d3c4c357f9643e739db9e79ab9681b2f6ae8ec5678d6ef2ea0d01532596", - "sha256:923dd91618b100bb4c92ab9ed7b65825a595b8524a094ce03c7cb2aaae7d353b", - "sha256:9849054e0355e2bc7f4668766a25517ba76095031c9ff5e39ae8949cee5bb024", - "sha256:c9d453933f0e3f44b9759189f2a18aa765f7f1a4345c727c18ebe8ad0d748d26", - "sha256:cb7514936277abce64c2f4c56883e5704d85ed04d98d2d432d1c6764003bb003" - ], - "index": "pypi", - "version": "==18.0.2" + "sha256:01636e95a88d60118479041c6aaaaf5419c6485b7b1d37c9c4dd424b7b9f1121", + "sha256:021dba0d1436516092c624359e5da51472b11ba8edffa334218912f7e8b65467", + "sha256:0463bd941b6aead494d4035f7eebd70035293dd6caf8425993e85ad41de13fa3", + "sha256:05fd51edd81eed798fccafdd49c936b6c166ffae7b32482e4d6d6a2e196af4e6", + "sha256:1fadc8fbdf3d22753c36d4172169d184ee6654f8d6539e7af25029643363c490", + "sha256:22efa0596cf245a78a99060fe5682c4cd00c58bb7614271129215c889062db80", + "sha256:260c70b7c018905ec3659d0f04db735ac830fe27236e43b9dc0532cf7c9873ef", + "sha256:2762c45e289732d4450406cedca35a9d4d71e449131ba2f491e0bf473e3d2ff2", + "sha256:2fc6cada8dc53521c1189596f1898d45c5f68603194d3a6453d6db4b27f4e12e", + "sha256:343b9710a61f2b167673bea1974e70b5dccfe64b5ed10626798f08c1f7227e72", + "sha256:41bf96d5f554598a0632c3ec28e3026f1d6591a50f580df38eff0b8067efb9e7", + "sha256:856b2cdf7a1e2cbb84928e1e8db0ea4018709b39804103d3a409e5584f553f57", + "sha256:85b869abc894672de9aecdf032158ea8ad01e2f0c3b09ef60e3687fb79418096", + "sha256:93f44739db69234c013a16990e43db1aa0af3cf5a4b8b377d028ff24515fbeb3", + "sha256:98fa3e75ccb22c0dc99654e3dd9ff693b956861459e8c8e8734dd6247b89eb29", + "sha256:9a22c94d2e93af8bebd4fcf5fa38830f5e3b1ff0d4424e2912b07651eb1bafb4", + "sha256:a7d3f4b4bbb5d7866ae727763268b5c15797cbd7b63ea17f3b0ec1067da8994b", + "sha256:b645a49376547b3816433a7e2d2a99135c8e651e50497e7ecac3bd126e4bea16", + "sha256:cf0765822e78cf9e45451647a346d443f66792aba906bc340f4e0ac7870c169c", + "sha256:dc398e1e047efb18bfab7a8989346c6921a847feae2cad69fedf6ca12fb99e2c", + "sha256:dd5995ae2e80044e33b5077fb4bc2b0c1788ac6feaf15a6b87a00c14b4bdd682", + "sha256:e03fe5e07e70f245dc9013a9d48ae8cc4b10c33a1968039c5a3b64b5d01d083d", + "sha256:ea09a306144dff2795e48439883349819bef2c53c0ee62a3c2fae429451843bb", + "sha256:f4e37f33da282c3c319849877e34f97f0a3acec09622ec61b7333205bdd13b52", + "sha256:fa4bad0d1d173dee3e8ef3c3eb6b2bb6c723fc7a661eeecc1ecb2fa99860dd45" + ], + "index": "pypi", + "version": "==18.1.0" }, "qtconsole": { "hashes": [ - "sha256:6a85456af7a98b0f554d140922b7b6a219757b039adb2b95e847cf115eaa20ae", - "sha256:767eb9ec3f9943bc84270198b5ff95d2d86d68d6b57792fafa4df4fc6b16cd7c" + "sha256:40d5d8e00d070ea266dbf6f0da74c4b9597b8b8d67cd8233c3ffd8debf923703", + "sha256:b91e7412587e6cfe1644696538f73baf5611e837be5406633218443b2827c6d9" ], - "version": "==4.5.2" + "version": "==4.5.5" }, "redis": { "hashes": [ - "sha256:6946b5dca72e86103edc8033019cc3814c031232d339d5f4533b02ea85685175", - "sha256:8ca418d2ddca1b1a850afa1680a7d2fd1f3322739271de4b704e0d4668449273" + "sha256:98a22fb750c9b9bb46e75e945dc3f61d0ab30d06117cbb21ff9cd1d315fedd3b", + "sha256:c504251769031b0dd7dd5cf786050a6050197c6de0d37778c80c08cb04ae8275" ], "index": "pypi", - "version": "==3.2.1" + "version": "==3.3.8" }, "redlock": { "hashes": [ @@ -2479,13 +2353,6 @@ "index": "pypi", "version": "==2.22.0" }, - "requests-oauthlib": { - "hashes": [ - "sha256:bd6533330e8748e94bf0b214775fed487d309b8b8fe823dc45641ebcd9a32f57", - "sha256:d3ed0c8f2e3bbc6b344fa63d6f933745ab394469da38db16bdddb461c7e25140" - ], - "version": "==1.2.0" - }, "reverse-geocoder": { "hashes": [ "sha256:2a2e781b5f69376d922b78fe8978f1350c84fce0ddb07e02c834ecf98b57c75c" @@ -2508,88 +2375,49 @@ ], "version": "==0.2.1" }, - "scandir": { - "hashes": [ - "sha256:2586c94e907d99617887daed6c1d102b5ca28f1085f90446554abf1faf73123e", - "sha256:2ae41f43797ca0c11591c0c35f2f5875fa99f8797cb1a1fd440497ec0ae4b022", - "sha256:2b8e3888b11abb2217a32af0766bc06b65cc4a928d8727828ee68af5a967fa6f", - "sha256:2c712840c2e2ee8dfaf36034080108d30060d759c7b73a01a52251cc8989f11f", - "sha256:4d4631f6062e658e9007ab3149a9b914f3548cb38bfb021c64f39a025ce578ae", - "sha256:67f15b6f83e6507fdc6fca22fedf6ef8b334b399ca27c6b568cbfaa82a364173", - "sha256:7d2d7a06a252764061a020407b997dd036f7bd6a175a5ba2b345f0a357f0b3f4", - "sha256:8c5922863e44ffc00c5c693190648daa6d15e7c1207ed02d6f46a8dcc2869d32", - "sha256:92c85ac42f41ffdc35b6da57ed991575bdbe69db895507af88b9f499b701c188", - "sha256:b24086f2375c4a094a6b51e78b4cf7ca16c721dcee2eddd7aa6494b42d6d519d", - "sha256:cb925555f43060a1745d0a321cca94bcea927c50114b623d73179189a4e100ac" - ], - "markers": "python_version < '3.5'", - "version": "==1.10.0" - }, "scikit-image": { "hashes": [ - "sha256:056632aa964528c484758829d295f11c86a405aa0294f2578eac4acd945d4300", - "sha256:1600628c96b76f265dede2393115f77d93a427c617202622dfd6ba27e075efcc", - "sha256:1e85573ed37e0205ea918475c1fbd12e6c118c6f1e166dd159af04bcd9d4fa30", - "sha256:1fc4a596d6b7295bd05dce3df1105d1c7c7abe9c65f5d3ced2eace1cd746c15e", - "sha256:24ebe2a9cf40f2196393bc575345bc514bc845366545361785696a76e3aeb89b", - "sha256:331ee6db27e434e467831e21c8489bec23038ede790c53e0b6040e1e638fff45", - "sha256:4c17f2919029bd68907e2bf80dfecfb8b601bee4f392ef01f835ba4aa8c616e9", - "sha256:4e59c25be3e9760ba181832b9b33e27ff3cea9c362842260ac06644ae08b23c8", - "sha256:4f12cdf72155f77b736902e87c6b4544e311241070e9548c03ac0fcf9aa0bbed", - "sha256:62718e67f1f058501055c7e6b7206eea96f792039ea4c87af8e6b706a22ae11e", - "sha256:6b88c64f8351f1755ccc7feec26a7e55359acba2375498409fa1380bd3789b6f", - "sha256:755ee87e4b0332fd1645c67fd1e5780908937f35d28a6bd3377af304fd54a8d9", - "sha256:8508b9a2fccaa52a30785316ae4b29aaf339ef8fc3dab1bb35d36468397e0b0d", - "sha256:8541cefddad87b08105583e946132e822b196fff437f407afa92742e1e763387", - "sha256:8d76474ad59e5339584a9c4317868e51c0fbf2c2d11a936e836279fc281633d6", - "sha256:b26462abeee13ee249c814723a3038ccd74af2144349422d1b344e1378f9f702", - "sha256:b7b5605c7737073c1bdffbfea1f6a257dd6e96ab109fc37f43a7bd3d1d581e2a", - "sha256:c7afc4231e9bb9d0d2b44958e6e403117e6823bb16bca61ab95540e737f2941f", - "sha256:cc97cfc239f1f7ee8cc5129e3cb29fe553237fa62380b62d6f7c0909974d1400", - "sha256:ce114f536941348998665360ea6fbbf1577a3c49a5c2b4d416c71d3edde05ab7", - "sha256:db9f4fb00db5ce5855737c22abbdc22d9663d44643cbdad674e2c9fc32ba9c16", - "sha256:e312e914d6f97e525460268cd0d215cd9c9c4fe131457316bd32c6c760171660", - "sha256:e50d053133c292efe0e70eefc6a6481002b32d7b4b72ef38bd7caae6b24fb7d6", - "sha256:ef3fb33404fbf1717e3d268e1cc0983264fc3154036b29950fbc9c3fbed98ee3", - "sha256:f05eab2df885fb6fde3df0e4d24c9c620d6474ea0eb949fd45f6f634925dd514", - "sha256:fb1de3dabbc7a429b38a016d01502920226b59d277578291fb18a28888ed5792" - ], - "index": "pypi", - "version": "==0.14.3" + "sha256:0fb4f61ba28e7034dc490b7fd37a35428493cc1180205991aea41ab78c1a3b2a", + "sha256:117244d206f014fcdc7fd3b03dc25ffd3c32be49c5103b916dadcf3c268ce629", + "sha256:2dee5c19893bbfebeb30c2edd47e3092d84fe671e1278c8e1b8ab0b541b88590", + "sha256:2edf2189a89d68e7909bfe939f6f9978d4807c4c2c6464b9d23944171272efe5", + "sha256:56f8ec5106c1b6037f25395eb6a2c29cbbb1baa9d8cedb48a6488a697f9e0c02", + "sha256:5c24501fbe0000bf215418ced56fc718ae5bbd004df7dc460fd3fb095385dec5", + "sha256:6665b00b649237171eb0c34ec7d2c5ee96f51cc826edf1b70654fc05fddec7a8", + "sha256:676838be922fdc7c65a1bfa71409b382874d60e2a7a0c968fe832f63b485842d", + "sha256:6b8697a52e1e3c2663f74a0a972cc601d2ceb5b3299cc9be3c3b6ac41d76d238", + "sha256:91208ff13381ccbacce8a38a771e9d9d8982dce146581bcf6656aa8fd05d06ea", + "sha256:a8fb7dc56b14656768fdf21d4325bf82f543fad51dc83c24aa6a27456a946a2d", + "sha256:bea86976ab9b7bebca43721b3ff8fd74a002e1fd95e7600987cd42664fde8a39", + "sha256:ce9354571e1323ed98251723a7e5ffb3526ddd3b533a27aaca4ebd13ed479c56", + "sha256:df111e654b47e5ea456c50553debe4c5ddd97258894c7ad3b7f2f9f10798e053", + "sha256:ed6d2dbb54a68b200df8783fcb17c406ece20420c8c86508ab0f5966e8631da5", + "sha256:f0491621a6b1d2828d47acaf41d3167a647eaae44ef8fcf83b72eb3e1cc7ac51" + ], + "index": "pypi", + "version": "==0.15.0" }, "scipy": { "hashes": [ - "sha256:0bcababa06ff83138a7f30a68f334dee034ce1cc7604f9278b96f62265fe7fd7", - "sha256:162b803984ebb76927990d7233cab825d146be8e2a3f6a0efb1b3a61ebacae73", - "sha256:271c6e56c8f9a3d6c3f0bc857d7a6e7cf7a8415c879a3915701cd011e82a83a3", - "sha256:2eb255b30dac7516c6f3c5237f2e0ad1f1213b5364de409d932249c9a8c5bffb", - "sha256:447c40d33ec5e0020750fadbb8599220b9eb9fd8798030efe9b308247800f364", - "sha256:4686d699f76068757a81269f1a111c0db689bf048a56b131a339803121534fa8", - "sha256:47d4623efa71948dc4a92f978fbf6b9fb69dac5b0f0fae4c1a1f3d955ac8aea9", - "sha256:49dcebc6f57bce0bd23cb55dbc6144f4990e5cbce9aab3128af03d6b1b4eab6a", - "sha256:5fa84b467b5f77c243c5701628ed7a4238e53bc4120db87be7dafa416e842fb9", - "sha256:67d2210c7f6f585e1055bee3dc9f15610b5ebb04e80bfaa757868937ee744fec", - "sha256:682b210ff7a65f6f5245fdf73d26a348b57e42d2059bc5fcf7ed25d063f35c45", - "sha256:7f58faa422aa493d7b70dd56d6e8783223e84dd6e7f4b4161bd776b39ecbac92", - "sha256:7fb4efff9895116428ad65564d2232fb1cac4b9d84398512a858b09dd4a7fd59", - "sha256:922e2370674c82dd1367fc13a08c8765f4e5281a584d871e7cb454828d84600f", - "sha256:97f26b4b5d4456f44849fd35cad8801f7cae4e64b75fc4e522d26a54aef17391", - "sha256:9a21d64d002cb3a9239a55c0aa100b48d58b5e38382c0fdfcdfc68cf417d8142", - "sha256:a4331e0b8dab1ff75d2c67b5158a8bb9a83c799d7140094dda936d876c7cfbb1", - "sha256:a9fc1fcaa560edf771d4545d7e6dd865a213fc5b485bb127de5dfd32f40094e1", - "sha256:b074a83299a82eae617dc46a830cfa7aaa588d07523990507848ee1ded3c52ce", - "sha256:bcd0d4b2de5cb3fab69007214a39737e917267f56f887ce9c7732ba3278fc33d", - "sha256:c390f1721757ec983616149f00e1bd0432aa32d2c1d9398930d7e7cc9542c922", - "sha256:c5b9db9e3f6537bf7b308de12c185b27f22fb9a66fd12efc7aefbcfa0adb4d82", - "sha256:d0d41a9ee3264f95820138170b447f5d3e453e5ebd10b411bca37c99237aac69", - "sha256:d18d1575d4a54f128c0f34422bd73ce0f177e462d6124f074388e211d8dc2616", - "sha256:e99cd49daffe7384fd35046c3b14bee98ce87d97c95865469227001905534e13", - "sha256:f4e355afa8fdda11010de308c2376edda29e064cec699974097364115f71e16f", - "sha256:f64e29a8b32d672fb6078f456bfff3cae8f36b6c8b64c337ad0942f29404b03f", - "sha256:fbdff021643c2dfa35efd29218e0318c4b4987f48ea432be7e8c02bdb1b0c314" - ], - "index": "pypi", - "version": "==1.2.2" + "sha256:0baa64bf42592032f6f6445a07144e355ca876b177f47ad8d0612901c9375bef", + "sha256:243b04730d7223d2b844bda9500310eecc9eda0cba9ceaf0cde1839f8287dfa8", + "sha256:2643cfb46d97b7797d1dbdb6f3c23fe3402904e3c90e6facfe6a9b98d808c1b5", + "sha256:396eb4cdad421f846a1498299474f0a3752921229388f91f60dc3eda55a00488", + "sha256:3ae3692616975d3c10aca6d574d6b4ff95568768d4525f76222fb60f142075b9", + "sha256:435d19f80b4dcf67dc090cc04fde2c5c8a70b3372e64f6a9c58c5b806abfa5a8", + "sha256:46a5e55850cfe02332998b3aef481d33f1efee1960fe6cfee0202c7dd6fc21ab", + "sha256:75b513c462e58eeca82b22fc00f0d1875a37b12913eee9d979233349fce5c8b2", + "sha256:7ccfa44a08226825126c4ef0027aa46a38c928a10f0a8a8483c80dd9f9a0ad44", + "sha256:89dd6a6d329e3f693d1204d5562dd63af0fd7a17854ced17f9cbc37d5b853c8d", + "sha256:a81da2fe32f4eab8b60d56ad43e44d93d392da228a77e229e59b51508a00299c", + "sha256:a9d606d11eb2eec7ef893eb825017fbb6eef1e1d0b98a5b7fc11446ebeb2b9b1", + "sha256:ac37eb652248e2d7cbbfd89619dce5ecfd27d657e714ed049d82f19b162e8d45", + "sha256:cbc0611699e420774e945f6a4e2830f7ca2b3ee3483fca1aa659100049487dd5", + "sha256:d02d813ec9958ed63b390ded463163685af6025cb2e9a226ec2c477df90c6957", + "sha256:dd3b52e00f93fd1c86f2d78243dfb0d02743c94dd1d34ffea10055438e63b99d" + ], + "index": "pypi", + "version": "==1.3.1" }, "seaborn": { "hashes": [ @@ -2624,38 +2452,33 @@ "index": "pypi", "version": "==1.6.4.post2" }, - "simplegeneric": { - "hashes": [ - "sha256:dc972e06094b9af5b855b3df4a646395e43d1c9d0d39ed345b7393560d0b9173" - ], - "version": "==0.8.1" - }, "simplejson": { "hashes": [ "sha256:067a7177ddfa32e1483ba5169ebea1bc2ea27f224853211ca669325648ca5642", + "sha256:2b8cb601d9ba0381499db719ccc9dfbb2fbd16013f5ff096b1a68a4775576a04", + "sha256:2c139daf167b96f21542248f8e0a06596c9b9a7a41c162cc5c9ee9f3833c93cd", "sha256:2fc546e6af49fb45b93bbe878dea4c48edc34083729c0abd09981fe55bdf7f91", "sha256:354fa32b02885e6dae925f1b5bbf842c333c1e11ea5453ddd67309dc31fdb40a", "sha256:37e685986cf6f8144607f90340cff72d36acf654f3653a6c47b84c5c38d00df7", "sha256:3af610ee72efbe644e19d5eaad575c73fb83026192114e5f6719f4901097fce2", "sha256:3b919fc9cf508f13b929a9b274c40786036b31ad28657819b3b9ba44ba651f50", "sha256:3dd289368bbd064974d9a5961101f080e939cbe051e6689a193c99fb6e9ac89b", + "sha256:491de7acc423e871a814500eb2dcea8aa66c4a4b1b4825d18f756cdf58e370cb", + "sha256:495511fe5f10ccf4e3ed4fc0c48318f533654db6c47ecbc970b4ed215c791968", + "sha256:65b41a5cda006cfa7c66eabbcf96aa704a6be2a5856095b9e2fd8c293bad2b46", "sha256:6c3258ffff58712818a233b9737fe4be943d306c40cf63d14ddc82ba563f483a", "sha256:75e3f0b12c28945c08f54350d91e624f8dd580ab74fd4f1bbea54bc6b0165610", + "sha256:79b129fe65fdf3765440f7a73edaffc89ae9e7885d4e2adafe6aa37913a00fbb", "sha256:b1f329139ba647a9548aa05fb95d046b4a677643070dc2afc05fa2e975d09ca5", + "sha256:c206f47cbf9f32b573c9885f0ec813d2622976cf5effcf7e472344bc2e020ac1", + "sha256:d8e238f20bcf70063ee8691d4a72162bcec1f4c38f83c93e6851e72ad545dabb", "sha256:ee9625fc8ee164902dfbb0ff932b26df112da9f871c32f0f9c1bcf20c350fe2a", - "sha256:fb2530b53c28f0d4d84990e945c2ebb470edb469d63e389bf02ff409012fe7c5" + "sha256:fb2530b53c28f0d4d84990e945c2ebb470edb469d63e389bf02ff409012fe7c5", + "sha256:feadb95170e45f439455354904768608e356c5b174ca30b3d11b0e3f24b5c0df" ], "index": "pypi", "version": "==3.16.0" }, - "singledispatch": { - "hashes": [ - "sha256:5b06af87df13818d14f08a028e42f566640aef80805c3b50c5056b086e3c2b9c", - "sha256:833b46966687b3de7f438c761ac475213e53b306740f1abfaa86e1d1aae56aa8" - ], - "markers": "python_version < '3.4'", - "version": "==3.4.0.3" - }, "six": { "hashes": [ "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", @@ -2673,10 +2496,10 @@ }, "sqlalchemy": { "hashes": [ - "sha256:d6cda03b0187d6ed796ff70e87c9a7dce2c2c9650a7bc3c022cd331416853c31" + "sha256:2f8ff566a4d3a92246d367f2e9cd6ed3edeef670dcd6dda6dfdc9efed88bcd80" ], "index": "pypi", - "version": "==1.2.7" + "version": "==1.3.8" }, "subprocess32": { "hashes": [ @@ -2696,38 +2519,39 @@ }, "tenacity": { "hashes": [ - "sha256:a0c3c5f7ae0c33f5556c775ca059c12d6fd8ab7121613a713e8b7d649908571b", - "sha256:b87c1934daa0b2ccc7db153c37b8bf91d12f165936ade8628e7b962b92dc7705" + "sha256:6a7511a59145c2e319b7d04ddd93c12d48cc3d3c8fa42c2846d33a620ee91f57", + "sha256:a4eb168dbf55ed2cae27e7c6b2bd48ab54dabaf294177d998330cf59f294c112" ], "index": "pypi", - "version": "==5.0.4" + "version": "==5.1.1" }, "tensorboard": { "hashes": [ - "sha256:6f194519f41762bfdf5eb410ccf33226d1c252caf5ad8893288648bfbcf4d135", - "sha256:81170f66bf8f95c2e9f6b3fefe0ddc5472655a9e3793e73b5b5d4ec0ba395e76" + "sha256:143e8c8226e812bed1ad26e9139e7aeda70ea4984aab40ade52a02454bec84e4", + "sha256:d3559616ccad8d72e7a259bff51be61a9bf1e66e2cebdc782c33e4b588b5e943" ], - "version": "==1.12.2" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.0.0" }, "tensorflow-estimator": { "hashes": [ - "sha256:3e460f43682c7d789e5fe966630029558434d32502e632ee7f6703451258528c" + "sha256:54fdfe8712d54627579bc6d524ced43bbd57042cb2ce411bdf2ae46b29a772da" ], "index": "pypi", - "version": "==1.10.12" + "version": "==2.0.0" }, "tensorflow-gpu": { "hashes": [ - "sha256:0c2fa74a53009f72eb73da46ef8e78ffc09514349ba3de179c6b419b69a4bf09", - "sha256:17460b5f3525ddbbb1fb9f639955d3a999f9656cc7bf1be65bc78dea1a0cedea", - "sha256:2f85fdfee4eb93432bf8ef11428f2b5e17fb3e1b733599612329e165bb74a3fd", - "sha256:38be54cb1e757f95f24b2e03e71d7bcab359429267ff36c9e32de2ed17943a42", - "sha256:42c13cf5538125d93177b7901f23a1f6759b64f9f3f2d8680099b1fbfec37b83", - "sha256:b771297d3b93f93a20af1d2d7dc049bb9617e2c2ab25c36156b011bf1a49bd7c", - "sha256:ca68f7eb91e6101300ffc59a59c3b5600359a0ab6f2e1e8cde4a8a65ec21bb92" + "sha256:6bb259ceadac6f9ccba7c07903570e4b495d6230efce8f4ab8831cede87cea42", + "sha256:73943249a1059ea8344487756939539bd32d2639f1fc0f92d6395863764b683b", + "sha256:767d775cb7b0f997b584a7441f47d76ff216cf05eb902fc56d9d3f664b03412a", + "sha256:a79fcb04092afa2737a45ff81cfc74f4423d239bfe642159eb34c90233900157", + "sha256:a87701141f8836205e20ba061246bc3a14e73f07f061a91325ca297c641995d0", + "sha256:bd6ad275b05132910b9d929cf299895c1b92cd66a01271c8e33818454d88888c", + "sha256:ccaae56548ab8a8148c1735ca176d2b2da103dc4cd8603fe86692b0b3c7530fb" ], "index": "pypi", - "version": "==1.13.0rc0" + "version": "==2.0.0" }, "termcolor": { "hashes": [ @@ -2740,6 +2564,7 @@ "sha256:d9d012de63acb8223ac969c17c3043337c2fcfd28f3aea1ee429b345d01ef460", "sha256:de08e141f83c3a0798b050ecb097ab6259c3f0331b2f7b7750c9075ced2c20c2" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==0.8.2" }, "testpath": { @@ -2756,54 +2581,54 @@ "index": "pypi", "version": "==1.0.4" }, - "torchfile": { - "hashes": [ - "sha256:a53dfe134b737845a9f2cb24fe0585317874f965932cebdb0439d13c8da4136e" - ], - "version": "==0.1.0" - }, "tornado": { "hashes": [ - "sha256:0662d28b1ca9f67108c7e3b77afabfb9c7e87bde174fbda78186ecedc2499a9d", - "sha256:4e5158d97583502a7e2739951553cbd88a72076f152b4b11b64b9a10c4c49409", - "sha256:732e836008c708de2e89a31cb2fa6c0e5a70cb60492bee6f1ea1047500feaf7f", - "sha256:8154ec22c450df4e06b35f131adc4f2f3a12ec85981a203301d310abf580500f", - "sha256:8e9d728c4579682e837c92fdd98036bd5cdefa1da2aaf6acf26947e6dd0c01c5", - "sha256:d4b3e5329f572f055b587efc57d29bd051589fb5a43ec8898c77a47ec2fa2bbb", - "sha256:e5f2585afccbff22390cddac29849df463b252b711aa2ce7c5f3f342a5b3b444" + "sha256:349884248c36801afa19e342a77cc4458caca694b0eda633f5878e458a44cb2c", + "sha256:398e0d35e086ba38a0427c3b37f4337327231942e731edaa6e9fd1865bbd6f60", + "sha256:4e73ef678b1a859f0cb29e1d895526a20ea64b5ffd510a2307b5998c7df24281", + "sha256:559bce3d31484b665259f50cd94c5c28b961b09315ccd838f284687245f416e5", + "sha256:abbe53a39734ef4aba061fca54e30c6b4639d3e1f59653f0da37a0003de148c7", + "sha256:c845db36ba616912074c5b1ee897f8e0124df269468f25e4fe21fe72f6edd7a9", + "sha256:c9399267c926a4e7c418baa5cbe91c7d1cf362d505a1ef898fde44a07c9dd8a5" ], - "version": "==5.1.1" + "markers": "python_version >= '3.5'", + "version": "==6.0.3" }, "traitlets": { "hashes": [ - "sha256:9c4bd2d267b7153df9152698efb1050a5d84982d3384a37b2c1f7723ba3e7835", - "sha256:c6cb5e6f57c5a9bdaa40fa71ce7b4af30298fbab9ece9815b5d995ab6217c7d9" - ], - "version": "==4.3.2" - }, - "transforms3d": { - "hashes": [ - "sha256:404c7797c78aa461cb8043081901fc5517cef342d5ff56becd74a7967ba88d78" - ], - "index": "pypi", - "version": "==0.3.1" - }, - "typing": { - "hashes": [ - "sha256:38566c558a0a94d6531012c8e917b1b8518a41e418f7f15f00e129cc80162ad3", - "sha256:53765ec4f83a2b720214727e319607879fec4acde22c4fbb54fa2604e79e44ce", - "sha256:84698954b4e6719e912ef9a42a2431407fe3755590831699debda6fba92aac55" - ], - "markers": "python_version < '3.5'", - "version": "==3.7.4" + "sha256:70b4c6a1d9019d7b4f6846832288f86998aa3b9207c6821f3578a6a6a467fe44", + "sha256:d023ee369ddd2763310e4c3eae1ff649689440d4ae59d7485eb4cfbbe3e359f7" + ], + "version": "==4.3.3" + }, + "typed-ast": { + "hashes": [ + "sha256:18511a0b3e7922276346bcb47e2ef9f38fb90fd31cb9223eed42c85d1312344e", + "sha256:262c247a82d005e43b5b7f69aff746370538e176131c32dda9cb0f324d27141e", + "sha256:2b907eb046d049bcd9892e3076c7a6456c93a25bebfe554e931620c90e6a25b0", + "sha256:354c16e5babd09f5cb0ee000d54cfa38401d8b8891eefa878ac772f827181a3c", + "sha256:4e0b70c6fc4d010f8107726af5fd37921b666f5b31d9331f0bd24ad9a088e631", + "sha256:630968c5cdee51a11c05a30453f8cd65e0cc1d2ad0d9192819df9978984529f4", + "sha256:66480f95b8167c9c5c5c87f32cf437d585937970f3fc24386f313a4c97b44e34", + "sha256:71211d26ffd12d63a83e079ff258ac9d56a1376a25bc80b1cdcdf601b855b90b", + "sha256:95bd11af7eafc16e829af2d3df510cecfd4387f6453355188342c3e79a2ec87a", + "sha256:bc6c7d3fa1325a0c6613512a093bc2a2a15aeec350451cbdf9e1d4bffe3e3233", + "sha256:cc34a6f5b426748a507dd5d1de4c1978f2eb5626d51326e43280941206c209e1", + "sha256:d755f03c1e4a51e9b24d899561fec4ccaf51f210d52abdf8c07ee2849b212a36", + "sha256:d7c45933b1bdfaf9f36c579671fec15d25b06c8398f113dab64c18ed1adda01d", + "sha256:d896919306dd0aa22d0132f62a1b78d11aaf4c9fc5b3410d3c666b818191630a", + "sha256:ffde2fbfad571af120fcbfbbc61c72469e72f550d676c3342492a9dfdefb8f12" + ], + "markers": "python_version < '3.8' and implementation_name == 'cpython'", + "version": "==1.4.0" }, "urllib3": { "hashes": [ - "sha256:b246607a25ac80bedac05c6f282e3cdaf3afb65420fd024ac94435cabe6e18d1", - "sha256:dbe59173209418ae49d485b87d1681aefa36252ee85884c31346debd19463232" + "sha256:3de946ffbed6e6746608990594d08faac602528ac7015ac28d33cee6a45b7398", + "sha256:9a107b99a5393caf59c7aa3c1249c16e6879447533d0887f4336dde834c7be86" ], "index": "pypi", - "version": "==1.25.3" + "version": "==1.25.6" }, "utm": { "hashes": [ @@ -2831,15 +2656,9 @@ "sha256:133ee6d7a9016f177ddeaf191c1f58421a1dcc6ee9a42c58b34bed40e1d2cd87", "sha256:ea4947cc56d1fd6f2095c8d543ee25dad966f78692528e68b4fada11ba3f98af" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.3.0" }, - "visdom": { - "hashes": [ - "sha256:77edd6811471282740846672a996348e963b5fa4220780f126c71481ad21d5a5" - ], - "index": "pypi", - "version": "==0.1.8.8" - }, "wcwidth": { "hashes": [ "sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e", @@ -2847,41 +2666,49 @@ ], "version": "==0.1.7" }, - "websocket-client": { + "webencodings": { "hashes": [ - "sha256:1151d5fb3a62dc129164292e1227655e4bbc5dd5340a5165dfae61128ec50aa9", - "sha256:1fd5520878b68b84b5748bb30e592b10d0a91529d5383f74f4964e72b297fd3a" + "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", + "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923" ], - "index": "pypi", - "version": "==0.56.0" + "version": "==0.5.1" }, "werkzeug": { "hashes": [ - "sha256:87ae4e5b5366da2347eb3116c0e6c681a0e939a33b2805e2c0cbd282664932c4", - "sha256:a13b74dd3c45f758d4ebdb224be8f1ab8ef58b3c0ffc1783a8c7d9f4f50227e6" + "sha256:7280924747b5733b246fe23972186c6b348f9ae29724135a6dfc1e53cea433e7", + "sha256:e5f4a1f98b52b18a93da705a7458e55afb26f32bff83ff5d19189f92462d65c4" ], - "version": "==0.15.5" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.16.0" }, "wheel": { "hashes": [ - "sha256:5e79117472686ac0c4aef5bad5172ea73a1c2d1646b808c35926bd26bdfb0c08", - "sha256:62fcfa03d45b5b722539ccbc07b190e4bfff4bb9e3a4d470dd9f6a0981002565" + "sha256:10c9da68765315ed98850f8e048347c3eb06dd81822dc2ab1d4fde9dc9702646", + "sha256:f4da1763d3becf2e2cd92a14a7c920f0f00eca30fdde9ea992c836685b9faf28" ], - "markers": "python_version < '3'", - "version": "==0.33.4" + "markers": "python_version >= '3'", + "version": "==0.33.6" }, "widgetsnbextension": { "hashes": [ - "sha256:120f85acc3976450220b03b8933ce48678e518905cca69fc3c856ea5a0144196", - "sha256:8c9b4d73e388f2484296be18432d3cc0b8d59de243079a0db16a56c5571e1f86" + "sha256:079f87d87270bce047512400efd70238820751a11d2d8cb137a5a5bdbaf255c7", + "sha256:bd314f8ceb488571a5ffea6cc5b9fc6cba0adaf88a9d2386b93a489751938bcd" ], - "version": "==3.5.0" + "version": "==3.5.1" }, "wrapt": { "hashes": [ "sha256:565a021fd19419476b9362b05eeaa094178de64f8361e44468f9e9d7843901e1" ], "version": "==1.11.2" + }, + "zipp": { + "hashes": [ + "sha256:3718b1cbcd963c7d4c5511a8240812904164b7f381b647143a89d3b98f9bcd8e", + "sha256:f06903e9f1f43b12d371004b4ac7b06ab39a44adc747266928ae6debfa7b3335" + ], + "markers": "python_version >= '2.7'", + "version": "==0.6.0" } } } diff --git a/README.md b/README.md index 23c81e4303d54c..b3ff4bb29b0552 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Welcome to openpilot ====== -[openpilot](http://github.com/commaai/openpilot) is an open source driving agent. Currently, it performs the functions of Adaptive Cruise Control (ACC) and Lane Keeping Assist System (LKAS) for selected Honda, Toyota, Acura, Lexus, Chevrolet, Hyundai, Kia. It's about on par with Tesla Autopilot and GM Super Cruise, and better than [all other manufacturers](http://www.thedrive.com/tech/5707/the-war-for-autonomous-driving-part-iii-us-vs-germany-vs-japan). +[openpilot](http://github.com/commaai/openpilot) is an open source driver assistance system. Currently, it performs the functions of Adaptive Cruise Control (ACC) and Lane Keeping Assist System (LKAS) for selected Honda, Toyota, Acura, Lexus, Chevrolet, Hyundai, Kia. It's about on par with Tesla Autopilot and GM Super Cruise, and better than [all other manufacturers](http://www.thedrive.com/tech/5707/the-war-for-autonomous-driving-part-iii-us-vs-germany-vs-japan). The openpilot codebase has been written to be concise and to enable rapid prototyping. We look forward to your contributions - improving real vehicle automation has never been easier. @@ -79,6 +79,7 @@ Supported Cars | Honda | CR-V 2015-16 | Touring | Yes | Yes | 25mph1| 12mph | Nidec | | Honda | CR-V 2017-19 | Honda Sensing | Yes | Stock | 0mph | 12mph | Bosch | | Honda | CR-V Hybrid 2017-2019 | Honda Sensing | Yes | Stock | 0mph | 12mph | Bosch | +| Honda | Fit 2018-19 | Honda Sensing | Yes | Yes | 25mph1| 12mph | Inverted Nidec | | Honda | Odyssey 2018-19 | Honda Sensing | Yes | Yes | 25mph1| 0mph | Inverted Nidec | | Honda | Passport 2019 | All | Yes | Yes | 25mph1| 12mph | Inverted Nidec | | Honda | Pilot 2016-18 | Honda Sensing | Yes | Yes | 25mph1| 12mph | Nidec | @@ -92,6 +93,7 @@ Supported Cars | Kia | Optima 2019 | SCC + LKAS | Yes | Stock | 0mph | 0mph | Custom6| | Kia | Sorento 2018 | All | Yes | Stock | 0mph | 0mph | Custom6| | Kia | Stinger 2018 | SCC + LKAS | Yes | Stock | 0mph | 0mph | Custom6| +| Lexus | CT Hybrid 2017-18 | All | Yes | Yes2| 0mph | 0mph | Toyota | | Lexus | ES Hybrid 2019 | All | Yes | Yes | 0mph | 0mph | Toyota | | Lexus | RX Hybrid 2016-19 | All | Yes | Yes2| 0mph | 0mph | Toyota | | Lexus | IS 2017-2019 | All | Yes | Stock | 22mph | 0mph | Toyota | @@ -111,7 +113,7 @@ Supported Cars | Toyota | Highlander Hybrid 2017-19 | All | Yes | Yes2| 0mph | 0mph | Toyota | | Toyota | Prius 2016 | TSS-P | Yes | Yes2| 0mph | 0mph | Toyota | | Toyota | Prius 2017-19 | All | Yes | Yes2| 0mph | 0mph | Toyota | -| Toyota | Prius Prime 2017-19 | All | Yes | Yes2| 0mph | 0mph | Toyota | +| Toyota | Prius Prime 2017-20 | All | Yes | Yes2| 0mph | 0mph | Toyota | | Toyota | Rav4 2016 | TSS-P | Yes | Yes2| 20mph1| 0mph | Toyota | | Toyota | Rav4 2017-18 | All | Yes | Yes2| 20mph1| 0mph | Toyota | | Toyota | Rav4 2019 | All | Yes | Yes | 0mph | 0mph | Toyota | @@ -143,7 +145,7 @@ In Progress Cars ------ - All TSS-P Toyota with Steering Assist and LSS-P Lexus with Steering Assist or Lane Keep Assist. - All Hyundai with SmartSense. -- All Kia with SCC and LKAS. +- All Kia, Genesis with SCC and LKAS. - All Chrysler, Jeep, Fiat with Adaptive Cruise Control and LaneSense. - All Subaru with EyeSight. diff --git a/RELEASES.md b/RELEASES.md index 14ddf78b6b30a5..2f6f6729a0b40c 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,17 @@ +Version 0.6.5 (2019-10-07) +======================== + * NEOS update: upgrade to Python3 and new installer! + * comma Harness support! + * New driving model: lateral control has lower reliance on lanelines + * New driver monitoring model: more accurate face and eye detection + * Redesign offroad screen to display updates and alerts + * Increase maximum allowed acceleration + * Prevent car 12V battery drain by cutting off EON charge after 3 days of no drive + * Lexus CT Hybrid support thanks to thomaspich! + * Louder chime for critical alerts + * Add toggle to switch to dashcam mode + * Fix "invalid vehicle params" error on DSU-less Toyota + Version 0.6.4 (2019-09-08) ======================== * Forward stock AEB for Honda Nidec diff --git a/apk/ai.comma.plus.frame.apk b/apk/ai.comma.plus.frame.apk index 374862a792d77a..bb12c328ba488b 100644 Binary files a/apk/ai.comma.plus.frame.apk and b/apk/ai.comma.plus.frame.apk differ diff --git a/apk/ai.comma.plus.offroad.apk b/apk/ai.comma.plus.offroad.apk index 682761bbc4ed89..224f4b066af432 100644 Binary files a/apk/ai.comma.plus.offroad.apk and b/apk/ai.comma.plus.offroad.apk differ diff --git a/cereal/car.capnp b/cereal/car.capnp index 21d3951c4ff9a6..c38bc7d312f6eb 100644 --- a/cereal/car.capnp +++ b/cereal/car.capnp @@ -82,6 +82,8 @@ struct CarEvent @0x9b1657f34caf3ad3 { preLaneChangeLeft @57; preLaneChangeRight @58; laneChange @59; + invalidGiraffeToyota @60; + internetConnectivityNeeded @61; } } @@ -133,6 +135,9 @@ struct CarState { seatbeltUnlatched @25 :Bool; canValid @26 :Bool; + # clutch (manual transmission only) + clutchPressed @28 :Bool; + # which packets this state came from canMonoTimes @12: List(UInt64); @@ -161,6 +166,8 @@ struct CarState { sport @5; low @6; brake @7; + eco @8; + manumatic @9; } @@ -179,6 +186,9 @@ struct CarState { altButton1 @6; altButton2 @7; altButton3 @8; + setCruise @9; + resumeCruise @10; + gapAdjustCruise @11; } } } @@ -271,6 +281,7 @@ struct CarControl { wrongGear @4; seatbeltUnbuckled @5; speedTooHigh @6; + ldw @7; } enum AudibleAlert { @@ -348,6 +359,7 @@ struct CarParams { carVin @38 :Text; # VIN number queried during fingerprinting isPandaBlack @39: Bool; dashcamOnly @41: Bool; + transmissionType @43 :TransmissionType; struct LateralPIDTuning { kpBP @0 :List(Float32); @@ -388,9 +400,7 @@ struct CarParams { l @7 :List(Float32); # Kalman gain } - enum SafetyModel { - # does NOT match board setting noOutput @0; honda @1; toyota @2; @@ -404,10 +414,22 @@ struct CarParams { tesla @10; subaru @11; gmPassive @12; + mazda @13; + nissan @14; + volkswagen @15; + toyotaIpas @16; + allOutput @17; + gmAscm @18; } enum SteerControlType { torque @0; angle @1; } + + enum TransmissionType { + unknown @0; + automatic @1; + manual @2; + } } diff --git a/cereal/log.capnp b/cereal/log.capnp index cc17deebc43fa0..30e346668d0ac8 100644 --- a/cereal/log.capnp +++ b/cereal/log.capnp @@ -305,7 +305,9 @@ struct HealthData { canSendErrs @7 :UInt32; canFwdErrs @8 :UInt32; gmlanSendErrs @9 :UInt32; - hwType @10: HwType; + hwType @10 :HwType; + fanSpeedRpm @11 :UInt16; + usbPowerMode @12 :UsbPowerMode; enum HwType { unknown @0; @@ -313,6 +315,14 @@ struct HealthData { greyPanda @2; blackPanda @3; pedal @4; + uno @5; + } + + enum UsbPowerMode { + none @0; + client @1; + cdp @2; + dcp @3; } } diff --git a/common/api/__init__.py b/common/api/__init__.py index 8eb9817399f9e7..b27520738e2f93 100644 --- a/common/api/__init__.py +++ b/common/api/__init__.py @@ -4,7 +4,7 @@ from selfdrive.version import version -class Api(object): +class Api(): def __init__(self, dongle_id): self.dongle_id = dongle_id with open('/persist/comma/id_rsa') as f: @@ -27,7 +27,7 @@ def get_token(self): 'iat': now, 'exp': now + timedelta(hours=1) } - return jwt.encode(payload, self.private_key, algorithm='RS256') + return jwt.encode(payload, self.private_key, algorithm='RS256').decode('utf8') def api_get(endpoint, method='GET', timeout=None, access_token=None, **params): backend = "https://api.commadotai.com/" diff --git a/common/cython_hacks.py b/common/cython_hacks.py new file mode 100644 index 00000000000000..d0e154746d3455 --- /dev/null +++ b/common/cython_hacks.py @@ -0,0 +1,23 @@ +import os +import sysconfig +from Cython.Distutils import build_ext + +def get_ext_filename_without_platform_suffix(filename): + name, ext = os.path.splitext(filename) + ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') + + if ext_suffix == ext: + return filename + + ext_suffix = ext_suffix.replace(ext, '') + idx = name.find(ext_suffix) + + if idx == -1: + return filename + else: + return name[:idx] + ext + +class BuildExtWithoutPlatformSuffix(build_ext): + def get_ext_filename(self, ext_name): + filename = super().get_ext_filename(ext_name) + return get_ext_filename_without_platform_suffix(filename) diff --git a/common/dbc.py b/common/dbc.py index 693b2985a4cf62..e65ee38be87b16 100755 --- a/common/dbc.py +++ b/common/dbc.py @@ -17,10 +17,10 @@ def int_or_float(s): "factor", "offset", "tmin", "tmax", "units"]) -class dbc(object): +class dbc(): def __init__(self, fn): self.name, _ = os.path.splitext(os.path.basename(fn)) - with open(fn) as f: + with open(fn, encoding="ascii") as f: self.txt = f.readlines() self._warned_addresses = set() @@ -41,7 +41,7 @@ def __init__(self, fn): self.def_vals = defaultdict(list) # lookup to bit reverse each byte - self.bits_index = [(i & ~0b111) + ((-i-1) & 0b111) for i in xrange(64)] + self.bits_index = [(i & ~0b111) + ((-i-1) & 0b111) for i in range(64)] for l in self.txt: l = l.strip() @@ -213,7 +213,7 @@ def decode(self, x, arr=None, debug=False): if debug: print(name) - st = x[2].ljust(8, '\x00') + st = x[2].ljust(8, b'\x00') le, be = None, None for s in msg[1]: diff --git a/common/ffi_wrapper.py b/common/ffi_wrapper.py index f41115d1ce721f..2c169881cee7af 100644 --- a/common/ffi_wrapper.py +++ b/common/ffi_wrapper.py @@ -9,7 +9,7 @@ def ffi_wrap(name, c_code, c_header, tmpdir="/tmp/ccache", cflags="", libraries= if libraries is None: libraries = [] - cache = name + "_" + hashlib.sha1(c_code).hexdigest() + cache = name + "_" + hashlib.sha1(c_code.encode('utf-8')).hexdigest() try: os.mkdir(tmpdir) except OSError: diff --git a/common/file_helpers.py b/common/file_helpers.py index beeee89088ab75..40c89fab0ead25 100644 --- a/common/file_helpers.py +++ b/common/file_helpers.py @@ -32,7 +32,7 @@ def get_tmpdir_on_same_filesystem(path): return "/{}/runner/tmp".format(parts[1]) return "/tmp" -class AutoMoveTempdir(object): +class AutoMoveTempdir(): def __init__(self, target_path, temp_dir=None): self._target_path = target_path self._path = tempfile.mkdtemp(dir=temp_dir) @@ -52,7 +52,7 @@ def __exit__(self, type, value, traceback): else: shutil.rmtree(self._path) -class NamedTemporaryDir(object): +class NamedTemporaryDir(): def __init__(self, temp_dir=None): self._path = tempfile.mkdtemp(dir=temp_dir) diff --git a/common/kalman/Makefile b/common/kalman/Makefile index 88b032af1bc4f5..df748197f23cec 100644 --- a/common/kalman/Makefile +++ b/common/kalman/Makefile @@ -1,7 +1,7 @@ all: simple_kalman_impl.so simple_kalman_impl.so: simple_kalman_impl.pyx simple_kalman_impl.pxd simple_kalman_setup.py - python2 simple_kalman_setup.py build_ext --inplace + python3 simple_kalman_setup.py build_ext --inplace rm -rf build rm simple_kalman_impl.c diff --git a/common/kalman/simple_kalman.py b/common/kalman/simple_kalman.py index 97b6d792dc967b..0b35555b614ba3 100644 --- a/common/kalman/simple_kalman.py +++ b/common/kalman/simple_kalman.py @@ -5,6 +5,6 @@ kalman_dir = os.path.dirname(os.path.abspath(__file__)) subprocess.check_call(["make", "simple_kalman_impl.so"], cwd=kalman_dir) -from simple_kalman_impl import KF1D as KF1D +from .simple_kalman_impl import KF1D as KF1D # Silence pyflakes assert KF1D diff --git a/common/kalman/simple_kalman_impl.pyx b/common/kalman/simple_kalman_impl.pyx index 43acf7e2a086fa..e65efd577e6b63 100644 --- a/common/kalman/simple_kalman_impl.pyx +++ b/common/kalman/simple_kalman_impl.pyx @@ -1,3 +1,4 @@ +# cython: language_level=3 cdef class KF1D: def __init__(self, x0, A, C, K): @@ -32,4 +33,4 @@ cdef class KF1D: @x.setter def x(self, x): self.x0_0 = x[0][0] - self.x1_0 = x[1][0] \ No newline at end of file + self.x1_0 = x[1][0] diff --git a/common/kalman/simple_kalman_setup.py b/common/kalman/simple_kalman_setup.py index bccd9f888f33b7..b7cad0ee2a27f3 100644 --- a/common/kalman/simple_kalman_setup.py +++ b/common/kalman/simple_kalman_setup.py @@ -1,5 +1,9 @@ -from distutils.core import setup, Extension +from distutils.core import Extension, setup # pylint: disable=import-error,no-name-in-module + from Cython.Build import cythonize +from common.cython_hacks import BuildExtWithoutPlatformSuffix + setup(name='Simple Kalman Implementation', - ext_modules=cythonize(Extension("simple_kalman_impl", ["simple_kalman_impl.pyx"]))) \ No newline at end of file + cmdclass={'build_ext': BuildExtWithoutPlatformSuffix}, + ext_modules=cythonize(Extension("simple_kalman_impl", ["simple_kalman_impl.pyx"]))) diff --git a/common/numpy_fast.py b/common/numpy_fast.py index eb706a908ff643..a5d5ad3f502b03 100644 --- a/common/numpy_fast.py +++ b/common/numpy_fast.py @@ -12,7 +12,10 @@ def get_interp(xv): hi += 1 low = hi - 1 return fp[-1] if hi == N and xv > xp[low] else ( - fp[0] if hi == 0 else + fp[0] if hi == 0 else (xv - xp[low]) * (fp[hi] - fp[low]) / (xp[hi] - xp[low]) + fp[low]) return [get_interp(v) for v in x] if hasattr( x, '__iter__') else get_interp(x) + +def mean(x): + return sum(x) / len(x) diff --git a/common/params.py b/common/params.py index 9af435361fbadb..3c5a63786caf71 100755 --- a/common/params.py +++ b/common/params.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 """ROS has a parameter server, we have files. The parameter store is a persistent key value store, implemented as a directory with a writer lock. @@ -59,29 +59,38 @@ class UnknownKeyName(Exception): "ControlsParams": [TxType.PERSISTENT], "DoUninstall": [TxType.CLEAR_ON_MANAGER_START], "DongleId": [TxType.PERSISTENT], - "GithubSshKeys": [TxType.PERSISTENT], "GitBranch": [TxType.PERSISTENT], "GitCommit": [TxType.PERSISTENT], "GitRemote": [TxType.PERSISTENT], + "GithubSshKeys": [TxType.PERSISTENT], "HasAcceptedTerms": [TxType.PERSISTENT], + "HasCompletedSetup": [TxType.PERSISTENT], "IsGeofenceEnabled": [TxType.PERSISTENT], "IsMetric": [TxType.PERSISTENT], "IsRHD": [TxType.PERSISTENT], "IsUpdateAvailable": [TxType.PERSISTENT], "IsUploadRawEnabled": [TxType.PERSISTENT], "IsUploadVideoOverCellularEnabled": [TxType.PERSISTENT], + "LastUpdateTime": [TxType.PERSISTENT], "LimitSetSpeed": [TxType.PERSISTENT], "LimitSetSpeedNeural": [TxType.PERSISTENT], "LiveParameters": [TxType.PERSISTENT], "LongitudinalControl": [TxType.PERSISTENT], + "OpenpilotEnabledToggle": [TxType.PERSISTENT], "Passive": [TxType.PERSISTENT], "RecordFront": [TxType.PERSISTENT], + "ReleaseNotes": [TxType.PERSISTENT], "ShouldDoUpdate": [TxType.CLEAR_ON_MANAGER_START], "SpeedLimitOffset": [TxType.PERSISTENT], "SubscriberInfo": [TxType.PERSISTENT], "TermsVersion": [TxType.PERSISTENT], "TrainingVersion": [TxType.PERSISTENT], + "UpdateAvailable": [TxType.CLEAR_ON_MANAGER_START], "Version": [TxType.PERSISTENT], + "Offroad_ChargeDisabled": [TxType.CLEAR_ON_MANAGER_START, TxType.CLEAR_ON_PANDA_DISCONNECT], + "Offroad_TemperatureTooHigh": [TxType.CLEAR_ON_MANAGER_START], + "Offroad_ConnectivityNeededPrompt": [TxType.CLEAR_ON_MANAGER_START], + "Offroad_ConnectivityNeeded": [TxType.CLEAR_ON_MANAGER_START], } @@ -93,7 +102,7 @@ def fsync_dir(path): os.close(fd) -class FileLock(object): +class FileLock(): def __init__(self, path, create): self._path = path self._create = create @@ -109,7 +118,7 @@ def release(self): self._fd = None -class DBAccessor(object): +class DBAccessor(): def __init__(self, path): self._path = path self._vals = None @@ -279,6 +288,9 @@ def read_db(params_path, key): return None def write_db(params_path, key, value): + if isinstance(value, str): + value = value.encode('utf8') + prev_umask = os.umask(0) lock = FileLock(params_path+"/.lock", True) lock.acquire() @@ -297,7 +309,7 @@ def write_db(params_path, key, value): os.umask(prev_umask) lock.release() -class Params(object): +class Params(): def __init__(self, db='/data/params'): self.db = db @@ -328,7 +340,7 @@ def delete(self, key): with self.transaction(write=True) as txn: txn.delete(key) - def get(self, key, block=False): + def get(self, key, block=False, encoding=None): if key not in keys: raise UnknownKeyName(key) @@ -338,9 +350,21 @@ def get(self, key, block=False): break # is polling really the best we can do? time.sleep(0.05) + + if ret is not None and encoding is not None: + ret = ret.decode(encoding) + return ret def put(self, key, dat): + """ + 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 + in general try to avoid writing params as much as possible. + """ + if key not in keys: raise UnknownKeyName(key) diff --git a/common/profiler.py b/common/profiler.py index 7f9b1a41ffb188..eab091c7fc4502 100644 --- a/common/profiler.py +++ b/common/profiler.py @@ -1,6 +1,6 @@ import time -class Profiler(object): +class Profiler(): def __init__(self, enabled=False): self.enabled = enabled self.cp = {} diff --git a/common/realtime.py b/common/realtime.py index 6fe64d0d720302..f8e489612ac4ee 100644 --- a/common/realtime.py +++ b/common/realtime.py @@ -19,6 +19,7 @@ DT_CTRL = 0.01 # controlsd DT_PLAN = 0.05 # mpc DT_MDL = 0.05 # model +DT_RDR = 0.05 # radar DT_DMON = 0.1 # driver monitoring DT_TRML = 0.5 # thermald and manager @@ -43,7 +44,7 @@ def set_realtime_priority(level): return subprocess.call(['chrt', '-f', '-p', str(level), str(tid)]) -class Ratekeeper(object): +class Ratekeeper(): def __init__(self, rate, print_delay_threshold=0.): """Rate in Hz for ratekeeping. print_delay_threshold must be nonnegative.""" self._interval = 1. / rate diff --git a/common/spinner.py b/common/spinner.py new file mode 100644 index 00000000000000..7da31a9dda9ce2 --- /dev/null +++ b/common/spinner.py @@ -0,0 +1,28 @@ +import os +import subprocess +from common.basedir import BASEDIR + +class Spinner(): + def __enter__(self): + self.spinner_proc = subprocess.Popen(["./spinner"], + stdin=subprocess.PIPE, + cwd=os.path.join(BASEDIR, "selfdrive", "ui", "spinner"), + close_fds=True) + return self + + def update(self, spinner_text): + self.spinner_proc.stdin.write(spinner_text.encode('utf8') + b"\n") + self.spinner_proc.stdin.flush() + + def __exit__(self, type, value, traceback): + self.spinner_proc.stdin.close() + self.spinner_proc.terminate() + + + +if __name__ == "__main__": + import time + with Spinner() as s: + s.update("Spinner text") + time.sleep(5.0) + diff --git a/common/stat_live.py b/common/stat_live.py index 06b4f993be3e17..f392956efd83f0 100644 --- a/common/stat_live.py +++ b/common/stat_live.py @@ -11,7 +11,7 @@ def __init__(self, priors=None, max_trackable=-1): self.n = priors[2] self.M_last = self.M self.S_last = self.S - + else: self.reset() @@ -70,4 +70,4 @@ def push_and_update(self, new_data): pass # self.filtered_stat.push_data(self.filtered_stat.mean()) -# class SequentialBayesian(): \ No newline at end of file +# class SequentialBayesian(): diff --git a/common/sympy_helpers.py b/common/sympy_helpers.py index f20bdb08a7132b..78688a84cf284a 100644 --- a/common/sympy_helpers.py +++ b/common/sympy_helpers.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import sympy as sp import numpy as np diff --git a/common/transformations/camera.py b/common/transformations/camera.py index a5c14bb4bfd635..97c7c37d1b655d 100644 --- a/common/transformations/camera.py +++ b/common/transformations/camera.py @@ -125,7 +125,7 @@ def img_from_device(pt_device): #TODO please use generic img transform below def rotate_img(img, eulers, crop=None, intrinsics=eon_intrinsics): - import cv2 + import cv2 # pylint: disable=no-name-in-module, import-error size = img.shape[:2] rot = orient.rot_from_euler(eulers) @@ -138,8 +138,8 @@ def rotate_img(img, eulers, crop=None, intrinsics=eon_intrinsics): warped_quadrangle = np.column_stack((warped_quadrangle_full[:,0]/warped_quadrangle_full[:,2], warped_quadrangle_full[:,1]/warped_quadrangle_full[:,2])).astype(np.float32) if crop: - W_border = (size[1] - crop[0])/2 - H_border = (size[0] - crop[1])/2 + W_border = (size[1] - crop[0])//2 + H_border = (size[0] - crop[1])//2 outside_crop = (((warped_quadrangle[:,0] < W_border) | (warped_quadrangle[:,0] >= size[1] - W_border)) & ((warped_quadrangle[:,1] < H_border) | @@ -183,7 +183,8 @@ def transform_img(base_img, alpha=1.0, beta=0, blur=0): - import cv2 + import cv2 # pylint: disable=no-name-in-module, import-error + cv2.setNumThreads(1) if yuv: base_img = cv2.cvtColor(base_img, cv2.COLOR_YUV2RGB_I420) @@ -240,7 +241,7 @@ def get_M(h=1.22): def yuv_crop(frame, output_size, center=None): # output_size in camera coordinates so u,v # center in array coordinates so row, column - import cv2 + import cv2 # pylint: disable=no-name-in-module, import-error rgb = cv2.cvtColor(frame, cv2.COLOR_YUV2RGB_I420) if not center: center = (rgb.shape[0]/2, rgb.shape[1]/2) diff --git a/common/transformations/coordinates.py b/common/transformations/coordinates.py index 568fb9bf2b3f4e..864bc4d807e174 100644 --- a/common/transformations/coordinates.py +++ b/common/transformations/coordinates.py @@ -65,7 +65,7 @@ def ecef2geodetic(ecef, radians=False): geodetic = np.column_stack((lat, lon, h)) return geodetic.reshape(input_shape) -class LocalCoord(object): +class LocalCoord(): """ Allows conversions to local frames. In this case NED. That is: North East Down from the start position in diff --git a/common/transformations/orientation.py b/common/transformations/orientation.py index 33a822ca3fd498..acbd4a2bf3e025 100644 --- a/common/transformations/orientation.py +++ b/common/transformations/orientation.py @@ -29,7 +29,7 @@ def euler2quat(eulers): np.sin(gamma / 2) * np.sin(theta / 2) * np.cos(psi / 2) quats = array([q0, q1, q2, q3]).T - for i in xrange(len(quats)): + for i in range(len(quats)): if quats[i,0] < 0: quats[i] = -quats[i] return quats.reshape(output_shape) @@ -99,7 +99,7 @@ def rot2quat(rots): 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 xrange(len(rots)): + for i in range(len(rots)): _, eigvecs = linalg.eigh(K3[i].T) eigvecs = eigvecs[:,3:] q[i, 0] = eigvecs[-1] diff --git a/installer/updater/update.json b/installer/updater/update.json index 2715fcaccc0b06..2ff5690fd5bb6c 100644 --- a/installer/updater/update.json +++ b/installer/updater/update.json @@ -1,7 +1,7 @@ { - "ota_url": "https://commadist.azureedge.net/neosupdate/ota-signed-4db25072191d24e204a816d73ac9e8c727822a26ed3baf01ecae18167fa2eb11.zip", - "ota_hash": "4db25072191d24e204a816d73ac9e8c727822a26ed3baf01ecae18167fa2eb11", - "recovery_url": "https://commadist.azureedge.net/neosupdate/recovery-31ef14206d3102edf18fb7417ef32ba2d9f37dd2f4443e234c374a70d1bf4662.img", - "recovery_len": 15136044, - "recovery_hash": "31ef14206d3102edf18fb7417ef32ba2d9f37dd2f4443e234c374a70d1bf4662" + "ota_url": "https://commadist.azureedge.net/neosupdate/ota-signed-7a0117425bc4a6673958d265312994e124654a566228f3cec2f0f9bc8120a9ab.zip", + "ota_hash": "7a0117425bc4a6673958d265312994e124654a566228f3cec2f0f9bc8120a9ab", + "recovery_url": "https://commadist.azureedge.net/neosupdate/recovery-3dc234d868c29a3739f6ca3bd47b1c2d3c570d9f478b6849a4fada129ee4af76.img", + "recovery_len": 15848748, + "recovery_hash": "3dc234d868c29a3739f6ca3bd47b1c2d3c570d9f478b6849a4fada129ee4af76" } diff --git a/launch_chffrplus.sh b/launch_chffrplus.sh index 287c72a78e7f14..56c25e6ffee090 100755 --- a/launch_chffrplus.sh +++ b/launch_chffrplus.sh @@ -32,6 +32,24 @@ function launch { echo 0-3 > /dev/cpuset/foreground/cpus echo 0-3 > /dev/cpuset/android/cpus + DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" + + # Remove old NEOS update file + if [ -d /data/neoupdate ]; then + rm -rf /data/neoupdate + fi + + # Check for NEOS update + if [ $(< /VERSION) != "12" ]; then + if [ -f "$DIR/scripts/continue.sh" ]; then + cp "$DIR/scripts/continue.sh" "/data/data/com.termux/files/continue.sh" + fi + + git clean -xdf + "$DIR/installer/updater/updater" "file://$DIR/installer/updater/update.json" + fi + + # handle pythonpath ln -s /data/openpilot /data/pythonpath export PYTHONPATH="$PWD" diff --git a/models/driving_model.dlc b/models/driving_model.dlc index 3dc890079f4ab5..419cee019c4df7 100644 Binary files a/models/driving_model.dlc and b/models/driving_model.dlc differ diff --git a/models/monitoring_model.dlc b/models/monitoring_model.dlc index f7496fb925d873..58615915b0f829 100644 Binary files a/models/monitoring_model.dlc and b/models/monitoring_model.dlc differ diff --git a/opendbc/cadillac_ct6_powertrain.dbc b/opendbc/cadillac_ct6_powertrain.dbc index f139b1dbd4a734..a91cdc14fe98d7 100644 --- a/opendbc/cadillac_ct6_powertrain.dbc +++ b/opendbc/cadillac_ct6_powertrain.dbc @@ -189,7 +189,7 @@ BO_ 1033 ASCMKeepAlive: 7 NEO SG_ ASCMKeepAliveAllZero : 7|56@0+ (1,0) [0|0] "" NEO BO_ 1217 ECMEngineCoolantTemp: 8 K20_ECM - SG_ EngineCoolantTemp : 23|8@0+ (1,-40) [0|0] "°C" NEO + SG_ EngineCoolantTemp : 23|8@0+ (1,-40) [0|0] "C" NEO BO_ 1249 VIN_Part2: 8 K20_ECM SG_ VINPart2 : 7|64@0+ (1,0) [0|0] "" NEO @@ -241,4 +241,3 @@ VAL_ 356 LKATorqueDeliveredStatus 7 "Override Fault" 6 "LKAS Fault but Responsiv VAL_ 489 BrakePedalPressed 1 "Pressed" 0 "Depressed" ; VAL_ 715 GasRegenCmdActiveInv 1 "Inactive" 0 "Active" ; VAL_ 715 GasRegenCmdActive 1 "Active" 0 "Inactive" ; - diff --git a/opendbc/generator/generator.py b/opendbc/generator/generator.py index 85f3f009e27d02..ca7daac5ca6e38 100755 --- a/opendbc/generator/generator.py +++ b/opendbc/generator/generator.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import os import re @@ -40,10 +40,10 @@ def create_dbc(dir_name, filename): if dir_name == cur_path: continue - print dir_name + print(dir_name) for filename in filenames: if filename.startswith('_'): continue - print filename + print(filename) create_dbc(dir_name, filename) diff --git a/opendbc/generator/honda/_bosch_2018.dbc b/opendbc/generator/honda/_bosch_2018.dbc index 8a7ff76561f0de..648f4b310c4367 100644 --- a/opendbc/generator/honda/_bosch_2018.dbc +++ b/opendbc/generator/honda/_bosch_2018.dbc @@ -123,7 +123,7 @@ BO_ 479 ACC_CONTROL: 8 EON SG_ SET_TO_0 : 20|5@0+ (1,0) [0|1] "" XXX SG_ CONTROL_ON : 23|3@0+ (1,0) [0|5] "" XXX SG_ GAS_COMMAND : 7|16@0- (1,0) [0|0] "" XXX - SG_ ACCEL_COMMAND : 31|11@0- (1,0) [0|0] "" XXX + SG_ ACCEL_COMMAND : 31|11@0- (0.01,0) [0|0] "m/s2" XXX SG_ BRAKE_LIGHTS : 62|1@0+ (1,0) [0|1] "" XXX SG_ BRAKE_REQUEST : 34|1@0+ (1,0) [0|1] "" XXX SG_ STANDSTILL : 35|1@0+ (1,0) [0|1] "" XXX diff --git a/opendbc/generator/toyota/_toyota_2017.dbc b/opendbc/generator/toyota/_toyota_2017.dbc index 6a54ce22ee0646..3ad15b80556732 100644 --- a/opendbc/generator/toyota/_toyota_2017.dbc +++ b/opendbc/generator/toyota/_toyota_2017.dbc @@ -36,8 +36,8 @@ BS_: BU_: XXX DSU HCU EPS IPAS CGW BO_ 36 KINEMATICS: 8 XXX - SG_ ACCEL_Y : 33|10@0+ (1,-512) [0|65535] "" XXX - SG_ YAW_RATE : 1|10@0+ (1,-512) [0|65535] "" XXX + SG_ ACCEL_Y : 33|10@0+ (0.03589,-18.375) [0|65535] "m/s^2" XXX + SG_ YAW_RATE : 1|10@0+ (0.244,-125) [0|65535] "deg/sec" XXX SG_ STEERING_TORQUE : 17|10@0+ (1,-512) [0|65535] "" XXX BO_ 37 STEER_ANGLE_SENSOR: 8 XXX @@ -57,8 +57,8 @@ BO_ 170 WHEEL_SPEEDS: 8 XXX BO_ 180 SPEED: 8 XXX SG_ ENCODER : 39|8@0+ (1,0) [0|255] "" XXX - SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX SG_ SPEED : 47|16@0+ (0.01,0) [0|250] "kph" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX BO_ 353 DSU_SPEED: 8 XXX SG_ FORWARD_SPEED : 15|16@0- (0.00390625,-30) [0|255] "kph" XXX @@ -150,6 +150,7 @@ BO_ 921 PCM_CRUISE_SM: 8 XXX BO_ 951 ESP_CONTROL: 8 ESP SG_ TC_DISABLED : 13|1@0+ (1,0) [0|1] "" XXX + SG_ VSC_DISABLED : 12|2@0+ (1,0) [0|1] "" XXX SG_ BRAKE_LIGHTS_ACC : 18|1@0+ (1,0) [0|1] "" XXX BO_ 1041 ACC_HUD: 8 DSU @@ -174,6 +175,17 @@ BO_ 1042 LKAS_HUD: 8 XXX SG_ SET_ME_X38 : 55|8@0+ (1,0) [0|1] "" XXX SG_ SET_ME_X02 : 63|8@0+ (1,0) [0|1] "" XXX +BO_ 1043 TIME : 8 CGW + SG_ YEAR : 7|8@0+ (1,0) [0|0] "year" XXX + SG_ MONTH : 15|8@0+ (1,0) [0|0] "month" XXX + SG_ DAY : 23|8@0+ (1,0) [0|0] "day" XXX + SG_ HOUR : 31|8@0+ (1,0) [0|0] "hour" XXX + SG_ MINUTE : 39|8@0+ (1,0) [0|0] "minute" XXX + SG_ GMT_DIFF : 55|1@0+ (1,0) [0|0] "" XXX + SG_ GMTDIFF_HOURS : 54|4@0+ (1,0) [0|0] "hours" XXX + SG_ GMTDIFF_MINUTES : 50|6@0+ (1,0) [0|0] "minutes" XXX + SG_ SUMMER : 60|1@0+ (1,0) [0|0] "" XXX + BO_ 1408 VIN_PART_1: 8 CGW SG_ VIN_1 : 7|8@0+ (1,0) [0|0] "" XXX SG_ VIN_2 : 15|8@0+ (1,0) [0|0] "" XXX diff --git a/opendbc/generator/toyota/lexus_ct200h_2018_pt.dbc b/opendbc/generator/toyota/lexus_ct200h_2018_pt.dbc index 55919570f94337..c6ec5e11d120e5 100644 --- a/opendbc/generator/toyota/lexus_ct200h_2018_pt.dbc +++ b/opendbc/generator/toyota/lexus_ct200h_2018_pt.dbc @@ -10,7 +10,7 @@ BO_ 581 GAS_PEDAL: 5 XXX SG_ GAS_PEDAL : 23|8@0+ (0.005,0) [0|1] "" XXX BO_ 608 STEER_TORQUE_SENSOR: 8 XXX - SG_ STEER_TORQUE_EPS : 47|16@0- (0.73,0) [-20000|20000] "" XXX + SG_ STEER_TORQUE_EPS : 47|16@0- (1,0) [-20000|20000] "" XXX SG_ STEER_TORQUE_DRIVER : 15|16@0- (1,0) [-32768|32767] "" XXX SG_ STEER_OVERRIDE : 0|1@0+ (1,0) [0|1] "" XXX SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX @@ -34,4 +34,4 @@ VAL_ 610 IPAS_STATE 5 "override" 3 "enabled" 1 "disabled"; VAL_ 610 LKA_STATE 25 "temporary_fault" 9 "temporary_fault2" 5 "active" 1 "standby"; VAL_ 956 GEAR 0 "D" 1 "S" 8 "N" 16 "R" 32 "P"; VAL_ 956 SPORT_ON 0 "off" 1 "on"; -VAL_ 956 ECON_ON 0 "off" 1 "on"; \ No newline at end of file +VAL_ 956 ECON_ON 0 "off" 1 "on"; diff --git a/opendbc/generator/toyota/toyota_camry_hybrid_2018_pt.dbc b/opendbc/generator/toyota/toyota_camry_hybrid_2018_pt.dbc index 1d41d1e2020a49..8b2cda1eb78fbe 100644 --- a/opendbc/generator/toyota/toyota_camry_hybrid_2018_pt.dbc +++ b/opendbc/generator/toyota/toyota_camry_hybrid_2018_pt.dbc @@ -20,7 +20,7 @@ BO_ 608 STEER_TORQUE_SENSOR: 8 XXX SG_ STEER_TORQUE_DRIVER : 15|16@0- (1,0) [-32768|32767] "" XXX SG_ STEER_OVERRIDE : 0|1@0+ (1,0) [0|1] "" XXX SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX - SG_ STEER_ANGLE : 31|16@0- (0.05527,0) [-500|500] "" XXX + SG_ STEER_ANGLE : 31|16@0- (0.0573,0) [-500|500] "" XXX BO_ 610 EPS_STATUS: 8 EPS SG_ IPAS_STATE : 3|4@0+ (1,0) [0|15] "" XXX diff --git a/opendbc/generator/toyota/toyota_nodsu_hybrid_pt.dbc b/opendbc/generator/toyota/toyota_nodsu_hybrid_pt.dbc index 4f641575188073..ac91c726f3970d 100644 --- a/opendbc/generator/toyota/toyota_nodsu_hybrid_pt.dbc +++ b/opendbc/generator/toyota/toyota_nodsu_hybrid_pt.dbc @@ -20,7 +20,7 @@ BO_ 608 STEER_TORQUE_SENSOR: 8 XXX SG_ STEER_TORQUE_DRIVER : 15|16@0- (1,0) [-32768|32767] "" XXX SG_ STEER_OVERRIDE : 0|1@0+ (1,0) [0|1] "" XXX SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX - SG_ STEER_ANGLE : 31|16@0- (0.056,0) [-500|500] "" XXX + SG_ STEER_ANGLE : 31|16@0- (0.0573,0) [-500|500] "" XXX BO_ 610 EPS_STATUS: 8 EPS SG_ IPAS_STATE : 3|4@0+ (1,0) [0|15] "" XXX diff --git a/opendbc/generator/toyota/toyota_nodsu_pt.dbc b/opendbc/generator/toyota/toyota_nodsu_pt.dbc index 026abdd88162a8..9bc1b1e6739079 100644 --- a/opendbc/generator/toyota/toyota_nodsu_pt.dbc +++ b/opendbc/generator/toyota/toyota_nodsu_pt.dbc @@ -8,7 +8,7 @@ BO_ 401 STEERING_LTA: 8 XXX SG_ PERCENTAGE : 39|8@0+ (1,0) [0|255] "" XXX SG_ SETME_X64 : 47|8@0+ (1,0) [0|255] "" XXX SG_ ANGLE : 55|8@0- (0.5,0) [0|255] "" XXX - SG_ STEER_ANGLE_CMD : 15|16@0- (0.056,0) [-540|540] "" XXX + SG_ STEER_ANGLE_CMD : 15|16@0- (0.0573,0) [-540|540] "" XXX SG_ STEER_REQUEST : 25|1@0+ (1,0) [0|1] "" XXX SG_ BIT : 30|1@0+ (1,0) [0|1] "" XXX @@ -26,7 +26,7 @@ BO_ 608 STEER_TORQUE_SENSOR: 8 XXX SG_ STEER_TORQUE_DRIVER : 15|16@0- (1,0) [-32768|32767] "" XXX SG_ STEER_OVERRIDE : 0|1@0+ (1,0) [0|1] "" XXX SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX - SG_ STEER_ANGLE : 31|16@0- (0.056,0) [-500|500] "" XXX + SG_ STEER_ANGLE : 31|16@0- (0.0573,0) [-500|500] "" XXX BO_ 610 EPS_STATUS: 8 EPS SG_ IPAS_STATE : 3|4@0+ (1,0) [0|15] "" XXX diff --git a/opendbc/generator/toyota/toyota_prius_2017_pt.dbc b/opendbc/generator/toyota/toyota_prius_2017_pt.dbc index d1a6d27db87ca1..cf04ee7c8e7f5b 100644 --- a/opendbc/generator/toyota/toyota_prius_2017_pt.dbc +++ b/opendbc/generator/toyota/toyota_prius_2017_pt.dbc @@ -20,6 +20,7 @@ BO_ 608 STEER_TORQUE_SENSOR: 8 XXX SG_ STEER_TORQUE_DRIVER : 15|16@0- (1,0) [-32768|32767] "" XXX SG_ STEER_OVERRIDE : 0|1@0+ (1,0) [0|1] "" XXX SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + SG_ STEER_ANGLE : 31|16@0- (0.0573,0) [-500|500] "" XXX BO_ 610 EPS_STATUS: 8 EPS SG_ IPAS_STATE : 3|4@0+ (1,0) [0|15] "" XXX diff --git a/opendbc/gm_global_a_powertrain.dbc b/opendbc/gm_global_a_powertrain.dbc index 3caf60ce4a01ec..2e3bd7c85dd435 100644 --- a/opendbc/gm_global_a_powertrain.dbc +++ b/opendbc/gm_global_a_powertrain.dbc @@ -195,7 +195,7 @@ BO_ 1033 ASCMKeepAlive: 7 NEO BO_ 1034 ASCM_40A: 7 K124_ASCM BO_ 1217 ECMEngineCoolantTemp: 8 K20_ECM - SG_ EngineCoolantTemp : 23|8@0+ (1,-40) [0|0] "°C" NEO + SG_ EngineCoolantTemp : 23|8@0+ (1,-40) [0|0] "C" NEO BO_ 1249 VIN_Part2: 8 K20_ECM SG_ VINPart2 : 7|64@0+ (1,0) [0|0] "" NEO diff --git a/opendbc/honda_accord_lx15t_2018_can_generated.dbc b/opendbc/honda_accord_lx15t_2018_can_generated.dbc index 3957c612477427..5b095ae79389f3 100644 --- a/opendbc/honda_accord_lx15t_2018_can_generated.dbc +++ b/opendbc/honda_accord_lx15t_2018_can_generated.dbc @@ -127,7 +127,7 @@ BO_ 479 ACC_CONTROL: 8 EON SG_ SET_TO_0 : 20|5@0+ (1,0) [0|1] "" XXX SG_ CONTROL_ON : 23|3@0+ (1,0) [0|5] "" XXX SG_ GAS_COMMAND : 7|16@0- (1,0) [0|0] "" XXX - SG_ ACCEL_COMMAND : 31|11@0- (1,0) [0|0] "" XXX + SG_ ACCEL_COMMAND : 31|11@0- (0.01,0) [0|0] "m/s2" XXX SG_ BRAKE_LIGHTS : 62|1@0+ (1,0) [0|1] "" XXX SG_ BRAKE_REQUEST : 34|1@0+ (1,0) [0|1] "" XXX SG_ STANDSTILL : 35|1@0+ (1,0) [0|1] "" XXX diff --git a/opendbc/honda_accord_s2t_2018_can_generated.dbc b/opendbc/honda_accord_s2t_2018_can_generated.dbc index 7ce9a31eac3c1e..12a2b889fd201d 100644 --- a/opendbc/honda_accord_s2t_2018_can_generated.dbc +++ b/opendbc/honda_accord_s2t_2018_can_generated.dbc @@ -127,7 +127,7 @@ BO_ 479 ACC_CONTROL: 8 EON SG_ SET_TO_0 : 20|5@0+ (1,0) [0|1] "" XXX SG_ CONTROL_ON : 23|3@0+ (1,0) [0|5] "" XXX SG_ GAS_COMMAND : 7|16@0- (1,0) [0|0] "" XXX - SG_ ACCEL_COMMAND : 31|11@0- (1,0) [0|0] "" XXX + SG_ ACCEL_COMMAND : 31|11@0- (0.01,0) [0|0] "m/s2" XXX SG_ BRAKE_LIGHTS : 62|1@0+ (1,0) [0|1] "" XXX SG_ BRAKE_REQUEST : 34|1@0+ (1,0) [0|1] "" XXX SG_ STANDSTILL : 35|1@0+ (1,0) [0|1] "" XXX diff --git a/opendbc/honda_civic_hatchback_ex_2017_can_generated.dbc b/opendbc/honda_civic_hatchback_ex_2017_can_generated.dbc index d36e45c3680e40..cfc8a6e48db410 100644 --- a/opendbc/honda_civic_hatchback_ex_2017_can_generated.dbc +++ b/opendbc/honda_civic_hatchback_ex_2017_can_generated.dbc @@ -127,7 +127,7 @@ BO_ 479 ACC_CONTROL: 8 EON SG_ SET_TO_0 : 20|5@0+ (1,0) [0|1] "" XXX SG_ CONTROL_ON : 23|3@0+ (1,0) [0|5] "" XXX SG_ GAS_COMMAND : 7|16@0- (1,0) [0|0] "" XXX - SG_ ACCEL_COMMAND : 31|11@0- (1,0) [0|0] "" XXX + SG_ ACCEL_COMMAND : 31|11@0- (0.01,0) [0|0] "m/s2" XXX SG_ BRAKE_LIGHTS : 62|1@0+ (1,0) [0|1] "" XXX SG_ BRAKE_REQUEST : 34|1@0+ (1,0) [0|1] "" XXX SG_ STANDSTILL : 35|1@0+ (1,0) [0|1] "" XXX diff --git a/opendbc/honda_crv_ex_2017_can_generated.dbc b/opendbc/honda_crv_ex_2017_can_generated.dbc index f8d8438dc800f5..f8b6846c53ad90 100644 --- a/opendbc/honda_crv_ex_2017_can_generated.dbc +++ b/opendbc/honda_crv_ex_2017_can_generated.dbc @@ -127,7 +127,7 @@ BO_ 479 ACC_CONTROL: 8 EON SG_ SET_TO_0 : 20|5@0+ (1,0) [0|1] "" XXX SG_ CONTROL_ON : 23|3@0+ (1,0) [0|5] "" XXX SG_ GAS_COMMAND : 7|16@0- (1,0) [0|0] "" XXX - SG_ ACCEL_COMMAND : 31|11@0- (1,0) [0|0] "" XXX + SG_ ACCEL_COMMAND : 31|11@0- (0.01,0) [0|0] "m/s2" XXX SG_ BRAKE_LIGHTS : 62|1@0+ (1,0) [0|1] "" XXX SG_ BRAKE_REQUEST : 34|1@0+ (1,0) [0|1] "" XXX SG_ STANDSTILL : 35|1@0+ (1,0) [0|1] "" XXX diff --git a/opendbc/honda_crv_hybrid_2019_can_generated.dbc b/opendbc/honda_crv_hybrid_2019_can_generated.dbc index 35036c6fea765c..eba7e72a2279d4 100644 --- a/opendbc/honda_crv_hybrid_2019_can_generated.dbc +++ b/opendbc/honda_crv_hybrid_2019_can_generated.dbc @@ -127,7 +127,7 @@ BO_ 479 ACC_CONTROL: 8 EON SG_ SET_TO_0 : 20|5@0+ (1,0) [0|1] "" XXX SG_ CONTROL_ON : 23|3@0+ (1,0) [0|5] "" XXX SG_ GAS_COMMAND : 7|16@0- (1,0) [0|0] "" XXX - SG_ ACCEL_COMMAND : 31|11@0- (1,0) [0|0] "" XXX + SG_ ACCEL_COMMAND : 31|11@0- (0.01,0) [0|0] "m/s2" XXX SG_ BRAKE_LIGHTS : 62|1@0+ (1,0) [0|1] "" XXX SG_ BRAKE_REQUEST : 34|1@0+ (1,0) [0|1] "" XXX SG_ STANDSTILL : 35|1@0+ (1,0) [0|1] "" XXX diff --git a/opendbc/honda_insight_ex_2019_can_generated.dbc b/opendbc/honda_insight_ex_2019_can_generated.dbc index 3cc76469806f2e..92fc0b50ac2132 100644 --- a/opendbc/honda_insight_ex_2019_can_generated.dbc +++ b/opendbc/honda_insight_ex_2019_can_generated.dbc @@ -127,7 +127,7 @@ BO_ 479 ACC_CONTROL: 8 EON SG_ SET_TO_0 : 20|5@0+ (1,0) [0|1] "" XXX SG_ CONTROL_ON : 23|3@0+ (1,0) [0|5] "" XXX SG_ GAS_COMMAND : 7|16@0- (1,0) [0|0] "" XXX - SG_ ACCEL_COMMAND : 31|11@0- (1,0) [0|0] "" XXX + SG_ ACCEL_COMMAND : 31|11@0- (0.01,0) [0|0] "m/s2" XXX SG_ BRAKE_LIGHTS : 62|1@0+ (1,0) [0|1] "" XXX SG_ BRAKE_REQUEST : 34|1@0+ (1,0) [0|1] "" XXX SG_ STANDSTILL : 35|1@0+ (1,0) [0|1] "" XXX diff --git a/opendbc/hyundai_2015_ccan.dbc b/opendbc/hyundai_2015_ccan.dbc index addc0cac31fa08..0c86beb9585aab 100644 --- a/opendbc/hyundai_2015_ccan.dbc +++ b/opendbc/hyundai_2015_ccan.dbc @@ -893,11 +893,11 @@ BO_ 67 DATC13: 8 DATC BO_ 66 DATC12: 8 DATC SG_ CR_Datc_DrTempDispC : 0|8@1+ (0.5,14.0) [15.0|32.0] "deg" CLU,IBOX - SG_ CR_Datc_DrTempDispF : 8|8@1+ (1.0,56.0) [58.0|90.0] "¢µ" CLU,IBOX + SG_ CR_Datc_DrTempDispF : 8|8@1+ (1.0,56.0) [58.0|90.0] "" CLU,IBOX SG_ CR_Datc_PsTempDispC : 16|8@1+ (0.5,14.0) [15.0|32.0] "deg" CLU,IBOX - SG_ CR_Datc_PsTempDispF : 24|8@1+ (1.0,56.0) [58.0|90.0] "¢µ" CLU,IBOX + SG_ CR_Datc_PsTempDispF : 24|8@1+ (1.0,56.0) [58.0|90.0] "" CLU,IBOX SG_ CR_Datc_RearDrTempDispC : 40|8@1+ (0.5,14.0) [15.0|32.0] "deg" CLU - SG_ CR_Datc_RearDrTempDispF : 48|8@1+ (1.0,58.0) [58.0|90.0] "¢µ" CLU + SG_ CR_Datc_RearDrTempDispF : 48|8@1+ (1.0,58.0) [58.0|90.0] "" CLU SG_ CF_Datc_CO2_Warning : 56|8@1+ (1.0,0.0) [0.0|3.0] "" CLU BO_ 1345 CGW1: 8 BCM diff --git a/opendbc/lexus_ct200h_2018_pt_generated.dbc b/opendbc/lexus_ct200h_2018_pt_generated.dbc index 79706e0b19166e..0f322dd16e49f1 100644 --- a/opendbc/lexus_ct200h_2018_pt_generated.dbc +++ b/opendbc/lexus_ct200h_2018_pt_generated.dbc @@ -70,8 +70,8 @@ BS_: BU_: XXX DSU HCU EPS IPAS CGW BO_ 36 KINEMATICS: 8 XXX - SG_ ACCEL_Y : 33|10@0+ (1,-512) [0|65535] "" XXX - SG_ YAW_RATE : 1|10@0+ (1,-512) [0|65535] "" XXX + SG_ ACCEL_Y : 33|10@0+ (0.03589,-18.375) [0|65535] "m/s^2" XXX + SG_ YAW_RATE : 1|10@0+ (0.244,-125) [0|65535] "deg/sec" XXX SG_ STEERING_TORQUE : 17|10@0+ (1,-512) [0|65535] "" XXX BO_ 37 STEER_ANGLE_SENSOR: 8 XXX @@ -91,8 +91,8 @@ BO_ 170 WHEEL_SPEEDS: 8 XXX BO_ 180 SPEED: 8 XXX SG_ ENCODER : 39|8@0+ (1,0) [0|255] "" XXX - SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX SG_ SPEED : 47|16@0+ (0.01,0) [0|250] "kph" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX BO_ 353 DSU_SPEED: 8 XXX SG_ FORWARD_SPEED : 15|16@0- (0.00390625,-30) [0|255] "kph" XXX @@ -184,6 +184,7 @@ BO_ 921 PCM_CRUISE_SM: 8 XXX BO_ 951 ESP_CONTROL: 8 ESP SG_ TC_DISABLED : 13|1@0+ (1,0) [0|1] "" XXX + SG_ VSC_DISABLED : 12|2@0+ (1,0) [0|1] "" XXX SG_ BRAKE_LIGHTS_ACC : 18|1@0+ (1,0) [0|1] "" XXX BO_ 1041 ACC_HUD: 8 DSU @@ -208,6 +209,17 @@ BO_ 1042 LKAS_HUD: 8 XXX SG_ SET_ME_X38 : 55|8@0+ (1,0) [0|1] "" XXX SG_ SET_ME_X02 : 63|8@0+ (1,0) [0|1] "" XXX +BO_ 1043 TIME : 8 CGW + SG_ YEAR : 7|8@0+ (1,0) [0|0] "year" XXX + SG_ MONTH : 15|8@0+ (1,0) [0|0] "month" XXX + SG_ DAY : 23|8@0+ (1,0) [0|0] "day" XXX + SG_ HOUR : 31|8@0+ (1,0) [0|0] "hour" XXX + SG_ MINUTE : 39|8@0+ (1,0) [0|0] "minute" XXX + SG_ GMT_DIFF : 55|1@0+ (1,0) [0|0] "" XXX + SG_ GMTDIFF_HOURS : 54|4@0+ (1,0) [0|0] "hours" XXX + SG_ GMTDIFF_MINUTES : 50|6@0+ (1,0) [0|0] "minutes" XXX + SG_ SUMMER : 60|1@0+ (1,0) [0|0] "" XXX + BO_ 1408 VIN_PART_1: 8 CGW SG_ VIN_1 : 7|8@0+ (1,0) [0|0] "" XXX SG_ VIN_2 : 15|8@0+ (1,0) [0|0] "" XXX @@ -357,7 +369,7 @@ BO_ 581 GAS_PEDAL: 5 XXX SG_ GAS_PEDAL : 23|8@0+ (0.005,0) [0|1] "" XXX BO_ 608 STEER_TORQUE_SENSOR: 8 XXX - SG_ STEER_TORQUE_EPS : 47|16@0- (0.73,0) [-20000|20000] "" XXX + SG_ STEER_TORQUE_EPS : 47|16@0- (1,0) [-20000|20000] "" XXX SG_ STEER_TORQUE_DRIVER : 15|16@0- (1,0) [-32768|32767] "" XXX SG_ STEER_OVERRIDE : 0|1@0+ (1,0) [0|1] "" XXX SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX @@ -381,4 +393,4 @@ VAL_ 610 IPAS_STATE 5 "override" 3 "enabled" 1 "disabled"; VAL_ 610 LKA_STATE 25 "temporary_fault" 9 "temporary_fault2" 5 "active" 1 "standby"; VAL_ 956 GEAR 0 "D" 1 "S" 8 "N" 16 "R" 32 "P"; VAL_ 956 SPORT_ON 0 "off" 1 "on"; -VAL_ 956 ECON_ON 0 "off" 1 "on"; \ No newline at end of file +VAL_ 956 ECON_ON 0 "off" 1 "on"; diff --git a/opendbc/lexus_gs300h_2017_pt_generated.dbc b/opendbc/lexus_gs300h_2017_pt_generated.dbc index 7dd2f7d5e3f973..5bd0bbf5d9d577 100644 --- a/opendbc/lexus_gs300h_2017_pt_generated.dbc +++ b/opendbc/lexus_gs300h_2017_pt_generated.dbc @@ -70,8 +70,8 @@ BS_: BU_: XXX DSU HCU EPS IPAS CGW BO_ 36 KINEMATICS: 8 XXX - SG_ ACCEL_Y : 33|10@0+ (1,-512) [0|65535] "" XXX - SG_ YAW_RATE : 1|10@0+ (1,-512) [0|65535] "" XXX + SG_ ACCEL_Y : 33|10@0+ (0.03589,-18.375) [0|65535] "m/s^2" XXX + SG_ YAW_RATE : 1|10@0+ (0.244,-125) [0|65535] "deg/sec" XXX SG_ STEERING_TORQUE : 17|10@0+ (1,-512) [0|65535] "" XXX BO_ 37 STEER_ANGLE_SENSOR: 8 XXX @@ -91,8 +91,8 @@ BO_ 170 WHEEL_SPEEDS: 8 XXX BO_ 180 SPEED: 8 XXX SG_ ENCODER : 39|8@0+ (1,0) [0|255] "" XXX - SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX SG_ SPEED : 47|16@0+ (0.01,0) [0|250] "kph" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX BO_ 353 DSU_SPEED: 8 XXX SG_ FORWARD_SPEED : 15|16@0- (0.00390625,-30) [0|255] "kph" XXX @@ -184,6 +184,7 @@ BO_ 921 PCM_CRUISE_SM: 8 XXX BO_ 951 ESP_CONTROL: 8 ESP SG_ TC_DISABLED : 13|1@0+ (1,0) [0|1] "" XXX + SG_ VSC_DISABLED : 12|2@0+ (1,0) [0|1] "" XXX SG_ BRAKE_LIGHTS_ACC : 18|1@0+ (1,0) [0|1] "" XXX BO_ 1041 ACC_HUD: 8 DSU @@ -208,6 +209,17 @@ BO_ 1042 LKAS_HUD: 8 XXX SG_ SET_ME_X38 : 55|8@0+ (1,0) [0|1] "" XXX SG_ SET_ME_X02 : 63|8@0+ (1,0) [0|1] "" XXX +BO_ 1043 TIME : 8 CGW + SG_ YEAR : 7|8@0+ (1,0) [0|0] "year" XXX + SG_ MONTH : 15|8@0+ (1,0) [0|0] "month" XXX + SG_ DAY : 23|8@0+ (1,0) [0|0] "day" XXX + SG_ HOUR : 31|8@0+ (1,0) [0|0] "hour" XXX + SG_ MINUTE : 39|8@0+ (1,0) [0|0] "minute" XXX + SG_ GMT_DIFF : 55|1@0+ (1,0) [0|0] "" XXX + SG_ GMTDIFF_HOURS : 54|4@0+ (1,0) [0|0] "hours" XXX + SG_ GMTDIFF_MINUTES : 50|6@0+ (1,0) [0|0] "minutes" XXX + SG_ SUMMER : 60|1@0+ (1,0) [0|0] "" XXX + BO_ 1408 VIN_PART_1: 8 CGW SG_ VIN_1 : 7|8@0+ (1,0) [0|0] "" XXX SG_ VIN_2 : 15|8@0+ (1,0) [0|0] "" XXX diff --git a/opendbc/lexus_is_2018_pt_generated.dbc b/opendbc/lexus_is_2018_pt_generated.dbc index e003881c12bca3..9e4eb514545dff 100644 --- a/opendbc/lexus_is_2018_pt_generated.dbc +++ b/opendbc/lexus_is_2018_pt_generated.dbc @@ -70,8 +70,8 @@ BS_: BU_: XXX DSU HCU EPS IPAS CGW BO_ 36 KINEMATICS: 8 XXX - SG_ ACCEL_Y : 33|10@0+ (1,-512) [0|65535] "" XXX - SG_ YAW_RATE : 1|10@0+ (1,-512) [0|65535] "" XXX + SG_ ACCEL_Y : 33|10@0+ (0.03589,-18.375) [0|65535] "m/s^2" XXX + SG_ YAW_RATE : 1|10@0+ (0.244,-125) [0|65535] "deg/sec" XXX SG_ STEERING_TORQUE : 17|10@0+ (1,-512) [0|65535] "" XXX BO_ 37 STEER_ANGLE_SENSOR: 8 XXX @@ -91,8 +91,8 @@ BO_ 170 WHEEL_SPEEDS: 8 XXX BO_ 180 SPEED: 8 XXX SG_ ENCODER : 39|8@0+ (1,0) [0|255] "" XXX - SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX SG_ SPEED : 47|16@0+ (0.01,0) [0|250] "kph" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX BO_ 353 DSU_SPEED: 8 XXX SG_ FORWARD_SPEED : 15|16@0- (0.00390625,-30) [0|255] "kph" XXX @@ -184,6 +184,7 @@ BO_ 921 PCM_CRUISE_SM: 8 XXX BO_ 951 ESP_CONTROL: 8 ESP SG_ TC_DISABLED : 13|1@0+ (1,0) [0|1] "" XXX + SG_ VSC_DISABLED : 12|2@0+ (1,0) [0|1] "" XXX SG_ BRAKE_LIGHTS_ACC : 18|1@0+ (1,0) [0|1] "" XXX BO_ 1041 ACC_HUD: 8 DSU @@ -208,6 +209,17 @@ BO_ 1042 LKAS_HUD: 8 XXX SG_ SET_ME_X38 : 55|8@0+ (1,0) [0|1] "" XXX SG_ SET_ME_X02 : 63|8@0+ (1,0) [0|1] "" XXX +BO_ 1043 TIME : 8 CGW + SG_ YEAR : 7|8@0+ (1,0) [0|0] "year" XXX + SG_ MONTH : 15|8@0+ (1,0) [0|0] "month" XXX + SG_ DAY : 23|8@0+ (1,0) [0|0] "day" XXX + SG_ HOUR : 31|8@0+ (1,0) [0|0] "hour" XXX + SG_ MINUTE : 39|8@0+ (1,0) [0|0] "minute" XXX + SG_ GMT_DIFF : 55|1@0+ (1,0) [0|0] "" XXX + SG_ GMTDIFF_HOURS : 54|4@0+ (1,0) [0|0] "hours" XXX + SG_ GMTDIFF_MINUTES : 50|6@0+ (1,0) [0|0] "minutes" XXX + SG_ SUMMER : 60|1@0+ (1,0) [0|0] "" XXX + BO_ 1408 VIN_PART_1: 8 CGW SG_ VIN_1 : 7|8@0+ (1,0) [0|0] "" XXX SG_ VIN_2 : 15|8@0+ (1,0) [0|0] "" XXX diff --git a/opendbc/lexus_rx_350_2016_pt_generated.dbc b/opendbc/lexus_rx_350_2016_pt_generated.dbc index be989c1b201220..2370835ae36b0c 100644 --- a/opendbc/lexus_rx_350_2016_pt_generated.dbc +++ b/opendbc/lexus_rx_350_2016_pt_generated.dbc @@ -70,8 +70,8 @@ BS_: BU_: XXX DSU HCU EPS IPAS CGW BO_ 36 KINEMATICS: 8 XXX - SG_ ACCEL_Y : 33|10@0+ (1,-512) [0|65535] "" XXX - SG_ YAW_RATE : 1|10@0+ (1,-512) [0|65535] "" XXX + SG_ ACCEL_Y : 33|10@0+ (0.03589,-18.375) [0|65535] "m/s^2" XXX + SG_ YAW_RATE : 1|10@0+ (0.244,-125) [0|65535] "deg/sec" XXX SG_ STEERING_TORQUE : 17|10@0+ (1,-512) [0|65535] "" XXX BO_ 37 STEER_ANGLE_SENSOR: 8 XXX @@ -91,8 +91,8 @@ BO_ 170 WHEEL_SPEEDS: 8 XXX BO_ 180 SPEED: 8 XXX SG_ ENCODER : 39|8@0+ (1,0) [0|255] "" XXX - SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX SG_ SPEED : 47|16@0+ (0.01,0) [0|250] "kph" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX BO_ 353 DSU_SPEED: 8 XXX SG_ FORWARD_SPEED : 15|16@0- (0.00390625,-30) [0|255] "kph" XXX @@ -184,6 +184,7 @@ BO_ 921 PCM_CRUISE_SM: 8 XXX BO_ 951 ESP_CONTROL: 8 ESP SG_ TC_DISABLED : 13|1@0+ (1,0) [0|1] "" XXX + SG_ VSC_DISABLED : 12|2@0+ (1,0) [0|1] "" XXX SG_ BRAKE_LIGHTS_ACC : 18|1@0+ (1,0) [0|1] "" XXX BO_ 1041 ACC_HUD: 8 DSU @@ -208,6 +209,17 @@ BO_ 1042 LKAS_HUD: 8 XXX SG_ SET_ME_X38 : 55|8@0+ (1,0) [0|1] "" XXX SG_ SET_ME_X02 : 63|8@0+ (1,0) [0|1] "" XXX +BO_ 1043 TIME : 8 CGW + SG_ YEAR : 7|8@0+ (1,0) [0|0] "year" XXX + SG_ MONTH : 15|8@0+ (1,0) [0|0] "month" XXX + SG_ DAY : 23|8@0+ (1,0) [0|0] "day" XXX + SG_ HOUR : 31|8@0+ (1,0) [0|0] "hour" XXX + SG_ MINUTE : 39|8@0+ (1,0) [0|0] "minute" XXX + SG_ GMT_DIFF : 55|1@0+ (1,0) [0|0] "" XXX + SG_ GMTDIFF_HOURS : 54|4@0+ (1,0) [0|0] "hours" XXX + SG_ GMTDIFF_MINUTES : 50|6@0+ (1,0) [0|0] "minutes" XXX + SG_ SUMMER : 60|1@0+ (1,0) [0|0] "" XXX + BO_ 1408 VIN_PART_1: 8 CGW SG_ VIN_1 : 7|8@0+ (1,0) [0|0] "" XXX SG_ VIN_2 : 15|8@0+ (1,0) [0|0] "" XXX diff --git a/opendbc/lexus_rx_hybrid_2017_pt_generated.dbc b/opendbc/lexus_rx_hybrid_2017_pt_generated.dbc index 62fd8f913a0464..ef9052b28133ee 100644 --- a/opendbc/lexus_rx_hybrid_2017_pt_generated.dbc +++ b/opendbc/lexus_rx_hybrid_2017_pt_generated.dbc @@ -70,8 +70,8 @@ BS_: BU_: XXX DSU HCU EPS IPAS CGW BO_ 36 KINEMATICS: 8 XXX - SG_ ACCEL_Y : 33|10@0+ (1,-512) [0|65535] "" XXX - SG_ YAW_RATE : 1|10@0+ (1,-512) [0|65535] "" XXX + SG_ ACCEL_Y : 33|10@0+ (0.03589,-18.375) [0|65535] "m/s^2" XXX + SG_ YAW_RATE : 1|10@0+ (0.244,-125) [0|65535] "deg/sec" XXX SG_ STEERING_TORQUE : 17|10@0+ (1,-512) [0|65535] "" XXX BO_ 37 STEER_ANGLE_SENSOR: 8 XXX @@ -91,8 +91,8 @@ BO_ 170 WHEEL_SPEEDS: 8 XXX BO_ 180 SPEED: 8 XXX SG_ ENCODER : 39|8@0+ (1,0) [0|255] "" XXX - SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX SG_ SPEED : 47|16@0+ (0.01,0) [0|250] "kph" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX BO_ 353 DSU_SPEED: 8 XXX SG_ FORWARD_SPEED : 15|16@0- (0.00390625,-30) [0|255] "kph" XXX @@ -184,6 +184,7 @@ BO_ 921 PCM_CRUISE_SM: 8 XXX BO_ 951 ESP_CONTROL: 8 ESP SG_ TC_DISABLED : 13|1@0+ (1,0) [0|1] "" XXX + SG_ VSC_DISABLED : 12|2@0+ (1,0) [0|1] "" XXX SG_ BRAKE_LIGHTS_ACC : 18|1@0+ (1,0) [0|1] "" XXX BO_ 1041 ACC_HUD: 8 DSU @@ -208,6 +209,17 @@ BO_ 1042 LKAS_HUD: 8 XXX SG_ SET_ME_X38 : 55|8@0+ (1,0) [0|1] "" XXX SG_ SET_ME_X02 : 63|8@0+ (1,0) [0|1] "" XXX +BO_ 1043 TIME : 8 CGW + SG_ YEAR : 7|8@0+ (1,0) [0|0] "year" XXX + SG_ MONTH : 15|8@0+ (1,0) [0|0] "month" XXX + SG_ DAY : 23|8@0+ (1,0) [0|0] "day" XXX + SG_ HOUR : 31|8@0+ (1,0) [0|0] "hour" XXX + SG_ MINUTE : 39|8@0+ (1,0) [0|0] "minute" XXX + SG_ GMT_DIFF : 55|1@0+ (1,0) [0|0] "" XXX + SG_ GMTDIFF_HOURS : 54|4@0+ (1,0) [0|0] "hours" XXX + SG_ GMTDIFF_MINUTES : 50|6@0+ (1,0) [0|0] "minutes" XXX + SG_ SUMMER : 60|1@0+ (1,0) [0|0] "" XXX + BO_ 1408 VIN_PART_1: 8 CGW SG_ VIN_1 : 7|8@0+ (1,0) [0|0] "" XXX SG_ VIN_2 : 15|8@0+ (1,0) [0|0] "" XXX diff --git a/opendbc/toyota_2017_ref_pt.dbc b/opendbc/toyota_2017_ref_pt.dbc index 0c23d05d00dbab..17cd8f1b36900e 100644 --- a/opendbc/toyota_2017_ref_pt.dbc +++ b/opendbc/toyota_2017_ref_pt.dbc @@ -126,7 +126,7 @@ BO_ 896 ACN1S01: 8 CGW SG_ GNRTIH : 27|1@0+ (1,0) [0|0] "" Vector__XXX SG_ R_COL_TM : 26|1@0+ (1,0) [0|0] "" Vector__XXX SG_ R_HET_TM : 24|1@0+ (1,0) [0|0] "" Vector__XXX - SG_ TAMOUT : 55|8@0- (0.625,0) [0|0] "ÂŽ" Vector__XXX + SG_ TAMOUT : 55|8@0- (0.625,0) [0|0] "" Vector__XXX BO_ 897 ACN1S04: 8 CGW SG_ R_ACCALL : 7|1@0+ (1,0) [0|0] "" Vector__XXX @@ -166,9 +166,9 @@ BO_ 897 ACN1S04: 8 CGW BO_ 944 ACN1S07: 6 CGW SG_ RDEF : 7|1@0+ (1,0) [0|0] "" Vector__XXX SG_ MHTR : 6|1@0+ (1,0) [0|0] "" Vector__XXX - SG_ TR_TEMP : 15|8@0+ (0.25,-6.5) [0|0] "ÂŽ" Vector__XXX - SG_ ACN_AMB : 31|8@0+ (1,0) [0|0] "ÂŽ" CSR,DS1,FCM - SG_ AC_AMB05 : 44|1@0+ (1,0) [0|0] "ÂŽ" Vector__XXX + SG_ TR_TEMP : 15|8@0+ (0.25,-6.5) [0|0] "" Vector__XXX + SG_ ACN_AMB : 31|8@0+ (1,0) [0|0] "" CSR,DS1,FCM + SG_ AC_AMB05 : 44|1@0+ (1,0) [0|0] "" Vector__XXX SG_ AC_MODE : 43|2@0+ (1,0) [0|0] "" Vector__XXX BO_ 1250 AFS1N01: 8 AFS @@ -851,7 +851,7 @@ BO_ 956 ECT1S92: 8 CGW SG_ B_R : 12|1@0+ (1,0) [0|0] "" AFS,BSR,CSR,DS1,FCM,MAV SG_ B_N : 11|1@0+ (1,0) [0|0] "" AFS,CSR,MAV SG_ B_ISPTM : 10|3@0+ (1,0) [0|0] "" Vector__XXX - SG_ BV_THOCL : 23|16@0+ (0.625,-50) [0|0] "ÂŽ" Vector__XXX + SG_ BV_THOCL : 23|16@0+ (0.625,-50) [0|0] "" Vector__XXX SG_ B_GEAR : 39|4@0+ (1,0) [0|0] "" Vector__XXX SG_ B_SMDE : 32|1@0+ (1,0) [0|0] "" Vector__XXX SG_ B_D : 47|1@0+ (1,0) [0|0] "" AFS,CSR,DS1,MAV @@ -988,7 +988,7 @@ BO_ 1017 ENG1F03: 8 CGW BO_ 452 ENG1F07: 8 CGW SG_ NE1 : 7|16@0- (0.78125,0) [0|0] "rpm" SCS - SG_ THA1 : 23|8@0+ (2.5,-40) [0|0] "ÂŽ" Vector__XXX + SG_ THA1 : 23|8@0+ (2.5,-40) [0|0] "" Vector__XXX SG_ THWX : 31|1@0+ (1,0) [0|0] "" Vector__XXX SG_ EGF : 30|1@0+ (1,0) [0|0] "" Vector__XXX SG_ T2ERXF : 29|1@0+ (1,0) [0|0] "" Vector__XXX @@ -1026,7 +1026,7 @@ BO_ 705 ENG1S01: 8 CGW BO_ 961 ENG1S23: 3 CGW SG_ EKLSM : 7|8@0+ (0.625,0) [0|0] "%" Vector__XXX - SG_ GATHW : 15|16@0- (0.625,0) [0|0] "ÂŽ" Vector__XXX + SG_ GATHW : 15|16@0- (0.625,0) [0|0] "" Vector__XXX BO_ 979 ENG1S28: 2 CGW SG_ B_FC : 7|16@0+ (0.0005,0) [0|0] "ml" Vector__XXX @@ -1067,7 +1067,7 @@ BO_ 955 ENG1S92: 8 CGW SG_ B_WSTP : 11|1@0+ (1,0) [0|0] "" Vector__XXX SG_ B_LOUT : 10|1@0+ (1,0) [0|0] "" Vector__XXX SG_ B_OILPL : 9|2@0+ (1,0) [0|0] "" Vector__XXX - SG_ B_TMP : 23|8@0+ (0.5,0) [0|0] "ÂŽ" Vector__XXX + SG_ B_TMP : 23|8@0+ (0.5,0) [0|0] "" Vector__XXX SG_ OGENETCS : 30|1@0+ (1,0) [0|0] "" Vector__XXX SG_ B_DPFW : 28|3@0+ (1,0) [0|0] "" Vector__XXX SG_ BOSLAMP : 37|3@0+ (1,0) [0|0] "" Vector__XXX @@ -1082,8 +1082,8 @@ BO_ 921 ENG1S95: 8 CGW SG_ B_SPU2 : 4|1@0+ (1,0) [0|0] "" Vector__XXX SG_ ACASID1 : 3|4@0+ (1,0) [0|0] "" Vector__XXX SG_ ACASID2 : 15|8@0+ (1,0) [0|0] "" Vector__XXX - SG_ B_LSP2 : 31|8@0+ (1,0) [0|0] "km/hÂEmph" Vector__XXX - SG_ B_ASLSP2 : 39|8@0+ (1,0) [0|0] "km/hÂEmph" Vector__XXX + SG_ B_LSP2 : 31|8@0+ (1,0) [0|0] "km/h Emph" Vector__XXX + SG_ B_ASLSP2 : 39|8@0+ (1,0) [0|0] "km/h Emph" Vector__XXX SG_ CACCTRN : 47|1@0+ (1,0) [0|0] "" Vector__XXX SG_ CACCINF : 46|1@0+ (1,0) [0|0] "" Vector__XXX SG_ CACCFR2 : 45|1@0+ (1,0) [0|0] "" Vector__XXX @@ -1096,7 +1096,7 @@ BO_ 921 ENG1S95: 8 CGW BO_ 238 ENG2F01: 4 CGW SG_ STOFOK : 7|1@0+ (1,0) [0|0] "" Vector__XXX SG_ GROWIND : 6|1@0+ (1,0) [0|0] "" Vector__XXX - SG_ B_TMP3 : 15|8@0+ (0.5,0) [0|0] "ÂŽ" Vector__XXX + SG_ B_TMP3 : 15|8@0+ (0.5,0) [0|0] "" Vector__XXX SG_ IMMINJST : 23|16@0+ (1,0) [0|0] "" Vector__XXX BO_ 466 ENG2F04: 8 CGW @@ -1113,7 +1113,7 @@ BO_ 466 ENG2F04: 8 CGW SG_ PLOCKF : 8|1@0+ (1,0) [0|0] "" Vector__XXX SG_ ACCREQ : 23|16@0- (0.0009765625,0) [0|0] "m/s^2" DS1 SG_ ACCAVL : 39|16@0- (2,0) [0|0] "N" Vector__XXX - SG_ SPDSTAT : 55|4@0+ (1,0) [0|0] "Â|" DS1 + SG_ SPDSTAT : 55|4@0+ (1,0) [0|0] "" DS1 SG_ SSTOK : 51|1@0+ (1,0) [0|0] "" Vector__XXX SG_ CANREQ : 49|1@0+ (1,0) [0|0] "" Vector__XXX SG_ FCACT : 48|1@0+ (1,0) [0|0] "" Vector__XXX @@ -1280,7 +1280,7 @@ BO_ 1076102682 MET1S05_24: 8 CGW SG_ MET05_IF : 15|8@0+ (1,0) [0|0] "" Vector__XXX SG_ TO_SP : 23|16@0+ (0.1,0) [0|0] "km/h,MPH" Vector__XXX SG_ UNIT_5 : 39|2@0+ (1,0) [0|0] "" Vector__XXX - SG_ TO_FC : 47|16@0+ (0.1,0) [0|0] "MPGÂEkm/lÂEl/100kmÂEkm/gallon" Vector__XXX + SG_ TO_FC : 47|16@0+ (0.1,0) [0|0] "MPG Ekm/l El/100km Ekm/gallon" Vector__XXX SG_ UNIT_6 : 63|3@0+ (1,0) [0|0] "" Vector__XXX BO_ 1076299282 MET1S08_27: 8 CGW @@ -1635,4 +1635,4 @@ BO_ 1073743494 YGW1S05_0: 8 CGW SG_ YGW05_IF : 15|8@0+ (1,0) [0|0] "" Vector__XXX SG_ YI_IMO_E : 23|1@0+ (1,0) [0|0] "" Vector__XXX SG_ YI_UREQ : 16|1@0+ (1,0) [0|0] "" Vector__XXX - SG_ YI_RE : 47|16@0+ (1,0) [0|0] "" Vector__XXX \ No newline at end of file + SG_ YI_RE : 47|16@0+ (1,0) [0|0] "" Vector__XXX diff --git a/opendbc/toyota_avalon_2017_pt_generated.dbc b/opendbc/toyota_avalon_2017_pt_generated.dbc index 8111fbaa4e88a3..026191e9bacc77 100644 --- a/opendbc/toyota_avalon_2017_pt_generated.dbc +++ b/opendbc/toyota_avalon_2017_pt_generated.dbc @@ -70,8 +70,8 @@ BS_: BU_: XXX DSU HCU EPS IPAS CGW BO_ 36 KINEMATICS: 8 XXX - SG_ ACCEL_Y : 33|10@0+ (1,-512) [0|65535] "" XXX - SG_ YAW_RATE : 1|10@0+ (1,-512) [0|65535] "" XXX + SG_ ACCEL_Y : 33|10@0+ (0.03589,-18.375) [0|65535] "m/s^2" XXX + SG_ YAW_RATE : 1|10@0+ (0.244,-125) [0|65535] "deg/sec" XXX SG_ STEERING_TORQUE : 17|10@0+ (1,-512) [0|65535] "" XXX BO_ 37 STEER_ANGLE_SENSOR: 8 XXX @@ -91,8 +91,8 @@ BO_ 170 WHEEL_SPEEDS: 8 XXX BO_ 180 SPEED: 8 XXX SG_ ENCODER : 39|8@0+ (1,0) [0|255] "" XXX - SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX SG_ SPEED : 47|16@0+ (0.01,0) [0|250] "kph" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX BO_ 353 DSU_SPEED: 8 XXX SG_ FORWARD_SPEED : 15|16@0- (0.00390625,-30) [0|255] "kph" XXX @@ -184,6 +184,7 @@ BO_ 921 PCM_CRUISE_SM: 8 XXX BO_ 951 ESP_CONTROL: 8 ESP SG_ TC_DISABLED : 13|1@0+ (1,0) [0|1] "" XXX + SG_ VSC_DISABLED : 12|2@0+ (1,0) [0|1] "" XXX SG_ BRAKE_LIGHTS_ACC : 18|1@0+ (1,0) [0|1] "" XXX BO_ 1041 ACC_HUD: 8 DSU @@ -208,6 +209,17 @@ BO_ 1042 LKAS_HUD: 8 XXX SG_ SET_ME_X38 : 55|8@0+ (1,0) [0|1] "" XXX SG_ SET_ME_X02 : 63|8@0+ (1,0) [0|1] "" XXX +BO_ 1043 TIME : 8 CGW + SG_ YEAR : 7|8@0+ (1,0) [0|0] "year" XXX + SG_ MONTH : 15|8@0+ (1,0) [0|0] "month" XXX + SG_ DAY : 23|8@0+ (1,0) [0|0] "day" XXX + SG_ HOUR : 31|8@0+ (1,0) [0|0] "hour" XXX + SG_ MINUTE : 39|8@0+ (1,0) [0|0] "minute" XXX + SG_ GMT_DIFF : 55|1@0+ (1,0) [0|0] "" XXX + SG_ GMTDIFF_HOURS : 54|4@0+ (1,0) [0|0] "hours" XXX + SG_ GMTDIFF_MINUTES : 50|6@0+ (1,0) [0|0] "minutes" XXX + SG_ SUMMER : 60|1@0+ (1,0) [0|0] "" XXX + BO_ 1408 VIN_PART_1: 8 CGW SG_ VIN_1 : 7|8@0+ (1,0) [0|0] "" XXX SG_ VIN_2 : 15|8@0+ (1,0) [0|0] "" XXX diff --git a/opendbc/toyota_camry_hybrid_2018_pt_generated.dbc b/opendbc/toyota_camry_hybrid_2018_pt_generated.dbc index ecc6b774f37d8a..f60681a17a184d 100644 --- a/opendbc/toyota_camry_hybrid_2018_pt_generated.dbc +++ b/opendbc/toyota_camry_hybrid_2018_pt_generated.dbc @@ -70,8 +70,8 @@ BS_: BU_: XXX DSU HCU EPS IPAS CGW BO_ 36 KINEMATICS: 8 XXX - SG_ ACCEL_Y : 33|10@0+ (1,-512) [0|65535] "" XXX - SG_ YAW_RATE : 1|10@0+ (1,-512) [0|65535] "" XXX + SG_ ACCEL_Y : 33|10@0+ (0.03589,-18.375) [0|65535] "m/s^2" XXX + SG_ YAW_RATE : 1|10@0+ (0.244,-125) [0|65535] "deg/sec" XXX SG_ STEERING_TORQUE : 17|10@0+ (1,-512) [0|65535] "" XXX BO_ 37 STEER_ANGLE_SENSOR: 8 XXX @@ -91,8 +91,8 @@ BO_ 170 WHEEL_SPEEDS: 8 XXX BO_ 180 SPEED: 8 XXX SG_ ENCODER : 39|8@0+ (1,0) [0|255] "" XXX - SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX SG_ SPEED : 47|16@0+ (0.01,0) [0|250] "kph" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX BO_ 353 DSU_SPEED: 8 XXX SG_ FORWARD_SPEED : 15|16@0- (0.00390625,-30) [0|255] "kph" XXX @@ -184,6 +184,7 @@ BO_ 921 PCM_CRUISE_SM: 8 XXX BO_ 951 ESP_CONTROL: 8 ESP SG_ TC_DISABLED : 13|1@0+ (1,0) [0|1] "" XXX + SG_ VSC_DISABLED : 12|2@0+ (1,0) [0|1] "" XXX SG_ BRAKE_LIGHTS_ACC : 18|1@0+ (1,0) [0|1] "" XXX BO_ 1041 ACC_HUD: 8 DSU @@ -208,6 +209,17 @@ BO_ 1042 LKAS_HUD: 8 XXX SG_ SET_ME_X38 : 55|8@0+ (1,0) [0|1] "" XXX SG_ SET_ME_X02 : 63|8@0+ (1,0) [0|1] "" XXX +BO_ 1043 TIME : 8 CGW + SG_ YEAR : 7|8@0+ (1,0) [0|0] "year" XXX + SG_ MONTH : 15|8@0+ (1,0) [0|0] "month" XXX + SG_ DAY : 23|8@0+ (1,0) [0|0] "day" XXX + SG_ HOUR : 31|8@0+ (1,0) [0|0] "hour" XXX + SG_ MINUTE : 39|8@0+ (1,0) [0|0] "minute" XXX + SG_ GMT_DIFF : 55|1@0+ (1,0) [0|0] "" XXX + SG_ GMTDIFF_HOURS : 54|4@0+ (1,0) [0|0] "hours" XXX + SG_ GMTDIFF_MINUTES : 50|6@0+ (1,0) [0|0] "minutes" XXX + SG_ SUMMER : 60|1@0+ (1,0) [0|0] "" XXX + BO_ 1408 VIN_PART_1: 8 CGW SG_ VIN_1 : 7|8@0+ (1,0) [0|0] "" XXX SG_ VIN_2 : 15|8@0+ (1,0) [0|0] "" XXX @@ -367,7 +379,7 @@ BO_ 608 STEER_TORQUE_SENSOR: 8 XXX SG_ STEER_TORQUE_DRIVER : 15|16@0- (1,0) [-32768|32767] "" XXX SG_ STEER_OVERRIDE : 0|1@0+ (1,0) [0|1] "" XXX SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX - SG_ STEER_ANGLE : 31|16@0- (0.05527,0) [-500|500] "" XXX + SG_ STEER_ANGLE : 31|16@0- (0.0573,0) [-500|500] "" XXX BO_ 610 EPS_STATUS: 8 EPS SG_ IPAS_STATE : 3|4@0+ (1,0) [0|15] "" XXX diff --git a/opendbc/toyota_corolla_2017_pt_generated.dbc b/opendbc/toyota_corolla_2017_pt_generated.dbc index 19e6e5ea3e2555..f02e50195caf59 100644 --- a/opendbc/toyota_corolla_2017_pt_generated.dbc +++ b/opendbc/toyota_corolla_2017_pt_generated.dbc @@ -70,8 +70,8 @@ BS_: BU_: XXX DSU HCU EPS IPAS CGW BO_ 36 KINEMATICS: 8 XXX - SG_ ACCEL_Y : 33|10@0+ (1,-512) [0|65535] "" XXX - SG_ YAW_RATE : 1|10@0+ (1,-512) [0|65535] "" XXX + SG_ ACCEL_Y : 33|10@0+ (0.03589,-18.375) [0|65535] "m/s^2" XXX + SG_ YAW_RATE : 1|10@0+ (0.244,-125) [0|65535] "deg/sec" XXX SG_ STEERING_TORQUE : 17|10@0+ (1,-512) [0|65535] "" XXX BO_ 37 STEER_ANGLE_SENSOR: 8 XXX @@ -91,8 +91,8 @@ BO_ 170 WHEEL_SPEEDS: 8 XXX BO_ 180 SPEED: 8 XXX SG_ ENCODER : 39|8@0+ (1,0) [0|255] "" XXX - SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX SG_ SPEED : 47|16@0+ (0.01,0) [0|250] "kph" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX BO_ 353 DSU_SPEED: 8 XXX SG_ FORWARD_SPEED : 15|16@0- (0.00390625,-30) [0|255] "kph" XXX @@ -184,6 +184,7 @@ BO_ 921 PCM_CRUISE_SM: 8 XXX BO_ 951 ESP_CONTROL: 8 ESP SG_ TC_DISABLED : 13|1@0+ (1,0) [0|1] "" XXX + SG_ VSC_DISABLED : 12|2@0+ (1,0) [0|1] "" XXX SG_ BRAKE_LIGHTS_ACC : 18|1@0+ (1,0) [0|1] "" XXX BO_ 1041 ACC_HUD: 8 DSU @@ -208,6 +209,17 @@ BO_ 1042 LKAS_HUD: 8 XXX SG_ SET_ME_X38 : 55|8@0+ (1,0) [0|1] "" XXX SG_ SET_ME_X02 : 63|8@0+ (1,0) [0|1] "" XXX +BO_ 1043 TIME : 8 CGW + SG_ YEAR : 7|8@0+ (1,0) [0|0] "year" XXX + SG_ MONTH : 15|8@0+ (1,0) [0|0] "month" XXX + SG_ DAY : 23|8@0+ (1,0) [0|0] "day" XXX + SG_ HOUR : 31|8@0+ (1,0) [0|0] "hour" XXX + SG_ MINUTE : 39|8@0+ (1,0) [0|0] "minute" XXX + SG_ GMT_DIFF : 55|1@0+ (1,0) [0|0] "" XXX + SG_ GMTDIFF_HOURS : 54|4@0+ (1,0) [0|0] "hours" XXX + SG_ GMTDIFF_MINUTES : 50|6@0+ (1,0) [0|0] "minutes" XXX + SG_ SUMMER : 60|1@0+ (1,0) [0|0] "" XXX + BO_ 1408 VIN_PART_1: 8 CGW SG_ VIN_1 : 7|8@0+ (1,0) [0|0] "" XXX SG_ VIN_2 : 15|8@0+ (1,0) [0|0] "" XXX diff --git a/opendbc/toyota_highlander_2017_pt_generated.dbc b/opendbc/toyota_highlander_2017_pt_generated.dbc index c22a331a64dcbc..a5306ac8f64d05 100644 --- a/opendbc/toyota_highlander_2017_pt_generated.dbc +++ b/opendbc/toyota_highlander_2017_pt_generated.dbc @@ -70,8 +70,8 @@ BS_: BU_: XXX DSU HCU EPS IPAS CGW BO_ 36 KINEMATICS: 8 XXX - SG_ ACCEL_Y : 33|10@0+ (1,-512) [0|65535] "" XXX - SG_ YAW_RATE : 1|10@0+ (1,-512) [0|65535] "" XXX + SG_ ACCEL_Y : 33|10@0+ (0.03589,-18.375) [0|65535] "m/s^2" XXX + SG_ YAW_RATE : 1|10@0+ (0.244,-125) [0|65535] "deg/sec" XXX SG_ STEERING_TORQUE : 17|10@0+ (1,-512) [0|65535] "" XXX BO_ 37 STEER_ANGLE_SENSOR: 8 XXX @@ -91,8 +91,8 @@ BO_ 170 WHEEL_SPEEDS: 8 XXX BO_ 180 SPEED: 8 XXX SG_ ENCODER : 39|8@0+ (1,0) [0|255] "" XXX - SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX SG_ SPEED : 47|16@0+ (0.01,0) [0|250] "kph" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX BO_ 353 DSU_SPEED: 8 XXX SG_ FORWARD_SPEED : 15|16@0- (0.00390625,-30) [0|255] "kph" XXX @@ -184,6 +184,7 @@ BO_ 921 PCM_CRUISE_SM: 8 XXX BO_ 951 ESP_CONTROL: 8 ESP SG_ TC_DISABLED : 13|1@0+ (1,0) [0|1] "" XXX + SG_ VSC_DISABLED : 12|2@0+ (1,0) [0|1] "" XXX SG_ BRAKE_LIGHTS_ACC : 18|1@0+ (1,0) [0|1] "" XXX BO_ 1041 ACC_HUD: 8 DSU @@ -208,6 +209,17 @@ BO_ 1042 LKAS_HUD: 8 XXX SG_ SET_ME_X38 : 55|8@0+ (1,0) [0|1] "" XXX SG_ SET_ME_X02 : 63|8@0+ (1,0) [0|1] "" XXX +BO_ 1043 TIME : 8 CGW + SG_ YEAR : 7|8@0+ (1,0) [0|0] "year" XXX + SG_ MONTH : 15|8@0+ (1,0) [0|0] "month" XXX + SG_ DAY : 23|8@0+ (1,0) [0|0] "day" XXX + SG_ HOUR : 31|8@0+ (1,0) [0|0] "hour" XXX + SG_ MINUTE : 39|8@0+ (1,0) [0|0] "minute" XXX + SG_ GMT_DIFF : 55|1@0+ (1,0) [0|0] "" XXX + SG_ GMTDIFF_HOURS : 54|4@0+ (1,0) [0|0] "hours" XXX + SG_ GMTDIFF_MINUTES : 50|6@0+ (1,0) [0|0] "minutes" XXX + SG_ SUMMER : 60|1@0+ (1,0) [0|0] "" XXX + BO_ 1408 VIN_PART_1: 8 CGW SG_ VIN_1 : 7|8@0+ (1,0) [0|0] "" XXX SG_ VIN_2 : 15|8@0+ (1,0) [0|0] "" XXX diff --git a/opendbc/toyota_highlander_hybrid_2018_pt_generated.dbc b/opendbc/toyota_highlander_hybrid_2018_pt_generated.dbc index 31b53400299ae7..d19ac45fff0727 100644 --- a/opendbc/toyota_highlander_hybrid_2018_pt_generated.dbc +++ b/opendbc/toyota_highlander_hybrid_2018_pt_generated.dbc @@ -70,8 +70,8 @@ BS_: BU_: XXX DSU HCU EPS IPAS CGW BO_ 36 KINEMATICS: 8 XXX - SG_ ACCEL_Y : 33|10@0+ (1,-512) [0|65535] "" XXX - SG_ YAW_RATE : 1|10@0+ (1,-512) [0|65535] "" XXX + SG_ ACCEL_Y : 33|10@0+ (0.03589,-18.375) [0|65535] "m/s^2" XXX + SG_ YAW_RATE : 1|10@0+ (0.244,-125) [0|65535] "deg/sec" XXX SG_ STEERING_TORQUE : 17|10@0+ (1,-512) [0|65535] "" XXX BO_ 37 STEER_ANGLE_SENSOR: 8 XXX @@ -91,8 +91,8 @@ BO_ 170 WHEEL_SPEEDS: 8 XXX BO_ 180 SPEED: 8 XXX SG_ ENCODER : 39|8@0+ (1,0) [0|255] "" XXX - SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX SG_ SPEED : 47|16@0+ (0.01,0) [0|250] "kph" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX BO_ 353 DSU_SPEED: 8 XXX SG_ FORWARD_SPEED : 15|16@0- (0.00390625,-30) [0|255] "kph" XXX @@ -184,6 +184,7 @@ BO_ 921 PCM_CRUISE_SM: 8 XXX BO_ 951 ESP_CONTROL: 8 ESP SG_ TC_DISABLED : 13|1@0+ (1,0) [0|1] "" XXX + SG_ VSC_DISABLED : 12|2@0+ (1,0) [0|1] "" XXX SG_ BRAKE_LIGHTS_ACC : 18|1@0+ (1,0) [0|1] "" XXX BO_ 1041 ACC_HUD: 8 DSU @@ -208,6 +209,17 @@ BO_ 1042 LKAS_HUD: 8 XXX SG_ SET_ME_X38 : 55|8@0+ (1,0) [0|1] "" XXX SG_ SET_ME_X02 : 63|8@0+ (1,0) [0|1] "" XXX +BO_ 1043 TIME : 8 CGW + SG_ YEAR : 7|8@0+ (1,0) [0|0] "year" XXX + SG_ MONTH : 15|8@0+ (1,0) [0|0] "month" XXX + SG_ DAY : 23|8@0+ (1,0) [0|0] "day" XXX + SG_ HOUR : 31|8@0+ (1,0) [0|0] "hour" XXX + SG_ MINUTE : 39|8@0+ (1,0) [0|0] "minute" XXX + SG_ GMT_DIFF : 55|1@0+ (1,0) [0|0] "" XXX + SG_ GMTDIFF_HOURS : 54|4@0+ (1,0) [0|0] "hours" XXX + SG_ GMTDIFF_MINUTES : 50|6@0+ (1,0) [0|0] "minutes" XXX + SG_ SUMMER : 60|1@0+ (1,0) [0|0] "" XXX + BO_ 1408 VIN_PART_1: 8 CGW SG_ VIN_1 : 7|8@0+ (1,0) [0|0] "" XXX SG_ VIN_2 : 15|8@0+ (1,0) [0|0] "" XXX diff --git a/opendbc/toyota_nodsu_hybrid_pt_generated.dbc b/opendbc/toyota_nodsu_hybrid_pt_generated.dbc index abd3af8db7b437..28ad1d61aca454 100644 --- a/opendbc/toyota_nodsu_hybrid_pt_generated.dbc +++ b/opendbc/toyota_nodsu_hybrid_pt_generated.dbc @@ -70,8 +70,8 @@ BS_: BU_: XXX DSU HCU EPS IPAS CGW BO_ 36 KINEMATICS: 8 XXX - SG_ ACCEL_Y : 33|10@0+ (1,-512) [0|65535] "" XXX - SG_ YAW_RATE : 1|10@0+ (1,-512) [0|65535] "" XXX + SG_ ACCEL_Y : 33|10@0+ (0.03589,-18.375) [0|65535] "m/s^2" XXX + SG_ YAW_RATE : 1|10@0+ (0.244,-125) [0|65535] "deg/sec" XXX SG_ STEERING_TORQUE : 17|10@0+ (1,-512) [0|65535] "" XXX BO_ 37 STEER_ANGLE_SENSOR: 8 XXX @@ -91,8 +91,8 @@ BO_ 170 WHEEL_SPEEDS: 8 XXX BO_ 180 SPEED: 8 XXX SG_ ENCODER : 39|8@0+ (1,0) [0|255] "" XXX - SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX SG_ SPEED : 47|16@0+ (0.01,0) [0|250] "kph" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX BO_ 353 DSU_SPEED: 8 XXX SG_ FORWARD_SPEED : 15|16@0- (0.00390625,-30) [0|255] "kph" XXX @@ -184,6 +184,7 @@ BO_ 921 PCM_CRUISE_SM: 8 XXX BO_ 951 ESP_CONTROL: 8 ESP SG_ TC_DISABLED : 13|1@0+ (1,0) [0|1] "" XXX + SG_ VSC_DISABLED : 12|2@0+ (1,0) [0|1] "" XXX SG_ BRAKE_LIGHTS_ACC : 18|1@0+ (1,0) [0|1] "" XXX BO_ 1041 ACC_HUD: 8 DSU @@ -208,6 +209,17 @@ BO_ 1042 LKAS_HUD: 8 XXX SG_ SET_ME_X38 : 55|8@0+ (1,0) [0|1] "" XXX SG_ SET_ME_X02 : 63|8@0+ (1,0) [0|1] "" XXX +BO_ 1043 TIME : 8 CGW + SG_ YEAR : 7|8@0+ (1,0) [0|0] "year" XXX + SG_ MONTH : 15|8@0+ (1,0) [0|0] "month" XXX + SG_ DAY : 23|8@0+ (1,0) [0|0] "day" XXX + SG_ HOUR : 31|8@0+ (1,0) [0|0] "hour" XXX + SG_ MINUTE : 39|8@0+ (1,0) [0|0] "minute" XXX + SG_ GMT_DIFF : 55|1@0+ (1,0) [0|0] "" XXX + SG_ GMTDIFF_HOURS : 54|4@0+ (1,0) [0|0] "hours" XXX + SG_ GMTDIFF_MINUTES : 50|6@0+ (1,0) [0|0] "minutes" XXX + SG_ SUMMER : 60|1@0+ (1,0) [0|0] "" XXX + BO_ 1408 VIN_PART_1: 8 CGW SG_ VIN_1 : 7|8@0+ (1,0) [0|0] "" XXX SG_ VIN_2 : 15|8@0+ (1,0) [0|0] "" XXX @@ -367,7 +379,7 @@ BO_ 608 STEER_TORQUE_SENSOR: 8 XXX SG_ STEER_TORQUE_DRIVER : 15|16@0- (1,0) [-32768|32767] "" XXX SG_ STEER_OVERRIDE : 0|1@0+ (1,0) [0|1] "" XXX SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX - SG_ STEER_ANGLE : 31|16@0- (0.056,0) [-500|500] "" XXX + SG_ STEER_ANGLE : 31|16@0- (0.0573,0) [-500|500] "" XXX BO_ 610 EPS_STATUS: 8 EPS SG_ IPAS_STATE : 3|4@0+ (1,0) [0|15] "" XXX diff --git a/opendbc/toyota_nodsu_pt_generated.dbc b/opendbc/toyota_nodsu_pt_generated.dbc index 6e14a2c5129a04..ab54939b50a4df 100644 --- a/opendbc/toyota_nodsu_pt_generated.dbc +++ b/opendbc/toyota_nodsu_pt_generated.dbc @@ -70,8 +70,8 @@ BS_: BU_: XXX DSU HCU EPS IPAS CGW BO_ 36 KINEMATICS: 8 XXX - SG_ ACCEL_Y : 33|10@0+ (1,-512) [0|65535] "" XXX - SG_ YAW_RATE : 1|10@0+ (1,-512) [0|65535] "" XXX + SG_ ACCEL_Y : 33|10@0+ (0.03589,-18.375) [0|65535] "m/s^2" XXX + SG_ YAW_RATE : 1|10@0+ (0.244,-125) [0|65535] "deg/sec" XXX SG_ STEERING_TORQUE : 17|10@0+ (1,-512) [0|65535] "" XXX BO_ 37 STEER_ANGLE_SENSOR: 8 XXX @@ -91,8 +91,8 @@ BO_ 170 WHEEL_SPEEDS: 8 XXX BO_ 180 SPEED: 8 XXX SG_ ENCODER : 39|8@0+ (1,0) [0|255] "" XXX - SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX SG_ SPEED : 47|16@0+ (0.01,0) [0|250] "kph" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX BO_ 353 DSU_SPEED: 8 XXX SG_ FORWARD_SPEED : 15|16@0- (0.00390625,-30) [0|255] "kph" XXX @@ -184,6 +184,7 @@ BO_ 921 PCM_CRUISE_SM: 8 XXX BO_ 951 ESP_CONTROL: 8 ESP SG_ TC_DISABLED : 13|1@0+ (1,0) [0|1] "" XXX + SG_ VSC_DISABLED : 12|2@0+ (1,0) [0|1] "" XXX SG_ BRAKE_LIGHTS_ACC : 18|1@0+ (1,0) [0|1] "" XXX BO_ 1041 ACC_HUD: 8 DSU @@ -208,6 +209,17 @@ BO_ 1042 LKAS_HUD: 8 XXX SG_ SET_ME_X38 : 55|8@0+ (1,0) [0|1] "" XXX SG_ SET_ME_X02 : 63|8@0+ (1,0) [0|1] "" XXX +BO_ 1043 TIME : 8 CGW + SG_ YEAR : 7|8@0+ (1,0) [0|0] "year" XXX + SG_ MONTH : 15|8@0+ (1,0) [0|0] "month" XXX + SG_ DAY : 23|8@0+ (1,0) [0|0] "day" XXX + SG_ HOUR : 31|8@0+ (1,0) [0|0] "hour" XXX + SG_ MINUTE : 39|8@0+ (1,0) [0|0] "minute" XXX + SG_ GMT_DIFF : 55|1@0+ (1,0) [0|0] "" XXX + SG_ GMTDIFF_HOURS : 54|4@0+ (1,0) [0|0] "hours" XXX + SG_ GMTDIFF_MINUTES : 50|6@0+ (1,0) [0|0] "minutes" XXX + SG_ SUMMER : 60|1@0+ (1,0) [0|0] "" XXX + BO_ 1408 VIN_PART_1: 8 CGW SG_ VIN_1 : 7|8@0+ (1,0) [0|0] "" XXX SG_ VIN_2 : 15|8@0+ (1,0) [0|0] "" XXX @@ -355,7 +367,7 @@ BO_ 401 STEERING_LTA: 8 XXX SG_ PERCENTAGE : 39|8@0+ (1,0) [0|255] "" XXX SG_ SETME_X64 : 47|8@0+ (1,0) [0|255] "" XXX SG_ ANGLE : 55|8@0- (0.5,0) [0|255] "" XXX - SG_ STEER_ANGLE_CMD : 15|16@0- (0.056,0) [-540|540] "" XXX + SG_ STEER_ANGLE_CMD : 15|16@0- (0.0573,0) [-540|540] "" XXX SG_ STEER_REQUEST : 25|1@0+ (1,0) [0|1] "" XXX SG_ BIT : 30|1@0+ (1,0) [0|1] "" XXX @@ -373,7 +385,7 @@ BO_ 608 STEER_TORQUE_SENSOR: 8 XXX SG_ STEER_TORQUE_DRIVER : 15|16@0- (1,0) [-32768|32767] "" XXX SG_ STEER_OVERRIDE : 0|1@0+ (1,0) [0|1] "" XXX SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX - SG_ STEER_ANGLE : 31|16@0- (0.056,0) [-500|500] "" XXX + SG_ STEER_ANGLE : 31|16@0- (0.0573,0) [-500|500] "" XXX BO_ 610 EPS_STATUS: 8 EPS SG_ IPAS_STATE : 3|4@0+ (1,0) [0|15] "" XXX diff --git a/opendbc/toyota_prius_2017_pt_generated.dbc b/opendbc/toyota_prius_2017_pt_generated.dbc index f29b7c0788a809..2bd788e2d2105c 100644 --- a/opendbc/toyota_prius_2017_pt_generated.dbc +++ b/opendbc/toyota_prius_2017_pt_generated.dbc @@ -70,8 +70,8 @@ BS_: BU_: XXX DSU HCU EPS IPAS CGW BO_ 36 KINEMATICS: 8 XXX - SG_ ACCEL_Y : 33|10@0+ (1,-512) [0|65535] "" XXX - SG_ YAW_RATE : 1|10@0+ (1,-512) [0|65535] "" XXX + SG_ ACCEL_Y : 33|10@0+ (0.03589,-18.375) [0|65535] "m/s^2" XXX + SG_ YAW_RATE : 1|10@0+ (0.244,-125) [0|65535] "deg/sec" XXX SG_ STEERING_TORQUE : 17|10@0+ (1,-512) [0|65535] "" XXX BO_ 37 STEER_ANGLE_SENSOR: 8 XXX @@ -91,8 +91,8 @@ BO_ 170 WHEEL_SPEEDS: 8 XXX BO_ 180 SPEED: 8 XXX SG_ ENCODER : 39|8@0+ (1,0) [0|255] "" XXX - SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX SG_ SPEED : 47|16@0+ (0.01,0) [0|250] "kph" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX BO_ 353 DSU_SPEED: 8 XXX SG_ FORWARD_SPEED : 15|16@0- (0.00390625,-30) [0|255] "kph" XXX @@ -184,6 +184,7 @@ BO_ 921 PCM_CRUISE_SM: 8 XXX BO_ 951 ESP_CONTROL: 8 ESP SG_ TC_DISABLED : 13|1@0+ (1,0) [0|1] "" XXX + SG_ VSC_DISABLED : 12|2@0+ (1,0) [0|1] "" XXX SG_ BRAKE_LIGHTS_ACC : 18|1@0+ (1,0) [0|1] "" XXX BO_ 1041 ACC_HUD: 8 DSU @@ -208,6 +209,17 @@ BO_ 1042 LKAS_HUD: 8 XXX SG_ SET_ME_X38 : 55|8@0+ (1,0) [0|1] "" XXX SG_ SET_ME_X02 : 63|8@0+ (1,0) [0|1] "" XXX +BO_ 1043 TIME : 8 CGW + SG_ YEAR : 7|8@0+ (1,0) [0|0] "year" XXX + SG_ MONTH : 15|8@0+ (1,0) [0|0] "month" XXX + SG_ DAY : 23|8@0+ (1,0) [0|0] "day" XXX + SG_ HOUR : 31|8@0+ (1,0) [0|0] "hour" XXX + SG_ MINUTE : 39|8@0+ (1,0) [0|0] "minute" XXX + SG_ GMT_DIFF : 55|1@0+ (1,0) [0|0] "" XXX + SG_ GMTDIFF_HOURS : 54|4@0+ (1,0) [0|0] "hours" XXX + SG_ GMTDIFF_MINUTES : 50|6@0+ (1,0) [0|0] "minutes" XXX + SG_ SUMMER : 60|1@0+ (1,0) [0|0] "" XXX + BO_ 1408 VIN_PART_1: 8 CGW SG_ VIN_1 : 7|8@0+ (1,0) [0|0] "" XXX SG_ VIN_2 : 15|8@0+ (1,0) [0|0] "" XXX @@ -367,6 +379,7 @@ BO_ 608 STEER_TORQUE_SENSOR: 8 XXX SG_ STEER_TORQUE_DRIVER : 15|16@0- (1,0) [-32768|32767] "" XXX SG_ STEER_OVERRIDE : 0|1@0+ (1,0) [0|1] "" XXX SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + SG_ STEER_ANGLE : 31|16@0- (0.0573,0) [-500|500] "" XXX BO_ 610 EPS_STATUS: 8 EPS SG_ IPAS_STATE : 3|4@0+ (1,0) [0|15] "" XXX diff --git a/opendbc/toyota_rav4_2017_pt_generated.dbc b/opendbc/toyota_rav4_2017_pt_generated.dbc index de8e55b7379201..a9e8a03e517da6 100644 --- a/opendbc/toyota_rav4_2017_pt_generated.dbc +++ b/opendbc/toyota_rav4_2017_pt_generated.dbc @@ -70,8 +70,8 @@ BS_: BU_: XXX DSU HCU EPS IPAS CGW BO_ 36 KINEMATICS: 8 XXX - SG_ ACCEL_Y : 33|10@0+ (1,-512) [0|65535] "" XXX - SG_ YAW_RATE : 1|10@0+ (1,-512) [0|65535] "" XXX + SG_ ACCEL_Y : 33|10@0+ (0.03589,-18.375) [0|65535] "m/s^2" XXX + SG_ YAW_RATE : 1|10@0+ (0.244,-125) [0|65535] "deg/sec" XXX SG_ STEERING_TORQUE : 17|10@0+ (1,-512) [0|65535] "" XXX BO_ 37 STEER_ANGLE_SENSOR: 8 XXX @@ -91,8 +91,8 @@ BO_ 170 WHEEL_SPEEDS: 8 XXX BO_ 180 SPEED: 8 XXX SG_ ENCODER : 39|8@0+ (1,0) [0|255] "" XXX - SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX SG_ SPEED : 47|16@0+ (0.01,0) [0|250] "kph" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX BO_ 353 DSU_SPEED: 8 XXX SG_ FORWARD_SPEED : 15|16@0- (0.00390625,-30) [0|255] "kph" XXX @@ -184,6 +184,7 @@ BO_ 921 PCM_CRUISE_SM: 8 XXX BO_ 951 ESP_CONTROL: 8 ESP SG_ TC_DISABLED : 13|1@0+ (1,0) [0|1] "" XXX + SG_ VSC_DISABLED : 12|2@0+ (1,0) [0|1] "" XXX SG_ BRAKE_LIGHTS_ACC : 18|1@0+ (1,0) [0|1] "" XXX BO_ 1041 ACC_HUD: 8 DSU @@ -208,6 +209,17 @@ BO_ 1042 LKAS_HUD: 8 XXX SG_ SET_ME_X38 : 55|8@0+ (1,0) [0|1] "" XXX SG_ SET_ME_X02 : 63|8@0+ (1,0) [0|1] "" XXX +BO_ 1043 TIME : 8 CGW + SG_ YEAR : 7|8@0+ (1,0) [0|0] "year" XXX + SG_ MONTH : 15|8@0+ (1,0) [0|0] "month" XXX + SG_ DAY : 23|8@0+ (1,0) [0|0] "day" XXX + SG_ HOUR : 31|8@0+ (1,0) [0|0] "hour" XXX + SG_ MINUTE : 39|8@0+ (1,0) [0|0] "minute" XXX + SG_ GMT_DIFF : 55|1@0+ (1,0) [0|0] "" XXX + SG_ GMTDIFF_HOURS : 54|4@0+ (1,0) [0|0] "hours" XXX + SG_ GMTDIFF_MINUTES : 50|6@0+ (1,0) [0|0] "minutes" XXX + SG_ SUMMER : 60|1@0+ (1,0) [0|0] "" XXX + BO_ 1408 VIN_PART_1: 8 CGW SG_ VIN_1 : 7|8@0+ (1,0) [0|0] "" XXX SG_ VIN_2 : 15|8@0+ (1,0) [0|0] "" XXX diff --git a/opendbc/toyota_rav4_hybrid_2017_pt_generated.dbc b/opendbc/toyota_rav4_hybrid_2017_pt_generated.dbc index a78e78c7fb126b..27ced0f9cdb393 100644 --- a/opendbc/toyota_rav4_hybrid_2017_pt_generated.dbc +++ b/opendbc/toyota_rav4_hybrid_2017_pt_generated.dbc @@ -70,8 +70,8 @@ BS_: BU_: XXX DSU HCU EPS IPAS CGW BO_ 36 KINEMATICS: 8 XXX - SG_ ACCEL_Y : 33|10@0+ (1,-512) [0|65535] "" XXX - SG_ YAW_RATE : 1|10@0+ (1,-512) [0|65535] "" XXX + SG_ ACCEL_Y : 33|10@0+ (0.03589,-18.375) [0|65535] "m/s^2" XXX + SG_ YAW_RATE : 1|10@0+ (0.244,-125) [0|65535] "deg/sec" XXX SG_ STEERING_TORQUE : 17|10@0+ (1,-512) [0|65535] "" XXX BO_ 37 STEER_ANGLE_SENSOR: 8 XXX @@ -91,8 +91,8 @@ BO_ 170 WHEEL_SPEEDS: 8 XXX BO_ 180 SPEED: 8 XXX SG_ ENCODER : 39|8@0+ (1,0) [0|255] "" XXX - SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX SG_ SPEED : 47|16@0+ (0.01,0) [0|250] "kph" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX BO_ 353 DSU_SPEED: 8 XXX SG_ FORWARD_SPEED : 15|16@0- (0.00390625,-30) [0|255] "kph" XXX @@ -184,6 +184,7 @@ BO_ 921 PCM_CRUISE_SM: 8 XXX BO_ 951 ESP_CONTROL: 8 ESP SG_ TC_DISABLED : 13|1@0+ (1,0) [0|1] "" XXX + SG_ VSC_DISABLED : 12|2@0+ (1,0) [0|1] "" XXX SG_ BRAKE_LIGHTS_ACC : 18|1@0+ (1,0) [0|1] "" XXX BO_ 1041 ACC_HUD: 8 DSU @@ -208,6 +209,17 @@ BO_ 1042 LKAS_HUD: 8 XXX SG_ SET_ME_X38 : 55|8@0+ (1,0) [0|1] "" XXX SG_ SET_ME_X02 : 63|8@0+ (1,0) [0|1] "" XXX +BO_ 1043 TIME : 8 CGW + SG_ YEAR : 7|8@0+ (1,0) [0|0] "year" XXX + SG_ MONTH : 15|8@0+ (1,0) [0|0] "month" XXX + SG_ DAY : 23|8@0+ (1,0) [0|0] "day" XXX + SG_ HOUR : 31|8@0+ (1,0) [0|0] "hour" XXX + SG_ MINUTE : 39|8@0+ (1,0) [0|0] "minute" XXX + SG_ GMT_DIFF : 55|1@0+ (1,0) [0|0] "" XXX + SG_ GMTDIFF_HOURS : 54|4@0+ (1,0) [0|0] "hours" XXX + SG_ GMTDIFF_MINUTES : 50|6@0+ (1,0) [0|0] "minutes" XXX + SG_ SUMMER : 60|1@0+ (1,0) [0|0] "" XXX + BO_ 1408 VIN_PART_1: 8 CGW SG_ VIN_1 : 7|8@0+ (1,0) [0|0] "" XXX SG_ VIN_2 : 15|8@0+ (1,0) [0|0] "" XXX diff --git a/opendbc/toyota_sienna_xle_2018_pt_generated.dbc b/opendbc/toyota_sienna_xle_2018_pt_generated.dbc index d427b1bef04d4f..2cbd918ce3e08a 100644 --- a/opendbc/toyota_sienna_xle_2018_pt_generated.dbc +++ b/opendbc/toyota_sienna_xle_2018_pt_generated.dbc @@ -70,8 +70,8 @@ BS_: BU_: XXX DSU HCU EPS IPAS CGW BO_ 36 KINEMATICS: 8 XXX - SG_ ACCEL_Y : 33|10@0+ (1,-512) [0|65535] "" XXX - SG_ YAW_RATE : 1|10@0+ (1,-512) [0|65535] "" XXX + SG_ ACCEL_Y : 33|10@0+ (0.03589,-18.375) [0|65535] "m/s^2" XXX + SG_ YAW_RATE : 1|10@0+ (0.244,-125) [0|65535] "deg/sec" XXX SG_ STEERING_TORQUE : 17|10@0+ (1,-512) [0|65535] "" XXX BO_ 37 STEER_ANGLE_SENSOR: 8 XXX @@ -91,8 +91,8 @@ BO_ 170 WHEEL_SPEEDS: 8 XXX BO_ 180 SPEED: 8 XXX SG_ ENCODER : 39|8@0+ (1,0) [0|255] "" XXX - SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX SG_ SPEED : 47|16@0+ (0.01,0) [0|250] "kph" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX BO_ 353 DSU_SPEED: 8 XXX SG_ FORWARD_SPEED : 15|16@0- (0.00390625,-30) [0|255] "kph" XXX @@ -184,6 +184,7 @@ BO_ 921 PCM_CRUISE_SM: 8 XXX BO_ 951 ESP_CONTROL: 8 ESP SG_ TC_DISABLED : 13|1@0+ (1,0) [0|1] "" XXX + SG_ VSC_DISABLED : 12|2@0+ (1,0) [0|1] "" XXX SG_ BRAKE_LIGHTS_ACC : 18|1@0+ (1,0) [0|1] "" XXX BO_ 1041 ACC_HUD: 8 DSU @@ -208,6 +209,17 @@ BO_ 1042 LKAS_HUD: 8 XXX SG_ SET_ME_X38 : 55|8@0+ (1,0) [0|1] "" XXX SG_ SET_ME_X02 : 63|8@0+ (1,0) [0|1] "" XXX +BO_ 1043 TIME : 8 CGW + SG_ YEAR : 7|8@0+ (1,0) [0|0] "year" XXX + SG_ MONTH : 15|8@0+ (1,0) [0|0] "month" XXX + SG_ DAY : 23|8@0+ (1,0) [0|0] "day" XXX + SG_ HOUR : 31|8@0+ (1,0) [0|0] "hour" XXX + SG_ MINUTE : 39|8@0+ (1,0) [0|0] "minute" XXX + SG_ GMT_DIFF : 55|1@0+ (1,0) [0|0] "" XXX + SG_ GMTDIFF_HOURS : 54|4@0+ (1,0) [0|0] "hours" XXX + SG_ GMTDIFF_MINUTES : 50|6@0+ (1,0) [0|0] "minutes" XXX + SG_ SUMMER : 60|1@0+ (1,0) [0|0] "" XXX + BO_ 1408 VIN_PART_1: 8 CGW SG_ VIN_1 : 7|8@0+ (1,0) [0|0] "" XXX SG_ VIN_2 : 15|8@0+ (1,0) [0|0] "" XXX diff --git a/opendbc/vw_golf_mk4.dbc b/opendbc/vw_golf_mk4.dbc index 596f2d082ad041..70cc8cc3aff74a 100644 --- a/opendbc/vw_golf_mk4.dbc +++ b/opendbc/vw_golf_mk4.dbc @@ -1,7 +1,7 @@ VERSION "" -NS_ : +NS_ : NS_DESC_ CM_ BA_DEF_ @@ -187,10 +187,10 @@ BO_ 1298 PSG_2: 8 XXX SG_ RAM_Inhalt_1 : 0|16@1+ (1,0) [0|0] "" XXX BO_ 274 PSG_1: 8 XXX - SG_ Pumpentemperatur__2_1_ : 48|16@1+ (0.0625,0) [0|4096] "°K" XXX + SG_ Pumpentemperatur__2_1_ : 48|16@1+ (0.0625,0) [0|4096] "K" XXX SG_ Pumpentemperatur__3_2_2_ : 44|12@1+ (1,0) [0|0] "" XXX - SG_ Zylinderzaehler__3_2_2_ : 43|3@1+ (1,0) [1|8] "Zähler" XXX - SG_ Ansteuerdauer__3_2_2_ : 32|11@1+ (0.0469,0) [0|96] "°NW" XXX + SG_ Zylinderzaehler__3_2_2_ : 43|3@1+ (1,0) [1|8] "Zaehler" XXX + SG_ Ansteuerdauer__3_2_2_ : 32|11@1+ (0.0469,0) [0|96] "NW" XXX SG_ Nockenwellendrehzahl__3_2_2_ : 20|12@1+ (4,0) [0|16380] "upm" XXX SG_ Pumpen_Statuswort__3_2_2_ : 0|20@1+ (1,0) [0|0] "" XXX @@ -233,7 +233,7 @@ BO_ 1424 Niveau_1: 6 XXX SG_ ESP_Beeinflussung : 14|1@1+ (1,0) [0|0] "" XXX SG_ Warnlampe_Niveau_1 : 13|1@1+ (1,0) [0|0] "" XXX SG_ Frei_Niveau_1_1 : 12|1@1+ (1,0) [0|0] "" XXX - SG_ Zaehler_Niveau_1 : 8|4@1+ (1,0) [0|15] "Zähler" XXX + SG_ Zaehler_Niveau_1 : 8|4@1+ (1,0) [0|15] "Zaehler" XXX SG_ Checksumme_Niveau_1 : 0|8@1+ (1,0) [0|0] "" XXX BO_ 1328 Navigation_1: 7 XXX @@ -248,11 +248,11 @@ BO_ 1328 Navigation_1: 7 XXX SG_ Laenderkennung : 16|8@1+ (1,0) [0|0] "" XXX SG_ Vorzeichen_Gierrate______ : 15|1@1+ (1,0) [0|0] "" XXX SG_ Gierratenfehler : 14|1@1+ (1,0) [0|0] "" XXX - SG_ Gierrate : 0|14@1+ (0.01,0) [0|100] "°/sek" XXX + SG_ Gierrate : 0|14@1+ (0.01,0) [0|100] "deg/sek" XXX BO_ 1792 MSG_3: 3 XXX SG_ MSG_Konfiguration : 16|8@1+ (1,0) [0|0] "" XXX - SG_ Lage_des_OT_Impuls : 0|16@1+ (0.01172,-384) [-384|384] "°KW" XXX + SG_ Lage_des_OT_Impuls : 0|16@1+ (0.01172,-384) [-384|384] "KW" XXX BO_ 1280 MSG_2: 8 XXX SG_ RAM_Adresse_4 : 48|16@1+ (1,0) [0|0] "" XXX @@ -262,8 +262,8 @@ BO_ 1280 MSG_2: 8 XXX BO_ 256 MSG_1: 8 XXX SG_ Kurbelwellendrehzahl__3_2_2_ : 56|8@1+ (1,0) [0|0] "" XXX - SG_ Soll_Foerderbeginn_KW__3_2_2_ : 40|16@1+ (0.01172,-384) [-384|384] "°KW" XXX - SG_ Soll_Foerderbeginn_NW__3_2_2_ : 28|12@1+ (0.01172,0) [0|768] "°NW" XXX + SG_ Soll_Foerderbeginn_KW__3_2_2_ : 40|16@1+ (0.01172,-384) [-384|384] "KW" XXX + SG_ Soll_Foerderbeginn_NW__3_2_2_ : 28|12@1+ (0.01172,0) [0|768] "degNW" XXX SG_ Soll_Voreinspritzung : 16|12@1+ (1,0) [0|0] "" XXX SG_ Soll_Einspritzmenge : 0|16@1+ (0.03125,0) [0|2047] "mg/H" XXX @@ -273,7 +273,7 @@ BO_ 1796 Motor_NOX: 8 XXX SG_ Heizleistungsanforderung : 18|1@1+ (1,0) [0|0] "" XXX SG_ Offsetkorrektur_moeglich : 17|1@1+ (1,0) [0|0] "" XXX SG_ Betriebsbereich : 16|1@1+ (1,0) [0|0] "" XXX - SG_ Abgastemperatur_NOX : 8|8@1+ (5,-40) [-40|1230] "°C" XXX + SG_ Abgastemperatur_NOX : 8|8@1+ (5,-40) [-40|1230] "C" XXX SG_ Abgasdruck_NOX : 0|8@1+ (5,600) [600|1870] "mbar" XXX BO_ 900 Motor_Momente: 8 XXX @@ -361,7 +361,7 @@ BO_ 896 Motor_3: 8 XXX SG_ Vorzeichen_Rad_Wunschmoment : 36|1@1+ (1,0) [0|0] "" XXX SG_ Rad_Wunschmoment : 24|12@1+ (0.39,0) [0|1597] "MDI" XXX SG_ Fahrpedal_Rohsignal : 16|8@1+ (0.4,0) [0|101.6] "%" XXX - SG_ Ansauglufttemperatur : 8|8@1+ (0.75,-48) [-48|142.5] "°" XXX + SG_ Ansauglufttemperatur : 8|8@1+ (0.75,-48) [-48|142.5] "" XXX SG_ Fehlerstatus_Ansauglufttemperat : 7|1@1+ (1,0) [0|0] "" XXX SG_ Motorsteuerger_t_gesperrt : 6|1@1+ (1,0) [0|0] "" XXX SG_ Drosselklappenwinkel_ungenau : 5|1@1+ (1,0) [0|0] "" XXX @@ -384,7 +384,7 @@ BO_ 648 Motor_2: 8 XXX SG_ Fehlerstatus_Kuhlmitteltempera : 18|1@1+ (1,0) [0|0] "" XXX SG_ Bremstestschalter : 17|1@1+ (1,0) [0|0] "" XXX SG_ Bremslichtschalter : 16|1@1+ (1,0) [0|0] "" XXX - SG_ Kuehlmitteltemperatur__Motor_2_ : 8|8@1+ (0.75,-48) [-48|142.5] "°" XXX + SG_ Kuehlmitteltemperatur__Motor_2_ : 8|8@1+ (0.75,-48) [-48|142.5] "" XXX SG_ Multiplex_Code_Motor_2 M : 6|2@1+ (1,0) [0|0] "" XXX SG_ Multiplex_Info_Motorcode__4_x_ m1 : 0|6@1+ (1,0) [0|0] "" XXX SG_ Multiplex_Info_Getriebecode m2 : 0|6@1+ (1,0) [0|0] "" XXX @@ -409,7 +409,7 @@ BO_ 640 Motor_1: 8 XXX BO_ 262 Master_3: 8 XXX SG_ Frei_Master_3_1 : 56|8@1+ (1,0) [0|0] "" XXX - SG_ Motortemperatur_linearisiert : 48|8@1+ (0.75,-48) [-48|143.25] "°" XXX + SG_ Motortemperatur_linearisiert : 48|8@1+ (0.75,-48) [-48|143.25] "" XXX SG_ Indiziertes_Sollmoment_f_r_Vmax : 32|16@1+ (0.0015259,0) [0|100] "%" XXX SG_ Relative_Momentenanforderung_de : 16|16@1+ (0.003052,0) [0|200] "%" XXX SG_ Delta_Motormoment_aus_Verlustmo : 0|16@1+ (0.003052,-100) [-100|100] "%" XXX @@ -448,7 +448,7 @@ BO_ 1986 Lenkwinkel_Init: 4 XXX BO_ 192 Lenkwinkel_1__RB_: 2 XXX SG_ Vorzeichen__RB_ : 15|1@1+ (1,0) [0|0] "" XXX - SG_ Lenkwinkel__RB_ : 5|10@1+ (2.5,-720) [-720|720] "°" XXX + SG_ Lenkwinkel__RB_ : 5|10@1+ (2.5,-720) [-720|720] "" XXX SG_ LWS_OK__RB_ : 4|1@1+ (1,0) [0|0] "" XXX SG_ LWS_Abgleich__RB_ : 3|1@1+ (1,0) [0|0] "" XXX SG_ Frei_Lenkwinkel_1_1__RB_ : 2|1@1+ (1,0) [0|0] "" XXX @@ -457,7 +457,7 @@ BO_ 192 Lenkwinkel_1__RB_: 2 XXX BO_ 196 Lenkwinkel_1__ITT_: 2 XXX SG_ Vorzeichen__ITT_ : 15|1@1+ (1,0) [0|0] "" XXX - SG_ Lenkwinkel__ITT_ : 5|10@1+ (1.5,-768) [-768|766.5] "°" XXX + SG_ Lenkwinkel__ITT_ : 5|10@1+ (1.5,-768) [-768|766.5] "" XXX SG_ LWS_OK : 4|1@1+ (1,0) [0|0] "" XXX SG_ LWS_Abgleich__ITT_ : 3|1@1+ (1,0) [0|0] "" XXX SG_ LWS_Initialisierung__ITT_ : 2|1@1+ (1,0) [0|0] "" XXX @@ -558,10 +558,10 @@ BO_ 1056 Kombi_2: 8 XXX SG_ Klemme_58s__Kombi_2_ : 48|7@1+ (1,0) [0|100] "%" XXX SG_ Fehlerstatus_Kl__58_d : 47|1@1+ (1,0) [0|0] "" XXX SG_ Klemme_58d__Kombi_2_ : 40|7@1+ (1,0) [0|100] "%" XXX - SG_ Kuehlmitteltemp__4_1__Kombi_2_ : 32|8@1+ (0.75,-48) [-48|142.5] "°C" XXX - SG_ Oeltemperatur_4_1 : 24|8@1+ (1,-60) [-60|194] "°C" XXX - SG_ Aussentemp__ungefiltert_4_1__Ko : 16|8@1+ (0.5,-50) [-50|77] "°C" XXX - SG_ Aussentemperatur_gefiltert : 8|8@1+ (0.5,-50) [-50|77] "°C" XXX + SG_ Kuehlmitteltemp__4_1__Kombi_2_ : 32|8@1+ (0.75,-48) [-48|142.5] "C" XXX + SG_ Oeltemperatur_4_1 : 24|8@1+ (1,-60) [-60|194] "C" XXX + SG_ Aussentemp__ungefiltert_4_1__Ko : 16|8@1+ (0.5,-50) [-50|77] "C" XXX + SG_ Aussentemperatur_gefiltert : 8|8@1+ (0.5,-50) [-50|77] "C" XXX SG_ Fehlerspeichereintrag__Kombi_ : 7|1@1+ (1,0) [0|0] "" XXX SG_ Frei_Kombi_2_1 : 4|3@1+ (1,0) [0|0] "" XXX SG_ Anhaenger_erkannt : 3|1@1+ (1,0) [0|0] "" XXX @@ -596,7 +596,7 @@ BO_ 800 Kombi_1: 8 XXX SG_ Fahrertuer_4_1 : 0|1@1+ (1,0) [0|0] "" XXX BO_ 1504 Klima_1: 8 XXX - SG_ Aussentemp__ungef__Sto_f__4_1 : 56|8@1+ (0.5,-50) [-50|77] "°C" XXX + SG_ Aussentemp__ungef__Sto_f__4_1 : 56|8@1+ (0.5,-50) [-50|77] "C" XXX SG_ Fehlerspeichereintrag__Klima_ : 55|1@1+ (1,0) [0|0] "" XXX SG_ Frei_Klima_1_5 : 50|5@1+ (1,0) [0|0] "" XXX SG_ AC_Schalter : 49|1@1+ (1,0) [0|0] "" XXX @@ -605,7 +605,7 @@ BO_ 1504 Klima_1: 8 XXX SG_ Geblaeselast_4_1 : 32|8@1+ (0.4,0) [0|101.6] "%" XXX SG_ Kompressorlast : 24|8@1+ (0.25,0) [0|63.5] "Nm" XXX SG_ Klimadrucksignal__Klima_1_ : 16|8@1+ (0.2,0) [0|50.8] "bar" XXX - SG_ Aussentemp__ungef__4_1__Klima_1 : 8|8@1+ (0.5,-50) [-50|77] "°C" XXX + SG_ Aussentemp__ungef__4_1__Klima_1 : 8|8@1+ (0.5,-50) [-50|77] "C" XXX SG_ Kaeltemitteldruck_veraltet : 7|1@1+ (1,0) [0|0] "" XXX SG_ Kompressormoment_veraltet_4_1 : 6|1@1+ (1,0) [0|0] "" XXX SG_ Keine_Heizleistg_gewuenscht_4_1 : 5|1@1+ (1,0) [0|0] "" XXX @@ -836,9 +836,9 @@ BO_ 1192 Bremse_5: 8 XXX SG_ Checksumme_Bremse_5 : 56|8@1+ (1,0) [0|0] "" XXX SG_ Zaehler_Bremse_5 : 52|4@1+ (1,0) [0|15] "" XXX SG_ Bremslicht_ECD : 51|1@1+ (1,0) [0|0] "" XXX - SG_ Bremsentemperatur_vorn : 48|3@1+ (125,125) [125|1000] "°C" XXX + SG_ Bremsentemperatur_vorn : 48|3@1+ (125,125) [125|1000] "C" XXX SG_ Frei_Bremse_5_5 : 40|8@1+ (1,0) [0|0] "" XXX - SG_ Offset_Gierrate : 32|8@1+ (0.05,-6.375) [-6.375|6.375] "°/s" XXX + SG_ Offset_Gierrate : 32|8@1+ (0.05,-6.375) [-6.375|6.375] "deg/s" XXX SG_ Vorzeichen_Bremsdruck : 31|1@1+ (1,0) [0|0] "" XXX SG_ Status_Bremsdruck_durch_ESP_Sys : 30|1@1+ (1,0) [0|0] "" XXX SG_ Bremsdruck_ungueltig : 29|1@1+ (1,0) [0|0] "" XXX diff --git a/panda/.circleci/config.yml b/panda/.circleci/config.yml index d74c1a20e09686..6348ff0f5542f0 100644 --- a/panda/.circleci/config.yml +++ b/panda/.circleci/config.yml @@ -11,7 +11,7 @@ jobs: - run: name: Run safety test command: | - docker run panda_safety /bin/bash -c "cd /panda/tests/safety; ./test.sh" + docker run panda_safety /bin/bash -c "cd /panda/tests/safety; PYTHONPATH=/ ./test.sh" misra-c2012: machine: diff --git a/panda/Dockerfile b/panda/Dockerfile index 1a0d924661d6ce..a029a5ffa4af14 100644 --- a/panda/Dockerfile +++ b/panda/Dockerfile @@ -17,11 +17,15 @@ RUN apt-get update && apt-get install -y \ gperf \ help2man \ iputils-ping \ + libbz2-dev \ libexpat-dev \ + libffi-dev \ + libssl-dev \ libstdc++-arm-none-eabi-newlib \ libtool \ libtool-bin \ libusb-1.0-0 \ + locales \ make \ ncurses-dev \ network-manager \ @@ -38,7 +42,21 @@ RUN apt-get update && apt-get install -y \ screen \ vim \ wget \ - wireless-tools + wireless-tools \ + zlib1g-dev + +RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 + +RUN curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash + +ENV PATH="/root/.pyenv/bin:/root/.pyenv/shims:${PATH}" +RUN pyenv install 3.7.3 +RUN pyenv install 2.7.12 +RUN pyenv global 3.7.3 +RUN pyenv rehash RUN pip install --upgrade pip==18.0 @@ -51,6 +69,7 @@ ENV HOME /home/batman ENV PYTHONPATH /tmp:$PYTHONPATH COPY ./boardesp/get_sdk_ci.sh /tmp/panda/boardesp/ +COPY ./boardesp/python2_make.py /tmp/panda/boardesp/ RUN useradd --system -s /sbin/nologin pandauser RUN mkdir -p /tmp/panda/boardesp/esp-open-sdk diff --git a/panda/Jenkinsfile b/panda/Jenkinsfile index 19dc3d4c80863c..7f147a2fe9e08d 100644 --- a/panda/Jenkinsfile +++ b/panda/Jenkinsfile @@ -46,19 +46,6 @@ pipeline { } } } - stage('Test Dev Build (WIFI)') { - steps { - lock(resource: "Pandas", inversePrecedence: true, quantity: 1){ - timeout(time: 60, unit: 'MINUTES') { - script { - sh "docker run --name ${env.DOCKER_NAME} --privileged --volume /dev/bus/usb:/dev/bus/usb --volume /var/run/dbus:/var/run/dbus --net host ${env.DOCKER_IMAGE_TAG} bash -c 'cd /tmp/panda; ./run_automated_tests.sh'" - sh "docker cp ${env.DOCKER_NAME}:/tmp/panda/nosetests.xml test_results_dev.xml" - sh "docker rm ${env.DOCKER_NAME}" - } - } - } - } - } } post { failure { diff --git a/panda/README.md b/panda/README.md index 42f432dfc32a38..7c9bd68bf7926a 100644 --- a/panda/README.md +++ b/panda/README.md @@ -37,6 +37,13 @@ And to send one on bus 0: ``` Find user made scripts on the [wiki](https://community.comma.ai/wiki/index.php/Panda_scripts) +Note that you may have to setup [udev rules](https://community.comma.ai/wiki/index.php/Panda#Linux_udev_rules) for Linux, such as +``` +sudo -i +echo 'SUBSYSTEMS=="usb", ATTR{idVendor}=="bbaa", ATTR{idProduct}=="ddcc", MODE:="0666"' > /etc/udev/rules.d/11-panda.rules +exit +``` + Usage (JavaScript) ------- @@ -80,9 +87,26 @@ To print out the serial console from the ESP8266, run PORT=1 tests/debug_console Safety Model ------ -When a panda powers up, by default it's in "SAFETY_NOOUTPUT" mode. While in no output mode, the buses are also forced to be silent. In order to send messages, you have to select a safety mode. Currently, setting safety modes is only supported over USB. +When a panda powers up, by default it's in `SAFETY_NOOUTPUT` mode. While in no output mode, the buses are also forced to be silent. In order to send messages, you have to select a safety mode. Currently, setting safety modes is only supported over USB. -Safety modes can also optionally support "controls_allowed", which allows or blocks a subset of messages based on a piece of state in the board. +Safety modes optionally supports `controls_allowed`, which allows or blocks a subset of messages based on a customizable state in the board. + +Code Rigor +------ +When compiled from an [EON Dev Kit](https://comma.ai/shop/products/eon-gold-dashcam-devkit), the panda FW is configured and optimized (at compile time) for its use in +conjuction with [openpilot](https://github.com/commaai/openpilot). The panda FW, through its safety model, provides and enforces the +[openpilot Safety](https://github.com/commaai/openpilot/blob/devel/SAFETY.md). Due to its critical function, it's important that the application code rigor within the `board` folder is held to high standards. + +These are the [CI regression tests](https://circleci.com/gh/commaai/panda) we have in place: +* A generic static code analysis is performed by [Cppcheck](https://github.com/danmar/cppcheck/). +* In addition, [Cppcheck](https://github.com/danmar/cppcheck/) has a specific addon to check for [MISRA C:2012](https://www.misra.org.uk/MISRAHome/MISRAC2012/tabid/196/Default.aspx) violations. See [current coverage](https://github.com/commaai/panda/blob/master/tests/misra/coverage_table). +* Compiler options are relatively strict: the flags `-Wall -Wextra -Wstrict-prototypes -Werror` are enforced on board and pedal makefiles. +* The [safety logic](https://github.com/commaai/panda/tree/master/board/safety) is tested and verified by [unit tests](https://github.com/commaai/panda/tree/master/tests/safety) for each supported car variant. +* A recorded drive for each supported car variant is [replayed through the safety logic](https://github.com/commaai/panda/tree/master/tests/safety_replay) +to ensure that the behavior remains unchanged. +* An internal Hardware-in-the-loop test, which currently only runs on pull requests opened by comma.ai's organization members, verifies the following functionalities: + * compiling the code in various configuration and flashing it both through USB and WiFi. + * Receiving, sending and forwarding CAN messages on all buses, over USB and WiFi. Hardware ------ diff --git a/panda/VERSION b/panda/VERSION index 880b851599e217..01558e339ad439 100644 --- a/panda/VERSION +++ b/panda/VERSION @@ -1 +1 @@ -v1.4.7 \ No newline at end of file +v1.5.3 \ No newline at end of file diff --git a/panda/board/board_declarations.h b/panda/board/board_declarations.h index cc93ec7c97e354..21eb140c3ef272 100644 --- a/panda/board/board_declarations.h +++ b/panda/board/board_declarations.h @@ -36,7 +36,7 @@ struct board { #define LED_GREEN 1U #define LED_BLUE 2U -// USB power modes +// USB power modes (from cereal.log.health) #define USB_POWER_NONE 0U #define USB_POWER_CLIENT 1U #define USB_POWER_CDP 2U diff --git a/panda/board/boards/black.h b/panda/board/boards/black.h index 62b3b674036177..c6078e3b56b370 100644 --- a/panda/board/boards/black.h +++ b/panda/board/boards/black.h @@ -38,7 +38,7 @@ void black_set_led(uint8_t color, bool enabled) { break; case LED_BLUE: set_gpio_output(GPIOC, 6, !enabled); - break; + break; default: break; } @@ -53,11 +53,22 @@ void black_set_usb_load_switch(bool enabled) { } void black_set_usb_power_mode(uint8_t mode) { - usb_power_mode = mode; - if (mode == USB_POWER_NONE) { - black_set_usb_load_switch(false); - } else { - black_set_usb_load_switch(true); + bool valid = false; + switch (mode) { + case USB_POWER_CLIENT: + black_set_usb_load_switch(false); + valid = true; + break; + case USB_POWER_CDP: + black_set_usb_load_switch(true); + valid = true; + break; + default: + puts("Invalid USB power mode\n"); + break; + } + if (valid) { + usb_power_mode = mode; } } @@ -67,18 +78,15 @@ void black_set_esp_gps_mode(uint8_t mode) { // GPS OFF set_gpio_output(GPIOC, 14, 0); set_gpio_output(GPIOC, 5, 0); - black_set_gps_load_switch(false); break; case ESP_GPS_ENABLED: // GPS ON set_gpio_output(GPIOC, 14, 1); set_gpio_output(GPIOC, 5, 1); - black_set_gps_load_switch(true); break; case ESP_GPS_BOOTMODE: set_gpio_output(GPIOC, 14, 1); set_gpio_output(GPIOC, 5, 0); - black_set_gps_load_switch(true); break; default: puts("Invalid ESP/GPS mode\n"); @@ -106,7 +114,7 @@ void black_set_can_mode(uint8_t mode){ // B12,B13: OBD mode set_gpio_alternate(GPIOB, 12, GPIO_AF9_CAN2); set_gpio_alternate(GPIOB, 13, GPIO_AF9_CAN2); - } + } break; default: puts("Tried to set unsupported CAN mode: "); puth(mode); puts("\n"); @@ -154,6 +162,9 @@ void black_init(void) { // Turn on USB load switch. black_set_usb_load_switch(true); + // Set right power mode + black_set_usb_power_mode(USB_POWER_CDP); + // Initialize harness harness_init(); @@ -203,4 +214,4 @@ const board board_black = { .set_can_mode = black_set_can_mode, .usb_power_mode_tick = black_usb_power_mode_tick, .check_ignition = black_check_ignition -}; \ No newline at end of file +}; diff --git a/panda/board/boards/white.h b/panda/board/boards/white.h index 46668c3a81f555..241f1b91bcf8dd 100644 --- a/panda/board/boards/white.h +++ b/panda/board/boards/white.h @@ -34,7 +34,7 @@ void white_set_led(uint8_t color, bool enabled) { break; case LED_BLUE: set_gpio_output(GPIOC, 6, !enabled); - break; + break; default: break; } @@ -125,7 +125,7 @@ void white_set_can_mode(uint8_t mode){ // A8,A15: normal CAN3 mode set_gpio_alternate(GPIOA, 8, GPIO_AF11_CAN3); - set_gpio_alternate(GPIOA, 15, GPIO_AF11_CAN3); + set_gpio_alternate(GPIOA, 15, GPIO_AF11_CAN3); break; case CAN_MODE_GMLAN_CAN3: // A8,A15: disable CAN3 mode @@ -143,7 +143,7 @@ void white_set_can_mode(uint8_t mode){ // B5,B6: normal CAN2 mode set_gpio_alternate(GPIOB, 5, GPIO_AF9_CAN2); set_gpio_alternate(GPIOB, 6, GPIO_AF9_CAN2); - break; + break; default: puts("Tried to set unsupported CAN mode: "); puth(mode); puts("\n"); break; @@ -152,7 +152,9 @@ void white_set_can_mode(uint8_t mode){ uint64_t marker = 0; void white_usb_power_mode_tick(uint64_t tcnt){ - #ifndef BOOTSTUB + + // on EON or BOOTSTUB, no state machine +#if !defined(BOOTSTUB) && !defined(EON) #define CURRENT_THRESHOLD 0xF00U #define CLICKS 5U // 5 seconds to switch modes @@ -177,22 +179,19 @@ void white_usb_power_mode_tick(uint64_t tcnt){ } break; case USB_POWER_CDP: - // On the EON, if we get into CDP mode we stay here. No need to go to DCP. - #ifndef EON - // been CLICKS clicks since we switched to CDP - if ((tcnt-marker) >= CLICKS) { - // measure current draw, if positive and no enumeration, switch to DCP - if (!is_enumerated && (current < CURRENT_THRESHOLD)) { - puts("USBP: no enumeration with current draw, switching to DCP mode\n"); - white_set_usb_power_mode(USB_POWER_DCP); - marker = tcnt; - } - } - // keep resetting the timer if there's no current draw in CDP - if (current >= CURRENT_THRESHOLD) { + // been CLICKS clicks since we switched to CDP + if ((tcnt-marker) >= CLICKS) { + // measure current draw, if positive and no enumeration, switch to DCP + if (!is_enumerated && (current < CURRENT_THRESHOLD)) { + puts("USBP: no enumeration with current draw, switching to DCP mode\n"); + white_set_usb_power_mode(USB_POWER_DCP); marker = tcnt; } - #endif + } + // keep resetting the timer if there's no current draw in CDP + if (current >= CURRENT_THRESHOLD) { + marker = tcnt; + } break; case USB_POWER_DCP: // been at least CLICKS clicks since we switched to DCP @@ -213,9 +212,9 @@ void white_usb_power_mode_tick(uint64_t tcnt){ puts("USB power mode invalid\n"); // set_usb_power_mode prevents assigning invalid values break; } - #else +#else UNUSED(tcnt); - #endif +#endif } bool white_check_ignition(void){ @@ -242,9 +241,6 @@ void white_init(void) { set_gpio_alternate(GPIOA, 6, GPIO_AF5_SPI1); set_gpio_alternate(GPIOA, 7, GPIO_AF5_SPI1); - // Set USB power mode - white_set_usb_power_mode(USB_POWER_CLIENT); - // B12: GMLAN, ignition sense, pull up set_gpio_pullup(GPIOB, 12, PULL_UP); @@ -292,6 +288,16 @@ void white_init(void) { EXTI->RTSR |= (1U << 1); EXTI->FTSR |= (1U << 1); NVIC_EnableIRQ(EXTI1_IRQn); + + // Init usb power mode + uint32_t voltage = adc_get_voltage(); + // Init in CDP mode only if panda is powered by 12V. + // Otherwise a PC would not be able to flash a standalone panda with EON build + if (voltage > 8000U) { // 8V threshold + white_set_usb_power_mode(USB_POWER_CDP); + } else { + white_set_usb_power_mode(USB_POWER_CLIENT); + } } const harness_configuration white_harness_config = { @@ -310,4 +316,4 @@ const board board_white = { .set_can_mode = white_set_can_mode, .usb_power_mode_tick = white_usb_power_mode_tick, .check_ignition = white_check_ignition -}; \ No newline at end of file +}; diff --git a/panda/board/bootstub.c b/panda/board/bootstub.c index 3b6b1e875e20f1..51ce6695db79ee 100644 --- a/panda/board/bootstub.c +++ b/panda/board/bootstub.c @@ -32,6 +32,7 @@ const board *current_board; #include "drivers/clock.h" #include "drivers/llgpio.h" +#include "drivers/adc.h" #include "board.h" @@ -68,8 +69,6 @@ int main(void) { detect_configuration(); detect_board_type(); - current_board->set_usb_power_mode(USB_POWER_CLIENT); - if (enter_bootloader_mode == ENTER_SOFTLOADER_MAGIC) { enter_bootloader_mode = 0; soft_flasher_start(); diff --git a/panda/board/config.h b/panda/board/config.h index 7fd203fc30e958..c2eb412e960903 100644 --- a/panda/board/config.h +++ b/panda/board/config.h @@ -2,6 +2,7 @@ #define PANDA_CONFIG_H //#define DEBUG +//#define DEBUG_UART //#define DEBUG_USB //#define DEBUG_SPI @@ -22,7 +23,7 @@ #include #define NULL ((void*)0) -#define COMPILE_TIME_ASSERT(pred) ((void)sizeof(char[1 - (2 * (!(pred)))])) +#define COMPILE_TIME_ASSERT(pred) ((void)sizeof(char[1 - (2 * ((int)(!(pred))))])) #define MIN(a,b) \ ({ __typeof__ (a) _a = (a); \ diff --git a/panda/board/drivers/adc.h b/panda/board/drivers/adc.h index efd0a168787471..2a91fef8dcd64e 100644 --- a/panda/board/drivers/adc.h +++ b/panda/board/drivers/adc.h @@ -36,3 +36,13 @@ uint32_t adc_get(unsigned int channel) { return ADC1->JDR1; } +uint32_t adc_get_voltage(void) { + // REVC has a 10, 1 (1/11) voltage divider + // Here is the calculation for the scale (s) + // ADCV = VIN_S * (1/11) * (4095/3.3) + // RETVAL = ADCV * s = VIN_S*1000 + // s = 1000/((4095/3.3)*(1/11)) = 8.8623046875 + + // Avoid needing floating point math, so output in mV + return (adc_get(ADCCHAN_VOLTAGE) * 8862U) / 1000U; +} diff --git a/panda/board/drivers/can.h b/panda/board/drivers/can.h index d0d7064972dc75..c45a3fe8d1d754 100644 --- a/panda/board/drivers/can.h +++ b/panda/board/drivers/can.h @@ -298,7 +298,7 @@ void process_can(uint8_t can_number) { to_push.RDTR = (CAN->sTxMailBox[0].TDTR & 0xFFFF000FU) | ((CAN_BUS_RET_FLAG | bus_number) << 4); to_push.RDLR = CAN->sTxMailBox[0].TDLR; to_push.RDHR = CAN->sTxMailBox[0].TDHR; - can_send_errs += !can_push(&can_rx_q, &to_push); + can_send_errs += can_push(&can_rx_q, &to_push) ? 0U : 1U; } if ((CAN->TSR & CAN_TSR_TERR0) == CAN_TSR_TERR0) { @@ -367,7 +367,7 @@ void can_rx(uint8_t can_number) { safety_rx_hook(&to_push); current_board->set_led(LED_BLUE, true); - can_send_errs += !can_push(&can_rx_q, &to_push); + can_send_errs += can_push(&can_rx_q, &to_push) ? 0U : 1U; // next CAN->RF0R |= CAN_RF0R_RFOM0; @@ -393,10 +393,9 @@ void can_send(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number) { // bus number isn't passed through to_push->RDTR &= 0xF; if ((bus_number == 3U) && (can_num_lookup[3] == 0xFFU)) { - // TODO: why uint8 bro? only int8? - gmlan_send_errs += !bitbang_gmlan(to_push); + gmlan_send_errs += bitbang_gmlan(to_push) ? 0U : 1U; } else { - can_fwd_errs += !can_push(can_queues[bus_number], to_push); + can_fwd_errs += can_push(can_queues[bus_number], to_push) ? 0U : 1U; process_can(CAN_NUM_FROM_BUS_NUM(bus_number)); } } diff --git a/panda/board/drivers/uart.h b/panda/board/drivers/uart.h index 451150d1af2e68..3a095f67261d8e 100644 --- a/panda/board/drivers/uart.h +++ b/panda/board/drivers/uart.h @@ -1,18 +1,43 @@ // IRQs: USART1, USART2, USART3, UART5 -#define FIFO_SIZE 0x400U +// ***************************** Definitions ***************************** +#define FIFO_SIZE_INT 0x400U +#define FIFO_SIZE_DMA 0x1000U + typedef struct uart_ring { volatile uint16_t w_ptr_tx; volatile uint16_t r_ptr_tx; - uint8_t elems_tx[FIFO_SIZE]; + uint8_t *elems_tx; + uint32_t tx_fifo_size; volatile uint16_t w_ptr_rx; volatile uint16_t r_ptr_rx; - uint8_t elems_rx[FIFO_SIZE]; + uint8_t *elems_rx; + uint32_t rx_fifo_size; USART_TypeDef *uart; void (*callback)(struct uart_ring*); + bool dma_rx; } uart_ring; -void uart_init(USART_TypeDef *u, int baud); +#define UART_BUFFER(x, size_rx, size_tx, uart_ptr, callback_ptr, rx_dma) \ + uint8_t elems_rx_##x[size_rx]; \ + uint8_t elems_tx_##x[size_tx]; \ + uart_ring uart_ring_##x = { \ + .w_ptr_tx = 0, \ + .r_ptr_tx = 0, \ + .elems_tx = ((uint8_t *)&elems_tx_##x), \ + .tx_fifo_size = size_tx, \ + .w_ptr_rx = 0, \ + .r_ptr_rx = 0, \ + .elems_rx = ((uint8_t *)&elems_rx_##x), \ + .rx_fifo_size = size_rx, \ + .uart = uart_ptr, \ + .callback = callback_ptr, \ + .dma_rx = rx_dma \ + }; + + +// ***************************** Function prototypes ***************************** +void uart_init(uart_ring *q, int baud); bool getc(uart_ring *q, char *elem); bool putc(uart_ring *q, char elem); @@ -21,48 +46,35 @@ void puts(const char *a); void puth(unsigned int i); void hexdump(const void *a, int l); +void debug_ring_callback(uart_ring *ring); -// ***************************** serial port queues ***************************** +// ******************************** UART buffers ******************************** -// esp = USART1 -uart_ring esp_ring = { .w_ptr_tx = 0, .r_ptr_tx = 0, - .w_ptr_rx = 0, .r_ptr_rx = 0, - .uart = USART1, - .callback = NULL}; +// esp_gps = USART1 +UART_BUFFER(esp_gps, FIFO_SIZE_DMA, FIFO_SIZE_INT, USART1, NULL, true) // lin1, K-LINE = UART5 // lin2, L-LINE = USART3 -uart_ring lin1_ring = { .w_ptr_tx = 0, .r_ptr_tx = 0, - .w_ptr_rx = 0, .r_ptr_rx = 0, - .uart = UART5, - .callback = NULL}; -uart_ring lin2_ring = { .w_ptr_tx = 0, .r_ptr_tx = 0, - .w_ptr_rx = 0, .r_ptr_rx = 0, - .uart = USART3, - .callback = NULL}; +UART_BUFFER(lin1, FIFO_SIZE_INT, FIFO_SIZE_INT, UART5, NULL, false) +UART_BUFFER(lin2, FIFO_SIZE_INT, FIFO_SIZE_INT, USART3, NULL, false) // debug = USART2 -void debug_ring_callback(uart_ring *ring); -uart_ring debug_ring = { .w_ptr_tx = 0, .r_ptr_tx = 0, - .w_ptr_rx = 0, .r_ptr_rx = 0, - .uart = USART2, - .callback = debug_ring_callback}; - +UART_BUFFER(debug, FIFO_SIZE_INT, FIFO_SIZE_INT, USART2, debug_ring_callback, false) uart_ring *get_ring_by_number(int a) { uart_ring *ring = NULL; switch(a) { case 0: - ring = &debug_ring; + ring = &uart_ring_debug; break; case 1: - ring = &esp_ring; + ring = &uart_ring_esp_gps; break; case 2: - ring = &lin1_ring; + ring = &uart_ring_lin1; break; case 3: - ring = &lin2_ring; + ring = &uart_ring_lin2; break; default: ring = NULL; @@ -71,52 +83,219 @@ uart_ring *get_ring_by_number(int a) { return ring; } -// ***************************** serial port ***************************** +// ***************************** Interrupt handlers ***************************** -void uart_ring_process(uart_ring *q) { +void uart_tx_ring(uart_ring *q){ ENTER_CRITICAL(); - // TODO: check if external serial is connected - int sr = q->uart->SR; - + // Send out next byte of TX buffer if (q->w_ptr_tx != q->r_ptr_tx) { - if ((sr & USART_SR_TXE) != 0) { - q->uart->DR = q->elems_tx[q->r_ptr_tx]; - q->r_ptr_tx = (q->r_ptr_tx + 1U) % FIFO_SIZE; + // Only send if transmit register is empty (aka last byte has been sent) + if ((q->uart->SR & USART_SR_TXE) != 0) { + q->uart->DR = q->elems_tx[q->r_ptr_tx]; // This clears TXE + q->r_ptr_tx = (q->r_ptr_tx + 1U) % q->tx_fifo_size; + } + + // Enable TXE interrupt if there is still data to be sent + if(q->r_ptr_tx != q->w_ptr_tx){ + q->uart->CR1 |= USART_CR1_TXEIE; + } else { + q->uart->CR1 &= ~USART_CR1_TXEIE; } - // there could be more to send - q->uart->CR1 |= USART_CR1_TXEIE; - } else { - // nothing to send - q->uart->CR1 &= ~USART_CR1_TXEIE; } + EXIT_CRITICAL(); +} - if ((sr & USART_SR_RXNE) || (sr & USART_SR_ORE)) { - uint8_t c = q->uart->DR; // TODO: can drop packets - if (q != &esp_ring) { - uint16_t next_w_ptr = (q->w_ptr_rx + 1U) % FIFO_SIZE; - if (next_w_ptr != q->r_ptr_rx) { - q->elems_rx[q->w_ptr_rx] = c; - q->w_ptr_rx = next_w_ptr; - if (q->callback != NULL) { - q->callback(q); - } +void uart_rx_ring(uart_ring *q){ + // Do not read out directly if DMA enabled + if (q->dma_rx == false) { + ENTER_CRITICAL(); + + // Read out RX buffer + uint8_t c = q->uart->DR; // This read after reading SR clears a bunch of interrupts + + uint16_t next_w_ptr = (q->w_ptr_rx + 1U) % q->rx_fifo_size; + // Do not overwrite buffer data + if (next_w_ptr != q->r_ptr_rx) { + q->elems_rx[q->w_ptr_rx] = c; + q->w_ptr_rx = next_w_ptr; + if (q->callback != NULL) { + q->callback(q); } } + + EXIT_CRITICAL(); } +} + +// This function should be called on: +// * Half-transfer DMA interrupt +// * Full-transfer DMA interrupt +// * UART IDLE detection +uint32_t prev_w_index = 0; +void dma_pointer_handler(uart_ring *q, uint32_t dma_ndtr) { + ENTER_CRITICAL(); + uint32_t w_index = (q->rx_fifo_size - dma_ndtr); + + // Check for new data + if (w_index != prev_w_index){ + // Check for overflow + if ( + ((prev_w_index < q->r_ptr_rx) && (q->r_ptr_rx <= w_index)) || // No rollover + ((w_index < prev_w_index) && ((q->r_ptr_rx <= w_index) || (prev_w_index < q->r_ptr_rx))) // Rollover + ){ + // We lost data. Set the new read pointer to the oldest byte still available + q->r_ptr_rx = (w_index + 1U) % q->rx_fifo_size; + } + + // Set write pointer + q->w_ptr_rx = w_index; + } + + prev_w_index = w_index; + EXIT_CRITICAL(); +} + +// This read after reading SR clears all error interrupts. We don't want compiler warnings, nor optimizations +#define UART_READ_DR(uart) volatile uint8_t t = (uart)->DR; UNUSED(t); + +void uart_interrupt_handler(uart_ring *q) { + ENTER_CRITICAL(); + + // Read UART status. This is also the first step necessary in clearing most interrupts + uint32_t status = q->uart->SR; + + // If RXNE is set, perform a read. This clears RXNE, ORE, IDLE, NF and FE + if((status & USART_SR_RXNE) != 0U){ + uart_rx_ring(q); + } + + // Detect errors and clear them + uint32_t err = (status & USART_SR_ORE) | (status & USART_SR_NE) | (status & USART_SR_FE) | (status & USART_SR_PE); + if(err != 0U){ + #ifdef DEBUG_UART + puts("Encountered UART error: "); puth(err); puts("\n"); + #endif + UART_READ_DR(q->uart) + } + // Send if necessary + uart_tx_ring(q); + + // Run DMA pointer handler if the line is idle + if(q->dma_rx && (status & USART_SR_IDLE)){ + // Reset IDLE flag + UART_READ_DR(q->uart) + + if(q == &uart_ring_esp_gps){ + dma_pointer_handler(&uart_ring_esp_gps, DMA2_Stream5->NDTR); + } else { + #ifdef DEBUG_UART + puts("No IDLE dma_pointer_handler implemented for this UART."); + #endif + } + } + + EXIT_CRITICAL(); +} + +void USART1_IRQHandler(void) { uart_interrupt_handler(&uart_ring_esp_gps); } +void USART2_IRQHandler(void) { uart_interrupt_handler(&uart_ring_debug); } +void USART3_IRQHandler(void) { uart_interrupt_handler(&uart_ring_lin2); } +void UART5_IRQHandler(void) { uart_interrupt_handler(&uart_ring_lin1); } + +void DMA2_Stream5_IRQHandler(void) { + ENTER_CRITICAL(); + + // Handle errors + if((DMA2->HISR & DMA_HISR_TEIF5) || (DMA2->HISR & DMA_HISR_DMEIF5) || (DMA2->HISR & DMA_HISR_FEIF5)){ + #ifdef DEBUG_UART + puts("Encountered UART DMA error. Clearing and restarting DMA...\n"); + #endif + + // Clear flags + DMA2->HIFCR = DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5; - if ((sr & USART_SR_ORE) != 0) { - // set dropped packet flag? + // Re-enable the DMA if necessary + DMA2_Stream5->CR |= DMA_SxCR_EN; } + // Re-calculate write pointer and reset flags + dma_pointer_handler(&uart_ring_esp_gps, DMA2_Stream5->NDTR); + DMA2->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5; + EXIT_CRITICAL(); } -// interrupt boilerplate +// ***************************** Hardware setup ***************************** + +void dma_rx_init(uart_ring *q) { + // Initialization is UART-dependent + if(q == &uart_ring_esp_gps){ + // DMA2, stream 5, channel 4 + + // Disable FIFO mode (enable direct) + DMA2_Stream5->FCR &= ~DMA_SxFCR_DMDIS; + + // Setup addresses + DMA2_Stream5->PAR = (uint32_t)&(USART1->DR); // Source + DMA2_Stream5->M0AR = (uint32_t)q->elems_rx; // Destination + DMA2_Stream5->NDTR = q->rx_fifo_size; // Number of bytes to copy + + // Circular, Increment memory, byte size, periph -> memory, enable + // Transfer complete, half transfer, transfer error and direct mode error interrupt enable + DMA2_Stream5->CR = DMA_SxCR_CHSEL_2 | DMA_SxCR_MINC | DMA_SxCR_CIRC | DMA_SxCR_HTIE | DMA_SxCR_TCIE | DMA_SxCR_TEIE | DMA_SxCR_DMEIE | DMA_SxCR_EN; + + // Enable DMA receiver in UART + q->uart->CR3 |= USART_CR3_DMAR; + + // Enable UART IDLE interrupt + q->uart->CR1 |= USART_CR1_IDLEIE; + + // Enable interrupt + NVIC_EnableIRQ(DMA2_Stream5_IRQn); + } else { + puts("Tried to initialize RX DMA for an unsupported UART\n"); + } +} + +#define __DIV(_PCLK_, _BAUD_) (((_PCLK_) * 25U) / (4U * (_BAUD_))) +#define __DIVMANT(_PCLK_, _BAUD_) (__DIV((_PCLK_), (_BAUD_)) / 100U) +#define __DIVFRAQ(_PCLK_, _BAUD_) ((((__DIV((_PCLK_), (_BAUD_)) - (__DIVMANT((_PCLK_), (_BAUD_)) * 100U)) * 16U) + 50U) / 100U) +#define __USART_BRR(_PCLK_, _BAUD_) ((__DIVMANT((_PCLK_), (_BAUD_)) << 4) | (__DIVFRAQ((_PCLK_), (_BAUD_)) & 0x0FU)) + +void uart_set_baud(USART_TypeDef *u, unsigned int baud) { + if (u == USART1) { + // USART1 is on APB2 + u->BRR = __USART_BRR(48000000U, baud); + } else { + u->BRR = __USART_BRR(24000000U, baud); + } +} + +void uart_init(uart_ring *q, int baud) { + // Set baud and enable peripheral with TX and RX mode + uart_set_baud(q->uart, baud); + q->uart->CR1 = USART_CR1_UE | USART_CR1_TE | USART_CR1_RE; + + // Enable UART interrupts + if(q->uart == USART1){ + NVIC_EnableIRQ(USART1_IRQn); + } else if (q->uart == USART2){ + NVIC_EnableIRQ(USART2_IRQn); + } else if (q->uart == USART3){ + NVIC_EnableIRQ(USART3_IRQn); + } else if (q->uart == UART5){ + NVIC_EnableIRQ(UART5_IRQn); + } else { + // UART not used. Skip enabling interrupts + } + + // Initialise RX DMA if used + if(q->dma_rx){ + dma_rx_init(q); + } +} -void USART1_IRQHandler(void) { uart_ring_process(&esp_ring); } -void USART2_IRQHandler(void) { uart_ring_process(&debug_ring); } -void USART3_IRQHandler(void) { uart_ring_process(&lin2_ring); } -void UART5_IRQHandler(void) { uart_ring_process(&lin1_ring); } +// ************************* Low-level buffer functions ************************* bool getc(uart_ring *q, char *elem) { bool ret = false; @@ -124,7 +303,7 @@ bool getc(uart_ring *q, char *elem) { ENTER_CRITICAL(); if (q->w_ptr_rx != q->r_ptr_rx) { if (elem != NULL) *elem = q->elems_rx[q->r_ptr_rx]; - q->r_ptr_rx = (q->r_ptr_rx + 1U) % FIFO_SIZE; + q->r_ptr_rx = (q->r_ptr_rx + 1U) % q->rx_fifo_size; ret = true; } EXIT_CRITICAL(); @@ -137,7 +316,7 @@ bool injectc(uart_ring *q, char elem) { uint16_t next_w_ptr; ENTER_CRITICAL(); - next_w_ptr = (q->w_ptr_rx + 1U) % FIFO_SIZE; + next_w_ptr = (q->w_ptr_rx + 1U) % q->tx_fifo_size; if (next_w_ptr != q->r_ptr_rx) { q->elems_rx[q->w_ptr_rx] = elem; q->w_ptr_rx = next_w_ptr; @@ -153,7 +332,7 @@ bool putc(uart_ring *q, char elem) { uint16_t next_w_ptr; ENTER_CRITICAL(); - next_w_ptr = (q->w_ptr_tx + 1U) % FIFO_SIZE; + next_w_ptr = (q->w_ptr_tx + 1U) % q->tx_fifo_size; if (next_w_ptr != q->r_ptr_tx) { q->elems_tx[q->w_ptr_tx] = elem; q->w_ptr_tx = next_w_ptr; @@ -161,11 +340,13 @@ bool putc(uart_ring *q, char elem) { } EXIT_CRITICAL(); - uart_ring_process(q); + uart_tx_ring(q); return ret; } +// Seems dangerous to use (might lock CPU if called with interrupts disabled f.e.) +// TODO: Remove? Not used anyways void uart_flush(uart_ring *q) { while (q->w_ptr_tx != q->r_ptr_tx) { __WFI(); @@ -175,7 +356,7 @@ void uart_flush(uart_ring *q) { void uart_flush_sync(uart_ring *q) { // empty the TX buffer while (q->w_ptr_tx != q->r_ptr_tx) { - uart_ring_process(q); + uart_tx_ring(q); } } @@ -193,119 +374,15 @@ void clear_uart_buff(uart_ring *q) { EXIT_CRITICAL(); } -// ***************************** start UART code ***************************** - -#define __DIV(_PCLK_, _BAUD_) (((_PCLK_) * 25U) / (4U * (_BAUD_))) -#define __DIVMANT(_PCLK_, _BAUD_) (__DIV((_PCLK_), (_BAUD_)) / 100U) -#define __DIVFRAQ(_PCLK_, _BAUD_) ((((__DIV((_PCLK_), (_BAUD_)) - (__DIVMANT((_PCLK_), (_BAUD_)) * 100U)) * 16U) + 50U) / 100U) -#define __USART_BRR(_PCLK_, _BAUD_) ((__DIVMANT((_PCLK_), (_BAUD_)) << 4) | (__DIVFRAQ((_PCLK_), (_BAUD_)) & 0x0FU)) - -void uart_set_baud(USART_TypeDef *u, unsigned int baud) { - if (u == USART1) { - // USART1 is on APB2 - u->BRR = __USART_BRR(48000000U, baud); - } else { - u->BRR = __USART_BRR(24000000U, baud); - } -} - -#define USART1_DMA_LEN 0x20 -char usart1_dma[USART1_DMA_LEN]; - -void uart_dma_drain(void) { - uart_ring *q = &esp_ring; - - ENTER_CRITICAL(); - - if ((DMA2->HISR & DMA_HISR_TCIF5) || (DMA2->HISR & DMA_HISR_HTIF5) || (DMA2_Stream5->NDTR != USART1_DMA_LEN)) { - // disable DMA - q->uart->CR3 &= ~USART_CR3_DMAR; - DMA2_Stream5->CR &= ~DMA_SxCR_EN; - while ((DMA2_Stream5->CR & DMA_SxCR_EN) != 0); - - unsigned int i; - for (i = 0; i < (USART1_DMA_LEN - DMA2_Stream5->NDTR); i++) { - char c = usart1_dma[i]; - uint16_t next_w_ptr = (q->w_ptr_rx + 1U) % FIFO_SIZE; - if (next_w_ptr != q->r_ptr_rx) { - q->elems_rx[q->w_ptr_rx] = c; - q->w_ptr_rx = next_w_ptr; - } - } - - // reset DMA len - DMA2_Stream5->NDTR = USART1_DMA_LEN; - - // clear interrupts - DMA2->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5; - //DMA2->HIFCR = DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5; - - // enable DMA - DMA2_Stream5->CR |= DMA_SxCR_EN; - q->uart->CR3 |= USART_CR3_DMAR; - } - - EXIT_CRITICAL(); -} - -void DMA2_Stream5_IRQHandler(void) { - //set_led(LED_BLUE, 1); - uart_dma_drain(); - //set_led(LED_BLUE, 0); -} - -void uart_init(USART_TypeDef *u, int baud) { - // enable uart and tx+rx mode - u->CR1 = USART_CR1_UE; - uart_set_baud(u, baud); - - u->CR1 |= USART_CR1_TE | USART_CR1_RE; - //u->CR2 = USART_CR2_STOP_0 | USART_CR2_STOP_1; - //u->CR2 = USART_CR2_STOP_0; - // ** UART is ready to work ** - - // enable interrupts - if (u != USART1) { - u->CR1 |= USART_CR1_RXNEIE; - } - - if (u == USART1) { - // DMA2, stream 2, channel 3 - DMA2_Stream5->M0AR = (uint32_t)usart1_dma; - DMA2_Stream5->NDTR = USART1_DMA_LEN; - DMA2_Stream5->PAR = (uint32_t)&(USART1->DR); - - // channel4, increment memory, periph -> memory, enable - DMA2_Stream5->CR = DMA_SxCR_CHSEL_2 | DMA_SxCR_MINC | DMA_SxCR_HTIE | DMA_SxCR_TCIE | DMA_SxCR_EN; - - // this one uses DMA receiver - u->CR3 = USART_CR3_DMAR; - - NVIC_EnableIRQ(DMA2_Stream5_IRQn); - NVIC_EnableIRQ(USART1_IRQn); - } else if (u == USART2) { - NVIC_EnableIRQ(USART2_IRQn); - } else if (u == USART3) { - NVIC_EnableIRQ(USART3_IRQn); - } else if (u == UART5) { - NVIC_EnableIRQ(UART5_IRQn); - } else { - // USART type undefined, skip - } -} - +// ************************ High-level debug functions ********************** void putch(const char a) { if (has_external_debug_serial) { - /*while ((debug_ring.uart->SR & USART_SR_TXE) == 0); - debug_ring.uart->DR = a;*/ - // assuming debugging is important if there's external serial connected - while (!putc(&debug_ring, a)); + while (!putc(&uart_ring_debug, a)); - //putc(&debug_ring, a); } else { // misra-c2012-17.7: serial debug function, ok to ignore output - (void)injectc(&debug_ring, a); + (void)injectc(&uart_ring_debug, a); } } @@ -327,7 +404,7 @@ void putui(uint32_t i) { idx--; i_copy /= 10; } while (i_copy != 0U); - puts(str + idx + 1U); + puts(&str[idx + 1U]); } void puth(unsigned int i) { @@ -345,10 +422,12 @@ void puth2(unsigned int i) { } void hexdump(const void *a, int l) { - for (int i=0; i < l; i++) { - if ((i != 0) && ((i & 0xf) == 0)) puts("\n"); - puth2(((const unsigned char*)a)[i]); - puts(" "); + if (a != NULL) { + for (int i=0; i < l; i++) { + if ((i != 0) && ((i & 0xf) == 0)) puts("\n"); + puth2(((const unsigned char*)a)[i]); + puts(" "); + } } puts("\n"); } diff --git a/panda/board/drivers/usb.h b/panda/board/drivers/usb.h index e55906d89eb8a2..88455c71ca0b3a 100644 --- a/panda/board/drivers/usb.h +++ b/panda/board/drivers/usb.h @@ -439,7 +439,7 @@ void USB_WritePacket_EP0(uint8_t *src, uint16_t len) { USB_WritePacket(src, wplen, 0); if (wplen < len) { - ep0_txdata = src + wplen; + ep0_txdata = &src[wplen]; ep0_txlen = len - wplen; USBx_DEVICE->DIEPEMPMSK |= 1; } else { @@ -985,7 +985,7 @@ void usb_irqhandler(void) { if ((ep0_txlen != 0U) && ((USBx_INEP(0)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) >= 0x40U)) { uint16_t len = MIN(ep0_txlen, 0x40); USB_WritePacket(ep0_txdata, len, 0); - ep0_txdata += len; + ep0_txdata = &ep0_txdata[len]; ep0_txlen -= len; if (ep0_txlen == 0U) { ep0_txdata = NULL; diff --git a/panda/board/main.c b/panda/board/main.c index dcf6e668bd1b9b..df134e046baaad 100644 --- a/panda/board/main.c +++ b/panda/board/main.c @@ -1,4 +1,4 @@ -//#define EON +//#define EON //#define PANDA // ********************* Includes ********************* @@ -78,10 +78,14 @@ void started_interrupt_handler(uint8_t interrupt_line) { // jenky debounce delay(100000); - // set power savings mode here if on EON build #ifdef EON + // set power savings mode here if on EON build int power_save_state = current_board->check_ignition() ? POWER_SAVE_STATUS_DISABLED : POWER_SAVE_STATUS_ENABLED; set_power_save_state(power_save_state); + // set CDP usb power mode everytime that the car starts to make sure EON is charging + if (current_board->check_ignition()) { + current_board->set_usb_power_mode(USB_POWER_CDP); + } #endif } EXTI->PR = (1U << interrupt_line); @@ -134,7 +138,7 @@ void set_safety_mode(uint16_t mode, int16_t param) { } can_silent = ALL_CAN_LIVE; break; - } + } if (safety_ignition_hook() != -1) { // if the ignition hook depends on something other than the started GPIO // we have to disable power savings (fix for GM and Tesla) @@ -159,19 +163,10 @@ int get_health_pkt(void *dat) { uint8_t controls_allowed_pkt; uint8_t gas_interceptor_detected_pkt; uint8_t car_harness_status_pkt; + uint8_t usb_power_mode_pkt; } *health = dat; - //Voltage will be measured in mv. 5000 = 5V - uint32_t voltage = adc_get(ADCCHAN_VOLTAGE); - - // REVC has a 10, 1 (1/11) voltage divider - // Here is the calculation for the scale (s) - // ADCV = VIN_S * (1/11) * (4095/3.3) - // RETVAL = ADCV * s = VIN_S*1000 - // s = 1000/((4095/3.3)*(1/11)) = 8.8623046875 - - // Avoid needing floating point math - health->voltage_pkt = (voltage * 8862U) / 1000U; + health->voltage_pkt = adc_get_voltage(); // No current sense on panda black if(hw_type != HW_TYPE_BLACK_PANDA){ @@ -195,7 +190,8 @@ int get_health_pkt(void *dat) { health->can_fwd_errs_pkt = can_fwd_errs; health->gmlan_send_errs_pkt = gmlan_send_errs; health->car_harness_status_pkt = car_harness_status; - + health->usb_power_mode_pkt = usb_power_mode; + return sizeof(*health); } @@ -215,7 +211,7 @@ void usb_cb_ep2_out(void *usbdata, int len, bool hardwired) { uint8_t *usbdata8 = (uint8_t *)usbdata; uart_ring *ur = get_ring_by_number(usbdata8[0]); if ((len != 0) && (ur != NULL)) { - if ((usbdata8[0] < 2U) || safety_tx_lin_hook(usbdata8[0] - 2U, usbdata8 + 1, len - 1)) { + if ((usbdata8[0] < 2U) || safety_tx_lin_hook(usbdata8[0] - 2U, &usbdata8[1], len - 1)) { for (int i = 1; i < len; i++) { while (!putc(ur, usbdata8[i])) { // wait @@ -346,7 +342,7 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired) } else { // Disable OBD CAN current_board->set_can_mode(CAN_MODE_NORMAL); - } + } } else { if (setup->b.wValue.w == 1U) { // GMLAN ON @@ -362,7 +358,7 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired) } } break; - + // **** 0xdc: set safety mode case 0xdc: // Blocked over WiFi. @@ -403,9 +399,12 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired) if (!ur) { break; } - if (ur == &esp_ring) { - uart_dma_drain(); + + // TODO: Remove this again and fix boardd code to hande the message bursts instead of single chars + if (ur == &uart_ring_esp_gps) { + dma_pointer_handler(ur, DMA2_Stream5->NDTR); } + // read while ((resp_len < MIN(setup->b.wLength.w, MAX_RESP_LEN)) && getc(ur, (char*)&resp[resp_len])) { @@ -460,19 +459,7 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired) break; // **** 0xe6: set USB power case 0xe6: - if (setup->b.wValue.w == 0U) { - puts("user setting NONE mode\n"); - current_board->set_usb_power_mode(USB_POWER_NONE); - } else if (setup->b.wValue.w == 1U) { - puts("user setting CDP mode\n"); - current_board->set_usb_power_mode(USB_POWER_CDP); - } else if (setup->b.wValue.w == 2U) { - puts("user setting DCP mode\n"); - current_board->set_usb_power_mode(USB_POWER_DCP); - } else { - puts("user setting CLIENT mode\n"); - current_board->set_usb_power_mode(USB_POWER_CLIENT); - } + current_board->set_usb_power_mode(setup->b.wValue.w); break; // **** 0xf0: do k-line wValue pulse on uart2 for Acura case 0xf0: @@ -591,8 +578,8 @@ void __attribute__ ((noinline)) enable_fpu(void) { uint64_t tcnt = 0; // go into NOOUTPUT when the EON does not send a heartbeat for this amount of seconds. -#define EON_HEARTBEAT_THRESHOLD_IGNITION_ON 5U -#define EON_HEARTBEAT_THRESHOLD_IGNITION_OFF 2U +#define EON_HEARTBEAT_IGNITION_CNT_ON 5U +#define EON_HEARTBEAT_IGNITION_CNT_OFF 2U // called once per second // cppcheck-suppress unusedFunction ; used in headers not included in cppcheck @@ -629,9 +616,11 @@ void TIM3_IRQHandler(void) { // check heartbeat counter if we are running EON code. If the heartbeat has been gone for a while, go to NOOUTPUT safety mode. #ifdef EON - if (heartbeat_counter >= (current_board->check_ignition() ? EON_HEARTBEAT_THRESHOLD_IGNITION_ON : EON_HEARTBEAT_THRESHOLD_IGNITION_OFF)) { + if (heartbeat_counter >= (current_board->check_ignition() ? EON_HEARTBEAT_IGNITION_CNT_ON : EON_HEARTBEAT_IGNITION_CNT_OFF)) { puts("EON hasn't sent a heartbeat for 0x"); puth(heartbeat_counter); puts(" seconds. Safety is set to NOOUTPUT mode.\n"); - set_safety_mode(SAFETY_NOOUTPUT, 0U); + if(current_safety_mode != SAFETY_NOOUTPUT){ + set_safety_mode(SAFETY_NOOUTPUT, 0U); + } } #endif @@ -651,7 +640,7 @@ int main(void) { detect_configuration(); detect_board_type(); adc_init(); - + // print hello puts("\n\n\n************************ MAIN START ************************\n"); @@ -676,22 +665,22 @@ int main(void) { if (has_external_debug_serial) { // WEIRDNESS: without this gate around the UART, it would "crash", but only if the ESP is enabled // assuming it's because the lines were left floating and spurious noise was on them - uart_init(USART2, 115200); + uart_init(&uart_ring_debug, 115200); } if (board_has_gps()) { - uart_init(USART1, 9600); + uart_init(&uart_ring_esp_gps, 9600); } else { // enable ESP uart - uart_init(USART1, 115200); + uart_init(&uart_ring_esp_gps, 115200); } // there is no LIN on panda black if(hw_type != HW_TYPE_BLACK_PANDA){ // enable LIN - uart_init(UART5, 10400); + uart_init(&uart_ring_lin1, 10400); UART5->CR2 |= USART_CR2_LINEN; - uart_init(USART3, 10400); + uart_init(&uart_ring_lin2, 10400); USART3->CR2 |= USART_CR2_LINEN; } diff --git a/panda/board/obj/panda.bin.signed b/panda/board/obj/panda.bin.signed index a1e01931c65790..3a6b76e664ebc4 100644 Binary files a/panda/board/obj/panda.bin.signed and b/panda/board/obj/panda.bin.signed differ diff --git a/panda/board/pedal/main.c b/panda/board/pedal/main.c index b6cfa516440b7c..e7642f0c005635 100644 --- a/panda/board/pedal/main.c +++ b/panda/board/pedal/main.c @@ -84,9 +84,6 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired) if (!ur) { break; } - if (ur == &esp_ring) { - uart_dma_drain(); - } // read while ((resp_len < MIN(setup->b.wLength.w, MAX_RESP_LEN)) && getc(ur, (char*)&resp[resp_len])) { diff --git a/panda/board/safety.h b/panda/board/safety.h index e542dde8e93389..ffdfebb45472b5 100644 --- a/panda/board/safety.h +++ b/panda/board/safety.h @@ -16,6 +16,26 @@ #include "safety/safety_mazda.h" #include "safety/safety_elm327.h" +// from cereal.car.CarParams.SafetyModel +#define SAFETY_NOOUTPUT 0U +#define SAFETY_HONDA 1U +#define SAFETY_TOYOTA 2U +#define SAFETY_ELM327 3U +#define SAFETY_GM 4U +#define SAFETY_HONDA_BOSCH 5U +#define SAFETY_FORD 6U +#define SAFETY_CADILLAC 7U +#define SAFETY_HYUNDAI 8U +#define SAFETY_CHRYSLER 9U +#define SAFETY_TESLA 10U +#define SAFETY_SUBARU 11U +#define SAFETY_GM_PASSIVE 12U +#define SAFETY_MAZDA 13U +#define SAFETY_TOYOTA_IPAS 16U +#define SAFETY_ALLOUTPUT 17U +#define SAFETY_GM_ASCM 18U + +uint16_t current_safety_mode = SAFETY_NOOUTPUT; const safety_hooks *current_hooks = &nooutput_hooks; void safety_rx_hook(CAN_FIFOMailBox_TypeDef *to_push){ @@ -45,42 +65,24 @@ typedef struct { const safety_hooks *hooks; } safety_hook_config; -#define SAFETY_NOOUTPUT 0U -#define SAFETY_HONDA 1U -#define SAFETY_TOYOTA 2U -#define SAFETY_GM 3U -#define SAFETY_HONDA_BOSCH 4U -#define SAFETY_FORD 5U -#define SAFETY_CADILLAC 6U -#define SAFETY_HYUNDAI 7U -#define SAFETY_TESLA 8U -#define SAFETY_CHRYSLER 9U -#define SAFETY_SUBARU 10U -#define SAFETY_GM_PASSIVE 11U -#define SAFETY_MAZDA 12U -#define SAFETY_GM_ASCM 0x1334U -#define SAFETY_TOYOTA_IPAS 0x1335U -#define SAFETY_ALLOUTPUT 0x1337U -#define SAFETY_ELM327 0xE327U - const safety_hook_config safety_hook_registry[] = { {SAFETY_NOOUTPUT, &nooutput_hooks}, {SAFETY_HONDA, &honda_hooks}, - {SAFETY_HONDA_BOSCH, &honda_bosch_hooks}, {SAFETY_TOYOTA, &toyota_hooks}, + {SAFETY_ELM327, &elm327_hooks}, {SAFETY_GM, &gm_hooks}, + {SAFETY_HONDA_BOSCH, &honda_bosch_hooks}, {SAFETY_FORD, &ford_hooks}, {SAFETY_CADILLAC, &cadillac_hooks}, {SAFETY_HYUNDAI, &hyundai_hooks}, {SAFETY_CHRYSLER, &chrysler_hooks}, + {SAFETY_TESLA, &tesla_hooks}, {SAFETY_SUBARU, &subaru_hooks}, + {SAFETY_GM_PASSIVE, &gm_passive_hooks}, {SAFETY_MAZDA, &mazda_hooks}, {SAFETY_TOYOTA_IPAS, &toyota_ipas_hooks}, - {SAFETY_GM_PASSIVE, &gm_passive_hooks}, - {SAFETY_GM_ASCM, &gm_ascm_hooks}, - {SAFETY_TESLA, &tesla_hooks}, {SAFETY_ALLOUTPUT, &alloutput_hooks}, - {SAFETY_ELM327, &elm327_hooks}, + {SAFETY_GM_ASCM, &gm_ascm_hooks}, }; int safety_set_mode(uint16_t mode, int16_t param) { @@ -89,6 +91,7 @@ int safety_set_mode(uint16_t mode, int16_t param) { for (int i = 0; i < hook_config_count; i++) { if (safety_hook_registry[i].id == mode) { current_hooks = safety_hook_registry[i].hooks; + current_safety_mode = safety_hook_registry[i].id; set_status = 0; // set break; } diff --git a/panda/board/safety/safety_gm.h b/panda/board/safety/safety_gm.h index 3cef579249f5d0..ed8217fc025c86 100644 --- a/panda/board/safety/safety_gm.h +++ b/panda/board/safety/safety_gm.h @@ -204,7 +204,7 @@ static int gm_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { // GAS/REGEN: safety check if (addr == 715) { int gas_regen = ((GET_BYTE(to_send, 2) & 0x7FU) << 5) + ((GET_BYTE(to_send, 3) & 0xF8U) >> 3); - // Disabled message is !engaed with gas + // Disabled message is !engaged with gas // value that corresponds to max regen. if (!current_controls_allowed || !long_controls_allowed) { bool apply = GET_BYTE(to_send, 0) & 1U; diff --git a/panda/board/tools/enter_download_mode.py b/panda/board/tools/enter_download_mode.py index ff3cf84ca97aa3..3dd6545f4caffe 100755 --- a/panda/board/tools/enter_download_mode.py +++ b/panda/board/tools/enter_download_mode.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python -from __future__ import print_function +#!/usr/bin/env python3 + import sys import time diff --git a/panda/boardesp/Makefile b/panda/boardesp/Makefile index 0b8fe32b693ff5..c713a0061c9a61 100644 --- a/panda/boardesp/Makefile +++ b/panda/boardesp/Makefile @@ -50,7 +50,7 @@ user1.bin: obj/proxy.o obj/elm327.o obj/webserver.o obj/sha.o obj/rsa.o $(OBJCP) --only-section .data -O binary a.out eagle.app.v6.data.bin $(OBJCP) --only-section .rodata -O binary a.out eagle.app.v6.rodata.bin $(OBJCP) --only-section .irom0.text -O binary a.out eagle.app.v6.irom0text.bin - COMPILE=gcc python ./esp-open-sdk/ESP8266_NONOS_SDK_V1.5.4_16_05_20/tools/gen_appbin.py a.out 2 0 32 4 0 + COMPILE=gcc python2 ./esp-open-sdk/ESP8266_NONOS_SDK_V1.5.4_16_05_20/tools/gen_appbin.py a.out 2 0 32 4 0 rm -f eagle.app.v6.*.bin mv eagle.app.flash.bin $@ ../crypto/sign.py $@ $@ $(CERT) @@ -61,7 +61,7 @@ user2.bin: obj/proxy.o obj/elm327.o obj/webserver.o obj/sha.o obj/rsa.o $(OBJCP) --only-section .data -O binary a.out eagle.app.v6.data.bin $(OBJCP) --only-section .rodata -O binary a.out eagle.app.v6.rodata.bin $(OBJCP) --only-section .irom0.text -O binary a.out eagle.app.v6.irom0text.bin - COMPILE=gcc python ./esp-open-sdk/ESP8266_NONOS_SDK_V1.5.4_16_05_20/tools/gen_appbin.py a.out 2 0 32 4 0 + COMPILE=gcc python2 ./esp-open-sdk/ESP8266_NONOS_SDK_V1.5.4_16_05_20/tools/gen_appbin.py a.out 2 0 32 4 0 rm -f eagle.app.v6.*.bin mv eagle.app.flash.bin $@ ../crypto/sign.py $@ $@ $(CERT) diff --git a/panda/boardesp/elm327.c b/panda/boardesp/elm327.c index 58ac4c86386aa1..cec9fd836d8554 100644 --- a/panda/boardesp/elm327.c +++ b/panda/boardesp/elm327.c @@ -52,6 +52,8 @@ typedef struct __attribute__((packed)) { #define PANDA_USB_CAN_WRITE_BUS_NUM 3 #define PANDA_USB_LIN_WRITE_BUS_NUM 2 +#define SAFETY_ELM327 3U + typedef struct _elm_tcp_conn { struct espconn *conn; struct _elm_tcp_conn *next; @@ -1420,7 +1422,7 @@ static void ICACHE_FLASH_ATTR elm_process_at_cmd(char *cmd, uint16_t len) { elm_append_rsp_const("\r\r"); elm_append_rsp_const(IDENT_MSG); - panda_set_safety_mode(0xE327); + panda_set_safety_mode(SAFETY_ELM327); elm_proto_reinit(elm_current_proto()); return; diff --git a/panda/boardesp/get_sdk.sh b/panda/boardesp/get_sdk.sh index adccf678f9c6a9..b1e8bf2be85eda 100755 --- a/panda/boardesp/get_sdk.sh +++ b/panda/boardesp/get_sdk.sh @@ -8,5 +8,5 @@ sudo apt-get install libtool-bin git clone --recursive https://github.com/pfalcon/esp-open-sdk.git cd esp-open-sdk git checkout 03f5e898a059451ec5f3de30e7feff30455f7cec -LD_LIBRARY_PATH="" make STANDALONE=y - +cp ../python2_make.py . +python2 python2_make.py 'LD_LIBRARY_PATH="" make STANDALONE=y' diff --git a/panda/boardesp/get_sdk_ci.sh b/panda/boardesp/get_sdk_ci.sh index b11cb099a6eb5c..e95b7bd2624c6d 100755 --- a/panda/boardesp/get_sdk_ci.sh +++ b/panda/boardesp/get_sdk_ci.sh @@ -2,4 +2,5 @@ git clone --recursive https://github.com/pfalcon/esp-open-sdk.git cd esp-open-sdk git checkout 03f5e898a059451ec5f3de30e7feff30455f7cec -LD_LIBRARY_PATH="" make STANDALONE=y +cp ../python2_make.py . +python2 python2_make.py 'LD_LIBRARY_PATH="" make STANDALONE=y' diff --git a/panda/boardesp/get_sdk_mac.sh b/panda/boardesp/get_sdk_mac.sh index a8c2d709d45811..c2cfcd53b4d904 100755 --- a/panda/boardesp/get_sdk_mac.sh +++ b/panda/boardesp/get_sdk_mac.sh @@ -28,5 +28,5 @@ git checkout 03f5e898a059451ec5f3de30e7feff30455f7cec git submodule init git submodule update --recursive -make STANDALONE=y - +cp ../python2_make.py . +python2 python2_make.py 'make STANDALONE=y' diff --git a/panda/boardesp/python2_make.py b/panda/boardesp/python2_make.py new file mode 100644 index 00000000000000..85bee3457719bf --- /dev/null +++ b/panda/boardesp/python2_make.py @@ -0,0 +1,4 @@ +#!/usr/bin/env python2 +import os +import sys +os.system(sys.argv[1]) diff --git a/panda/crypto/getcertheader.py b/panda/crypto/getcertheader.py index 75d04e977ad8c1..b323cd101d81b3 100755 --- a/panda/crypto/getcertheader.py +++ b/panda/crypto/getcertheader.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import sys import struct from Crypto.PublicKey import RSA @@ -26,7 +26,7 @@ def to_c_uint32(x): nums = [] for i in range(0x20): nums.append(x%(2**32)) - x /= (2**32) + x //= (2**32) return "{"+'U,'.join(map(str, nums))+"U}" for fn in sys.argv[1:]: @@ -36,11 +36,11 @@ def to_c_uint32(x): cname = fn.split("/")[-1].split(".")[0] + "_rsa_key" - print 'RSAPublicKey '+cname+' = {.len = 0x20,' - print ' .n0inv = %dU,' % n0inv - print ' .n = %s,' % to_c_uint32(rsa.n) - print ' .rr = %s,' % to_c_uint32(rr) - print ' .exponent = %d,' % rsa.e - print '};' + print('RSAPublicKey '+cname+' = {.len = 0x20,') + print(' .n0inv = %dU,' % n0inv) + print(' .n = %s,' % to_c_uint32(rsa.n)) + print(' .rr = %s,' % to_c_uint32(rr)) + print(' .exponent = %d,' % rsa.e) + print('};') diff --git a/panda/crypto/sign.py b/panda/crypto/sign.py index 159299271e91e0..0f1ce030815b6d 100755 --- a/panda/crypto/sign.py +++ b/panda/crypto/sign.py @@ -1,16 +1,17 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import os import sys import struct import hashlib from Crypto.PublicKey import RSA +import binascii rsa = RSA.importKey(open(sys.argv[3]).read()) -with open(sys.argv[1]) as f: +with open(sys.argv[1], "rb") as f: dat = f.read() -print "signing", len(dat), "bytes" +print("signing", len(dat), "bytes") with open(sys.argv[2], "wb") as f: if os.getenv("SETLEN") is not None: @@ -20,10 +21,11 @@ else: x = dat dd = hashlib.sha1(dat).digest() - print "hash:",dd.encode("hex") - dd = "\x00\x01" + "\xff"*0x69 + "\x00" + dd - rsa_out = pow(int(dd.encode("hex"), 16), rsa.d, rsa.n) - sig = (hex(rsa_out)[2:-1].rjust(0x100, '0')).decode("hex") - x += sig + + print("hash:", str(binascii.hexlify(dd), "utf-8")) + dd = b"\x00\x01" + b"\xff"*0x69 + b"\x00" + dd + rsa_out = pow(int.from_bytes(dd, byteorder='big', signed=False), rsa.d, rsa.n) + sig = (hex(rsa_out)[2:].rjust(0x100, '0')) + x += binascii.unhexlify(sig) f.write(x) diff --git a/panda/drivers/linux/panda.c b/panda/drivers/linux/panda.c index 4c5980a9d2ff3c..3d4f957f9c5083 100644 --- a/panda/drivers/linux/panda.c +++ b/panda/drivers/linux/panda.c @@ -38,6 +38,9 @@ #define PANDA_DLC_MASK 0x0F +#define SAFETY_ALLOUTPUT 17 +#define SAFETY_NOOUTPUT 0 + struct panda_usb_ctx { struct panda_inf_priv *priv; u32 ndx; @@ -156,7 +159,7 @@ static int panda_set_output_enable(struct panda_inf_priv* priv, bool enable){ return usb_control_msg(priv->priv_dev->udev, usb_sndctrlpipe(priv->priv_dev->udev, 0), 0xDC, USB_TYPE_VENDOR | USB_RECIP_DEVICE, - enable ? 0x1337 : 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); + enable ? SAFETY_ALLOUTPUT : SAFETY_NOOUTPUT, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); } static void panda_usb_write_bulk_callback(struct urb *urb) diff --git a/panda/drivers/windows/panda_shared/panda.h b/panda/drivers/windows/panda_shared/panda.h index ade8fa36a8601e..8d98b08b71a405 100644 --- a/panda/drivers/windows/panda_shared/panda.h +++ b/panda/drivers/windows/panda_shared/panda.h @@ -40,7 +40,7 @@ namespace panda { typedef enum _PANDA_SAFETY_MODE : uint16_t { SAFETY_NOOUTPUT = 0, SAFETY_HONDA = 1, - SAFETY_ALLOUTPUT = 0x1337, + SAFETY_ALLOUTPUT = 17, } PANDA_SAFETY_MODE; typedef enum _PANDA_SERIAL_PORT : uint8_t { diff --git a/panda/examples/can_bit_transition.py b/panda/examples/can_bit_transition.py index 5c15e4bbc26eed..1cd72a6831cde5 100755 --- a/panda/examples/can_bit_transition.py +++ b/panda/examples/can_bit_transition.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import binascii import csv @@ -13,13 +13,13 @@ def __init__(self, message_id): def printBitDiff(self, other): """Prints bits that transition from always zero to always 1 and vice versa.""" - for i in xrange(len(self.ones)): + for i in range(len(self.ones)): zero_to_one = other.zeros[i] & self.ones[i] if zero_to_one: - print 'id %s 0 -> 1 at byte %d bitmask %d' % (self.message_id, i, zero_to_one) + print('id %s 0 -> 1 at byte %d bitmask %d' % (self.message_id, i, zero_to_one)) one_to_zero = other.ones[i] & self.zeros[i] if one_to_zero: - print 'id %s 1 -> 0 at byte %d bitmask %d' % (self.message_id, i, one_to_zero) + print('id %s 1 -> 0 at byte %d bitmask %d' % (self.message_id, i, one_to_zero)) class Info(): @@ -56,7 +56,7 @@ def load(self, filename, start, end): new_message = True message = self.messages[message_id] bytes = bytearray.fromhex(data) - for i in xrange(len(bytes)): + for i in range(len(bytes)): ones = int(bytes[i]) message.ones[i] = ones if new_message else message.ones[i] & ones # Inverts the data and masks it to a byte to get the zeros as ones. @@ -65,11 +65,11 @@ def load(self, filename, start, end): def PrintUnique(log_file, low_range, high_range): # find messages with bits that are always low - start, end = map(float, low_range.split('-')) + start, end = list(map(float, low_range.split('-'))) low = Info() low.load(log_file, start, end) # find messages with bits that are always high - start, end = map(float, high_range.split('-')) + start, end = list(map(float, high_range.split('-'))) high = Info() high.load(log_file, start, end) # print messages that go from low to high @@ -78,10 +78,10 @@ def PrintUnique(log_file, low_range, high_range): if message_id in low.messages: high.messages[message_id].printBitDiff(low.messages[message_id]) found = True - if not found: print 'No messages that transition from always low to always high found!' + if not found: print('No messages that transition from always low to always high found!') if __name__ == "__main__": if len(sys.argv) < 4: - print 'Usage:\n%s log.csv - -' % sys.argv[0] + print('Usage:\n%s log.csv - -' % sys.argv[0]) sys.exit(0) PrintUnique(sys.argv[1], sys.argv[2], sys.argv[3]) diff --git a/panda/examples/can_logger.py b/panda/examples/can_logger.py index 05c28a26df1228..203023dc92c106 100755 --- a/panda/examples/can_logger.py +++ b/panda/examples/can_logger.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python -from __future__ import print_function +#!/usr/bin/env python3 + import binascii import csv import sys diff --git a/panda/examples/can_unique.py b/panda/examples/can_unique.py index ad6de296ee4174..05f24a7d91d254 100755 --- a/panda/examples/can_unique.py +++ b/panda/examples/can_unique.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Given an interesting CSV file of CAN messages and a list of background CAN # messages, print which bits in the interesting file have never appeared @@ -28,15 +28,15 @@ def __init__(self, message_id): def printBitDiff(self, other): """Prints bits that are set or cleared compared to other background.""" - for i in xrange(len(self.ones)): + for i in range(len(self.ones)): new_ones = ((~other.ones[i]) & 0xff) & self.ones[i] if new_ones: - print 'id %s new one at byte %d bitmask %d' % ( - self.message_id, i, new_ones) + print('id %s new one at byte %d bitmask %d' % ( + self.message_id, i, new_ones)) new_zeros = ((~other.zeros[i]) & 0xff) & self.zeros[i] if new_zeros: - print 'id %s new zero at byte %d bitmask %d' % ( - self.message_id, i, new_zeros) + print('id %s new zero at byte %d bitmask %d' % ( + self.message_id, i, new_zeros)) class Info(): @@ -67,7 +67,7 @@ def load(self, filename): if data not in self.messages[message_id].data: message.data[data] = True bytes = bytearray.fromhex(data) - for i in xrange(len(bytes)): + for i in range(len(bytes)): message.ones[i] = message.ones[i] | int(bytes[i]) # Inverts the data and masks it to a byte to get the zeros as ones. message.zeros[i] = message.zeros[i] | ( (~int(bytes[i])) & 0xff) @@ -80,7 +80,7 @@ def PrintUnique(interesting_file, background_files): interesting.load(interesting_file) for message_id in sorted(interesting.messages): if message_id not in background.messages: - print 'New message_id: %s' % message_id + print('New message_id: %s' % message_id) else: interesting.messages[message_id].printBitDiff( background.messages[message_id]) @@ -88,6 +88,6 @@ def PrintUnique(interesting_file, background_files): if __name__ == "__main__": if len(sys.argv) < 3: - print 'Usage:\n%s interesting.csv background*.csv' % sys.argv[0] + print('Usage:\n%s interesting.csv background*.csv' % sys.argv[0]) sys.exit(0) PrintUnique(sys.argv[1], sys.argv[2:]) diff --git a/panda/examples/get_panda_password.py b/panda/examples/get_panda_password.py index 575cbb0795b6c4..13dacf25340c4b 100644 --- a/panda/examples/get_panda_password.py +++ b/panda/examples/get_panda_password.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 from panda import Panda def get_panda_password(): @@ -17,4 +17,4 @@ def get_panda_password(): print("Password: " + wifi[1]) if __name__ == "__main__": - get_panda_password() \ No newline at end of file + get_panda_password() diff --git a/panda/examples/query_vin_and_stats.py b/panda/examples/query_vin_and_stats.py index f3d6c198aff9f1..9a0df78ec1d05a 100755 --- a/panda/examples/query_vin_and_stats.py +++ b/panda/examples/query_vin_and_stats.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import time import struct from panda import Panda @@ -36,15 +36,15 @@ def get_supported_pids(): isotp_send(panda, "\x09\x02", 0x7df) ret = isotp_recv(panda, 0x7e8) hexdump(ret) - print "VIN: %s" % ret[2:] + print("VIN: %s" % ret[2:]) # 03 = get DTCS isotp_send(panda, "\x03", 0x7e0) dtcs = isotp_recv(panda, 0x7e8) - print "DTCs:", dtcs[2:].encode("hex") + print("DTCs:", dtcs[2:].encode("hex")) supported_pids = get_supported_pids() - print "Supported PIDs:",supported_pids + print("Supported PIDs:",supported_pids) while 1: speed = struct.unpack(">B", get_current_data_for_pid(13)[2:])[0] # kph @@ -52,7 +52,7 @@ def get_supported_pids(): throttle = struct.unpack(">B", get_current_data_for_pid(17)[2:])[0]/255.0 * 100 # percent temp = struct.unpack(">B", get_current_data_for_pid(5)[2:])[0] - 40 # degrees C load = struct.unpack(">B", get_current_data_for_pid(4)[2:])[0]/255.0 * 100 # percent - print "%d KPH, %d RPM, %.1f%% Throttle, %d deg C, %.1f%% load" % (speed, rpm, throttle, temp, load) + print("%d KPH, %d RPM, %.1f%% Throttle, %d deg C, %.1f%% load" % (speed, rpm, throttle, temp, load)) time.sleep(0.2) diff --git a/panda/examples/tesla_tester.py b/panda/examples/tesla_tester.py index 4365e424bb9911..74f19f25528da7 100644 --- a/panda/examples/tesla_tester.py +++ b/panda/examples/tesla_tester.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import sys import binascii from panda import Panda diff --git a/panda/python/__init__.py b/panda/python/__init__.py index 573d6f159a3c9d..565770918a61e9 100644 --- a/panda/python/__init__.py +++ b/panda/python/__init__.py @@ -1,5 +1,5 @@ # python library to interface with panda -from __future__ import print_function + import binascii import struct import hashlib @@ -9,12 +9,12 @@ import time import traceback import subprocess -from dfu import PandaDFU -from esptool import ESPROM, CesantaFlasher -from flash_release import flash_release -from update import ensure_st_up_to_date -from serial import PandaSerial -from isotp import isotp_send, isotp_recv +from .dfu import PandaDFU +from .esptool import ESPROM, CesantaFlasher +from .flash_release import flash_release +from .update import ensure_st_up_to_date +from .serial import PandaSerial +from .isotp import isotp_send, isotp_recv __version__ = '0.0.9' @@ -23,7 +23,6 @@ DEBUG = os.getenv("PANDADEBUG") is not None # *** wifi mode *** - def build_st(target, mkfile="Makefile"): from panda import BASEDIR cmd = 'cd %s && make -f %s clean && make -f %s %s >/dev/null' % (os.path.join(BASEDIR, "board"), mkfile, mkfile, target) @@ -46,7 +45,7 @@ def parse_can_buffer(dat): address = f1 >> 21 dddat = ddat[8:8+(f2&0xF)] if DEBUG: - print(" R %x: %s" % (address, str(dddat).encode("hex"))) + print(" R %x: %s" % (address, binascii.hexlify(dddat))) ret.append((address, f2>>16, dddat, (f2>>4)&0xFF)) return ret @@ -109,20 +108,25 @@ def close(self): # *** normal mode *** class Panda(object): + + # matches cereal.car.CarParams.SafetyModel SAFETY_NOOUTPUT = 0 SAFETY_HONDA = 1 SAFETY_TOYOTA = 2 - SAFETY_GM = 3 - SAFETY_HONDA_BOSCH = 4 - SAFETY_FORD = 5 - SAFETY_CADILLAC = 6 - SAFETY_HYUNDAI = 7 - SAFETY_TESLA = 8 + SAFETY_ELM327 = 3 + SAFETY_GM = 4 + SAFETY_HONDA_BOSCH = 5 + SAFETY_FORD = 6 + SAFETY_CADILLAC = 7 + SAFETY_HYUNDAI = 8 SAFETY_CHRYSLER = 9 - SAFETY_TOYOTA_IPAS = 0x1335 - SAFETY_TOYOTA_NOLIMITS = 0x1336 - SAFETY_ALLOUTPUT = 0x1337 - SAFETY_ELM327 = 0xE327 + SAFETY_TESLA = 10 + SAFETY_SUBARU = 11 + SAFETY_GM_PASSIVE = 12 + SAFETY_MAZDA = 13 + SAFETY_TOYOTA_IPAS = 16 + SAFETY_ALLOUTPUT = 17 + SAFETY_GM_ASCM = 18 SERIAL_DEBUG = 0 SERIAL_ESP = 1 @@ -135,11 +139,11 @@ class Panda(object): REQUEST_IN = usb1.ENDPOINT_IN | usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE REQUEST_OUT = usb1.ENDPOINT_OUT | usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE - HW_TYPE_UNKNOWN = '\x00' - HW_TYPE_WHITE_PANDA = '\x01' - HW_TYPE_GREY_PANDA = '\x02' - HW_TYPE_BLACK_PANDA = '\x03' - HW_TYPE_PEDAL = '\x04' + HW_TYPE_UNKNOWN = b'\x00' + HW_TYPE_WHITE_PANDA = b'\x01' + HW_TYPE_GREY_PANDA = b'\x02' + HW_TYPE_BLACK_PANDA = b'\x03' + HW_TYPE_PEDAL = b'\x04' def __init__(self, serial=None, claim=True): self._serial = serial @@ -232,7 +236,7 @@ def reconnect(self): def flash_static(handle, code): # confirm flasher is present fr = handle.controlRead(Panda.REQUEST_IN, 0xb0, 0, 0, 0xc) - assert fr[4:8] == "\xde\xad\xd0\x0d" + assert fr[4:8] == b"\xde\xad\xd0\x0d" # unlock flash print("flash: unlocking") @@ -274,7 +278,7 @@ def flash(self, fn=None, code=None, reconnect=True): fn = os.path.join(BASEDIR, "board", fn) if code is None: - with open(fn) as f: + with open(fn, "rb") as f: code = f.read() # get version @@ -364,7 +368,7 @@ def enter_bootloader(self): pass def get_version(self): - return self._handle.controlRead(Panda.REQUEST_IN, 0xd6, 0, 0, 0x40) + return self._handle.controlRead(Panda.REQUEST_IN, 0xd6, 0, 0, 0x40).decode('utf8') def get_type(self): return self._handle.controlRead(Panda.REQUEST_IN, 0xc1, 0, 0, 0x40) @@ -429,7 +433,7 @@ def set_can_speed_kbps(self, bus, speed): self._handle.controlWrite(Panda.REQUEST_OUT, 0xde, bus, int(speed*10), b'') def set_uart_baud(self, uart, rate): - self._handle.controlWrite(Panda.REQUEST_OUT, 0xe4, uart, rate/300, b'') + self._handle.controlWrite(Panda.REQUEST_OUT, 0xe4, uart, int(rate/300), b'') def set_uart_parity(self, uart, parity): # parity, 0=off, 1=even, 2=odd @@ -447,7 +451,7 @@ def can_send_many(self, arr): for addr, _, dat, bus in arr: assert len(dat) <= 8 if DEBUG: - print(" W %x: %s" % (addr, dat.encode("hex"))) + print(" W %x: %s" % (addr, binascii.hexlify(dat))) if addr >= 0x800: rir = (addr << 3) | transmit | extended else: @@ -479,7 +483,7 @@ def can_recv(self): break except (usb1.USBErrorIO, usb1.USBErrorOverflow): print("CAN: BAD RECV, RETRYING") - time.sleep(0.1) + time.sleep(0.1) return parse_can_buffer(dat) def can_clear(self, bus): @@ -546,7 +550,7 @@ def kline_drain(self, bus=2): if len(ret) == 0: break elif DEBUG: - print("kline drain: "+str(ret).encode("hex")) + print("kline drain: " + binascii.hexlify(ret)) bret += ret return bytes(bret) @@ -555,7 +559,7 @@ def kline_ll_recv(self, cnt, bus=2): while len(echo) != cnt: ret = str(self._handle.controlRead(Panda.REQUEST_OUT, 0xe0, bus, 0, cnt-len(echo))) if DEBUG and len(ret) > 0: - print("kline recv: "+ret.encode("hex")) + print("kline recv: " + binascii.hexlify(ret)) echo += ret return str(echo) @@ -572,7 +576,7 @@ def get_checksum(dat): for i in range(0, len(x), 0xf): ts = x[i:i+0xf] if DEBUG: - print("kline send: "+ts.encode("hex")) + print("kline send: " + binascii.hexlify(ts)) self._handle.bulkWrite(2, chr(bus).encode()+ts) echo = self.kline_ll_recv(len(ts), bus=bus) if echo != ts: diff --git a/panda/python/dfu.py b/panda/python/dfu.py index 02deed47bbe2ec..bbab812b0709ea 100644 --- a/panda/python/dfu.py +++ b/panda/python/dfu.py @@ -1,8 +1,9 @@ -from __future__ import print_function + import os import usb1 import struct import time +import binascii # *** DFU mode *** @@ -46,28 +47,27 @@ def list(): def st_serial_to_dfu_serial(st): if st == None or st == "none": return None - uid_base = struct.unpack("H"*6, st.decode("hex")) - return struct.pack("!HHH", uid_base[1] + uid_base[5], uid_base[0] + uid_base[4] + 0xA, uid_base[3]).encode("hex").upper() - + uid_base = struct.unpack("H"*6, bytes.fromhex(st)) + return binascii.hexlify(struct.pack("!HHH", uid_base[1] + uid_base[5], uid_base[0] + uid_base[4] + 0xA, uid_base[3])).upper().decode("utf-8") def status(self): while 1: - dat = str(self._handle.controlRead(0x21, DFU_GETSTATUS, 0, 0, 6)) - if dat[1] == "\x00": + dat = self._handle.controlRead(0x21, DFU_GETSTATUS, 0, 0, 6) + if dat[1] == 0: break def clear_status(self): # Clear status - stat = str(self._handle.controlRead(0x21, DFU_GETSTATUS, 0, 0, 6)) - if stat[4] == "\x0a": + stat = self._handle.controlRead(0x21, DFU_GETSTATUS, 0, 0, 6) + if stat[4] == 0xa: self._handle.controlRead(0x21, DFU_CLRSTATUS, 0, 0, 0) - elif stat[4] == "\x09": - self._handle.controlWrite(0x21, DFU_ABORT, 0, 0, "") + elif stat[4] == 0x9: + self._handle.controlWrite(0x21, DFU_ABORT, 0, 0, b"") self.status() stat = str(self._handle.controlRead(0x21, DFU_GETSTATUS, 0, 0, 6)) def erase(self, address): - self._handle.controlWrite(0x21, DFU_DNLOAD, 0, 0, "\x41" + struct.pack("I", address)) + self._handle.controlWrite(0x21, DFU_DNLOAD, 0, 0, b"\x41" + struct.pack("I", address)) self.status() def program(self, address, dat, block_size=None): @@ -75,12 +75,12 @@ def program(self, address, dat, block_size=None): block_size = len(dat) # Set Address Pointer - self._handle.controlWrite(0x21, DFU_DNLOAD, 0, 0, "\x21" + struct.pack("I", address)) + self._handle.controlWrite(0x21, DFU_DNLOAD, 0, 0, b"\x21" + struct.pack("I", address)) self.status() # Program - dat += "\xFF"*((block_size-len(dat)) % block_size) - for i in range(0, len(dat)/block_size): + dat += b"\xFF"*((block_size-len(dat)) % block_size) + for i in range(0, len(dat)//block_size): ldat = dat[i*block_size:(i+1)*block_size] print("programming %d with length %d" % (i, len(ldat))) self._handle.controlWrite(0x21, DFU_DNLOAD, 2+i, 0, ldat) @@ -105,17 +105,17 @@ def recover(self): build_st(fn) fn = os.path.join(BASEDIR, "board", fn) - with open(fn) as f: + with open(fn, "rb") as f: code = f.read() self.program_bootstub(code) def reset(self): # **** Reset **** - self._handle.controlWrite(0x21, DFU_DNLOAD, 0, 0, "\x21" + struct.pack("I", 0x8000000)) + self._handle.controlWrite(0x21, DFU_DNLOAD, 0, 0, b"\x21" + struct.pack("I", 0x8000000)) self.status() try: - self._handle.controlWrite(0x21, DFU_DNLOAD, 2, 0, "") + self._handle.controlWrite(0x21, DFU_DNLOAD, 2, 0, b"") stat = str(self._handle.controlRead(0x21, DFU_GETSTATUS, 0, 0, 6)) except Exception: pass diff --git a/panda/python/esptool.py b/panda/python/esptool.py index 970aa3d4d83fd5..941c3557c8a00c 100755 --- a/panda/python/esptool.py +++ b/panda/python/esptool.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# NB: Before sending a PR to change the above line to '#!/usr/bin/env python2', please read https://github.com/themadinventor/esptool/issues/21 +# NB: Before sending a PR to change the above line to '#!/usr/bin/env python3', please read https://github.com/themadinventor/esptool/issues/21 # # ESP8266 ROM Bootloader Utility # https://github.com/themadinventor/esptool @@ -48,7 +48,7 @@ def baudrate(self): @baudrate.setter def baudrate(self, x): - print "set baud to", x + print("set baud to", x) self.panda.set_uart_baud(1, x) def write(self, buf): @@ -114,7 +114,7 @@ def __init__(self, port=None, baud=ESP_ROM_BAUD): """ Read a SLIP packet from the serial port """ def read(self): - return self._slip_reader.next() + return next(self._slip_reader) """ Write bytes to the serial port while performing SLIP escaping """ def write(self, packet): @@ -140,7 +140,7 @@ def command(self, op=None, data=None, chk=0): # same operation as the request or a retries limit has # exceeded. This is needed for some esp8266s that # reply with more sync responses than expected. - for retry in xrange(100): + for retry in range(100): p = self.read() if len(p) < 8: continue @@ -156,14 +156,14 @@ def command(self, op=None, data=None, chk=0): """ Perform a connection test """ def sync(self): self.command(ESPROM.ESP_SYNC, '\x07\x07\x12\x20' + 32 * '\x55') - for i in xrange(7): + for i in range(7): self.command() """ Try connecting repeatedly until successful, or giving up """ def connect(self): - print 'Connecting...' + print('Connecting...') - for _ in xrange(4): + for _ in range(4): # issue reset-to-bootloader: # RTS = either CH_PD or nRESET (both active low = chip in reset) # DTR = GPIO0 (active low = boot to flasher) @@ -180,7 +180,7 @@ def connect(self): # worst-case latency timer should be 255ms (probably <20ms) self._port.timeout = 0.3 - for _ in xrange(4): + for _ in range(4): try: self._port.flushInput() self._slip_reader = slip_reader(self._port) @@ -250,7 +250,7 @@ def flash_begin(self, size, offset): result = self.command(ESPROM.ESP_FLASH_BEGIN, struct.pack(' 16: raise FatalError('Invalid firmware image magic=%d segments=%d' % (magic, segments)) - for i in xrange(segments): + for i in range(segments): self.load_segment(load_file) self.checksum = self.read_checksum(load_file) @@ -480,7 +480,7 @@ def __init__(self, load_file=None): raise FatalError('Invalid V2 image magic=%d' % (magic)) if segments != 4: # segment count is not really segment count here, but we expect to see '4' - print 'Warning: V2 header has unexpected "segment" count %d (usually 4)' % segments + print('Warning: V2 header has unexpected "segment" count %d (usually 4)' % segments) # irom segment comes before the second header self.load_segment(load_file, True) @@ -501,7 +501,7 @@ def __init__(self, load_file=None): raise FatalError('Invalid V2 second header magic=%d segments=%d' % (magic, segments)) # load all the usual segments - for _ in xrange(segments): + for _ in range(segments): self.load_segment(load_file) self.checksum = self.read_checksum(load_file) @@ -543,13 +543,13 @@ def _fetch_symbols(self): tool_nm = "xt-nm" proc = subprocess.Popen([tool_nm, self.name], stdout=subprocess.PIPE) except OSError: - print "Error calling %s, do you have Xtensa toolchain in PATH?" % tool_nm + print("Error calling %s, do you have Xtensa toolchain in PATH?" % tool_nm) sys.exit(1) for l in proc.stdout: fields = l.strip().split() try: if fields[0] == "U": - print "Warning: ELF binary has undefined symbol %s" % fields[1] + print("Warning: ELF binary has undefined symbol %s" % fields[1]) continue if fields[0] == "w": continue # can skip weak symbols @@ -568,7 +568,7 @@ def get_entry_point(self): try: proc = subprocess.Popen([tool_readelf, "-h", self.name], stdout=subprocess.PIPE) except OSError: - print "Error calling %s, do you have Xtensa toolchain in PATH?" % tool_readelf + print("Error calling %s, do you have Xtensa toolchain in PATH?" % tool_readelf) sys.exit(1) for l in proc.stdout: fields = l.strip().split() @@ -599,7 +599,7 @@ class CesantaFlasher(object): CMD_BOOT_FW = 6 def __init__(self, esp, baud_rate=0): - print 'Running Cesanta flasher stub...' + print('Running Cesanta flasher stub...') if baud_rate <= ESPROM.ESP_ROM_BAUD: # don't change baud rates if we already synced at that rate baud_rate = 0 self._esp = esp @@ -640,7 +640,7 @@ def flash_write(self, addr, data, show_progress=False): raise FatalError('Expected digest, got: %s' % hexify(p)) digest = hexify(p).upper() expected_digest = hashlib.md5(data).hexdigest().upper() - print + print() if digest != expected_digest: raise FatalError('Digest mismatch: expected %s, got %s' % (expected_digest, digest)) p = self._esp.read() @@ -679,7 +679,7 @@ def flash_read(self, addr, length, show_progress=False): raise FatalError('Expected digest, got: %s' % hexify(p)) expected_digest = hexify(p).upper() digest = hashlib.md5(data).hexdigest().upper() - print + print() if digest != expected_digest: raise FatalError('Digest mismatch: expected %s, got %s' % (expected_digest, digest)) p = self._esp.read() @@ -791,7 +791,7 @@ def binutils_safe_path(p): try: return subprocess.check_output(["cygpath", "-w", p]).rstrip('\n') except subprocess.CalledProcessError: - print "WARNING: Failed to call cygpath to sanitise Cygwin path." + print("WARNING: Failed to call cygpath to sanitise Cygwin path.") return p @@ -837,9 +837,9 @@ def WithResult(message, result): def load_ram(esp, args): image = LoadFirmwareImage(args.filename) - print 'RAM boot...' + print('RAM boot...') for (offset, size, data) in image.segments: - print 'Downloading %d bytes at %08x...' % (size, offset), + print('Downloading %d bytes at %08x...' % (size, offset), end=' ') sys.stdout.flush() esp.mem_begin(size, div_roundup(size, esp.ESP_RAM_BLOCK), esp.ESP_RAM_BLOCK, offset) @@ -848,31 +848,31 @@ def load_ram(esp, args): esp.mem_block(data[0:esp.ESP_RAM_BLOCK], seq) data = data[esp.ESP_RAM_BLOCK:] seq += 1 - print 'done!' + print('done!') - print 'All segments done, executing at %08x' % image.entrypoint + print('All segments done, executing at %08x' % image.entrypoint) esp.mem_finish(image.entrypoint) def read_mem(esp, args): - print '0x%08x = 0x%08x' % (args.address, esp.read_reg(args.address)) + print('0x%08x = 0x%08x' % (args.address, esp.read_reg(args.address))) def write_mem(esp, args): esp.write_reg(args.address, args.value, args.mask, 0) - print 'Wrote %08x, mask %08x to %08x' % (args.value, args.mask, args.address) + print('Wrote %08x, mask %08x to %08x' % (args.value, args.mask, args.address)) def dump_mem(esp, args): f = file(args.filename, 'wb') - for i in xrange(args.size / 4): + for i in range(args.size / 4): d = esp.read_reg(args.address + (i * 4)) f.write(struct.pack('> 16 args.flash_size = {18: '2m', 19: '4m', 20: '8m', 21: '16m', 22: '32m'}.get(size_id) if args.flash_size is None: - print 'Warning: Could not auto-detect Flash size (FlashID=0x%x, SizeID=0x%x), defaulting to 4m' % (flash_id, size_id) + print('Warning: Could not auto-detect Flash size (FlashID=0x%x, SizeID=0x%x), defaulting to 4m' % (flash_id, size_id)) args.flash_size = '4m' else: - print 'Auto-detected Flash size:', args.flash_size + print('Auto-detected Flash size:', args.flash_size) def write_flash(esp, args): @@ -900,10 +900,10 @@ def write_flash(esp, args): image = argfile.read() argfile.seek(0) # rewind in case we need it again if address + len(image) > int(args.flash_size.split('m')[0]) * (1 << 17): - print 'WARNING: Unlikely to work as data goes beyond end of flash. Hint: Use --flash_size' + print('WARNING: Unlikely to work as data goes beyond end of flash. Hint: Use --flash_size') # Fix sflash config data. if address == 0 and image[0] == '\xe9': - print 'Flash params set to 0x%02x%02x' % (flash_mode, flash_size_freq) + print('Flash params set to 0x%02x%02x' % (flash_mode, flash_size_freq)) image = image[0:2] + flash_params + image[4:] # Pad to sector size, which is the minimum unit of writing (erasing really). if len(image) % esp.ESP_FLASH_SECTOR != 0: @@ -911,11 +911,11 @@ def write_flash(esp, args): t = time.time() flasher.flash_write(address, image, not args.no_progress) t = time.time() - t - print ('\rWrote %d bytes at 0x%x in %.1f seconds (%.1f kbit/s)...' + print('\rWrote %d bytes at 0x%x in %.1f seconds (%.1f kbit/s)...' % (len(image), address, t, len(image) / t * 8 / 1000)) - print 'Leaving...' + print('Leaving...') if args.verify: - print 'Verifying just-written flash...' + print('Verifying just-written flash...') _verify_flash(flasher, args, flash_params) flasher.boot_fw() @@ -923,18 +923,18 @@ def write_flash(esp, args): def image_info(args): image = LoadFirmwareImage(args.filename) print('Image version: %d' % image.version) - print('Entry point: %08x' % image.entrypoint) if image.entrypoint != 0 else 'Entry point not set' - print '%d segments' % len(image.segments) - print + print(('Entry point: %08x' % image.entrypoint) if image.entrypoint != 0 else 'Entry point not set') + print('%d segments' % len(image.segments)) + print() checksum = ESPROM.ESP_CHECKSUM_MAGIC for (idx, (offset, size, data)) in enumerate(image.segments): if image.version == 2 and idx == 0: - print 'Segment 1: %d bytes IROM0 (no load address)' % size + print('Segment 1: %d bytes IROM0 (no load address)' % size) else: - print 'Segment %d: %5d bytes at %08x' % (idx + 1, size, offset) + print('Segment %d: %5d bytes at %08x' % (idx + 1, size, offset)) checksum = ESPROM.checksum(data, checksum) - print - print 'Checksum: %02x (%s)' % (image.checksum, 'valid' if image.checksum == checksum else 'invalid!') + print() + print('Checksum: %02x (%s)' % (image.checksum, 'valid' if image.checksum == checksum else 'invalid!')) def make_image(args): @@ -979,7 +979,7 @@ def elf2image(args): if irom_offs < 0: raise FatalError('Address of symbol _irom0_text_start in ELF is located before flash mapping address. Bad linker script?') if (irom_offs & 0xFFF) != 0: # irom0 isn't flash sector aligned - print "WARNING: irom0 section offset is 0x%08x. ELF is probably linked for 'elf2image --version=2'" % irom_offs + print("WARNING: irom0 section offset is 0x%08x. ELF is probably linked for 'elf2image --version=2'" % irom_offs) with open(args.output + "0x%05x.bin" % irom_offs, "wb") as f: f.write(data) f.close() @@ -991,21 +991,21 @@ def elf2image(args): def read_mac(esp, args): mac = esp.read_mac() - print 'MAC: %s' % ':'.join(map(lambda x: '%02x' % x, mac)) + print('MAC: %s' % ':'.join(['%02x' % x for x in mac])) def chip_id(esp, args): chipid = esp.chip_id() - print 'Chip ID: 0x%08x' % chipid + print('Chip ID: 0x%08x' % chipid) def erase_flash(esp, args): flasher = CesantaFlasher(esp, args.baud) - print 'Erasing flash (this may take a while)...' + print('Erasing flash (this may take a while)...') t = time.time() flasher.flash_erase_chip() t = time.time() - t - print 'Erase took %.1f seconds' % t + print('Erase took %.1f seconds' % t) def run(esp, args): @@ -1015,8 +1015,8 @@ def run(esp, args): def flash_id(esp, args): flash_id = esp.flash_id() esp.flash_finish(False) - print 'Manufacturer: %02x' % (flash_id & 0xff) - print 'Device: %02x%02x' % ((flash_id >> 8) & 0xff, (flash_id >> 16) & 0xff) + print('Manufacturer: %02x' % (flash_id & 0xff)) + print('Device: %02x%02x' % ((flash_id >> 8) & 0xff, (flash_id >> 16) & 0xff)) def read_flash(esp, args): @@ -1024,7 +1024,7 @@ def read_flash(esp, args): t = time.time() data = flasher.flash_read(args.address, args.size, not args.no_progress) t = time.time() - t - print ('\rRead %d bytes at 0x%x in %.1f seconds (%.1f kbit/s)...' + print('\rRead %d bytes at 0x%x in %.1f seconds (%.1f kbit/s)...' % (len(data), args.address, t, len(data) / t * 8 / 1000)) file(args.filename, 'wb').write(data) @@ -1037,26 +1037,26 @@ def _verify_flash(flasher, args, flash_params=None): if address == 0 and image[0] == '\xe9' and flash_params is not None: image = image[0:2] + flash_params + image[4:] image_size = len(image) - print 'Verifying 0x%x (%d) bytes @ 0x%08x in flash against %s...' % (image_size, image_size, address, argfile.name) + print('Verifying 0x%x (%d) bytes @ 0x%08x in flash against %s...' % (image_size, image_size, address, argfile.name)) # Try digest first, only read if there are differences. digest, _ = flasher.flash_digest(address, image_size) digest = hexify(digest).upper() expected_digest = hashlib.md5(image).hexdigest().upper() if digest == expected_digest: - print '-- verify OK (digest matched)' + print('-- verify OK (digest matched)') continue else: differences = True if getattr(args, 'diff', 'no') != 'yes': - print '-- verify FAILED (digest mismatch)' + print('-- verify FAILED (digest mismatch)') continue flash = flasher.flash_read(address, image_size) assert flash != image - diff = [i for i in xrange(image_size) if flash[i] != image[i]] - print '-- verify FAILED: %d differences, first @ 0x%08x' % (len(diff), address + diff[0]) + diff = [i for i in range(image_size) if flash[i] != image[i]] + print('-- verify FAILED: %d differences, first @ 0x%08x' % (len(diff), address + diff[0])) for d in diff: - print ' %08x %02x %02x' % (address + d, ord(flash[d]), ord(image[d])) + print(' %08x %02x %02x' % (address + d, ord(flash[d]), ord(image[d]))) if differences: raise FatalError("Verify failed.") @@ -1067,7 +1067,7 @@ def verify_flash(esp, args, flash_params=None): def version(args): - print __version__ + print(__version__) # # End of operations functions @@ -1203,12 +1203,12 @@ def add_spi_flash_subparsers(parent, auto_detect=False): 'version', help='Print esptool version') # internal sanity check - every operation matches a module function of the same name - for operation in subparsers.choices.keys(): + for operation in list(subparsers.choices.keys()): assert operation in globals(), "%s should be a module function" % operation args = parser.parse_args() - print 'esptool.py v%s' % __version__ + print('esptool.py v%s' % __version__) # operation function can take 1 arg (args), 2 args (esp, arg) # or be a member function of the ESPROM class. @@ -1310,5 +1310,5 @@ def __call__(self, parser, namespace, values, option_string=None): try: main() except FatalError as e: - print '\nA fatal error occurred: %s' % e + print('\nA fatal error occurred: %s' % e) sys.exit(2) diff --git a/panda/python/flash_release.py b/panda/python/flash_release.py index 0f407ff22f05a0..b50c9b36b3af78 100755 --- a/panda/python/flash_release.py +++ b/panda/python/flash_release.py @@ -1,10 +1,10 @@ -#!/usr/bin/env python -from __future__ import print_function +#!/usr/bin/env python3 + import sys import time import requests import json -import StringIO +import io def flash_release(path=None, st_serial=None): from panda import Panda, PandaDFU, ESPROM, CesantaFlasher @@ -29,7 +29,7 @@ def status(x): url = json.loads(r.text)['url'] r = requests.get(url) print("Fetching firmware from %s" % url) - path = StringIO.StringIO(r.content) + path = io.StringIO(r.content) zf = ZipFile(path) zf.printdir() diff --git a/panda/python/isotp.py b/panda/python/isotp.py index 971827007a6f26..00200f888b3997 100644 --- a/panda/python/isotp.py +++ b/panda/python/isotp.py @@ -1,13 +1,15 @@ +import binascii + DEBUG = False def msg(x): if DEBUG: - print "S:",x.encode("hex") + print("S:", binascii.hexlify(x)) if len(x) <= 7: ret = chr(len(x)) + x else: assert False - return ret.ljust(8, "\x00") + return ret.ljust(8, b"\x00") kmsgs = [] def recv(panda, cnt, addr, nbus): @@ -24,35 +26,35 @@ def recv(panda, cnt, addr, nbus): # leave around nmsgs.append((ids, ts, dat, bus)) kmsgs = nmsgs[-256:] - return map(str, ret) + return ret def isotp_recv_subaddr(panda, addr, bus, sendaddr, subaddr): msg = recv(panda, 1, addr, bus)[0] # TODO: handle other subaddr also communicating - assert ord(msg[0]) == subaddr + assert msg[0] == subaddr - if ord(msg[1])&0xf0 == 0x10: + if msg[1]&0xf0 == 0x10: # first - tlen = ((ord(msg[1]) & 0xf) << 8) | ord(msg[2]) + tlen = ((msg[1] & 0xf) << 8) | msg[2] dat = msg[3:] # 0 block size? - CONTINUE = chr(subaddr) + "\x30" + "\x00"*6 + CONTINUE = chr(subaddr).encode("utf8") + b"\x30" + b"\x00"*6 panda.can_send(sendaddr, CONTINUE, bus) idx = 1 - for mm in recv(panda, (tlen-len(dat) + 5)/6, addr, bus): - assert ord(mm[0]) == subaddr - assert ord(mm[1]) == (0x20 | (idx&0xF)) + for mm in recv(panda, (tlen-len(dat) + 5)//6, addr, bus): + assert mm[0] == subaddr + assert mm[1] == (0x20 | (idx&0xF)) dat += mm[2:] idx += 1 - elif ord(msg[1])&0xf0 == 0x00: + elif msg[1]&0xf0 == 0x00: # single - tlen = ord(msg[1]) & 0xf + tlen = msg[1] & 0xf dat = msg[2:] else: - print msg.encode("hex") + print(binascii.hexlify(msg)) assert False return dat[0:tlen] @@ -69,26 +71,26 @@ def isotp_send(panda, x, addr, bus=0, recvaddr=None, subaddr=None): panda.can_send(addr, chr(subaddr)+msg(x)[0:7], bus) else: if subaddr: - ss = chr(subaddr) + chr(0x10 + (len(x)>>8)) + chr(len(x)&0xFF) + x[0:5] + ss = (chr(subaddr) + chr(0x10 + (len(x)>>8)) + chr(len(x)&0xFF)).encode("utf8") + x[0:5] x = x[5:] else: - ss = chr(0x10 + (len(x)>>8)) + chr(len(x)&0xFF) + x[0:6] + ss = (chr(0x10 + (len(x)>>8)) + chr(len(x)&0xFF)).encode("utf8") + x[0:6] x = x[6:] idx = 1 sends = [] while len(x) > 0: if subaddr: - sends.append(((chr(subaddr) + chr(0x20 + (idx&0xF)) + x[0:6]).ljust(8, "\x00"))) + sends.append((((chr(subaddr) + chr(0x20 + (idx&0xF))).encode('utf8') + x[0:6]).ljust(8, b"\x00"))) x = x[6:] else: - sends.append(((chr(0x20 + (idx&0xF)) + x[0:7]).ljust(8, "\x00"))) + sends.append(((chr(0x20 + (idx&0xF)).encode("utf8") + x[0:7]).ljust(8, b"\x00"))) x = x[7:] idx += 1 # actually send panda.can_send(addr, ss, bus) rr = recv(panda, 1, recvaddr, bus)[0] - if rr.find("\x30\x01") != -1: + if rr.find(b"\x30\x01") != -1: for s in sends[:-1]: panda.can_send(addr, s, 0) rr = recv(panda, 1, recvaddr, bus)[0] @@ -105,31 +107,31 @@ def isotp_recv(panda, addr, bus=0, sendaddr=None, subaddr=None): else: msg = recv(panda, 1, addr, bus)[0] - if ord(msg[0])&0xf0 == 0x10: + if msg[0]&0xf0 == 0x10: # first - tlen = ((ord(msg[0]) & 0xf) << 8) | ord(msg[1]) + tlen = ((msg[0] & 0xf) << 8) | msg[1] dat = msg[2:] # 0 block size? - CONTINUE = "\x30" + "\x00"*7 + CONTINUE = b"\x30" + b"\x00"*7 panda.can_send(sendaddr, CONTINUE, bus) idx = 1 - for mm in recv(panda, (tlen-len(dat) + 6)/7, addr, bus): - assert ord(mm[0]) == (0x20 | (idx&0xF)) + for mm in recv(panda, (tlen-len(dat) + 6)//7, addr, bus): + assert mm[0] == (0x20 | (idx&0xF)) dat += mm[1:] idx += 1 - elif ord(msg[0])&0xf0 == 0x00: + elif msg[0]&0xf0 == 0x00: # single - tlen = ord(msg[0]) & 0xf + tlen = msg[0] & 0xf dat = msg[1:] else: assert False dat = dat[0:tlen] if DEBUG: - print "R:",dat.encode("hex") + print("R:", binascii.hexlify(dat)) return dat diff --git a/panda/python/serial.py b/panda/python/serial.py index 1bcfebb32eabd0..72ab3de92b6752 100644 --- a/panda/python/serial.py +++ b/panda/python/serial.py @@ -5,7 +5,7 @@ def __init__(self, panda, port, baud): self.port = port self.panda.set_uart_parity(self.port, 0) self.panda.set_uart_baud(self.port, baud) - self.buf = "" + self.buf = b"" def read(self, l=1): tt = self.panda.serial_read(self.port) @@ -19,7 +19,10 @@ def read(self, l=1): def write(self, dat): #print "W: ", dat.encode("hex") #print ' pigeon_send("' + ''.join(map(lambda x: "\\x%02X" % ord(x), dat)) + '");' - return self.panda.serial_write(self.port, dat) + if(isinstance(dat, bytes)): + return self.panda.serial_write(self.port, dat) + else: + return self.panda.serial_write(self.port, str.encode(dat)) def close(self): pass diff --git a/panda/python/update.py b/panda/python/update.py index ce730e4919119e..d72de11645f0c6 100755 --- a/panda/python/update.py +++ b/panda/python/update.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import os import time @@ -27,7 +27,7 @@ def ensure_st_up_to_date(): panda_dfu = PandaDFU(panda_dfu[0]) panda_dfu.recover() - print "waiting for board..." + print("waiting for board...") time.sleep(1) if panda.bootstub or not panda.get_version().startswith(repo_version): diff --git a/panda/release/make_release.sh b/panda/release/make_release.sh index 7be994c82c8813..5aec1a79495fe1 100755 --- a/panda/release/make_release.sh +++ b/panda/release/make_release.sh @@ -7,6 +7,7 @@ if [ ! -d "../../pandaextra" ]; then fi export RELEASE=1 +export BUILDER=DEV # make ST + bootstub pushd . diff --git a/panda/run_automated_tests.sh b/panda/run_automated_tests.sh index 583d6c1ed7599a..e876c670a74c0e 100755 --- a/panda/run_automated_tests.sh +++ b/panda/run_automated_tests.sh @@ -18,4 +18,4 @@ do nmcli connection delete "$NAME" done -PYTHONPATH="." python $(which nosetests) -v --with-xunit --xunit-file=./$TEST_FILENAME --xunit-testsuite-name=$TESTSUITE_NAME -s $TEST_SCRIPTS +PYTHONPATH="." $(which nosetests) -v --with-xunit --xunit-file=./$TEST_FILENAME --xunit-testsuite-name=$TESTSUITE_NAME -s $TEST_SCRIPTS diff --git a/panda/tests/all_wifi_test.py b/panda/tests/all_wifi_test.py index 4e9d3a5318a16c..85dc173b07625c 100755 --- a/panda/tests/all_wifi_test.py +++ b/panda/tests/all_wifi_test.py @@ -1,7 +1,7 @@ -#!/usr/bin/python +#!/usr/bin/env python3 import requests import json -from automated.helpers import _connect_wifi +from .automated.helpers import _connect_wifi from panda import Panda from nose.tools import assert_equal @@ -12,12 +12,12 @@ for p in Panda.list(): dongle_id, pw = Panda(p).get_serial() - print dongle_id, pw + print(dongle_id, pw) assert(dongle_id.isalnum()) _connect_wifi(dongle_id, pw) r = requests.get("http://192.168.0.10/") - print r.text + print(r.text) wifi_dongle_id = r.text.split("ssid: panda-")[1].split("
")[0] st_version = r.text.split("st version:")[1].strip().split("
")[0] esp_version = r.text.split("esp version:")[1].strip().split("
")[0] diff --git a/panda/tests/automated/1_program.py b/panda/tests/automated/1_program.py index 6b8a3ad4875657..944db18d9aaed6 100644 --- a/panda/tests/automated/1_program.py +++ b/panda/tests/automated/1_program.py @@ -1,6 +1,6 @@ import os from panda import Panda -from helpers import panda_type_to_serial, test_white_and_grey, test_all_pandas, panda_connect_and_init +from .helpers import panda_type_to_serial, test_white_and_grey, test_all_pandas, panda_connect_and_init @test_all_pandas @panda_connect_and_init diff --git a/panda/tests/automated/2_usb_to_can.py b/panda/tests/automated/2_usb_to_can.py index f0411b32c66aae..645f686e155914 100644 --- a/panda/tests/automated/2_usb_to_can.py +++ b/panda/tests/automated/2_usb_to_can.py @@ -1,10 +1,10 @@ -from __future__ import print_function + import os import sys import time from panda import Panda from nose.tools import assert_equal, assert_less, assert_greater -from helpers import SPEED_NORMAL, SPEED_GMLAN, time_many_sends, test_white_and_grey, panda_type_to_serial, test_all_pandas, panda_connect_and_init +from .helpers import SPEED_NORMAL, SPEED_GMLAN, time_many_sends, test_white_and_grey, panda_type_to_serial, test_all_pandas, panda_connect_and_init @test_all_pandas @panda_connect_and_init @@ -25,19 +25,19 @@ def test_can_loopback(p): p.set_can_speed_kbps(bus, 250) # send a message on bus 0 - p.can_send(0x1aa, "message", bus) + p.can_send(0x1aa, b"message", bus) # confirm receive both on loopback and send receipt time.sleep(0.05) r = p.can_recv() - sr = filter(lambda x: x[3] == 0x80 | bus, r) - lb = filter(lambda x: x[3] == bus, r) + sr = [x for x in r if x[3] == 0x80 | bus] + lb = [x for x in r if x[3] == bus] assert len(sr) == 1 assert len(lb) == 1 # confirm data is correct assert 0x1aa == sr[0][0] == lb[0][0] - assert "message" == sr[0][2] == lb[0][2] + assert b"message" == sr[0][2] == lb[0][2] @test_all_pandas @panda_connect_and_init @@ -49,7 +49,7 @@ def test_safety_nooutput(p): p.set_can_loopback(True) # send a message on bus 0 - p.can_send(0x1aa, "message", 0) + p.can_send(0x1aa, b"message", 0) # confirm receive nothing time.sleep(0.05) @@ -67,8 +67,8 @@ def test_reliability(p): p.set_can_loopback(True) p.set_can_speed_kbps(0, 1000) - addrs = range(100, 100+MSG_COUNT) - ts = [(j, 0, "\xaa"*8, 0) for j in addrs] + addrs = list(range(100, 100+MSG_COUNT)) + ts = [(j, 0, b"\xaa"*8, 0) for j in addrs] # 100 loops for i in range(LOOP_COUNT): @@ -80,11 +80,11 @@ def test_reliability(p): while len(r) < 200 and (time.time() - st) < 0.5: r.extend(p.can_recv()) - sent_echo = filter(lambda x: x[3] == 0x80, r) - loopback_resp = filter(lambda x: x[3] == 0, r) + sent_echo = [x for x in r if x[3] == 0x80] + loopback_resp = [x for x in r if x[3] == 0] - assert_equal(sorted(map(lambda x: x[0], loopback_resp)), addrs) - assert_equal(sorted(map(lambda x: x[0], sent_echo)), addrs) + assert_equal(sorted([x[0] for x in loopback_resp]), addrs) + assert_equal(sorted([x[0] for x in sent_echo]), addrs) assert_equal(len(r), 200) # take sub 20ms @@ -182,4 +182,4 @@ def test_gmlan_bad_toggle(p): def test_serial_debug(p): junk = p.serial_read(Panda.SERIAL_DEBUG) p.call_control_api(0xc0) - assert(p.serial_read(Panda.SERIAL_DEBUG).startswith("can ")) + assert(p.serial_read(Panda.SERIAL_DEBUG).startswith(b"can ")) diff --git a/panda/tests/automated/3_wifi.py b/panda/tests/automated/3_wifi.py index 2e9c81f3f4efe4..f57dbbd0210c69 100644 --- a/panda/tests/automated/3_wifi.py +++ b/panda/tests/automated/3_wifi.py @@ -1,8 +1,8 @@ -from __future__ import print_function + import os import time from panda import Panda -from helpers import connect_wifi, test_white, test_all_pandas, panda_type_to_serial, panda_connect_and_init +from .helpers import connect_wifi, test_white, test_all_pandas, panda_type_to_serial, panda_connect_and_init import requests @test_all_pandas diff --git a/panda/tests/automated/4_wifi_functionality.py b/panda/tests/automated/4_wifi_functionality.py index ee9857d09e1817..67cce4bf9c37a6 100644 --- a/panda/tests/automated/4_wifi_functionality.py +++ b/panda/tests/automated/4_wifi_functionality.py @@ -1,7 +1,7 @@ -from __future__ import print_function + import time from panda import Panda -from helpers import time_many_sends, connect_wifi, test_white, panda_type_to_serial +from .helpers import time_many_sends, connect_wifi, test_white, panda_type_to_serial from nose.tools import timed, assert_equal, assert_less, assert_greater @test_white diff --git a/panda/tests/automated/5_wifi_udp.py b/panda/tests/automated/5_wifi_udp.py index 8b62cf082ee705..642d8f02a59961 100644 --- a/panda/tests/automated/5_wifi_udp.py +++ b/panda/tests/automated/5_wifi_udp.py @@ -1,7 +1,7 @@ -from __future__ import print_function + import sys import time -from helpers import time_many_sends, connect_wifi, test_white, panda_type_to_serial +from .helpers import time_many_sends, connect_wifi, test_white, panda_type_to_serial from panda import Panda, PandaWifiStreaming from nose.tools import timed, assert_equal, assert_less, assert_greater @@ -54,7 +54,7 @@ def test_udp_doesnt_drop(serials=None): missing = True while len(r) > 0: r = p.can_recv() - r = filter(lambda x: x[3] == bus and x[0] == msg_id, r) + r = [x for x in r if x[3] == bus and x[0] == msg_id] if len(r) > 0: missing = False usb_ok_cnt += len(r) diff --git a/panda/tests/automated/6_two_panda.py b/panda/tests/automated/6_two_panda.py index 8b308ce500ff8c..711b83fddf63e6 100644 --- a/panda/tests/automated/6_two_panda.py +++ b/panda/tests/automated/6_two_panda.py @@ -1,10 +1,10 @@ -from __future__ import print_function + import os import time import random from panda import Panda from nose.tools import assert_equal, assert_less, assert_greater -from helpers import time_many_sends, test_two_panda, test_two_black_panda, panda_type_to_serial, clear_can_buffers, panda_connect_and_init +from .helpers import time_many_sends, test_two_panda, test_two_black_panda, panda_type_to_serial, clear_can_buffers, panda_connect_and_init @test_two_panda @panda_type_to_serial @@ -18,7 +18,7 @@ def test_send_recv(p_send, p_recv): assert not p_send.legacy assert not p_recv.legacy - p_send.can_send_many([(0x1ba, 0, "message", 0)]*2) + p_send.can_send_many([(0x1ba, 0, b"message", 0)]*2) time.sleep(0.05) p_recv.can_recv() p_send.can_recv() @@ -55,7 +55,7 @@ def test_latency(p_send, p_recv): p_recv.set_can_speed_kbps(0, 100) time.sleep(0.05) - p_send.can_send_many([(0x1ba, 0, "testmsg", 0)]*10) + p_send.can_send_many([(0x1ba, 0, b"testmsg", 0)]*10) time.sleep(0.05) p_recv.can_recv() p_send.can_recv() @@ -80,7 +80,7 @@ def test_latency(p_send, p_recv): for i in range(num_messages): st = time.time() - p_send.can_send(0x1ab, "message", bus) + p_send.can_send(0x1ab, b"message", bus) r = [] while len(r) < 1 and (time.time() - st) < 5: r = p_recv.can_recv() @@ -127,7 +127,7 @@ def test_black_loopback(panda0, panda1): panda1.set_can_loopback(False) # clear stuff - panda0.can_send_many([(0x1ba, 0, "testmsg", 0)]*10) + panda0.can_send_many([(0x1ba, 0, b"testmsg", 0)]*10) time.sleep(0.05) panda0.can_recv() panda1.can_recv() @@ -155,7 +155,7 @@ def get_test_string(): def _test_buses(send_panda, recv_panda, _test_array): for send_bus, send_obd, recv_obd, recv_buses in _test_array: print("\nSend bus:", send_bus, " Send OBD:", send_obd, " Recv OBD:", recv_obd) - + # set OBD on pandas send_panda.set_gmlan(True if send_obd else None) recv_panda.set_gmlan(True if recv_obd else None) @@ -180,7 +180,7 @@ def _test_buses(send_panda, recv_panda, _test_array): loop_buses.append(loop[3]) if len(cans_loop) == 0: print(" No loop") - + # test loop buses recv_buses.sort() loop_buses.sort() @@ -192,4 +192,4 @@ def _test_buses(send_panda, recv_panda, _test_array): print("***************** TESTING (0 --> 1) *****************") _test_buses(panda0, panda1, test_array) print("***************** TESTING (1 --> 0) *****************") - _test_buses(panda1, panda0, test_array) \ No newline at end of file + _test_buses(panda1, panda0, test_array) diff --git a/panda/tests/automated/helpers.py b/panda/tests/automated/helpers.py index c9e0c676267583..f73a17dc043e21 100644 --- a/panda/tests/automated/helpers.py +++ b/panda/tests/automated/helpers.py @@ -2,9 +2,10 @@ import sys import time import random +import binascii import subprocess import requests -import thread +import _thread from functools import wraps from panda import Panda from nose.tools import timed, assert_equal, assert_less, assert_greater @@ -49,7 +50,7 @@ def connect_wifi(serial=None): FNULL = open(os.devnull, 'w') def _connect_wifi(dongle_id, pw, insecure_okay=False): - ssid = str("panda-" + dongle_id) + ssid = "panda-" + dongle_id.decode("utf8") r = subprocess.call(["ping", "-W", "4", "-c", "1", "192.168.0.10"], stdout=FNULL, stderr=subprocess.STDOUT) if not r: @@ -75,7 +76,8 @@ def _connect_wifi(dongle_id, pw, insecure_okay=False): print("WIFI: scanning %d" % cnt) os.system("iwlist %s scanning > /dev/null" % wlan_interface) os.system("nmcli device wifi rescan") - wifi_scan = filter(lambda x: ssid in x, subprocess.check_output(["nmcli","dev", "wifi", "list"]).split("\n")) + wifi_networks = [x.decode("utf8") for x in subprocess.check_output(["nmcli","dev", "wifi", "list"]).split(b"\n")] + wifi_scan = [x for x in wifi_networks if ssid in x] if len(wifi_scan) != 0: break time.sleep(0.1) @@ -140,7 +142,7 @@ def time_many_sends(p, bus, precv=None, msg_count=100, msg_id=None, two_pandas=F raise ValueError("Cannot have two pandas that are the same panda") st = time.time() - p.can_send_many([(msg_id, 0, "\xaa"*8, bus)]*msg_count) + p.can_send_many([(msg_id, 0, b"\xaa"*8, bus)]*msg_count) r = [] r_echo = [] r_len_expected = msg_count if two_pandas else msg_count*2 @@ -153,11 +155,11 @@ def time_many_sends(p, bus, precv=None, msg_count=100, msg_id=None, two_pandas=F while len(r_echo) < r_echo_len_exected and (time.time() - st) < 10: r_echo.extend(p.can_recv()) - sent_echo = filter(lambda x: x[3] == 0x80 | bus and x[0] == msg_id, r) - sent_echo.extend(filter(lambda x: x[3] == 0x80 | bus and x[0] == msg_id, r_echo)) - resp = filter(lambda x: x[3] == bus and x[0] == msg_id, r) + sent_echo = [x for x in r if x[3] == 0x80 | bus and x[0] == msg_id] + sent_echo.extend([x for x in r_echo if x[3] == 0x80 | bus and x[0] == msg_id]) + resp = [x for x in r if x[3] == bus and x[0] == msg_id] - leftovers = filter(lambda x: (x[3] != 0x80 | bus and x[3] != bus) or x[0] != msg_id, r) + leftovers = [x for x in r if (x[3] != 0x80 | bus and x[3] != bus) or x[0] != msg_id] assert_equal(len(leftovers), 0) assert_equal(len(resp), msg_count) @@ -176,7 +178,7 @@ def wrapper(panda_type=None, **kwargs): if panda_type is not None: if not isinstance(panda_type, list): panda_type = [panda_type] - + # If not done already, get panda serials and their type global _panda_serials if _panda_serials == None: @@ -185,7 +187,7 @@ def wrapper(panda_type=None, **kwargs): p = Panda(serial=serial) _panda_serials.append((serial, p.get_type())) p.close() - + # Find a panda with the correct types and add the corresponding serial serials = [] for p_type in panda_type: @@ -216,7 +218,7 @@ def wrapper(panda_serials=None, **kwargs): if panda_serials is not None: if not isinstance(panda_serials, list): panda_serials = [panda_serials] - + # Connect to pandas pandas = [] for panda_serial in panda_serials: @@ -230,7 +232,7 @@ def wrapper(panda_serials=None, **kwargs): for bus, speed in [(0, SPEED_NORMAL), (1, SPEED_NORMAL), (2, SPEED_NORMAL), (3, SPEED_GMLAN)]: panda.set_can_speed_kbps(bus, speed) clear_can_buffers(panda) - thread.start_new_thread(heartbeat_thread, (panda,)) + _thread.start_new_thread(heartbeat_thread, (panda,)) # Run test function ret = fn(*pandas, **kwargs) @@ -247,7 +249,7 @@ def clear_can_buffers(panda): # clear tx buffers for i in range(4): panda.can_clear(i) - + # clear rx buffers panda.can_clear(0xFFFF) r = [1] @@ -257,4 +259,4 @@ def clear_can_buffers(panda): time.sleep(0.05) if (time.time() - st) > 10: print("Unable to clear can buffers for panda ", panda.get_serial()) - assert False \ No newline at end of file + assert False diff --git a/panda/tests/black_loopback_test.py b/panda/tests/black_loopback_test.py index d16ac21af14776..0953cba4faba02 100755 --- a/panda/tests/black_loopback_test.py +++ b/panda/tests/black_loopback_test.py @@ -1,10 +1,10 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Loopback test between two black pandas (+ harness and power) # Tests all buses, including OBD CAN, which is on the same bus as CAN0 in this test. # To be sure, the test should be run with both harness orientations -from __future__ import print_function + import os import sys import time @@ -33,11 +33,8 @@ def run_test(sleep_duration): pandas[0] = Panda(pandas[0]) pandas[1] = Panda(pandas[1]) - # find out the hardware types - type0 = pandas[0].get_type() - type1 = pandas[1].get_type() - - if type0 != "\x03" or type1 != "\x03": + # find out the hardware types + if not pandas[0].is_black() or not pandas[1].is_black(): print("Connect two black pandas to run this test!") assert False diff --git a/panda/tests/black_white_loopback_test.py b/panda/tests/black_white_loopback_test.py index 7e121343930d64..7ad2107fa0918f 100755 --- a/panda/tests/black_white_loopback_test.py +++ b/panda/tests/black_white_loopback_test.py @@ -1,10 +1,10 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Loopback test between black panda (+ harness and power) and white/grey panda # Tests all buses, including OBD CAN, which is on the same bus as CAN0 in this test. # To be sure, the test should be run with both harness orientations -from __future__ import print_function + import os import sys import time @@ -40,17 +40,14 @@ def run_test(sleep_duration): pandas[0] = Panda(pandas[0]) pandas[1] = Panda(pandas[1]) - # find out which one is black - type0 = pandas[0].get_type() - type1 = pandas[1].get_type() - black_panda = None other_panda = None - - if type0 == "\x03" and type1 != "\x03": + + # find out which one is black + if pandas[0].is_black() and not pandas[1].is_black(): black_panda = pandas[0] other_panda = pandas[1] - elif type0 != "\x03" and type1 == "\x03": + elif not pandas[0].is_black() and pandas[1].is_black(): black_panda = pandas[1] other_panda = pandas[0] else: @@ -71,13 +68,13 @@ def run_test(sleep_duration): test_buses(black_panda, other_panda, False, [(0, False, [0]), (1, False, [1]), (2, False, [2]), (0, True, [0, 1])], sleep_duration) counter += 1 print("Number of cycles:", counter, "Non-zero bus errors:", nonzero_bus_errors, "Zero bus errors:", zero_bus_errors, "Content errors:", content_errors) - + # Toggle relay black_panda.set_safety_mode(Panda.SAFETY_NOOUTPUT) time.sleep(1) black_panda.set_safety_mode(Panda.SAFETY_ALLOUTPUT) time.sleep(1) - + def test_buses(black_panda, other_panda, direction, test_array, sleep_duration): global nonzero_bus_errors, zero_bus_errors, content_errors @@ -91,7 +88,7 @@ def test_buses(black_panda, other_panda, direction, test_array, sleep_duration): black_panda.send_heartbeat() other_panda.send_heartbeat() print("\ntest can: ", send_bus, " OBD: ", obd) - + # set OBD on black panda black_panda.set_gmlan(True if obd else None) @@ -105,8 +102,8 @@ def test_buses(black_panda, other_panda, direction, test_array, sleep_duration): if direction: other_panda.can_clear(recv_bus) else: - black_panda.can_clear(recv_bus) - + black_panda.can_clear(recv_bus) + black_panda.can_recv() other_panda.can_recv() @@ -138,7 +135,7 @@ def test_buses(black_panda, other_panda, direction, test_array, sleep_duration): print(" No loop") if not os.getenv("NOASSERT"): assert False - + # test loop buses recv_buses.sort() loop_buses.sort() diff --git a/panda/tests/black_white_relay_endurance.py b/panda/tests/black_white_relay_endurance.py index 8868b9848f4e10..3eaaa1655575e1 100755 --- a/panda/tests/black_white_relay_endurance.py +++ b/panda/tests/black_white_relay_endurance.py @@ -1,10 +1,10 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Loopback test between black panda (+ harness and power) and white/grey panda # Tests all buses, including OBD CAN, which is on the same bus as CAN0 in this test. # To be sure, the test should be run with both harness orientations -from __future__ import print_function + import os import sys import time @@ -40,17 +40,14 @@ def run_test(sleep_duration): pandas[0] = Panda(pandas[0]) pandas[1] = Panda(pandas[1]) - # find out which one is black - type0 = pandas[0].get_type() - type1 = pandas[1].get_type() - black_panda = None other_panda = None - if type0 == "\x03" and type1 != "\x03": + # find out which one is black + if pandas[0].is_black() and not pandas[1].is_black(): black_panda = pandas[0] other_panda = pandas[1] - elif type0 != "\x03" and type1 == "\x03": + elif not pandas[0].is_black() and pandas[1].is_black(): black_panda = pandas[1] other_panda = pandas[0] else: @@ -78,11 +75,11 @@ def run_test(sleep_duration): if (time.time() - temp_start_time) > 3600*6: # Toggle relay - black_panda.set_safety_mode(Panda.SAFETY_NOOUTPUT) - time.sleep(1) - black_panda.set_safety_mode(Panda.SAFETY_ALLOUTPUT) - time.sleep(1) - temp_start_time = time.time() + black_panda.set_safety_mode(Panda.SAFETY_NOOUTPUT) + time.sleep(1) + black_panda.set_safety_mode(Panda.SAFETY_ALLOUTPUT) + time.sleep(1) + temp_start_time = time.time() def test_buses(black_panda, other_panda, direction, test_array, sleep_duration): @@ -111,7 +108,7 @@ def test_buses(black_panda, other_panda, direction, test_array, sleep_duration): if direction: other_panda.can_clear(recv_bus) else: - black_panda.can_clear(recv_bus) + black_panda.can_clear(recv_bus) black_panda.can_recv() other_panda.can_recv() diff --git a/panda/tests/black_white_relay_test.py b/panda/tests/black_white_relay_test.py index 21a2ef6d7f0bbd..65877dc29f7058 100755 --- a/panda/tests/black_white_relay_test.py +++ b/panda/tests/black_white_relay_test.py @@ -1,9 +1,9 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Relay test with loopback between black panda (+ harness and power) and white/grey panda # Tests the relay switching multiple times / second by looking at the buses on which loop occurs. -from __future__ import print_function + import os import sys import time diff --git a/panda/tests/build/Dockerfile b/panda/tests/build/Dockerfile index 276a25ed0b9495..0f982160beb8de 100644 --- a/panda/tests/build/Dockerfile +++ b/panda/tests/build/Dockerfile @@ -1,6 +1,19 @@ FROM ubuntu:16.04 -RUN apt-get update && apt-get install -y gcc-arm-none-eabi libnewlib-arm-none-eabi python python-pip gcc g++ git autoconf gperf bison flex automake texinfo wget help2man gawk libtool libtool-bin ncurses-dev unzip unrar-free libexpat-dev sed bzip2 +RUN apt-get update && apt-get install -y gcc-arm-none-eabi libnewlib-arm-none-eabi python python-pip gcc g++ git autoconf gperf bison flex automake texinfo wget help2man gawk libtool libtool-bin ncurses-dev unzip unrar-free libexpat-dev sed bzip2 locales curl zlib1g-dev libffi-dev libssl-dev + +RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 + +RUN curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash + +ENV PATH="/root/.pyenv/bin:/root/.pyenv/shims:${PATH}" +RUN pyenv install 2.7.12 +RUN pyenv install 3.7.3 +RUN pyenv global 3.7.3 +RUN pyenv rehash RUN pip install pycrypto==2.6.1 @@ -10,7 +23,8 @@ WORKDIR /panda/boardesp RUN git clone --recursive https://github.com/pfalcon/esp-open-sdk.git WORKDIR /panda/boardesp/esp-open-sdk RUN git checkout 03f5e898a059451ec5f3de30e7feff30455f7ce -RUN CT_ALLOW_BUILD_AS_ROOT_SURE=1 make STANDALONE=y +COPY ./boardesp/python2_make.py /panda/boardesp/esp-open-sdk +RUN python2 python2_make.py "CT_ALLOW_BUILD_AS_ROOT_SURE=1 make STANDALONE=y" COPY . /panda diff --git a/panda/tests/can_printer.py b/panda/tests/can_printer.py index e863889c16424b..c8bbc3f18442b7 100755 --- a/panda/tests/can_printer.py +++ b/panda/tests/can_printer.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python -from __future__ import print_function +#!/usr/bin/env python3 + import os import sys import time @@ -15,7 +15,7 @@ def sec_since_boot(): def can_printer(): p = Panda() - p.set_safety_mode(0x1337) + p.set_safety_mode(Panda.SAFETY_ALLOUTPUT) start = sec_since_boot() lp = sec_since_boot() @@ -30,7 +30,7 @@ def can_printer(): if sec_since_boot() - lp > 0.1: dd = chr(27) + "[2J" dd += "%5.2f\n" % (sec_since_boot() - start) - for k,v in sorted(zip(msgs.keys(), map(lambda x: binascii.hexlify(x[-1]), msgs.values()))): + for k,v in sorted(zip(list(msgs.keys()), [binascii.hexlify(x[-1]) for x in list(msgs.values())])): dd += "%s(%6d) %s\n" % ("%04X(%4d)" % (k,k),len(msgs[k]), v) print(dd) lp = sec_since_boot() diff --git a/panda/tests/debug_console.py b/panda/tests/debug_console.py index e341b266c8ddc4..8e66946dd4d8db 100755 --- a/panda/tests/debug_console.py +++ b/panda/tests/debug_console.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python -from __future__ import print_function +#!/usr/bin/env python3 + import os import sys import time @@ -19,9 +19,9 @@ serials = Panda.list() if os.getenv("SERIAL"): - serials = filter(lambda x: x==os.getenv("SERIAL"), serials) + serials = [x for x in serials if x==os.getenv("SERIAL")] - pandas = list(map(lambda x: Panda(x, claim=claim), serials)) + pandas = list([Panda(x, claim=claim) for x in serials]) if not len(pandas): sys.exit("no pandas found") @@ -33,16 +33,16 @@ while True: for i, panda in enumerate(pandas): while True: - ret = panda.serial_read(port_number) - if len(ret) > 0: - sys.stdout.write(setcolor[i] + str(ret) + unsetcolor) - sys.stdout.flush() - else: - break + ret = panda.serial_read(port_number) + if len(ret) > 0: + sys.stdout.write(setcolor[i] + ret.decode('ascii') + unsetcolor) + sys.stdout.flush() + else: + break if select.select([sys.stdin], [], [], 0) == ([sys.stdin], [], []): - ln = sys.stdin.readline() - if claim: - panda.serial_write(port_number, ln) + ln = sys.stdin.readline() + if claim: + panda.serial_write(port_number, ln) time.sleep(0.01) except: print("panda disconnected!") diff --git a/panda/tests/disable_esp.py b/panda/tests/disable_esp.py index abebd9c17b8a5d..ce1dd6db2eec36 100755 --- a/panda/tests/disable_esp.py +++ b/panda/tests/disable_esp.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 from panda import Panda Panda().set_esp_power(False) diff --git a/panda/tests/elm_car_simulator.py b/panda/tests/elm_car_simulator.py index f931e66ff40999..ffb309664e4532 100755 --- a/panda/tests/elm_car_simulator.py +++ b/panda/tests/elm_car_simulator.py @@ -1,6 +1,6 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 """Used to Reverse/Test ELM protocol auto detect and OBD message response without a car.""" -from __future__ import print_function + import sys import os import struct diff --git a/panda/tests/elm_throughput.py b/panda/tests/elm_throughput.py index 39625728899a74..2895b0926119d9 100755 --- a/panda/tests/elm_throughput.py +++ b/panda/tests/elm_throughput.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python -from __future__ import print_function +#!/usr/bin/env python3 + import socket import threading import select diff --git a/panda/tests/elm_wifi.py b/panda/tests/elm_wifi.py index f5a8849833df60..6c4a334b73d152 100644 --- a/panda/tests/elm_wifi.py +++ b/panda/tests/elm_wifi.py @@ -1,4 +1,4 @@ -from __future__ import print_function + import os import sys import time @@ -8,7 +8,7 @@ import struct sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), "..")) -import elm_car_simulator +from . import elm_car_simulator sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), "..", "..")) from panda import Panda @@ -301,7 +301,7 @@ def test_elm_panda_safety_mode_KWPFast(): p_car.kline_drain() p_elm = Panda("WIFI") - p_elm.set_safety_mode(0xE327); + p_elm.set_safety_mode(Panda.SAFETY_ELM327); def get_checksum(dat): result = 0 @@ -625,7 +625,7 @@ def test_elm_panda_safety_mode_ISO15765(): p_car.set_safety_mode(Panda.SAFETY_ALLOUTPUT) p_elm = Panda("WIFI") - p_elm.set_safety_mode(0xE327); + p_elm.set_safety_mode(Panda.SAFETY_ELM327); #sim = elm_car_simulator.ELMCarSimulator(serial, lin=False) #sim.start() diff --git a/panda/tests/get_version.py b/panda/tests/get_version.py index 0cd7795fdcc71d..73e51e1f0df2ab 100755 --- a/panda/tests/get_version.py +++ b/panda/tests/get_version.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 from panda import Panda if __name__ == "__main__": diff --git a/panda/tests/gmbitbang/recv.py b/panda/tests/gmbitbang/recv.py index 6eb70aa4ad3abb..92111ed7eca369 100755 --- a/panda/tests/gmbitbang/recv.py +++ b/panda/tests/gmbitbang/recv.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import time from panda import Panda @@ -12,6 +12,6 @@ if len(ret) > 0: add = ret[0][0] if last_add is not None and add != last_add+1: - print "MISS %d %d" % (last_add, add) + print("MISS %d %d" % (last_add, add)) last_add = add - print ret + print(ret) diff --git a/panda/tests/gmbitbang/rigol.py b/panda/tests/gmbitbang/rigol.py index 3d690fdd84c725..f2efb0340ec06e 100755 --- a/panda/tests/gmbitbang/rigol.py +++ b/panda/tests/gmbitbang/rigol.py @@ -1,10 +1,10 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import numpy as np import visa import matplotlib.pyplot as plt resources = visa.ResourceManager() -print resources.list_resources() +print(resources.list_resources()) scope = resources.open_resource('USB0::0x1AB1::0x04CE::DS1ZA184652242::INSTR', timeout=2000, chunk_size=1024000) print(scope.query('*IDN?').strip()) @@ -17,7 +17,7 @@ scope.write(":WAV:DATA? CHAN1")[10:] rawdata = scope.read_raw() data = np.frombuffer(rawdata, 'B') -print data.shape +print(data.shape) s1 = data[0:650] s2 = data[650:] @@ -31,5 +31,5 @@ plt.show() #data = (data - 130.0 - voltoffset/voltscale*25) / 25 * voltscale -print data +print(data) diff --git a/panda/tests/gmbitbang/test.py b/panda/tests/gmbitbang/test.py index 652ac1ddd8ad24..0934c6442028cd 100755 --- a/panda/tests/gmbitbang/test.py +++ b/panda/tests/gmbitbang/test.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import time from panda import Panda @@ -28,6 +28,6 @@ #p1.set_gmlan(bus=2) #p1.can_send(iden, dat, bus=3) time.sleep(0.01) - print p2.can_recv() + print(p2.can_recv()) #exit(0) diff --git a/panda/tests/gmbitbang/test_one.py b/panda/tests/gmbitbang/test_one.py index d7d430437dcabb..635cd2c91f4a45 100755 --- a/panda/tests/gmbitbang/test_one.py +++ b/panda/tests/gmbitbang/test_one.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import time from panda import Panda @@ -9,9 +9,9 @@ p.set_gmlan(bus=2) time.sleep(0.1) while len(p.can_recv()) > 0: - print "clearing" + print("clearing") time.sleep(0.1) -print "cleared" +print("cleared") p.set_gmlan(bus=None) iden = 18000 diff --git a/panda/tests/gps_stability_test.py b/panda/tests/gps_stability_test.py new file mode 100755 index 00000000000000..c96aaf123b3529 --- /dev/null +++ b/panda/tests/gps_stability_test.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python3 + +import os +import sys +import time +import random +import threading + +sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), "..")) +from panda import Panda, PandaSerial + +INIT_GPS_BAUD = 9600 +GPS_BAUD = 460800 + +def connect(): + pandas = Panda.list() + print(pandas) + + # make sure two pandas are connected + if len(pandas) != 2: + print("Connect white and grey/black panda to run this test!") + assert False + + # connect + pandas[0] = Panda(pandas[0]) + pandas[1] = Panda(pandas[1]) + + white_panda = None + gps_panda = None + + # find out which one is white (for spamming the CAN buses) + if pandas[0].is_white() and not pandas[1].is_white(): + white_panda = pandas[0] + gps_panda = pandas[1] + elif not pandas[0].is_white() and pandas[1].is_white(): + white_panda = pandas[1] + gps_panda = pandas[0] + else: + print("Connect white and grey/black panda to run this test!") + assert False + return white_panda, gps_panda + +def spam_buses_thread(panda): + try: + panda.set_safety_mode(Panda.SAFETY_ALLOUTPUT) + while True: + at = random.randint(1, 2000) + st = (b"test"+os.urandom(10))[0:8] + bus = random.randint(0, 2) + panda.can_send(at, st, bus) + except Exception as e: + print(e) + +def read_can_thread(panda): + try: + while True: + panda.can_recv() + except Exception as e: + print(e) + +def init_gps(panda): + def add_nmea_checksum(msg): + d = msg[1:] + cs = 0 + for i in d: + cs ^= ord(i) + return msg + "*%02X" % cs + + ser = PandaSerial(panda, 1, INIT_GPS_BAUD) + + # Power cycle the gps by toggling reset + print("Resetting GPS") + panda.set_esp_power(0) + time.sleep(0.5) + panda.set_esp_power(1) + time.sleep(0.5) + + # Upping baud rate + print("Upping GPS baud rate") + msg = add_nmea_checksum("$PUBX,41,1,0007,0003,%d,0" % GPS_BAUD)+"\r\n" + ser.write(msg) + time.sleep(1) # needs a wait for it to actually send + + # Reconnecting with the correct baud + ser = PandaSerial(panda, 1, GPS_BAUD) + + # Sending all config messages boardd sends + print("Sending config") + ser.write("\xB5\x62\x06\x00\x14\x00\x03\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01\x00\x00\x00\x00\x00\x1E\x7F") + ser.write("\xB5\x62\x06\x3E\x00\x00\x44\xD2") + ser.write("\xB5\x62\x06\x00\x14\x00\x00\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x35") + ser.write("\xB5\x62\x06\x00\x14\x00\x01\x00\x00\x00\xC0\x08\x00\x00\x00\x08\x07\x00\x01\x00\x01\x00\x00\x00\x00\x00\xF4\x80") + ser.write("\xB5\x62\x06\x00\x14\x00\x04\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1D\x85") + ser.write("\xB5\x62\x06\x00\x00\x00\x06\x18") + ser.write("\xB5\x62\x06\x00\x01\x00\x01\x08\x22") + ser.write("\xB5\x62\x06\x00\x01\x00\x02\x09\x23") + ser.write("\xB5\x62\x06\x00\x01\x00\x03\x0A\x24") + ser.write("\xB5\x62\x06\x08\x06\x00\x64\x00\x01\x00\x00\x00\x79\x10") + ser.write("\xB5\x62\x06\x24\x24\x00\x05\x00\x04\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x5A\x63") + ser.write("\xB5\x62\x06\x1E\x14\x00\x00\x00\x00\x00\x01\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3C\x37") + ser.write("\xB5\x62\x06\x24\x00\x00\x2A\x84") + ser.write("\xB5\x62\x06\x23\x00\x00\x29\x81") + ser.write("\xB5\x62\x06\x1E\x00\x00\x24\x72") + ser.write("\xB5\x62\x06\x01\x03\x00\x01\x07\x01\x13\x51") + ser.write("\xB5\x62\x06\x01\x03\x00\x02\x15\x01\x22\x70") + ser.write("\xB5\x62\x06\x01\x03\x00\x02\x13\x01\x20\x6C") + + print("Initialized GPS") + +received_messages = 0 +received_bytes = 0 +send_something = False +def gps_read_thread(panda): + global received_messages, received_bytes, send_something + ser = PandaSerial(panda, 1, GPS_BAUD) + while True: + ret = ser.read(1024) + time.sleep(0.001) + l = len(ret) + if l > 0: + received_messages+=1 + received_bytes+=l + if send_something: + ser.write("test") + send_something = False + + +CHECK_PERIOD = 5 +MIN_BYTES = 10000 +MAX_BYTES = 50000 + +min_failures = 0 +max_failures = 0 + +if __name__ == "__main__": + white_panda, gps_panda = connect() + + # Start spamming the CAN buses with the white panda. Also read the messages to add load on the GPS panda + threading.Thread(target=spam_buses_thread, args=(white_panda,)).start() + threading.Thread(target=read_can_thread, args=(gps_panda,)).start() + + # Start GPS checking + init_gps(gps_panda) + + read_thread = threading.Thread(target=gps_read_thread, args=(gps_panda,)) + read_thread.start() + while True: + time.sleep(CHECK_PERIOD) + if(received_bytes < MIN_BYTES): + print("Panda is not sending out enough data! Got " + str(received_messages) + " (" + str(received_bytes) + "B) in the last " + str(CHECK_PERIOD) + " seconds") + send_something = True + min_failures+=1 + elif(received_bytes > MAX_BYTES): + print("Panda is not sending out too much data! Got " + str(received_messages) + " (" + str(received_bytes) + "B) in the last " + str(CHECK_PERIOD) + " seconds") + print("Probably not on the right baud rate, got reset somehow? Resetting...") + max_failures+=1 + init_gps(gps_panda) + else: + print("Got " + str(received_messages) + " (" + str(received_bytes) + "B) messages in the last " + str(CHECK_PERIOD) + " seconds.") + if(min_failures > 0): + print("Total min failures: ", min_failures) + if(max_failures > 0): + print("Total max failures: ", max_failures) + received_messages = 0 + received_bytes = 0 + + + + \ No newline at end of file diff --git a/panda/tests/health_test.py b/panda/tests/health_test.py index 1042c860d866f1..69234c7d6462f2 100755 --- a/panda/tests/health_test.py +++ b/panda/tests/health_test.py @@ -1,7 +1,7 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import time from panda import Panda - + if __name__ == "__main__": panda_serials = Panda.list() pandas = [] diff --git a/panda/tests/language/Dockerfile b/panda/tests/language/Dockerfile index 068847145e4b0f..fe957ff7230722 100644 --- a/panda/tests/language/Dockerfile +++ b/panda/tests/language/Dockerfile @@ -1,6 +1,18 @@ FROM ubuntu:16.04 -RUN apt-get update && apt-get install -y make python python-pip +RUN apt-get update && apt-get install -y make python python-pip locales curl git zlib1g-dev libffi-dev bzip2 libssl-dev + +RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 + +RUN curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash + +ENV PATH="/root/.pyenv/bin:/root/.pyenv/shims:${PATH}" +RUN pyenv install 3.7.3 +RUN pyenv global 3.7.3 +RUN pyenv rehash + COPY tests/safety/requirements.txt /panda/tests/safety/requirements.txt -RUN pip install -r /panda/tests/safety/requirements.txt COPY . /panda diff --git a/panda/tests/language/test_language.py b/panda/tests/language/test_language.py index 3afb34619aa19f..353f37e8546fb8 100755 --- a/panda/tests/language/test_language.py +++ b/panda/tests/language/test_language.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import subprocess import sys @@ -18,11 +18,11 @@ try: cmd = "cd ../../; grep -R -i -w " + suffix_cmd + " '" + line + "'" res = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT) - print res + print(res) found_bad_language = True except subprocess.CalledProcessError as e: pass if found_bad_language: sys.exit("Failed: found bad language") else: - print "Success" + print("Success") diff --git a/panda/tests/location_listener.py b/panda/tests/location_listener.py index cbbb00d794f5e3..62ade10f03fdde 100755 --- a/panda/tests/location_listener.py +++ b/panda/tests/location_listener.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import os import time import sys @@ -18,20 +18,20 @@ def add_nmea_checksum(msg): ser = PandaSerial(panda, 1, 9600) # power cycle by toggling reset - print "resetting" + print("resetting") panda.set_esp_power(0) time.sleep(0.5) panda.set_esp_power(1) time.sleep(0.5) - print "done" - print ser.read(1024) + print("done") + print(ser.read(1024)) # upping baud rate baudrate = 460800 - print "upping baud rate" + print("upping baud rate") msg = add_nmea_checksum("$PUBX,41,1,0007,0003,%d,0" % baudrate)+"\r\n" - print msg + print(msg) ser.write(msg) time.sleep(0.1) # needs a wait for it to actually send @@ -41,7 +41,7 @@ def add_nmea_checksum(msg): while True: ret = ser.read(1024) if len(ret) > 0: - sys.stdout.write(ret) + sys.stdout.write(ret.decode('ascii', 'ignore')) sys.stdout.flush() #print str(ret).encode("hex") diff --git a/panda/tests/loopback_test.py b/panda/tests/loopback_test.py index a871295ad6fd83..02c8d2cd144a12 100755 --- a/panda/tests/loopback_test.py +++ b/panda/tests/loopback_test.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python -from __future__ import print_function +#!/usr/bin/env python3 + import os import sys import time @@ -29,14 +29,14 @@ def run_test(sleep_duration): run_test_w_pandas(pandas, sleep_duration) def run_test_w_pandas(pandas, sleep_duration): - h = list(map(lambda x: Panda(x), pandas)) + h = list([Panda(x) for x in pandas]) print("H", h) for hh in h: hh.set_safety_mode(Panda.SAFETY_ALLOUTPUT) # test both directions - for ho in permutations(range(len(h)), r=2): + for ho in permutations(list(range(len(h))), r=2): print("***************** TESTING", ho) panda0, panda1 = h[ho[0]], h[ho[1]] diff --git a/panda/tests/misra/coverage_table b/panda/tests/misra/coverage_table new file mode 100644 index 00000000000000..a00cd84a5f304d --- /dev/null +++ b/panda/tests/misra/coverage_table @@ -0,0 +1,143 @@ +1.1 +1.2 +1.3 X (Cppcheck) +2.1 X (Cppcheck) +2.2 X (Cppcheck) +2.3 +2.4 X (Cppcheck) +2.5 +2.6 X (Cppcheck) +2.7 +3.1 X (Addon) +3.2 +4.1 X (Addon) +4.2 +5.1 X (Addon) +5.2 X (Addon) +5.3 X (Addon) +5.4 X (Addon) +5.5 X (Addon) +5.6 +5.7 +5.8 +5.9 +6.1 +6.2 +7.1 X (Addon) +7.2 +7.3 X (Addon) +7.4 +8.1 +8.2 +8.3 X (Cppcheck) +8.4 +8.5 +8.6 +8.7 +8.8 +8.9 +8.10 +8.11 X (Addon) +8.12 X (Addon) +8.13 +8.14 X (Addon) +9.1 +9.2 +9.3 +9.4 +9.5 X (Addon) +10.1 X (Addon) +10.2 +10.3 +10.4 X (Addon) +10.5 +10.6 X (Addon) +10.7 +10.8 X (Addon) +11.1 +11.2 +11.3 X (Addon) +11.4 X (Addon) +11.5 X (Addon) +11.6 X (Addon) +11.7 X (Addon) +11.8 X (Addon) +11.9 X (Addon) +12.1 X (Addon) +12.2 X (Addon) +12.3 X (Addon) +12.4 X (Addon) +13.1 X (Addon) +13.2 X (Cppcheck) +13.3 X (Addon) +13.4 X (Addon) +13.5 X (Addon) +13.6 X (Addon) +14.1 X (Addon) +14.2 X (Addon) +14.3 X (Cppcheck) +14.4 X (Addon) +15.1 X (Addon) +15.2 X (Addon) +15.3 X (Addon) +15.4 +15.5 X (Addon) +15.6 X (Addon) +15.7 X (Addon) +16.1 +16.2 X (Addon) +16.3 X (Addon) +16.4 X (Addon) +16.5 X (Addon) +16.6 X (Addon) +16.7 X (Addon) +17.1 X (Addon) +17.2 X (Addon) +17.3 +17.4 +17.5 X (Cppcheck) +17.6 X (Addon) +17.7 X (Addon) +17.8 X (Addon) +18.1 X (Cppcheck) +18.2 X (Cppcheck) +18.3 X (Cppcheck) +18.4 X (Addon) +18.5 X (Addon) +18.6 X (Cppcheck) +18.7 X (Addon) +18.8 X (Addon) +19.1 +19.2 X (Addon) +20.1 X (Addon) +20.2 X (Addon) +20.3 X (Addon) +20.4 X (Addon) +20.5 X (Addon) +20.6 X (Cppcheck) +20.7 X (Addon) +20.8 +20.9 +20.10 X (Addon) +20.11 +20.12 +20.13 X (Addon) +20.14 X (Addon) +21.1 +21.2 +21.3 X (Addon) +21.4 X (Addon) +21.5 X (Addon) +21.6 X (Addon) +21.7 X (Addon) +21.8 X (Addon) +21.9 X (Addon) +21.10 X (Addon) +21.11 X (Addon) +21.12 +22.1 X (Cppcheck) +22.2 X (Cppcheck) +22.3 +22.4 X (Cppcheck) +22.5 +22.6 X (Cppcheck) diff --git a/panda/tests/misra/suppressions.txt b/panda/tests/misra/suppressions.txt index 8e58b6e34024a4..b98a491eeb07ad 100644 --- a/panda/tests/misra/suppressions.txt +++ b/panda/tests/misra/suppressions.txt @@ -1,7 +1,5 @@ # Advisory: union types can be used misra.19.2 -# FIXME: add it back when fixed in cppcheck. Macro identifiers are unique but it false triggers on defines in #ifdef..#else conditions -misra.5.4 # Advisory: casting from void pointer to type pointer is ok. Done by STM libraries as well misra.11.4 # Advisory: casting from void pointer to type pointer is ok. Done by STM libraries as well diff --git a/panda/tests/misra/test_misra.sh b/panda/tests/misra/test_misra.sh index 6338009120b055..c4aceaa92c010d 100755 --- a/panda/tests/misra/test_misra.sh +++ b/panda/tests/misra/test_misra.sh @@ -4,10 +4,12 @@ mkdir /tmp/misra || true git clone https://github.com/danmar/cppcheck.git || true cd cppcheck git fetch -git checkout 862c4ef87b109ae86c2d5f12769b7c8d199f35c5 +git checkout ff7dba91e177dfb712477faddb9e91bece7e743c make -j4 cd ../../../ +# generate coverage matrix +python tests/misra/cppcheck/addons/misra.py -generate-table > tests/misra/coverage_table printf "\nPANDA CODE\n" tests/misra/cppcheck/cppcheck -DPANDA -UPEDAL -DCAN3 -DUID_BASE -DEON \ @@ -18,8 +20,8 @@ tests/misra/cppcheck/cppcheck -DPANDA -UPEDAL -DCAN3 -DUID_BASE -DEON \ python tests/misra/cppcheck/addons/misra.py board/main.c.dump 2> /tmp/misra/misra_output.txt || true # strip (information) lines -cppcheck_output=$( cat /tmp/misra/cppcheck_output.txt | grep -v "(information) " ) || true -misra_output=$( cat /tmp/misra/misra_output.txt | grep -v "(information) " ) || true +cppcheck_output=$( cat /tmp/misra/cppcheck_output.txt | grep -v ": information: " ) || true +misra_output=$( cat /tmp/misra/misra_output.txt | grep -v ": information: " ) || true printf "\nPEDAL CODE\n" @@ -31,8 +33,8 @@ tests/misra/cppcheck/cppcheck -UPANDA -DPEDAL -UCAN3 \ python tests/misra/cppcheck/addons/misra.py board/pedal/main.c.dump 2> /tmp/misra/misra_pedal_output.txt || true # strip (information) lines -cppcheck_pedal_output=$( cat /tmp/misra/cppcheck_pedal_output.txt | grep -v "(information) " ) || true -misra_pedal_output=$( cat /tmp/misra/misra_pedal_output.txt | grep -v "(information) " ) || true +cppcheck_pedal_output=$( cat /tmp/misra/cppcheck_pedal_output.txt | grep -v ": information: " ) || true +misra_pedal_output=$( cat /tmp/misra/misra_pedal_output.txt | grep -v ": information: " ) || true if [[ -n "$misra_output" ]] || [[ -n "$cppcheck_output" ]] then diff --git a/panda/tests/pedal/enter_canloader.py b/panda/tests/pedal/enter_canloader.py index c6f06ca35499a0..cc37f2b843533c 100755 --- a/panda/tests/pedal/enter_canloader.py +++ b/panda/tests/pedal/enter_canloader.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import sys import time import struct @@ -53,24 +53,24 @@ def bulkRead(self, endpoint, length, timeout=0): args = parser.parse_args() p = Panda() - p.set_safety_mode(0x1337) + p.set_safety_mode(Panda.SAFETY_ALLOUTPUT) while 1: if len(p.can_recv()) == 0: break if args.recover: - p.can_send(0x200, "\xce\xfa\xad\xde\x1e\x0b\xb0\x02", 0) + p.can_send(0x200, b"\xce\xfa\xad\xde\x1e\x0b\xb0\x02", 0) exit(0) else: - p.can_send(0x200, "\xce\xfa\xad\xde\x1e\x0b\xb0\x0a", 0) + p.can_send(0x200, b"\xce\xfa\xad\xde\x1e\x0b\xb0\x0a", 0) if args.fn: time.sleep(0.1) - print "flashing", args.fn - code = open(args.fn).read() + print("flashing", args.fn) + code = open(args.fn, "rb").read() Panda.flash_static(CanHandle(p), code) - print "can flash done" + print("can flash done") diff --git a/panda/tests/read_winusb_descriptors.py b/panda/tests/read_winusb_descriptors.py index e38df8d1caa9c3..ea5e93f32dfce8 100644 --- a/panda/tests/read_winusb_descriptors.py +++ b/panda/tests/read_winusb_descriptors.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 from panda import Panda from hexdump import hexdump @@ -8,22 +8,22 @@ p = Panda() len = p._handle.controlRead(Panda.REQUEST_IN, 0x06, 3 << 8 | 238, 0, 1) - print 'Microsoft OS String Descriptor' + print('Microsoft OS String Descriptor') dat = p._handle.controlRead(Panda.REQUEST_IN, 0x06, 3 << 8 | 238, 0, len[0]) - if DEBUG: print 'LEN: {}'.format(hex(len[0])) + if DEBUG: print('LEN: {}'.format(hex(len[0]))) hexdump("".join(map(chr, dat))) ms_vendor_code = dat[16] - if DEBUG: print 'MS_VENDOR_CODE: {}'.format(hex(len[0])) + if DEBUG: print('MS_VENDOR_CODE: {}'.format(hex(len[0]))) - print '\nMicrosoft Compatible ID Feature Descriptor' + print('\nMicrosoft Compatible ID Feature Descriptor') len = p._handle.controlRead(Panda.REQUEST_IN, ms_vendor_code, 0, 4, 1) - if DEBUG: print 'LEN: {}'.format(hex(len[0])) + if DEBUG: print('LEN: {}'.format(hex(len[0]))) dat = p._handle.controlRead(Panda.REQUEST_IN, ms_vendor_code, 0, 4, len[0]) hexdump("".join(map(chr, dat))) - print '\nMicrosoft Extended Properties Feature Descriptor' + print('\nMicrosoft Extended Properties Feature Descriptor') len = p._handle.controlRead(Panda.REQUEST_IN, ms_vendor_code, 0, 5, 1) - if DEBUG: print 'LEN: {}'.format(hex(len[0])) + if DEBUG: print('LEN: {}'.format(hex(len[0]))) dat = p._handle.controlRead(Panda.REQUEST_IN, ms_vendor_code, 0, 5, len[0]) hexdump("".join(map(chr, dat))) diff --git a/panda/tests/safety/Dockerfile b/panda/tests/safety/Dockerfile index 9381fdc4085759..b0135b085f6595 100644 --- a/panda/tests/safety/Dockerfile +++ b/panda/tests/safety/Dockerfile @@ -1,6 +1,19 @@ FROM ubuntu:16.04 -RUN apt-get update && apt-get install -y clang make python python-pip -COPY tests/safety/requirements.txt /panda/tests/safety/requirements.txt -RUN pip install -r /panda/tests/safety/requirements.txt +RUN apt-get update && apt-get install -y clang make python python-pip git curl locales zlib1g-dev libffi-dev bzip2 libssl-dev libbz2-dev libusb-1.0-0 + +RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 + +RUN curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash + +ENV PATH="/root/.pyenv/bin:/root/.pyenv/shims:${PATH}" +RUN pyenv install 3.7.3 +RUN pyenv global 3.7.3 +RUN pyenv rehash + +COPY tests/safety/requirements.txt requirements.txt +RUN pip install -r requirements.txt COPY . /panda diff --git a/panda/tests/safety/requirements.txt b/panda/tests/safety/requirements.txt index 8bbfb1d7df38a2..0c3124d87fb216 100644 --- a/panda/tests/safety/requirements.txt +++ b/panda/tests/safety/requirements.txt @@ -1,2 +1,4 @@ cffi==1.11.4 -numpy==1.14.1 +numpy==1.14.5 +libusb1==1.6.6 +requests diff --git a/panda/tests/safety/test_cadillac.py b/panda/tests/safety/test_cadillac.py index af89e69cc7710e..5573682d0cd44c 100644 --- a/panda/tests/safety/test_cadillac.py +++ b/panda/tests/safety/test_cadillac.py @@ -1,7 +1,8 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import unittest import numpy as np import libpandasafety_py +from panda import Panda MAX_RATE_UP = 2 MAX_RATE_DOWN = 5 @@ -31,7 +32,7 @@ class TestCadillacSafety(unittest.TestCase): @classmethod def setUp(cls): cls.safety = libpandasafety_py.libpandasafety - cls.safety.safety_set_mode(6, 0) + cls.safety.safety_set_mode(Panda.SAFETY_CADILLAC, 0) cls.safety.init_tests_cadillac() def _send_msg(self, bus, addr, length): @@ -183,8 +184,8 @@ def test_realtime_limits(self): def test_fwd_hook(self): # nothing allowed - buss = range(0x0, 0x3) - msgs = range(0x1, 0x800) + buss = list(range(0x0, 0x3)) + msgs = list(range(0x1, 0x800)) for b in buss: for m in msgs: diff --git a/panda/tests/safety/test_chrysler.py b/panda/tests/safety/test_chrysler.py index 09aa424dd99b28..25f50a11f9fb31 100755 --- a/panda/tests/safety/test_chrysler.py +++ b/panda/tests/safety/test_chrysler.py @@ -1,9 +1,10 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import csv import glob import unittest import numpy as np import libpandasafety_py +from panda import Panda MAX_RATE_UP = 3 MAX_RATE_DOWN = 3 @@ -35,7 +36,7 @@ class TestChryslerSafety(unittest.TestCase): @classmethod def setUp(cls): cls.safety = libpandasafety_py.libpandasafety - cls.safety.safety_set_mode(9, 0) + cls.safety.safety_set_mode(Panda.SAFETY_CHRYSLER, 0) cls.safety.init_tests_chrysler() def _send_msg(self, bus, addr, length): @@ -181,8 +182,8 @@ def test_torque_measurements(self): self.assertEqual(0, self.safety.get_chrysler_torque_meas_min()) def test_fwd_hook(self): - buss = range(0x0, 0x3) - msgs = range(0x1, 0x800) + buss = list(range(0x0, 0x3)) + msgs = list(range(0x1, 0x800)) chrysler_camera_detected = [0, 1] for ccd in chrysler_camera_detected: diff --git a/panda/tests/safety/test_gm.py b/panda/tests/safety/test_gm.py index d9a1d39ec76dd3..e2251f7b557f8f 100644 --- a/panda/tests/safety/test_gm.py +++ b/panda/tests/safety/test_gm.py @@ -1,7 +1,8 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import unittest import numpy as np import libpandasafety_py +from panda import Panda MAX_RATE_UP = 7 MAX_RATE_DOWN = 17 @@ -32,7 +33,7 @@ class TestGmSafety(unittest.TestCase): @classmethod def setUp(cls): cls.safety = libpandasafety_py.libpandasafety - cls.safety.safety_set_mode(3, 0) + cls.safety.safety_set_mode(Panda.SAFETY_GM, 0) cls.safety.init_tests_gm() def _send_msg(self, bus, addr, length): @@ -282,8 +283,8 @@ def test_realtime_limits(self): def test_fwd_hook(self): # nothing allowed - buss = range(0x0, 0x3) - msgs = range(0x1, 0x800) + buss = list(range(0x0, 0x3)) + msgs = list(range(0x1, 0x800)) for b in buss: for m in msgs: diff --git a/panda/tests/safety/test_honda.py b/panda/tests/safety/test_honda.py index f2f59389767ec1..a5eb04ad6632c5 100755 --- a/panda/tests/safety/test_honda.py +++ b/panda/tests/safety/test_honda.py @@ -1,7 +1,8 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import unittest import numpy as np import libpandasafety_py +from panda import Panda MAX_BRAKE = 255 @@ -11,7 +12,7 @@ class TestHondaSafety(unittest.TestCase): @classmethod def setUp(cls): cls.safety = libpandasafety_py.libpandasafety - cls.safety.safety_set_mode(1, 0) + cls.safety.safety_set_mode(Panda.SAFETY_HONDA, 0) cls.safety.init_tests_honda() def _send_msg(self, bus, addr, length): @@ -254,8 +255,8 @@ def test_spam_cancel_safety_check(self): self.assertTrue(self.safety.safety_tx_hook(self._button_msg(RESUME_BTN, BUTTON_MSG))) def test_fwd_hook(self): - buss = range(0x0, 0x3) - msgs = range(0x1, 0x800) + buss = list(range(0x0, 0x3)) + msgs = list(range(0x1, 0x800)) long_controls_allowed = [0, 1] fwd_brake = [False, True] diff --git a/panda/tests/safety/test_honda_bosch.py b/panda/tests/safety/test_honda_bosch.py index 0d37cbe8072a0b..3affc74c9a72f8 100755 --- a/panda/tests/safety/test_honda_bosch.py +++ b/panda/tests/safety/test_honda_bosch.py @@ -1,7 +1,8 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import unittest import numpy as np import libpandasafety_py +from panda import Panda MAX_BRAKE = 255 @@ -9,7 +10,7 @@ class TestHondaSafety(unittest.TestCase): @classmethod def setUp(cls): cls.safety = libpandasafety_py.libpandasafety - cls.safety.safety_set_mode(4, 0) + cls.safety.safety_set_mode(Panda.SAFETY_HONDA_BOSCH, 0) cls.safety.init_tests_honda() def _send_msg(self, bus, addr, length): @@ -21,8 +22,8 @@ def _send_msg(self, bus, addr, length): return to_send def test_fwd_hook(self): - buss = range(0x0, 0x3) - msgs = range(0x1, 0x800) + buss = list(range(0x0, 0x3)) + msgs = list(range(0x1, 0x800)) is_panda_black = self.safety.get_hw_type() == 3 # black panda bus_rdr_cam = 2 if is_panda_black else 1 bus_rdr_car = 0 if is_panda_black else 2 diff --git a/panda/tests/safety/test_hyundai.py b/panda/tests/safety/test_hyundai.py index 539982fab92a26..d836dad37b266f 100644 --- a/panda/tests/safety/test_hyundai.py +++ b/panda/tests/safety/test_hyundai.py @@ -1,7 +1,8 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import unittest import numpy as np import libpandasafety_py +from panda import Panda MAX_RATE_UP = 3 MAX_RATE_DOWN = 7 @@ -29,7 +30,7 @@ class TestHyundaiSafety(unittest.TestCase): @classmethod def setUp(cls): cls.safety = libpandasafety_py.libpandasafety - cls.safety.safety_set_mode(7, 0) + cls.safety.safety_set_mode(Panda.SAFETY_HYUNDAI, 0) cls.safety.init_tests_hyundai() def _send_msg(self, bus, addr, length): @@ -190,8 +191,8 @@ def test_realtime_limits(self): def test_fwd_hook(self): - buss = range(0x0, 0x3) - msgs = range(0x1, 0x800) + buss = list(range(0x0, 0x3)) + msgs = list(range(0x1, 0x800)) hyundai_giraffe_switch_2 = [0, 1] self.safety.set_hyundai_camera_bus(2) diff --git a/panda/tests/safety/test_subaru.py b/panda/tests/safety/test_subaru.py index 13fe1fb14f2b91..93859e0217837b 100644 --- a/panda/tests/safety/test_subaru.py +++ b/panda/tests/safety/test_subaru.py @@ -1,7 +1,8 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import unittest import numpy as np import libpandasafety_py +from panda import Panda MAX_RATE_UP = 50 MAX_RATE_DOWN = 70 @@ -29,7 +30,7 @@ class TestSubaruSafety(unittest.TestCase): @classmethod def setUp(cls): cls.safety = libpandasafety_py.libpandasafety - cls.safety.safety_set_mode(10, 0) + cls.safety.safety_set_mode(Panda.SAFETY_SUBARU, 0) cls.safety.init_tests_subaru() def _send_msg(self, bus, addr, length): @@ -174,8 +175,8 @@ def test_realtime_limits(self): def test_fwd_hook(self): - buss = range(0x0, 0x3) - msgs = range(0x1, 0x800) + buss = list(range(0x0, 0x3)) + msgs = list(range(0x1, 0x800)) blocked_msgs = [290, 356, 545, 802] for b in buss: for m in msgs: diff --git a/panda/tests/safety/test_toyota.py b/panda/tests/safety/test_toyota.py index dc5b21ac8f7b42..135207779d8a31 100644 --- a/panda/tests/safety/test_toyota.py +++ b/panda/tests/safety/test_toyota.py @@ -1,7 +1,8 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import unittest import numpy as np import libpandasafety_py +from panda import Panda MAX_RATE_UP = 10 MAX_RATE_DOWN = 25 @@ -33,7 +34,7 @@ class TestToyotaSafety(unittest.TestCase): @classmethod def setUp(cls): cls.safety = libpandasafety_py.libpandasafety - cls.safety.safety_set_mode(2, 100) + cls.safety.safety_set_mode(Panda.SAFETY_TOYOTA, 100) cls.safety.init_tests_toyota() def _send_msg(self, bus, addr, length): @@ -281,8 +282,8 @@ def test_gas_interceptor_safety_check(self): def test_fwd_hook(self): - buss = range(0x0, 0x3) - msgs = range(0x1, 0x800) + buss = list(range(0x0, 0x3)) + msgs = list(range(0x1, 0x800)) long_controls_allowed = [0, 1] toyota_camera_forwarded = [0, 1] diff --git a/panda/tests/safety/test_toyota_ipas.py b/panda/tests/safety/test_toyota_ipas.py index 7a382093e0b45b..8d565553fd2144 100644 --- a/panda/tests/safety/test_toyota_ipas.py +++ b/panda/tests/safety/test_toyota_ipas.py @@ -1,7 +1,8 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import unittest import numpy as np import libpandasafety_py +from panda import Panda IPAS_OVERRIDE_THRESHOLD = 200 @@ -25,7 +26,7 @@ class TestToyotaSafety(unittest.TestCase): @classmethod def setUp(cls): cls.safety = libpandasafety_py.libpandasafety - cls.safety.safety_set_mode(0x1335, 66) + cls.safety.safety_set_mode(Panda.SAFETY_TOYOTA_IPAS, 66) cls.safety.init_tests_toyota() def _torque_driver_msg(self, torque): @@ -135,7 +136,7 @@ def test_angle_cmd_when_disabled(self): # test angle cmd too far from actual angle_refs = [-10, 10] - deltas = range(-2, 3) + deltas = list(range(-2, 3)) expected_results = [False, True, True, True, False] for a in angle_refs: diff --git a/panda/tests/safety_replay/Dockerfile b/panda/tests/safety_replay/Dockerfile index 5d59ca38d51960..80663964d3e2da 100644 --- a/panda/tests/safety_replay/Dockerfile +++ b/panda/tests/safety_replay/Dockerfile @@ -1,6 +1,18 @@ FROM ubuntu:16.04 -RUN apt-get update && apt-get install -y make clang python python-pip git libarchive-dev libusb-1.0-0 +RUN apt-get update && apt-get install -y make clang python python-pip git libarchive-dev libusb-1.0-0 locales curl zlib1g-dev libffi-dev bzip2 libssl-dev libbz2-dev + +RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 + +RUN curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash + +ENV PATH="/root/.pyenv/bin:/root/.pyenv/shims:${PATH}" +RUN pyenv install 3.7.3 +RUN pyenv global 3.7.3 +RUN pyenv rehash COPY tests/safety_replay/requirements.txt requirements.txt RUN pip install -r requirements.txt @@ -17,4 +29,4 @@ COPY . /openpilot/panda WORKDIR /openpilot/panda/tests/safety_replay RUN git clone https://github.com/commaai/openpilot-tools.git tools || true WORKDIR tools -RUN git checkout feb724a14f0f5223c700c94317efaf46923fd48a +RUN git checkout d69c6bc85f221766305ec53956e9a1d3bf283160 diff --git a/panda/tests/safety_replay/helpers.py b/panda/tests/safety_replay/helpers.py index 05bbe08930ac7b..6f4e63c3256304 100644 --- a/panda/tests/safety_replay/helpers.py +++ b/panda/tests/safety_replay/helpers.py @@ -1,23 +1,7 @@ +#!/usr/bin/env python3 import struct import panda.tests.safety.libpandasafety_py as libpandasafety_py - -safety_modes = { - "NOOUTPUT": 0, - "HONDA": 1, - "TOYOTA": 2, - "GM": 3, - "HONDA_BOSCH": 4, - "FORD": 5, - "CADILLAC": 6, - "HYUNDAI": 7, - "TESLA": 8, - "CHRYSLER": 9, - "SUBARU": 10, - "GM_ASCM": 0x1334, - "TOYOTA_IPAS": 0x1335, - "ALLOUTPUT": 0x1337, - "ELM327": 0xE327 -} +from panda import Panda def to_signed(d, bits): ret = d @@ -27,51 +11,51 @@ def to_signed(d, bits): def is_steering_msg(mode, addr): ret = False - if mode == safety_modes["HONDA"] or mode == safety_modes["HONDA_BOSCH"]: + if mode == Panda.SAFETY_HONDA or mode == Panda.SAFETY_HONDA_BOSCH: ret = (addr == 0xE4) or (addr == 0x194) or (addr == 0x33D) - elif mode == safety_modes["TOYOTA"]: + elif mode == Panda.SAFETY_TOYOTA: ret = addr == 0x2E4 - elif mode == safety_modes["GM"]: + elif mode == Panda.SAFETY_GM: ret = addr == 384 - elif mode == safety_modes["HYUNDAI"]: + elif mode == Panda.SAFETY_HYUNDAI: ret = addr == 832 - elif mode == safety_modes["CHRYSLER"]: + elif mode == Panda.SAFETY_CHRYSLER: ret = addr == 0x292 - elif mode == safety_modes["SUBARU"]: + elif mode == Panda.SAFETY_SUBARU: ret = addr == 0x122 return ret def get_steer_torque(mode, to_send): ret = 0 - if mode == safety_modes["HONDA"] or mode == safety_modes["HONDA_BOSCH"]: + if mode == Panda.SAFETY_HONDA or mode == Panda.SAFETY_HONDA_BOSCH: ret = to_send.RDLR & 0xFFFF0000 - elif mode == safety_modes["TOYOTA"]: + elif mode == Panda.SAFETY_TOYOTA: ret = (to_send.RDLR & 0xFF00) | ((to_send.RDLR >> 16) & 0xFF) ret = to_signed(ret, 16) - elif mode == safety_modes["GM"]: + elif mode == Panda.SAFETY_GM: ret = ((to_send.RDLR & 0x7) << 8) + ((to_send.RDLR & 0xFF00) >> 8) ret = to_signed(ret, 11) - elif mode == safety_modes["HYUNDAI"]: + elif mode == Panda.SAFETY_HYUNDAI: ret = ((to_send.RDLR >> 16) & 0x7ff) - 1024 - elif mode == safety_modes["CHRYSLER"]: + elif mode == Panda.SAFETY_CHRYSLER: ret = ((to_send.RDLR & 0x7) << 8) + ((to_send.RDLR & 0xFF00) >> 8) - 1024 - elif mode == safety_modes["SUBARU"]: + elif mode == Panda.SAFETY_SUBARU: ret = ((to_send.RDLR >> 16) & 0x1FFF) ret = to_signed(ret, 13) return ret def set_desired_torque_last(safety, mode, torque): - if mode == safety_modes["HONDA"] or mode == safety_modes["HONDA_BOSCH"]: + if mode == Panda.SAFETY_HONDA or mode == Panda.SAFETY_HONDA_BOSCH: pass # honda safety mode doesn't enforce a rate on steering msgs - elif mode == safety_modes["TOYOTA"]: + elif mode == Panda.SAFETY_TOYOTA: safety.set_toyota_desired_torque_last(torque) - elif mode == safety_modes["GM"]: + elif mode == Panda.SAFETY_GM: safety.set_gm_desired_torque_last(torque) - elif mode == safety_modes["HYUNDAI"]: + elif mode == Panda.SAFETY_HYUNDAI: safety.set_hyundai_desired_torque_last(torque) - elif mode == safety_modes["CHRYSLER"]: + elif mode == Panda.SAFETY_CHRYSLER: safety.set_chrysler_desired_torque_last(torque) - elif mode == safety_modes["SUBARU"]: + elif mode == Panda.SAFETY_SUBARU: safety.set_subaru_desired_torque_last(torque) def package_can_msg(msg): diff --git a/panda/tests/safety_replay/replay_drive.py b/panda/tests/safety_replay/replay_drive.py index 1b2ba082ac9821..d92ab8e7080533 100755 --- a/panda/tests/safety_replay/replay_drive.py +++ b/panda/tests/safety_replay/replay_drive.py @@ -1,11 +1,12 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import os import sys +from panda import Panda import panda.tests.safety.libpandasafety_py as libpandasafety_py from panda.tests.safety_replay.helpers import is_steering_msg, get_steer_torque, \ set_desired_torque_last, package_can_msg, \ - init_segment, safety_modes + init_segment from tools.lib.logreader import LogReader # replay a drive to check for safety violations @@ -25,7 +26,7 @@ def replay_drive(lr, safety_mode, param): for msg in lr: if start_t is None: start_t = msg.logMonoTime - safety.set_timer(((msg.logMonoTime / 1000)) % 0xFFFFFFFF) + safety.set_timer(((msg.logMonoTime // 1000)) % 0xFFFFFFFF) if msg.which() == 'sendcan': for canmsg in msg.sendcan: @@ -37,7 +38,7 @@ def replay_drive(lr, safety_mode, param): blocked_addrs.add(canmsg.address) if "DEBUG" in os.environ: - print "blocked %d at %f" % (canmsg.address, (msg.logMonoTime - start_t)/(1e9)) + print("blocked %d at %f" % (canmsg.address, (msg.logMonoTime - start_t)/(1e9))) tx_controls += safety.get_controls_allowed() tx_tot += 1 elif msg.which() == 'can': @@ -48,23 +49,20 @@ def replay_drive(lr, safety_mode, param): to_push = package_can_msg(canmsg) safety.safety_rx_hook(to_push) - print "total openpilot msgs:", tx_tot - print "total msgs with controls allowed:", tx_controls - print "blocked msgs:", tx_blocked - print "blocked with controls allowed:", tx_controls_blocked - print "blocked addrs:", blocked_addrs + print("total openpilot msgs:", tx_tot) + print("total msgs with controls allowed:", tx_controls) + print("blocked msgs:", tx_blocked) + print("blocked with controls allowed:", tx_controls_blocked) + print("blocked addrs:", blocked_addrs) return tx_controls_blocked == 0 if __name__ == "__main__": - if sys.argv[2] in safety_modes: - mode = safety_modes[sys.argv[2]] - else: - mode = int(sys.argv[2]) + mode = int(sys.argv[2]) param = 0 if len(sys.argv) < 4 else int(sys.argv[3]) lr = LogReader(sys.argv[1]) - print "replaying drive %s with safety mode %d and param %d" % (sys.argv[1], mode, param) + print("replaying drive %s with safety mode %d and param %d" % (sys.argv[1], mode, param)) replay_drive(lr, mode, param) diff --git a/panda/tests/safety_replay/test_safety_replay.py b/panda/tests/safety_replay/test_safety_replay.py index ecc34161f2d868..e6e49dc02d8556 100755 --- a/panda/tests/safety_replay/test_safety_replay.py +++ b/panda/tests/safety_replay/test_safety_replay.py @@ -1,9 +1,9 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import os import requests -from helpers import safety_modes +from panda import Panda from replay_drive import replay_drive from tools.lib.logreader import LogReader @@ -11,31 +11,30 @@ # (route, safety mode, param) logs = [ - ("b0c9d2329ad1606b|2019-05-30--20-23-57.bz2", "HONDA", 0), # HONDA.CIVIC - ("38bfd238edecbcd7|2019-06-07--10-15-25.bz2", "TOYOTA", 66), # TOYOTA.PRIUS - ("f89c604cf653e2bf|2018-09-29--13-46-50.bz2", "GM", 0), # GM.VOLT - ("0375fdf7b1ce594d|2019-05-21--20-10-33.bz2", "HONDA_BOSCH", 1), # HONDA.ACCORD - ("02ec6bea180a4d36|2019-04-17--11-21-35.bz2", "HYUNDAI", 0), # HYUNDAI.SANTA_FE - ("03efb1fda29e30fe|2019-02-21--18-03-45.bz2", "CHRYSLER", 0), # CHRYSLER.PACIFICA_2018_HYBRID - ("791340bc01ed993d|2019-04-08--10-26-00.bz2", "SUBARU", 0), # SUBARU.IMPREZA + ("b0c9d2329ad1606b|2019-05-30--20-23-57.bz2", Panda.SAFETY_HONDA, 0), # HONDA.CIVIC + ("38bfd238edecbcd7|2019-06-07--10-15-25.bz2", Panda.SAFETY_TOYOTA, 66), # TOYOTA.PRIUS + ("f89c604cf653e2bf|2018-09-29--13-46-50.bz2", Panda.SAFETY_GM, 0), # GM.VOLT + ("0375fdf7b1ce594d|2019-05-21--20-10-33.bz2", Panda.SAFETY_HONDA_BOSCH, 1), # HONDA.ACCORD + ("02ec6bea180a4d36|2019-04-17--11-21-35.bz2", Panda.SAFETY_HYUNDAI, 0), # HYUNDAI.SANTA_FE + ("03efb1fda29e30fe|2019-02-21--18-03-45.bz2", Panda.SAFETY_CHRYSLER, 0), # CHRYSLER.PACIFICA_2018_HYBRID + ("791340bc01ed993d|2019-04-08--10-26-00.bz2", Panda.SAFETY_SUBARU, 0), # SUBARU.IMPREZA ] if __name__ == "__main__": for route, _, _ in logs: if not os.path.isfile(route): - with open(route, "w") as f: + with open(route, "wb") as f: f.write(requests.get(BASE_URL + route).content) failed = [] for route, mode, param in logs: lr = LogReader(route) - m = safety_modes.get(mode, mode) - print "\nreplaying %s with safety mode %d and param %s" % (route, m, param) - if not replay_drive(lr, m, int(param)): + print("\nreplaying %s with safety mode %d and param %s" % (route, mode, param)) + if not replay_drive(lr, mode, int(param)): failed.append(route) for f in failed: - print "\n**** failed on %s ****" % f + print("\n**** failed on %s ****" % f) assert len(failed) == 0, "\nfailed on %d logs" % len(failed) diff --git a/panda/tests/spam_can.py b/panda/tests/spam_can.py new file mode 100755 index 00000000000000..6b0c2d9c60a581 --- /dev/null +++ b/panda/tests/spam_can.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 + +import os +import sys +import time +import random + +sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), "..")) +from panda import Panda + +def get_test_string(): + return b"test"+os.urandom(10) + +if __name__ == "__main__": + p = Panda() + p.set_safety_mode(Panda.SAFETY_ALLOUTPUT) + + print("Spamming all buses...") + while True: + at = random.randint(1, 2000) + st = get_test_string()[0:8] + bus = random.randint(0, 2) + p.can_send(at, st, bus) + #print("Sent message on bus: ", bus) \ No newline at end of file diff --git a/panda/tests/standalone_test.py b/panda/tests/standalone_test.py index ca6ea49f1056de..9e181d8fc95fca 100755 --- a/panda/tests/standalone_test.py +++ b/panda/tests/standalone_test.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import os import sys import struct diff --git a/panda/tests/throughput_test.py b/panda/tests/throughput_test.py index 5812ce42c2aa1c..69b06c7646d0b2 100755 --- a/panda/tests/throughput_test.py +++ b/panda/tests/throughput_test.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python -from __future__ import print_function +#!/usr/bin/env python3 + import os import sys import struct @@ -34,7 +34,7 @@ p_in.can_recv() BATCH_SIZE = 16 - for a in tqdm(range(0, 10000, BATCH_SIZE)): + for a in tqdm(list(range(0, 10000, BATCH_SIZE))): for b in range(0, BATCH_SIZE): msg = b"\xaa"*4 + struct.pack("I", a+b) if a%1 == 0: @@ -61,4 +61,4 @@ if len(set_out - set_in): print("MISSING %d" % len(set_out - set_in)) if len(set_out - set_in) < 256: - print(map(hex, sorted(list(set_out - set_in)))) + print(list(map(hex, sorted(list(set_out - set_in))))) diff --git a/panda/tests/tucan_loopback.py b/panda/tests/tucan_loopback.py index a3f3e6e2d7cbad..1b5ed016633837 100755 --- a/panda/tests/tucan_loopback.py +++ b/panda/tests/tucan_loopback.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python -from __future__ import print_function +#!/usr/bin/env python3 + import os import sys import time @@ -29,14 +29,14 @@ def run_test(sleep_duration): run_test_w_pandas(pandas, sleep_duration) def run_test_w_pandas(pandas, sleep_duration): - h = list(map(lambda x: Panda(x), pandas)) + h = list([Panda(x) for x in pandas]) print("H", h) for hh in h: hh.set_controls_allowed(True) # test both directions - for ho in permutations(range(len(h)), r=2): + for ho in permutations(list(range(len(h))), r=2): print("***************** TESTING", ho) panda0, panda1 = h[ho[0]], h[ho[1]] diff --git a/run_docker_tests.sh b/run_docker_tests.sh index 21549ab08946ba..3c4ef03e432e67 100755 --- a/run_docker_tests.sh +++ b/run_docker_tests.sh @@ -11,6 +11,6 @@ docker run --rm tmppilot /bin/sh -c 'cd /tmp/openpilot/ && make -C cereal && pyt docker run --rm tmppilot /bin/sh -c 'cd /tmp/openpilot/ && make -C cereal && python -m unittest discover selfdrive/boardd' docker run --rm tmppilot /bin/sh -c 'cd /tmp/openpilot/ && make -C cereal && python -m unittest discover selfdrive/controls' docker run --rm tmppilot /bin/sh -c 'cd /tmp/openpilot/ && python -m unittest discover selfdrive/loggerd' -docker run --rm -v "$(pwd)"/selfdrive/test/tests/plant/out:/tmp/openpilot/selfdrive/test/tests/plant/out tmppilot /bin/sh -c 'cd /tmp/openpilot/selfdrive/test/tests/plant && OPTEST=1 ./test_longitudinal.py' -docker run --rm tmppilot /bin/sh -c 'cd /tmp/openpilot/ && make -C cereal && cd /tmp/openpilot/selfdrive/test/tests/process_replay/ && ./test_processes.py' +docker run --rm -v "$(pwd)"/selfdrive/test/longitudinal_maneuvers/out:/tmp/openpilot/selfdrive/test/longitudinal_maneuvers/out tmppilot /bin/sh -c 'cd /tmp/openpilot/selfdrive/test/longitudinal_maneuvers && OPTEST=1 ./test_longitudinal.py' +docker run --rm tmppilot /bin/sh -c 'cd /tmp/openpilot/ && make -C cereal && cd /tmp/openpilot/selfdrive/test/process_replay/ && ./test_processes.py' docker run --rm tmppilot /bin/sh -c 'mkdir -p /data/params && cd /tmp/openpilot/ && make -C cereal && cd /tmp/openpilot/selfdrive/test/ && ./test_car_models.py' diff --git a/selfdrive/assets/sounds/warning_repeat.wav b/selfdrive/assets/sounds/warning_repeat.wav new file mode 100644 index 00000000000000..fbde4f933cf32d Binary files /dev/null and b/selfdrive/assets/sounds/warning_repeat.wav differ diff --git a/selfdrive/athena/athenad.py b/selfdrive/athena/athenad.py index 4f1059930cb03d..1474b346ba780d 100755 --- a/selfdrive/athena/athenad.py +++ b/selfdrive/athena/athenad.py @@ -1,6 +1,7 @@ -#!/usr/bin/env python2.7 +#!/usr/bin/env python3.7 import json import os +import io import random import re import select @@ -10,6 +11,7 @@ import threading import traceback import zmq +import base64 import requests import six.moves.queue from functools import partial @@ -24,6 +26,7 @@ from selfdrive.services import service_list from selfdrive.swaglog import cloudlog from selfdrive.version import version, dirty +from functools import reduce ATHENA_HOST = os.getenv('ATHENA_HOST', 'wss://athena.comma.ai') HANDLER_THREADS = os.getenv('HANDLER_THREADS', 4) @@ -41,10 +44,11 @@ def handle_long_poll(ws): threading.Thread(target=ws_send, args=(ws, end_event)) ] + [ threading.Thread(target=jsonrpc_handler, args=(end_event,)) - for x in xrange(HANDLER_THREADS) + for x in range(HANDLER_THREADS) ] - map(lambda thread: thread.start(), threads) + for thread in threads: + thread.start() try: while not end_event.is_set(): time.sleep(0.1) @@ -101,7 +105,7 @@ def startLocalProxy(global_end_event, remote_ws_uri, local_port): raise Exception("Requested local port not whitelisted") params = Params() - dongle_id = params.get("DongleId") + dongle_id = params.get("DongleId").decode('utf8') identity_token = Api(dongle_id).get_token() ws = create_connection(remote_ws_uri, cookie="jwt=" + identity_token, @@ -117,8 +121,8 @@ def startLocalProxy(global_end_event, remote_ws_uri, local_port): threading.Thread(target=ws_proxy_recv, args=(ws, local_sock, ssock, proxy_end_event, global_end_event)), threading.Thread(target=ws_proxy_send, args=(ws, local_sock, csock, proxy_end_event)) ] - - map(lambda thread: thread.start(), threads) + for thread in threads: + thread.start() return {"success": 1} except Exception as e: @@ -135,16 +139,15 @@ def getPublicKey(): @dispatcher.add_method def getSshAuthorizedKeys(): - with open('/system/comma/home/.ssh/authorized_keys', 'r') as f: - return f.read() + return Params().get("GithubSshKeys", encoding='utf8') or '' @dispatcher.add_method def getSimInfo(): - sim_state = subprocess.check_output(['getprop', 'gsm.sim.state']).strip().split(',') - network_type = subprocess.check_output(['getprop', 'gsm.network.type']).strip().split(',') - mcc_mnc = subprocess.check_output(['getprop', 'gsm.sim.operator.numeric']).strip() or None + sim_state = subprocess.check_output(['getprop', 'gsm.sim.state'], encoding='utf8').strip().split(',') # pylint: disable=unexpected-keyword-arg + network_type = subprocess.check_output(['getprop', 'gsm.network.type'], encoding='utf8').strip().split(',') # pylint: disable=unexpected-keyword-arg + mcc_mnc = subprocess.check_output(['getprop', 'gsm.sim.operator.numeric'], encoding='utf8').strip() or None # pylint: disable=unexpected-keyword-arg - sim_id_aidl_out = subprocess.check_output(['service', 'call', 'iphonesubinfo', '11']) + sim_id_aidl_out = subprocess.check_output(['service', 'call', 'iphonesubinfo', '11'], encoding='utf8') # pylint: disable=unexpected-keyword-arg sim_id_aidl_lines = sim_id_aidl_out.split('\n') if len(sim_id_aidl_lines) > 3: sim_id_lines = sim_id_aidl_lines[1:4] @@ -160,6 +163,20 @@ def getSimInfo(): 'sim_state': sim_state } +@dispatcher.add_method +def takeSnapshot(): + from selfdrive.visiond.snapshot.snapshot import snapshot, jpeg_write + ret = snapshot() + if ret is not None: + def b64jpeg(x): + f = io.BytesIO() + jpeg_write(f, x) + return base64.b64encode(f.getvalue()).decode("utf-8") + return {'jpegBack': b64jpeg(ret[0]), + 'jpegFront': b64jpeg(ret[1])} + else: + raise Exception("not available while visiond is started") + def ws_proxy_recv(ws, local_sock, ssock, end_event, global_end_event): while not (end_event.is_set() or global_end_event.is_set()): try: @@ -221,7 +238,7 @@ def backoff(retries): def main(gctx=None): params = Params() - dongle_id = params.get("DongleId") + dongle_id = params.get("DongleId").decode('utf-8') ws_uri = ATHENA_HOST + "/ws/v2/" + dongle_id crash.bind_user(id=dongle_id) diff --git a/selfdrive/boardd/Makefile b/selfdrive/boardd/Makefile index c6b5f21910fe56..67a315d8d98e82 100644 --- a/selfdrive/boardd/Makefile +++ b/selfdrive/boardd/Makefile @@ -78,7 +78,7 @@ boardd.o: boardd.cc boardd_api_impl.so: libcan_list_to_can_capnp.a boardd_api_impl.pyx boardd_setup.py - python2 boardd_setup.py build_ext --inplace + python3 boardd_setup.py build_ext --inplace rm -rf build rm -f boardd_api_impl.cpp diff --git a/selfdrive/boardd/boardd.cc b/selfdrive/boardd/boardd.cc index 8468238f310f47..bd60c34087184a 100644 --- a/selfdrive/boardd/boardd.cc +++ b/selfdrive/boardd/boardd.cc @@ -32,26 +32,9 @@ #define RECV_SIZE (0x1000) #define TIMEOUT 0 -#define SAFETY_NOOUTPUT 0 -#define SAFETY_HONDA 1 -#define SAFETY_TOYOTA 2 -#define SAFETY_GM 3 -#define SAFETY_HONDA_BOSCH 4 -#define SAFETY_FORD 5 -#define SAFETY_CADILLAC 6 -#define SAFETY_HYUNDAI 7 -#define SAFETY_TESLA 8 -#define SAFETY_CHRYSLER 9 -#define SAFETY_SUBARU 10 -#define SAFETY_GM_PASSIVE 11 -#define SAFETY_TOYOTA_IPAS 0x1335 -#define SAFETY_TOYOTA_NOLIMITS 0x1336 -#define SAFETY_ALLOUTPUT 0x1337 -#define SAFETY_ELM327 0xE327 // diagnostic only - namespace { -volatile int do_exit = 0; +volatile sig_atomic_t do_exit = 0; libusb_context *ctx = NULL; libusb_device_handle *dev_handle; @@ -62,6 +45,10 @@ bool fake_send = false; bool loopback_can = false; cereal::HealthData::HwType hw_type = cereal::HealthData::HwType::UNKNOWN; bool is_pigeon = false; +const uint32_t NO_IGNITION_CNT_MAX = 2 * 60 * 60 * 24 * 3; // turn off charge after 3 days +uint32_t no_ignition_cnt = 0; +bool connected_once = false; +uint8_t ignition_last = 0; pthread_t safety_setter_thread_handle = -1; pthread_t pigeon_thread_handle = -1; @@ -89,8 +76,8 @@ void *safety_setter_thread(void *s) { pthread_mutex_lock(&usb_lock); - // VIN qury done, stop listening to OBDII - libusb_control_transfer(dev_handle, 0x40, 0xdc, SAFETY_NOOUTPUT, 0, NULL, 0, TIMEOUT); + // VIN query done, stop listening to OBDII + libusb_control_transfer(dev_handle, 0x40, 0xdc, (uint16_t)(cereal::CarParams::SafetyModel::NO_OUTPUT), 0, NULL, 0, TIMEOUT); pthread_mutex_unlock(&usb_lock); @@ -119,48 +106,6 @@ void *safety_setter_thread(void *s) { auto safety_param = car_params.getSafetyParam(); LOGW("setting safety model: %d with param %d", safety_model, safety_param); - int safety_setting = 0; - switch (safety_model) { - case cereal::CarParams::SafetyModel::NO_OUTPUT: - safety_setting = SAFETY_NOOUTPUT; - break; - case cereal::CarParams::SafetyModel::HONDA: - safety_setting = SAFETY_HONDA; - break; - case cereal::CarParams::SafetyModel::TOYOTA: - safety_setting = SAFETY_TOYOTA; - break; - case cereal::CarParams::SafetyModel::ELM327: - safety_setting = SAFETY_ELM327; - break; - case cereal::CarParams::SafetyModel::GM: - safety_setting = SAFETY_GM; - break; - case cereal::CarParams::SafetyModel::GM_PASSIVE: - safety_setting = SAFETY_GM_PASSIVE; - break; - case cereal::CarParams::SafetyModel::HONDA_BOSCH: - safety_setting = SAFETY_HONDA_BOSCH; - break; - case cereal::CarParams::SafetyModel::FORD: - safety_setting = SAFETY_FORD; - break; - case cereal::CarParams::SafetyModel::CADILLAC: - safety_setting = SAFETY_CADILLAC; - break; - case cereal::CarParams::SafetyModel::HYUNDAI: - safety_setting = SAFETY_HYUNDAI; - break; - case cereal::CarParams::SafetyModel::CHRYSLER: - safety_setting = SAFETY_CHRYSLER; - break; - case cereal::CarParams::SafetyModel::SUBARU: - safety_setting = SAFETY_SUBARU; - break; - default: - LOGE("unknown safety model: %d", safety_model); - } - pthread_mutex_lock(&usb_lock); // set in the mutex to avoid race @@ -169,7 +114,7 @@ void *safety_setter_thread(void *s) { // set if long_control is allowed by openpilot. Hardcoded to True for now libusb_control_transfer(dev_handle, 0x40, 0xdf, 1, 0, NULL, 0, TIMEOUT); - libusb_control_transfer(dev_handle, 0x40, 0xdc, safety_setting, safety_param, NULL, 0, TIMEOUT); + libusb_control_transfer(dev_handle, 0x40, 0xdc, (uint16_t)(cereal::CarParams::SafetyModel(safety_model)), safety_param, NULL, 0, TIMEOUT); pthread_mutex_unlock(&usb_lock); @@ -180,6 +125,7 @@ void *safety_setter_thread(void *s) { bool usb_connect() { int err; unsigned char hw_query[1] = {0}; + ignition_last = 0; dev_handle = libusb_open_device_with_vid_pid(ctx, 0xbbaa, 0xddcc); if (dev_handle == NULL) { goto fail; } @@ -197,25 +143,20 @@ bool usb_connect() { // power off ESP libusb_control_transfer(dev_handle, 0xc0, 0xd9, 0, 0, NULL, 0, TIMEOUT); - // power on charging (may trigger a reconnection, should be okay) - #ifndef __x86_64__ - libusb_control_transfer(dev_handle, 0xc0, 0xe6, 1, 0, NULL, 0, TIMEOUT); - #else - LOGW("not enabling charging on x86_64"); - #endif - - // diagnostic only is the default, needed for VIN query - libusb_control_transfer(dev_handle, 0x40, 0xdc, SAFETY_ELM327, 0, NULL, 0, TIMEOUT); - - if (safety_setter_thread_handle == -1) { - err = pthread_create(&safety_setter_thread_handle, NULL, safety_setter_thread, NULL); - assert(err == 0); + // power on charging, only the first time. Panda can also change mode and it causes a brief disconneciton +#ifndef __x86_64__ + if (!connected_once) { + libusb_control_transfer(dev_handle, 0xc0, 0xe6, (uint16_t)(cereal::HealthData::UsbPowerMode::CDP), 0, NULL, 0, TIMEOUT); } +#endif + connected_once = true; libusb_control_transfer(dev_handle, 0xc0, 0xc1, 0, 0, hw_query, 1, TIMEOUT); hw_type = (cereal::HealthData::HwType)(hw_query[0]); - is_pigeon = (hw_type == cereal::HealthData::HwType::GREY_PANDA) || (hw_type == cereal::HealthData::HwType::BLACK_PANDA); + is_pigeon = (hw_type == cereal::HealthData::HwType::GREY_PANDA) || + (hw_type == cereal::HealthData::HwType::BLACK_PANDA) || + (hw_type == cereal::HealthData::HwType::UNO); if (is_pigeon) { LOGW("panda with gps detected"); pigeon_needs_init = true; @@ -304,8 +245,9 @@ void can_recv(void *s) { void can_health(void *s) { int cnt; + int err; - // copied from board/main.c + // copied from panda/board/main.c struct __attribute__((packed)) health { uint32_t voltage; uint32_t current; @@ -315,7 +257,8 @@ void can_health(void *s) { uint8_t started; uint8_t controls_allowed; uint8_t gas_interceptor_detected; - uint8_t car_harness_status_pkt; + uint8_t car_harness_status; + uint8_t usb_power_mode; } health; // recv from board @@ -330,6 +273,42 @@ void can_health(void *s) { pthread_mutex_unlock(&usb_lock); + if (health.started == 0) { + no_ignition_cnt += 1; + } else { + no_ignition_cnt = 0; + } + +#ifndef __x86_64__ + if ((no_ignition_cnt > NO_IGNITION_CNT_MAX) && (health.usb_power_mode == (uint8_t)(cereal::HealthData::UsbPowerMode::CDP))) { + printf("TURN OFF CHARGING!\n"); + pthread_mutex_lock(&usb_lock); + libusb_control_transfer(dev_handle, 0xc0, 0xe6, (uint16_t)(cereal::HealthData::UsbPowerMode::CLIENT), 0, NULL, 0, TIMEOUT); + pthread_mutex_unlock(&usb_lock); + } +#endif + + // clear VIN, CarParams, and set new safety on car start + if ((health.started != 0) && (ignition_last == 0)) { + + int result = delete_db_value(NULL, "CarVin"); + assert((result == 0) || (result == ERR_NO_VALUE)); + result = delete_db_value(NULL, "CarParams"); + assert((result == 0) || (result == ERR_NO_VALUE)); + + // diagnostic only is the default, needed for VIN query + pthread_mutex_lock(&usb_lock); + libusb_control_transfer(dev_handle, 0x40, 0xdc, (uint16_t)(cereal::CarParams::SafetyModel::ELM327), 0, NULL, 0, TIMEOUT); + pthread_mutex_unlock(&usb_lock); + + if (safety_setter_thread_handle == -1) { + err = pthread_create(&safety_setter_thread_handle, NULL, safety_setter_thread, NULL); + assert(err == 0); + } + } + + ignition_last = health.started; + // create message capnp::MallocMessageBuilder msg; cereal::Event::Builder event = msg.initRoot(); @@ -351,6 +330,7 @@ void can_health(void *s) { healthData.setCanFwdErrs(health.can_fwd_errs); healthData.setGmlanSendErrs(health.gmlan_send_errs); healthData.setHwType(hw_type); + healthData.setUsbPowerMode(cereal::HealthData::UsbPowerMode(health.usb_power_mode)); // send to health auto words = capnp::messageToFlatArray(msg); @@ -481,7 +461,6 @@ void *can_recv_thread(void *crap) { void *can_health_thread(void *crap) { LOGD("start health thread"); - // health = 8011 void *context = zmq_ctx_new(); void *publisher = zmq_socket(context, ZMQ_PUB); @@ -628,7 +607,7 @@ void *pigeon_thread(void *crap) { } if (alen > 0) { if (dat[0] == (char)0x00){ - LOGW("received invalid ublox message, resetting pigeon"); + LOGW("received invalid ublox message, resetting panda GPS"); pigeon_init(); } else { pigeon_publish_raw(publisher, dat, alen); diff --git a/selfdrive/boardd/boardd_api_impl.pyx b/selfdrive/boardd/boardd_api_impl.pyx index eddf1fbf7aedf6..3f50fbaab6c5ca 100644 --- a/selfdrive/boardd/boardd_api_impl.pyx +++ b/selfdrive/boardd/boardd_api_impl.pyx @@ -1,4 +1,5 @@ # distutils: language = c++ +# cython: language_level=3 from libcpp.vector cimport vector from libcpp.string cimport string from libcpp cimport bool diff --git a/selfdrive/boardd/boardd_setup.py b/selfdrive/boardd/boardd_setup.py index f614a06161dc7f..887a1b71053f22 100644 --- a/selfdrive/boardd/boardd_setup.py +++ b/selfdrive/boardd/boardd_setup.py @@ -1,25 +1,29 @@ import subprocess -from distutils.core import setup, Extension +from distutils.core import Extension, setup # pylint: disable=import-error,no-name-in-module + from Cython.Build import cythonize +from common.cython_hacks import BuildExtWithoutPlatformSuffix + PHONELIBS = '../../phonelibs' -ARCH = subprocess.check_output(["uname", "-m"]).rstrip() +ARCH = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip() # pylint: disable=unexpected-keyword-arg ARCH_DIR = 'x64' if ARCH == "x86_64" else 'aarch64' setup(name='Boardd API Implementation', - ext_modules=cythonize( - Extension( - "boardd_api_impl", - libraries=[':libcan_list_to_can_capnp.a', ':libcapnp.a', ':libcapnp.a', ':libkj.a'], - library_dirs=[ - './', - PHONELIBS + '/capnp-cpp/' + ARCH_DIR + '/lib/', - PHONELIBS + '/capnp-c/' + ARCH_DIR + '/lib/' - ], - sources=['boardd_api_impl.pyx'], - language="c++", - extra_compile_args=["-std=c++11"], - ) - ) + cmdclass={'build_ext': BuildExtWithoutPlatformSuffix}, + ext_modules=cythonize( + Extension( + "boardd_api_impl", + libraries=[':libcan_list_to_can_capnp.a', ':libcapnp.a', ':libcapnp.a', ':libkj.a'], + library_dirs=[ + './', + PHONELIBS + '/capnp-cpp/' + ARCH_DIR + '/lib/', + PHONELIBS + '/capnp-c/' + ARCH_DIR + '/lib/' + ], + sources=['boardd_api_impl.pyx'], + language="c++", + extra_compile_args=["-std=c++11"], + ) + ) ) diff --git a/selfdrive/boardd/tests/boardd_old.py b/selfdrive/boardd/tests/boardd_old.py index 5989e627463a8c..3f5ad7cf6c22b3 100755 --- a/selfdrive/boardd/tests/boardd_old.py +++ b/selfdrive/boardd/tests/boardd_old.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # This file is not used by OpenPilot. Only boardd.cc is used. # The python version is slower, but has more options for development. @@ -15,6 +15,9 @@ from selfdrive.services import service_list from selfdrive.swaglog import cloudlog from selfdrive.boardd.boardd import can_capnp_to_can_list +from cereal import car + +SafetyModel = car.CarParams.SafetyModel # USB is optional try: @@ -23,13 +26,6 @@ except Exception: pass -SAFETY_NOOUTPUT = 0 -SAFETY_HONDA = 1 -SAFETY_TOYOTA = 2 -SAFETY_CHRYSLER = 9 -SAFETY_TOYOTA_NOLIMITS = 0x1336 -SAFETY_ALLOUTPUT = 0x1337 - # *** serialization functions *** def can_list_to_can_capnp(can_msgs, msgtype='can'): dat = messaging.new_message() @@ -41,7 +37,7 @@ def can_list_to_can_capnp(can_msgs, msgtype='can'): cc = dat.can[i] cc.address = can_msg[0] cc.busTime = can_msg[1] - cc.dat = str(can_msg[2]) + cc.dat = bytes(can_msg[2]) cc.src = can_msg[3] return dat @@ -71,17 +67,17 @@ def can_send_many(arr): for addr, _, dat, alt in arr: if addr < 0x800: # only support 11 bit addr snd = struct.pack("II", ((addr << 21) | 1), len(dat) | (alt << 4)) + dat - snd = snd.ljust(0x10, '\x00') + snd = snd.ljust(0x10, b'\x00') snds.append(snd) while 1: try: - handle.bulkWrite(3, ''.join(snds)) + handle.bulkWrite(3, b''.join(snds)) break except (USBErrorIO, USBErrorOverflow): cloudlog.exception("CAN: BAD SEND MANY, RETRYING") def can_recv(): - dat = "" + dat = b"" while 1: try: dat = handle.bulkRead(1, 0x10*256) @@ -102,10 +98,10 @@ def can_init(): if device.getVendorID() == 0xbbaa and device.getProductID() == 0xddcc: handle = device.open() handle.claimInterface(0) - handle.controlWrite(0x40, 0xdc, SAFETY_ALLOUTPUT, 0, b'') + handle.controlWrite(0x40, 0xdc, SafetyModel.allOutput, 0, b'') if handle is None: - cloudlog.warn("CAN NOT FOUND") + cloudlog.warning("CAN NOT FOUND") exit(-1) cloudlog.info("got handle") @@ -113,7 +109,7 @@ def can_init(): def boardd_mock_loop(): can_init() - handle.controlWrite(0x40, 0xdc, SAFETY_ALLOUTPUT, 0, b'') + handle.controlWrite(0x40, 0xdc, SafetyModel.allOutput, 0, b'') logcan = messaging.sub_sock(service_list['can'].port) sendcan = messaging.pub_sock(service_list['sendcan'].port) @@ -124,17 +120,17 @@ def boardd_mock_loop(): snd = [] for s in snds: snd += s - snd = filter(lambda x: x[-1] <= 2, snd) - snd_0 = len(filter(lambda x: x[-1] == 0, snd)) - snd_1 = len(filter(lambda x: x[-1] == 1, snd)) - snd_2 = len(filter(lambda x: x[-1] == 2, snd)) + snd = list(filter(lambda x: x[-1] <= 2, snd)) + snd_0 = len(list(filter(lambda x: x[-1] == 0, snd))) + snd_1 = len(list(filter(lambda x: x[-1] == 1, snd))) + snd_2 = len(list(filter(lambda x: x[-1] == 2, snd))) can_send_many(snd) # recv @ 100hz can_msgs = can_recv() - got_0 = len(filter(lambda x: x[-1] == 0+0x80, can_msgs)) - got_1 = len(filter(lambda x: x[-1] == 1+0x80, can_msgs)) - got_2 = len(filter(lambda x: x[-1] == 2+0x80, can_msgs)) + got_0 = len(list(filter(lambda x: x[-1] == 0+0x80, can_msgs))) + got_1 = len(list(filter(lambda x: x[-1] == 1+0x80, can_msgs))) + got_2 = len(list(filter(lambda x: x[-1] == 2+0x80, can_msgs))) print("sent %3d (%3d/%3d/%3d) got %3d (%3d/%3d/%3d)" % (len(snd), snd_0, snd_1, snd_2, len(can_msgs), got_0, got_1, got_2)) m = can_list_to_can_capnp(can_msgs, msgtype='sendcan') diff --git a/selfdrive/boardd/tests/fuzzer.py b/selfdrive/boardd/tests/fuzzer.py index cb6edf710603ce..bb58f8b5e07a53 100755 --- a/selfdrive/boardd/tests/fuzzer.py +++ b/selfdrive/boardd/tests/fuzzer.py @@ -1,4 +1,5 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 +from __future__ import print_function import time import random @@ -9,9 +10,9 @@ while 1: c = random.randint(0, 3) if c == 0: - print can_recv() + print(can_recv()) elif c == 1: - print can_health() + print(can_health()) elif c == 2: many = [[0x123, 0, "abcdef", 0]] * random.randint(1, 10) can_send_many(many) diff --git a/selfdrive/boardd/tests/replay_many.py b/selfdrive/boardd/tests/replay_many.py index 710cfee486ded5..548ec6549adbaa 100755 --- a/selfdrive/boardd/tests/replay_many.py +++ b/selfdrive/boardd/tests/replay_many.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import sys import time import signal diff --git a/selfdrive/boardd/tests/test_boardd_api.py b/selfdrive/boardd/tests/test_boardd_api.py index 0e862b0952c3c2..f41e1e3571049d 100644 --- a/selfdrive/boardd/tests/test_boardd_api.py +++ b/selfdrive/boardd/tests/test_boardd_api.py @@ -1,7 +1,7 @@ import random import numpy as np -import boardd_old +import selfdrive.boardd.tests.boardd_old as boardd_old import selfdrive.boardd.boardd as boardd from common.realtime import sec_since_boot @@ -12,7 +12,7 @@ def generate_random_can_data_list(): can_list = [] cnt = random.randint(1, 64) - for j in xrange(cnt): + for j in range(cnt): can_data = np.random.bytes(random.randint(1, 8)) can_list.append([random.randint(0, 128), random.randint(0, 128), can_data, random.randint(0, 128)]) return can_list, cnt @@ -20,7 +20,7 @@ def generate_random_can_data_list(): class TestBoarddApiMethods(unittest.TestCase): def test_correctness(self): - for i in xrange(1000): + for i in range(1000): can_list, _ = generate_random_can_data_list() # Sendcan @@ -31,9 +31,10 @@ def test_correctness(self): ev_old = log.Event.from_bytes(m_old) ev = log.Event.from_bytes(m) + self.assertEqual(ev_old.which(), ev.which()) self.assertEqual(len(ev.sendcan), len(ev_old.sendcan)) - for i in xrange(len(ev.sendcan)): + for i in range(len(ev.sendcan)): attrs = ['address', 'busTime', 'dat', 'src'] for attr in attrs: self.assertEqual(getattr(ev.sendcan[i], attr, 'new'), getattr(ev_old.sendcan[i], attr, 'old')) @@ -47,7 +48,7 @@ def test_correctness(self): ev = log.Event.from_bytes(m) self.assertEqual(ev_old.which(), ev.which()) self.assertEqual(len(ev.can), len(ev_old.can)) - for i in xrange(len(ev.can)): + for i in range(len(ev.can)): attrs = ['address', 'busTime', 'dat', 'src'] for attr in attrs: self.assertEqual(getattr(ev.can[i], attr, 'new'), getattr(ev_old.can[i], attr, 'old')) @@ -57,14 +58,14 @@ def test_performance(self): recursions = 1000 n1 = sec_since_boot() - for i in xrange(recursions): + for i in range(recursions): boardd_old.can_list_to_can_capnp(can_list, 'sendcan').to_bytes() n2 = sec_since_boot() elapsed_old = n2 - n1 # print('Old API, elapsed time: {} secs'.format(elapsed_old)) n1 = sec_since_boot() - for i in xrange(recursions): + for i in range(recursions): boardd.can_list_to_can_capnp(can_list) n2 = sec_since_boot() elapsed_new = n2 - n1 diff --git a/selfdrive/boardd/tests/test_boardd_loopback.py b/selfdrive/boardd/tests/test_boardd_loopback.py index 042a5783a5f13a..c3992bdac44e80 100755 --- a/selfdrive/boardd/tests/test_boardd_loopback.py +++ b/selfdrive/boardd/tests/test_boardd_loopback.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 """Run boardd with the BOARDD_LOOPBACK envvar before running this test.""" import os diff --git a/selfdrive/can/Makefile b/selfdrive/can/Makefile index a9ee1e6861ef5d..85d2c494a96699 100644 --- a/selfdrive/can/Makefile +++ b/selfdrive/can/Makefile @@ -36,7 +36,7 @@ endif OBJDIR = obj -OPENDBC_PATH := $(shell python2 -c 'import opendbc; print opendbc.DBC_PATH') +OPENDBC_PATH := $(shell python3 -c 'import opendbc; print(opendbc.DBC_PATH)') DBC_SOURCES := $(sort $(wildcard $(OPENDBC_PATH)/*.dbc)) DBC_OBJS := $(patsubst $(OPENDBC_PATH)/%.dbc,$(OBJDIR)/%.o,$(DBC_SOURCES)) @@ -70,12 +70,12 @@ libdbc.so:: $(LIBDBC_OBJS) $(DBC_OBJS) $(CEREAL_LIBS) packer_impl.so: packer_impl.pyx packer_setup.py - python2 packer_setup.py build_ext --inplace + python3 packer_setup.py build_ext --inplace rm -rf build rm -f packer_impl.cpp parser_pyx.so: parser_pyx_setup.py parser_pyx.pyx parser_pyx.pxd - python $< build_ext --inplace + python3 $< build_ext --inplace rm -rf build rm -f parser_pyx.cpp diff --git a/selfdrive/can/can_define.py b/selfdrive/can/can_define.py index 48ff8798fdf150..d6ffc5c669e9fb 100644 --- a/selfdrive/can/can_define.py +++ b/selfdrive/can/can_define.py @@ -1,11 +1,11 @@ from collections import defaultdict from selfdrive.can.libdbc_py import libdbc, ffi -class CANDefine(object): +class CANDefine(): def __init__(self, dbc_name): self.dv = defaultdict(dict) self.dbc_name = dbc_name - self.dbc = libdbc.dbc_lookup(dbc_name) + self.dbc = libdbc.dbc_lookup(dbc_name.encode('utf8')) num_vals = self.dbc[0].num_vals @@ -13,16 +13,16 @@ def __init__(self, dbc_name): num_msgs = self.dbc[0].num_msgs for i in range(num_msgs): msg = self.dbc[0].msgs[i] - name = ffi.string(msg.name) + name = ffi.string(msg.name).decode('utf8') address = msg.address self.address_to_msg_name[address] = name for i in range(num_vals): val = self.dbc[0].vals[i] - sgname = ffi.string(val.name) + sgname = ffi.string(val.name).decode('utf8') address = val.address - def_val = ffi.string(val.def_val) + def_val = ffi.string(val.def_val).decode('utf8') #separate definition/value pairs def_val = def_val.split() diff --git a/selfdrive/can/packer_impl.pyx b/selfdrive/can/packer_impl.pyx index 26ce8c12679314..7429338ac40721 100644 --- a/selfdrive/can/packer_impl.pyx +++ b/selfdrive/can/packer_impl.pyx @@ -1,4 +1,6 @@ # distutils: language = c++ +# cython: c_string_encoding=ascii, language_level=3 + from libc.stdint cimport uint32_t, uint64_t from libcpp.vector cimport vector from libcpp.map cimport map @@ -54,7 +56,7 @@ ctypedef uint64_t (*canpack_pack_vector_func)(void* inst, uint32_t address, cons ctypedef const DBC * (*dbc_lookup_func)(const char* dbc_name) -cdef class CANPacker(object): +cdef class CANPacker(): cdef void *packer cdef const DBC *dbc cdef map[string, (int, int)] name_to_address_and_size @@ -66,11 +68,14 @@ cdef class CANPacker(object): def __init__(self, dbc_name): can_dir = os.path.dirname(os.path.abspath(__file__)) libdbc_fn = os.path.join(can_dir, "libdbc.so") + libdbc_fn = str(libdbc_fn).encode('utf8') subprocess.check_call(["make"], cwd=can_dir) + cdef void *libdbc = dlopen(libdbc_fn, RTLD_LAZY) self.canpack_init = dlsym(libdbc, 'canpack_init') self.canpack_pack_vector = dlsym(libdbc, 'canpack_pack_vector') self.dbc_lookup = dlsym(libdbc, 'dbc_lookup') + self.packer = self.canpack_init(dbc_name) self.dbc = self.dbc_lookup(dbc_name) num_msgs = self.dbc[0].num_msgs @@ -82,8 +87,14 @@ cdef class CANPacker(object): cdef uint64_t pack(self, addr, values, counter): cdef vector[SignalPackValue] values_thing cdef SignalPackValue spv + + names = [] + for name, value in values.iteritems(): - spv.name = name + n = name.encode('utf8') + names.append(n) # TODO: find better way to keep reference to temp string arround + + spv.name = n spv.value = value values_thing.push_back(spv) @@ -105,7 +116,7 @@ cdef class CANPacker(object): addr = name_or_addr size = self.address_to_size[name_or_addr] else: - addr, size = self.name_to_address_and_size[name_or_addr] + addr, size = self.name_to_address_and_size[name_or_addr.encode('utf8')] cdef uint64_t val = self.pack(addr, values, counter) val = self.ReverseBytes(val) return [addr, 0, (&val)[:size], bus] diff --git a/selfdrive/can/packer_setup.py b/selfdrive/can/packer_setup.py index a36d4199ee57dc..8b25e605802841 100644 --- a/selfdrive/can/packer_setup.py +++ b/selfdrive/can/packer_setup.py @@ -1,5 +1,9 @@ -from distutils.core import setup, Extension +from distutils.core import Extension, setup # pylint: disable=import-error,no-name-in-module + from Cython.Build import cythonize +from common.cython_hacks import BuildExtWithoutPlatformSuffix + setup(name='CAN Packer API Implementation', + cmdclass={'build_ext': BuildExtWithoutPlatformSuffix}, ext_modules=cythonize(Extension("packer_impl", ["packer_impl.pyx"], language="c++", extra_compile_args=["-std=c++11"]))) diff --git a/selfdrive/can/parser_pyx.pxd b/selfdrive/can/parser_pyx.pxd index 6b1e50ce6dc753..28048bbc1f0e53 100644 --- a/selfdrive/can/parser_pyx.pxd +++ b/selfdrive/can/parser_pyx.pxd @@ -1,4 +1,6 @@ # distutils: language = c++ +#cython: language_level=3 + from libc.stdint cimport uint32_t, uint64_t, uint16_t from libcpp.vector cimport vector from libcpp.map cimport map diff --git a/selfdrive/can/parser_pyx.pyx b/selfdrive/can/parser_pyx.pyx index 4f92970960fb3f..61a61aed60545c 100644 --- a/selfdrive/can/parser_pyx.pyx +++ b/selfdrive/can/parser_pyx.pyx @@ -1,4 +1,6 @@ # distutils: language = c++ +# cython: c_string_encoding=ascii, language_level=3 + from posix.dlfcn cimport dlopen, dlsym, RTLD_LAZY from libcpp cimport bool @@ -8,10 +10,11 @@ import numbers cdef int CAN_INVALID_CNT = 5 cdef class CANParser: - def __init__(self, dbc_name, signals, checks=None, bus=0, sendcan=False, tcp_addr="", timeout=-1): + def __init__(self, dbc_name, signals, checks=None, bus=0, sendcan=False, tcp_addr=b"", timeout=-1): self.test_mode_enabled = False can_dir = os.path.dirname(os.path.abspath(__file__)) libdbc_fn = os.path.join(can_dir, "libdbc.so") + libdbc_fn = str(libdbc_fn).encode('utf8') cdef void *libdbc = dlopen(libdbc_fn, RTLD_LAZY) self.can_init_with_vectors = dlsym(libdbc, 'can_init_with_vectors') @@ -33,24 +36,28 @@ cdef class CANParser: num_msgs = self.dbc[0].num_msgs for i in range(num_msgs): msg = self.dbc[0].msgs[i] - self.msg_name_to_address[string(msg.name)] = msg.address - self.address_to_msg_name[msg.address] = string(msg.name) + name = msg.name.decode('utf8') + + self.msg_name_to_address[name] = msg.address + self.address_to_msg_name[msg.address] = name self.vl[msg.address] = {} - self.vl[str(msg.name)] = {} + self.vl[name] = {} self.ts[msg.address] = {} - self.ts[str(msg.name)] = {} + self.ts[name] = {} # Convert message names into addresses for i in range(len(signals)): s = signals[i] if not isinstance(s[1], numbers.Number): - s = (s[0], self.msg_name_to_address[s[1]], s[2]) + name = s[1].encode('utf8') + s = (s[0], self.msg_name_to_address[name], s[2]) signals[i] = s for i in range(len(checks)): c = checks[i] if not isinstance(c[0], numbers.Number): - c = (self.msg_name_to_address[c[0]], c[1]) + name = c[0].encode('utf8') + c = (self.msg_name_to_address[name], c[1]) checks[i] = c cdef vector[SignalParseOptions] signal_options_v @@ -89,12 +96,15 @@ cdef class CANParser: for cv in self.can_values: - self.vl[cv.address][string(cv.name)] = cv.value - self.ts[cv.address][string(cv.name)] = cv.ts + # Cast char * directly to unicde + name = self.address_to_msg_name[cv.address].c_str() + cv_name = cv.name + + self.vl[cv.address][cv_name] = cv.value + self.ts[cv.address][cv_name] = cv.ts - sig_name = self.address_to_msg_name[cv.address] - self.vl[sig_name][string(cv.name)] = cv.value - self.ts[sig_name][string(cv.name)] = cv.ts + self.vl[name][cv_name] = cv.value + self.ts[name][cv_name] = cv.ts updated_val.insert(cv.address) diff --git a/selfdrive/can/parser_pyx_setup.py b/selfdrive/can/parser_pyx_setup.py index f20224f34352ae..29102ee0269b22 100644 --- a/selfdrive/can/parser_pyx_setup.py +++ b/selfdrive/can/parser_pyx_setup.py @@ -1,14 +1,19 @@ -from distutils.core import setup, Extension -from Cython.Build import cythonize import subprocess +from distutils.core import Extension, setup # pylint: disable=import-error,no-name-in-module + +from Cython.Build import cythonize + +from common.cython_hacks import BuildExtWithoutPlatformSuffix sourcefiles = ['parser_pyx.pyx'] extra_compile_args = ["-std=c++11"] -ARCH = subprocess.check_output(["uname", "-m"]).rstrip() +ARCH = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip() # pylint: disable=unexpected-keyword-arg + if ARCH == "aarch64": extra_compile_args += ["-Wno-deprecated-register"] setup(name='Radard Thread', + cmdclass={'build_ext': BuildExtWithoutPlatformSuffix}, ext_modules=cythonize( Extension( "parser_pyx", diff --git a/selfdrive/can/plant_can_parser.py b/selfdrive/can/plant_can_parser.py index e58906d7a0a04b..65fcfc64152f19 100644 --- a/selfdrive/can/plant_can_parser.py +++ b/selfdrive/can/plant_can_parser.py @@ -7,7 +7,7 @@ from common.realtime import sec_since_boot from common.dbc import dbc -class CANParser(object): +class CANParser(): def __init__(self, dbc_f, signals, checks=None): ### input: # dbc_f : dbc file @@ -73,7 +73,7 @@ def update_can(self, can_recv): self.ck[msg] = True if "CHECKSUM" in out.keys() and msg in self.msgs_ck: # remove checksum (half byte) - ck_portion = cdat[:-1] + chr(ord(cdat[-1]) & 0xF0) + ck_portion = cdat[:-1] + (cdat[-1] & 0xF0).to_bytes(1, 'little') # recalculate checksum msg_vl = fix(ck_portion, msg) # compare recalculated vs received checksum diff --git a/selfdrive/can/process_dbc.py b/selfdrive/can/process_dbc.py index 5f9237020b8221..187d413584dcd7 100755 --- a/selfdrive/can/process_dbc.py +++ b/selfdrive/can/process_dbc.py @@ -1,4 +1,5 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 +from __future__ import print_function import os import glob import sys @@ -10,7 +11,7 @@ def main(): if len(sys.argv) != 3: - print "usage: %s dbc_directory output_directory" % (sys.argv[0],) + print("usage: %s dbc_directory output_directory" % (sys.argv[0],)) sys.exit(0) dbc_dir = sys.argv[1] @@ -38,7 +39,7 @@ def main(): if dbc_mtime < out_mtime and template_mtime < out_mtime and this_file_mtime < out_mtime: continue #skip output is newer than template and dbc - msgs = [(address, msg_name, msg_size, sorted(msg_sigs, key=lambda s: s.name not in ("COUNTER", "CHECKSUM"))) # process counter and checksums first + msgs = [(address, msg_name, msg_size, sorted(msg_sigs, key=lambda s: s.name not in (b"COUNTER", b"CHECKSUM"))) # process counter and checksums first for address, ((msg_name, msg_size), msg_sigs) in sorted(can_dbc.msgs.items()) if msg_sigs] def_vals = {a: set(b) for a,b in can_dbc.def_vals.items()} #remove duplicates @@ -55,22 +56,22 @@ def main(): for address, msg_name, msg_size, sigs in msgs: for sig in sigs: - if checksum_type is not None and sig.name == "CHECKSUM": + if checksum_type is not None and sig.name == b"CHECKSUM": if sig.size != checksum_size: sys.exit("CHECKSUM is not %d bits longs %s" % (checksum_size, msg_name)) if checksum_type == "honda" and sig.start_bit % 8 != 3: sys.exit("CHECKSUM starts at wrong bit %s" % msg_name) if checksum_type == "toyota" and sig.start_bit % 8 != 7: sys.exit("CHECKSUM starts at wrong bit %s" % msg_name) - if checksum_type == "honda" and sig.name == "COUNTER": + if checksum_type == "honda" and sig.name == b"COUNTER": if sig.size != 2: sys.exit("COUNTER is not 2 bits longs %s" % msg_name) if sig.start_bit % 8 != 5: sys.exit("COUNTER starts at wrong bit %s" % msg_name) if address in [0x200, 0x201]: - if sig.name == "COUNTER_PEDAL" and sig.size != 4: + if sig.name == b"COUNTER_PEDAL" and sig.size != 4: sys.exit("PEDAL COUNTER is not 4 bits longs %s" % msg_name) - if sig.name == "CHECKSUM_PEDAL" and sig.size != 8: + if sig.name == b"CHECKSUM_PEDAL" and sig.size != 8: sys.exit("PEDAL CHECKSUM is not 8 bits longs %s" % msg_name) # Fail on duplicate message names diff --git a/selfdrive/can/tests/packer_old.py b/selfdrive/can/tests/packer_old.py index 0c17c2e4d9177a..63120218e96c0a 100644 --- a/selfdrive/can/tests/packer_old.py +++ b/selfdrive/can/tests/packer_old.py @@ -2,8 +2,9 @@ from selfdrive.can.libdbc_py import libdbc, ffi -class CANPacker(object): +class CANPacker(): def __init__(self, dbc_name): + dbc_name = dbc_name.encode('utf8') self.packer = libdbc.canpack_init(dbc_name) self.dbc = libdbc.dbc_lookup(dbc_name) self.sig_names = {} @@ -13,16 +14,16 @@ def __init__(self, dbc_name): for i in range(num_msgs): msg = self.dbc[0].msgs[i] - name = ffi.string(msg.name) + name = ffi.string(msg.name).decode('utf8') address = msg.address self.name_to_address_and_size[name] = (address, msg.size) self.name_to_address_and_size[address] = (address, msg.size) def pack(self, addr, values, counter): values_thing = [] - for name, value in values.iteritems(): + for name, value in values.items(): if name not in self.sig_names: - self.sig_names[name] = ffi.new("char[]", name) + self.sig_names[name] = ffi.new("char[]", name.encode('utf8')) values_thing.append({ 'name': self.sig_names[name], diff --git a/selfdrive/can/tests/parser_old.py b/selfdrive/can/tests/parser_old.py index ccf613ab3cdf76..1d2da57862f3f9 100644 --- a/selfdrive/can/tests/parser_old.py +++ b/selfdrive/can/tests/parser_old.py @@ -5,7 +5,7 @@ CAN_INVALID_CNT = 5 # after so many consecutive CAN data with wrong checksum, counter or frequency, flag CAN invalidity -class CANParser(object): +class CANParser(): def __init__(self, dbc_name, signals, checks=None, bus=0, sendcan=False, tcp_addr="127.0.0.1", timeout=-1): if checks is None: checks = [] @@ -16,7 +16,7 @@ def __init__(self, dbc_name, signals, checks=None, bus=0, sendcan=False, tcp_add self.ts = {} self.dbc_name = dbc_name - self.dbc = libdbc.dbc_lookup(dbc_name) + self.dbc = libdbc.dbc_lookup(dbc_name.encode('utf8')) self.msg_name_to_addres = {} self.address_to_msg_name = {} @@ -24,7 +24,7 @@ def __init__(self, dbc_name, signals, checks=None, bus=0, sendcan=False, tcp_add for i in range(num_msgs): msg = self.dbc[0].msgs[i] - name = ffi.string(msg.name) + name = ffi.string(msg.name).decode('utf8') address = msg.address self.msg_name_to_addres[name] = address @@ -48,7 +48,7 @@ def __init__(self, dbc_name, signals, checks=None, bus=0, sendcan=False, tcp_add c = (self.msg_name_to_addres[c[0]], c[1]) checks[i] = c - sig_names = dict((name, ffi.new("char[]", name)) for name, _, _ in signals) + sig_names = dict((name, ffi.new("char[]", name.encode('utf8'))) for name, _, _ in signals) signal_options_c = ffi.new("SignalParseOptions[]", [ { @@ -66,8 +66,8 @@ def __init__(self, dbc_name, signals, checks=None, bus=0, sendcan=False, tcp_add 'check_frequency': freq, } for msg_address, freq in message_options.items()]) - self.can = libdbc.can_init(bus, dbc_name, len(message_options_c), message_options_c, - len(signal_options_c), signal_options_c, sendcan, tcp_addr, timeout) + self.can = libdbc.can_init(bus, dbc_name.encode('utf8'), len(message_options_c), message_options_c, + len(signal_options_c), signal_options_c, sendcan, tcp_addr.encode('utf8'), timeout) self.p_can_valid = ffi.new("bool*") @@ -85,11 +85,11 @@ def update_vl(self, sec): self.can_valid = self.can_invalid_cnt < CAN_INVALID_CNT ret = set() - for i in xrange(can_values_len): + for i in range(can_values_len): cv = self.can_values[i] address = cv.address # print("{0} {1}".format(hex(cv.address), ffi.string(cv.name))) - name = ffi.string(cv.name) + name = ffi.string(cv.name).decode('utf8') self.vl[address][name] = cv.value self.ts[address][name] = cv.ts diff --git a/selfdrive/can/tests/test_packer_chrysler.py b/selfdrive/can/tests/test_packer_chrysler.py index da85a9841500fb..e566d87a72a40a 100644 --- a/selfdrive/can/tests/test_packer_chrysler.py +++ b/selfdrive/can/tests/test_packer_chrysler.py @@ -13,7 +13,7 @@ def setUp(self): def test_correctness(self): # Test all commands, randomize the params. - for _ in xrange(1000): + for _ in range(1000): gear = ('drive', 'reverse', 'low')[random.randint(0, 3) % 3] lkas_active = (random.randint(0, 2) % 2 == 0) hud_alert = random.randint(0, 6) diff --git a/selfdrive/can/tests/test_packer_gm.py b/selfdrive/can/tests/test_packer_gm.py index db5631fbbe4986..54119fbe436b0b 100644 --- a/selfdrive/can/tests/test_packer_gm.py +++ b/selfdrive/can/tests/test_packer_gm.py @@ -17,7 +17,7 @@ def setUp(self): def test_correctness(self): # Test all cars' commands, randomize the params. - for _ in xrange(1000): + for _ in range(1000): bus = random.randint(0, 65536) apply_steer = (random.randint(0, 2) % 2 == 0) idx = random.randint(0, 65536) diff --git a/selfdrive/can/tests/test_packer_honda.py b/selfdrive/can/tests/test_packer_honda.py index b6e779e40cf60d..3a9548a3ef5f5a 100644 --- a/selfdrive/can/tests/test_packer_honda.py +++ b/selfdrive/can/tests/test_packer_honda.py @@ -15,8 +15,8 @@ def setUp(self): def test_correctness(self): # Test all commands, randomize the params. - for _ in xrange(1000): - is_panda_black = False + for _ in range(1000): + has_relay = False car_fingerprint = HONDA_BOSCH[0] apply_brake = (random.randint(0, 2) % 2 == 0) @@ -25,15 +25,15 @@ def test_correctness(self): pcm_cancel_cmd = (random.randint(0, 2) % 2 == 0) fcw = random.randint(0, 65536) idx = random.randint(0, 65536) - m_old = hondacan.create_brake_command(self.honda_cp_old, apply_brake, pump_on, pcm_override, pcm_cancel_cmd, fcw, idx, car_fingerprint, is_panda_black) - m = hondacan.create_brake_command(self.honda_cp, apply_brake, pump_on, pcm_override, pcm_cancel_cmd, fcw, idx, car_fingerprint, is_panda_black) + m_old = hondacan.create_brake_command(self.honda_cp_old, apply_brake, pump_on, pcm_override, pcm_cancel_cmd, fcw, idx, car_fingerprint, has_relay) + m = hondacan.create_brake_command(self.honda_cp, apply_brake, pump_on, pcm_override, pcm_cancel_cmd, fcw, idx, car_fingerprint, has_relay) self.assertEqual(m_old, m) apply_steer = (random.randint(0, 2) % 2 == 0) lkas_active = (random.randint(0, 2) % 2 == 0) idx = random.randint(0, 65536) - m_old = hondacan.create_steering_control(self.honda_cp_old, apply_steer, lkas_active, car_fingerprint, idx, is_panda_black) - m = hondacan.create_steering_control(self.honda_cp, apply_steer, lkas_active, car_fingerprint, idx, is_panda_black) + m_old = hondacan.create_steering_control(self.honda_cp_old, apply_steer, lkas_active, car_fingerprint, idx, has_relay) + m = hondacan.create_steering_control(self.honda_cp, apply_steer, lkas_active, car_fingerprint, idx, has_relay) self.assertEqual(m_old, m) pcm_speed = random.randint(0, 65536) @@ -41,14 +41,14 @@ def test_correctness(self): 0xc1, random.randint(0, 65536), random.randint(0, 65536), random.randint(0, 65536), random.randint(0, 65536)) idx = random.randint(0, 65536) is_metric = (random.randint(0, 2) % 2 == 0) - m_old = hondacan.create_ui_commands(self.honda_cp_old, pcm_speed, hud, car_fingerprint, is_metric, idx, is_panda_black) - m = hondacan.create_ui_commands(self.honda_cp, pcm_speed, hud, car_fingerprint, is_metric, idx, is_panda_black) + m_old = hondacan.create_ui_commands(self.honda_cp_old, pcm_speed, hud, car_fingerprint, is_metric, idx, has_relay) + m = hondacan.create_ui_commands(self.honda_cp, pcm_speed, hud, car_fingerprint, is_metric, idx, has_relay) self.assertEqual(m_old, m) button_val = random.randint(0, 65536) idx = random.randint(0, 65536) - m_old = hondacan.spam_buttons_command(self.honda_cp_old, button_val, idx, car_fingerprint, is_panda_black) - m = hondacan.spam_buttons_command(self.honda_cp, button_val, idx, car_fingerprint, is_panda_black) + m_old = hondacan.spam_buttons_command(self.honda_cp_old, button_val, idx, car_fingerprint, has_relay) + m = hondacan.spam_buttons_command(self.honda_cp, button_val, idx, car_fingerprint, has_relay) self.assertEqual(m_old, m) diff --git a/selfdrive/can/tests/test_packer_hyundai.py b/selfdrive/can/tests/test_packer_hyundai.py index d9e829ad59dafe..c2bcb04014c560 100644 --- a/selfdrive/can/tests/test_packer_hyundai.py +++ b/selfdrive/can/tests/test_packer_hyundai.py @@ -14,7 +14,7 @@ def setUp(self): def test_correctness(self): # Test all commands, randomize the params. - for _ in xrange(1000): + for _ in range(1000): # Hyundai car_fingerprint = hyundai_checksum["crc8"][0] apply_steer = (random.randint(0, 2) % 2 == 0) diff --git a/selfdrive/can/tests/test_packer_subaru.py b/selfdrive/can/tests/test_packer_subaru.py index 65dd77cf8311b9..0690806d7c1917 100644 --- a/selfdrive/can/tests/test_packer_subaru.py +++ b/selfdrive/can/tests/test_packer_subaru.py @@ -14,7 +14,7 @@ def setUp(self): def test_correctness(self): # Test all cars' commands, randomize the params. - for _ in xrange(1000): + for _ in range(1000): apply_steer = (random.randint(0, 2) % 2 == 0) frame = random.randint(1, 65536) steer_step = random.randint(1, 65536) diff --git a/selfdrive/can/tests/test_packer_toyota.py b/selfdrive/can/tests/test_packer_toyota.py index fc53399ee526b8..05f5eeed2e0348 100644 --- a/selfdrive/can/tests/test_packer_toyota.py +++ b/selfdrive/can/tests/test_packer_toyota.py @@ -17,7 +17,7 @@ def setUp(self): def test_correctness(self): # Test all commands, randomize the params. - for _ in xrange(1000): + for _ in range(1000): # Toyota steer = random.randint(-1, 1) enabled = (random.randint(0, 2) % 2 == 0) @@ -66,14 +66,14 @@ def test_performance(self): left_lane_depart = (random.randint(0, 2) % 2 == 0) right_lane_depart = (random.randint(0, 2) % 2 == 0) - for _ in xrange(recursions): + for _ in range(recursions): create_ui_command(self.cp_old, steer, chime, left_line, right_line, left_lane_depart, right_lane_depart) n2 = sec_since_boot() elapsed_old = n2 - n1 # print('Old API, elapsed time: {} secs'.format(elapsed_old)) n1 = sec_since_boot() - for _ in xrange(recursions): + for _ in range(recursions): create_ui_command(self.cp, steer, chime, left_line, right_line, left_lane_depart, right_lane_depart) n2 = sec_since_boot() elapsed_new = n2 - n1 diff --git a/selfdrive/can/tests/test_parser.py b/selfdrive/can/tests/test_parser.py index ff3cbddf7eda0d..09d153c1bd45ca 100755 --- a/selfdrive/can/tests/test_parser.py +++ b/selfdrive/can/tests/test_parser.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import os import unittest @@ -45,7 +45,7 @@ def dicts_vals_differ(dict1, dict2): def run_route(route): can = messaging.pub_sock(service_list['can'].port) - CP = CarInterface.get_params(CAR.CIVIC, {}) + CP = CarInterface.get_params(CAR.CIVIC) signals, checks = get_can_signals(CP) parser_old = CANParserOld(DBC[CP.carFingerprint]['pt'], signals, checks, 0, timeout=-1, tcp_addr="127.0.0.1") parser_new = CANParserNew(DBC[CP.carFingerprint]['pt'], signals, checks, 0, timeout=-1, tcp_addr="127.0.0.1") @@ -95,7 +95,7 @@ def setUp(self): for route in self.routes.values(): route_filename = route + ".bz2" if not os.path.isfile(route_filename): - with open(route + ".bz2", "w") as f: + with open(route + ".bz2", "wb") as f: f.write(requests.get(BASE_URL + route_filename).content) def test_parser_civic(self): diff --git a/selfdrive/car/__init__.py b/selfdrive/car/__init__.py index 3b259c622289fd..b0232daf44aede 100644 --- a/selfdrive/car/__init__.py +++ b/selfdrive/car/__init__.py @@ -4,6 +4,9 @@ # kg of standard extra cargo to count for drive, gas, etc... STD_CARGO_KG = 136. +def gen_empty_fingerprint(): + return {i: {} for i in range(0, 4)} + # FIXME: hardcoding honda civic 2016 touring params so they can be used to # scale unknown params for other cars class CivicParams: @@ -31,7 +34,7 @@ def scale_tire_stiffness(mass, wheelbase, center_to_front, tire_stiffness_factor (center_to_front / wheelbase) / (CivicParams.CENTER_TO_FRONT / CivicParams.WHEELBASE) return tire_stiffness_front, tire_stiffness_rear - + def dbc_dict(pt_dbc, radar_dbc, chassis_dbc=None): return {'pt': pt_dbc, 'radar': radar_dbc, 'chassis': chassis_dbc} @@ -53,11 +56,10 @@ def apply_std_steer_torque_limits(apply_torque, apply_torque_last, driver_torque apply_torque = clip(apply_torque, apply_torque_last - LIMITS.STEER_DELTA_UP, min(apply_torque_last + LIMITS.STEER_DELTA_DOWN, LIMITS.STEER_DELTA_UP)) - return int(round(apply_torque)) + return int(round(float(apply_torque))) def apply_toyota_steer_torque_limits(apply_torque, apply_torque_last, motor_torque, LIMITS): - # limits due to comparison of commanded torque VS motor reported torque max_lim = min(max(motor_torque + LIMITS.STEER_ERROR_MAX, LIMITS.STEER_ERROR_MAX), LIMITS.STEER_MAX) min_lim = max(min(motor_torque - LIMITS.STEER_ERROR_MAX, -LIMITS.STEER_ERROR_MAX), -LIMITS.STEER_MAX) @@ -74,7 +76,7 @@ def apply_toyota_steer_torque_limits(apply_torque, apply_torque_last, motor_torq apply_torque_last - LIMITS.STEER_DELTA_UP, min(apply_torque_last + LIMITS.STEER_DELTA_DOWN, LIMITS.STEER_DELTA_UP)) - return int(round(apply_torque)) + return int(round(float(apply_torque))) def crc8_pedal(data): @@ -106,8 +108,19 @@ def create_gas_command(packer, gas_amount, idx): dat = packer.make_can_msg("GAS_COMMAND", 0, values)[2] - dat = [ord(i) for i in dat] checksum = crc8_pedal(dat[:-1]) values["CHECKSUM_PEDAL"] = checksum return packer.make_can_msg("GAS_COMMAND", 0, values) + + +def is_ecu_disconnected(fingerprint, fingerprint_list, ecu_fingerprint, car, ecu): + # check if a stock ecu is disconnected by looking for specific CAN msgs in the fingerprint + # return True if the reference car fingerprint contains the ecu fingerprint msg and + # fingerprint does not contains messages normally sent by a given ecu + ecu_in_car = False + for car_finger in fingerprint_list[car]: + if any(msg in car_finger for msg in ecu_fingerprint[ecu]): + ecu_in_car = True + + return ecu_in_car and not any(msg in fingerprint for msg in ecu_fingerprint[ecu]) diff --git a/selfdrive/car/car_helpers.py b/selfdrive/car/car_helpers.py index a90f8d43e063b4..eaff50a3b7f7e1 100644 --- a/selfdrive/car/car_helpers.py +++ b/selfdrive/car/car_helpers.py @@ -2,11 +2,12 @@ import zmq from cereal import car from common.params import Params -from common.vin import get_vin, VIN_UNKNOWN from common.basedir import BASEDIR -from common.fingerprints import eliminate_incompatible_cars, all_known_cars +from selfdrive.car.fingerprints import eliminate_incompatible_cars, all_known_cars +from selfdrive.car.vin import get_vin, VIN_UNKNOWN from selfdrive.swaglog import cloudlog import selfdrive.messaging as messaging +from selfdrive.car import gen_empty_fingerprint def get_one_can(logcan): @@ -67,12 +68,7 @@ def only_toyota_left(candidate_cars): # BOUNTY: every added fingerprint in selfdrive/car/*/values.py is a $100 coupon code on shop.comma.ai # **** for use live only **** -def fingerprint(logcan, sendcan, is_panda_black): - if os.getenv("SIMULATOR2") is not None: - return ("simulator2", None, "") - elif os.getenv("SIMULATOR") is not None: - return ("simulator", None, "") - +def fingerprint(logcan, sendcan, has_relay): params = Params() car_params = params.get("CarParams") @@ -80,7 +76,7 @@ def fingerprint(logcan, sendcan, is_panda_black): # use already stored VIN: a new VIN query cannot be done, since panda isn't in ELM327 mode car_params = car.CarParams.from_bytes(car_params) vin = VIN_UNKNOWN if car_params.carVin == "" else car_params.carVin - elif is_panda_black: + elif has_relay: # Vin query only reliably works thorugh OBDII vin = get_vin(logcan, sendcan, 1) else: @@ -89,7 +85,7 @@ def fingerprint(logcan, sendcan, is_panda_black): cloudlog.warning("VIN %s", vin) Params().put("CarVin", vin) - finger = {i: {} for i in range(0, 4)} # collect on all buses + finger = gen_empty_fingerprint() candidate_cars = {i: all_known_cars() for i in [0, 1]} # attempt fingerprint on both bus 0 and 1 frame = 0 frame_fingerprint = 10 # 0.1s @@ -105,10 +101,11 @@ def fingerprint(logcan, sendcan, is_panda_black): # and VIN query response. # Include bus 2 for toyotas to disambiguate cars using camera messages # (ideally should be done for all cars but we can't for Honda Bosch) + if can.src in range(0, 4): + finger[can.src][can.address] = len(can.dat) for b in candidate_cars: if (can.src == b or (only_toyota_left(candidate_cars[b]) and can.src == 2)) and \ can.address < 0x800 and can.address not in [0x7df, 0x7e0, 0x7e8]: - finger[can.src][can.address] = len(can.dat) candidate_cars[b] = eliminate_incompatible_cars(can, candidate_cars[b]) # if we only have one car choice and the time since we got our first @@ -123,7 +120,7 @@ def fingerprint(logcan, sendcan, is_panda_black): car_fingerprint = candidate_cars[b][0] # bail if no cars left or we've been waiting for more than 2s - failed = all(len(cc) == 0 for cc in candidate_cars.itervalues()) or frame > 200 + failed = all(len(cc) == 0 for cc in candidate_cars.values()) or frame > 200 succeeded = car_fingerprint is not None done = failed or succeeded @@ -133,15 +130,15 @@ def fingerprint(logcan, sendcan, is_panda_black): return car_fingerprint, finger, vin -def get_car(logcan, sendcan, is_panda_black=False): +def get_car(logcan, sendcan, has_relay=False): - candidate, fingerprints, vin = fingerprint(logcan, sendcan, is_panda_black) + candidate, fingerprints, vin = fingerprint(logcan, sendcan, has_relay) if candidate is None: cloudlog.warning("car doesn't match any fingerprints: %r", fingerprints) candidate = "mock" CarInterface, CarController = interfaces[candidate] - car_params = CarInterface.get_params(candidate, fingerprints[0], vin, is_panda_black) + car_params = CarInterface.get_params(candidate, fingerprints, vin, has_relay) return CarInterface(car_params, CarController), car_params diff --git a/selfdrive/car/chrysler/carcontroller.py b/selfdrive/car/chrysler/carcontroller.py index 2ddc4bdaf309ea..7e2dc5cff60170 100644 --- a/selfdrive/car/chrysler/carcontroller.py +++ b/selfdrive/car/chrysler/carcontroller.py @@ -11,7 +11,7 @@ class SteerLimitParams: STEER_ERROR_MAX = 80 -class CarController(object): +class CarController(): def __init__(self, dbc_name, car_fingerprint, enable_camera): self.braking = False # redundant safety check with the board diff --git a/selfdrive/car/chrysler/carstate.py b/selfdrive/car/chrysler/carstate.py index 13ea25b59ce82a..93b354e0f8de93 100644 --- a/selfdrive/car/chrysler/carstate.py +++ b/selfdrive/car/chrysler/carstate.py @@ -77,7 +77,7 @@ def get_camera_parser(CP): return CANParser(DBC[CP.carFingerprint]['pt'], signals, checks, 2) -class CarState(object): +class CarState(): def __init__(self, CP): self.CP = CP diff --git a/selfdrive/car/chrysler/chryslercan.py b/selfdrive/car/chrysler/chryslercan.py index d710262e9169ea..047ae82580b27d 100644 --- a/selfdrive/car/chrysler/chryslercan.py +++ b/selfdrive/car/chrysler/chryslercan.py @@ -1,6 +1,7 @@ from cereal import car +GearShifter = car.CarState.GearShifter VisualAlert = car.CarControl.HUDControl.VisualAlert def calc_checksum(data): @@ -48,7 +49,7 @@ def create_lkas_hud(packer, gear, lkas_active, hud_alert, hud_count, lkas_car_mo # LKAS_HUD 0x2a6 (678) Controls what lane-keeping icon is displayed. if hud_alert == VisualAlert.steerRequired: - msg = '0000000300000000'.decode('hex') + msg = b'\x00\x00\x00\x03\x00\x00\x00\x00' return make_can_msg(0x2a6, msg) color = 1 # default values are for park or neutral in 2017 are 0 0, but trying 1 1 for 2019 @@ -59,7 +60,7 @@ def create_lkas_hud(packer, gear, lkas_active, hud_alert, hud_count, lkas_car_mo alerts = 1 # CAR.PACIFICA_2018_HYBRID and CAR.PACIFICA_2019_HYBRID # had color = 1 and lines = 1 but trying 2017 hybrid style for now. - if gear in ('drive', 'reverse', 'low'): + if gear in (GearShifter.drive, GearShifter.reverse, GearShifter.low): if lkas_active: color = 2 # control active, display green. lines = 6 @@ -86,7 +87,7 @@ def create_lkas_command(packer, apply_steer, moving_fast, frame): } dat = packer.make_can_msg("LKAS_COMMAND", 0, values)[2] - dat = [ord(i) for i in dat][:-1] + dat = dat[:-1] checksum = calc_checksum(dat) values["CHECKSUM"] = checksum @@ -95,8 +96,8 @@ def create_lkas_command(packer, apply_steer, moving_fast, frame): def create_wheel_buttons(frame): # WHEEL_BUTTONS (571) Message sent to cancel ACC. - start = [0x01] # acc cancel set + start = b"\x01" # acc cancel set counter = (frame % 10) << 4 - dat = start + [counter] - dat = dat + [calc_checksum(dat)] - return make_can_msg(0x23b, str(bytearray(dat))) + dat = start + counter.to_bytes(1, 'little') + dat = dat + calc_checksum(dat).to_bytes(1, 'little') + return make_can_msg(0x23b, dat) diff --git a/selfdrive/car/chrysler/interface.py b/selfdrive/car/chrysler/interface.py index e470b3c1d80783..8a3cd750a42d36 100755 --- a/selfdrive/car/chrysler/interface.py +++ b/selfdrive/car/chrysler/interface.py @@ -1,16 +1,17 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 from cereal import car from selfdrive.config import Conversions as CV from selfdrive.controls.lib.drive_helpers import EventTypes as ET, create_event from selfdrive.controls.lib.vehicle_model import VehicleModel from selfdrive.car.chrysler.carstate import CarState, get_can_parser, get_camera_parser -from selfdrive.car.chrysler.values import ECU, check_ecu_msgs, CAR -from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness +from selfdrive.car.chrysler.values import ECU, ECU_FINGERPRINT, CAR, FINGERPRINTS +from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, is_ecu_disconnected, gen_empty_fingerprint +from selfdrive.car.interfaces import CarInterfaceBase GearShifter = car.CarState.GearShifter ButtonType = car.CarState.ButtonEvent.Type -class CarInterface(object): +class CarInterface(CarInterfaceBase): def __init__(self, CP, CarController): self.CP = CP self.VM = VehicleModel(CP) @@ -34,18 +35,14 @@ def compute_gb(accel, speed): return float(accel) / 3.0 @staticmethod - def calc_accel_override(a_ego, a_target, v_ego, v_target): - return 1.0 - - @staticmethod - def get_params(candidate, fingerprint, vin="", is_panda_black=False): + def get_params(candidate, fingerprint=gen_empty_fingerprint(), vin="", has_relay=False): ret = car.CarParams.new_message() ret.carName = "chrysler" ret.carFingerprint = candidate ret.carVin = vin - ret.isPandaBlack = is_panda_black + ret.isPandaBlack = has_relay ret.safetyModel = car.CarParams.SafetyModel.chrysler @@ -95,7 +92,7 @@ def get_params(candidate, fingerprint, vin="", is_panda_black=False): ret.brakeMaxBP = [5., 20.] ret.brakeMaxV = [1., 0.8] - ret.enableCamera = not check_ecu_msgs(fingerprint, ECU.CAM) or is_panda_black + ret.enableCamera = is_ecu_disconnected(fingerprint[0], FINGERPRINTS, ECU_FINGERPRINT, candidate, ECU.CAM) or has_relay print("ECU Camera Simulated: {0}".format(ret.enableCamera)) ret.openpilotLongitudinalControl = False diff --git a/selfdrive/car/chrysler/radar_interface.py b/selfdrive/car/chrysler/radar_interface.py index 815d2c3e4c49ed..3130c2ca719999 100755 --- a/selfdrive/car/chrysler/radar_interface.py +++ b/selfdrive/car/chrysler/radar_interface.py @@ -1,10 +1,11 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import os from selfdrive.can.parser import CANParser from cereal import car +from selfdrive.car.interfaces import RadarInterfaceBase -RADAR_MSGS_C = range(0x2c2, 0x2d4+2, 2) # c_ messages 706,...,724 -RADAR_MSGS_D = range(0x2a2, 0x2b4+2, 2) # d_ messages +RADAR_MSGS_C = list(range(0x2c2, 0x2d4+2, 2)) # c_ messages 706,...,724 +RADAR_MSGS_D = list(range(0x2a2, 0x2b4+2, 2)) # d_ messages LAST_MSG = max(RADAR_MSGS_C + RADAR_MSGS_D) NUMBER_MSGS = len(RADAR_MSGS_C) + len(RADAR_MSGS_D) @@ -45,10 +46,10 @@ def _address_to_track(address): return (address - RADAR_MSGS_D[0]) // 2 raise ValueError("radar received unexpected address %d" % address) -class RadarInterface(object): +class RadarInterface(RadarInterfaceBase): def __init__(self, CP): self.pts = {} - self.delay = 0.0 # Delay of radar #TUNE + self.delay = 0 # Delay of radar #TUNE self.rcp = _create_radar_can_parser() self.updated_messages = set() self.trigger_msg = LAST_MSG diff --git a/selfdrive/car/chrysler/run_tests.sh b/selfdrive/car/chrysler/run_tests.sh deleted file mode 100755 index 1dcc8b2acf0bbf..00000000000000 --- a/selfdrive/car/chrysler/run_tests.sh +++ /dev/null @@ -1 +0,0 @@ -PYTHONPATH=`realpath ../../../` python chryslercan_test.py diff --git a/selfdrive/car/chrysler/chryslercan_test.py b/selfdrive/car/chrysler/test_chryslercan.py similarity index 55% rename from selfdrive/car/chrysler/chryslercan_test.py rename to selfdrive/car/chrysler/test_chryslercan.py index 54b845342fcb15..292fec5222ef86 100644 --- a/selfdrive/car/chrysler/chryslercan_test.py +++ b/selfdrive/car/chrysler/test_chryslercan.py @@ -1,55 +1,57 @@ -from selfdrive.car.chrysler import chryslercan -from selfdrive.can.packer import CANPacker +import unittest from cereal import car +from selfdrive.can.packer import CANPacker +from selfdrive.car.chrysler import chryslercan + VisualAlert = car.CarControl.HUDControl.VisualAlert +GearShifter = car.CarState.GearShifter -import unittest class TestChryslerCan(unittest.TestCase): def test_checksum(self): - self.assertEqual(0x75, chryslercan.calc_checksum([0x01, 0x20])) - self.assertEqual(0xcc, chryslercan.calc_checksum([0x14, 0, 0, 0, 0x20])) + self.assertEqual(0x75, chryslercan.calc_checksum(b"\x01\x20")) + self.assertEqual(0xcc, chryslercan.calc_checksum(b"\x14\x00\x00\x00\x20")) def test_hud(self): packer = CANPacker('chrysler_pacifica_2017_hybrid') self.assertEqual( - [0x2a6, 0, '0100010100000000'.decode('hex'), 0], + [0x2a6, 0, b'\x01\x00\x01\x01\x00\x00\x00\x00', 0], chryslercan.create_lkas_hud( packer, - 'park', False, False, 1, 0)) + GearShifter.park, False, False, 1, 0)) self.assertEqual( - [0x2a6, 0, '0100010000000000'.decode('hex'), 0], + [0x2a6, 0, b'\x01\x00\x01\x00\x00\x00\x00\x00', 0], chryslercan.create_lkas_hud( packer, - 'park', False, False, 5*4, 0)) + GearShifter.park, False, False, 5*4, 0)) self.assertEqual( - [0x2a6, 0, '0100010000000000'.decode('hex'), 0], + [0x2a6, 0, b'\x01\x00\x01\x00\x00\x00\x00\x00', 0], chryslercan.create_lkas_hud( packer, - 'park', False, False, 99999, 0)) + GearShifter.park, False, False, 99999, 0)) self.assertEqual( - [0x2a6, 0, '0200060000000000'.decode('hex'), 0], + [0x2a6, 0, b'\x02\x00\x06\x00\x00\x00\x00\x00', 0], chryslercan.create_lkas_hud( packer, - 'drive', True, False, 99999, 0)) + GearShifter.drive, True, False, 99999, 0)) self.assertEqual( - [0x2a6, 0, '0264060000000000'.decode('hex'), 0], + [0x2a6, 0, b'\x02\x64\x06\x00\x00\x00\x00\x00', 0], chryslercan.create_lkas_hud( packer, - 'drive', True, False, 99999, 0x64)) + GearShifter.drive, True, False, 99999, 0x64)) def test_command(self): packer = CANPacker('chrysler_pacifica_2017_hybrid') self.assertEqual( - [0x292, 0, '140000001086'.decode('hex'), 0], + [0x292, 0, b'\x14\x00\x00\x00\x10\x86', 0], chryslercan.create_lkas_command( packer, 0, True, 1)) self.assertEqual( - [0x292, 0, '040000008083'.decode('hex'), 0], + [0x292, 0, b'\x04\x00\x00\x00\x80\x83', 0], chryslercan.create_lkas_command( packer, 0, False, 8)) diff --git a/selfdrive/car/chrysler/values.py b/selfdrive/car/chrysler/values.py index 2e74d70239dca6..1832c8cd0849e9 100644 --- a/selfdrive/car/chrysler/values.py +++ b/selfdrive/car/chrysler/values.py @@ -4,7 +4,7 @@ class CAR: PACIFICA_2017_HYBRID = "CHRYSLER PACIFICA HYBRID 2017" PACIFICA_2018_HYBRID = "CHRYSLER PACIFICA HYBRID 2018" PACIFICA_2019_HYBRID = "CHRYSLER PACIFICA HYBRID 2019" - PACIFICA_2018 = "CHRYSLER PACIFICA 2018" + PACIFICA_2018 = "CHRYSLER PACIFICA 2018" # Also covers Pacifica 2017. JEEP_CHEROKEE = "JEEP GRAND CHEROKEE V6 2018" # Also covers Tailhawk 2017. JEEP_CHEROKEE_2019 = "JEEP GRAND CHEROKEE 2019" @@ -25,14 +25,15 @@ class CAR: ], CAR.PACIFICA_2018: [ {55: 8, 257: 5, 258: 8, 264: 8, 268: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 292: 8, 294: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 368: 8, 376: 3, 384: 8, 388: 4, 416: 7, 448: 6, 456: 4, 464: 8, 469: 8, 480: 8, 500: 8, 501: 8, 512: 8, 514: 8, 516: 7, 517: 7, 520: 8, 524: 8, 526: 6, 528: 8, 532: 8, 542: 8, 544: 8, 557: 8, 559: 8, 560: 4, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 624: 8, 625: 8, 632: 8, 639: 8, 656: 4, 658: 6, 660: 8, 669: 3, 671: 8, 672: 8, 678: 8, 680: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 729: 5, 736: 8, 746: 5, 752: 2, 760: 8, 764: 8, 766: 8, 770: 8, 773: 8, 779: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 808: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 832: 8, 838: 2, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 882: 8, 897: 8, 924: 8, 926: 3, 937: 8, 947: 8, 948: 8, 969: 4, 974: 5, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1098: 8, 1100: 8, 1537: 8, 1538: 8, 1562: 8}, + {55: 8, 257: 5, 258: 8, 264: 8, 268: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 292: 8, 294: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 368: 8, 376: 3, 384: 8, 388: 4, 416: 7, 448: 6, 456: 4, 464: 8, 469: 8, 480: 8, 500: 8, 501: 8, 512: 8, 514: 8, 516: 7, 517: 7, 520: 8, 524: 8, 526: 6, 528: 8, 532: 8, 542: 8, 544: 8, 557: 8, 559: 8, 560: 4, 564: 4, 571: 3, 584: 8, 608: 8, 624: 8, 625: 8, 632: 8, 639: 8, 656: 4, 658: 6, 660: 8, 669: 3, 671: 8, 672: 8, 678: 8, 680: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 729: 5, 736: 8, 746: 5, 752: 2, 760: 8, 764: 8, 766: 8, 770: 8, 773: 8, 779: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 808: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 832: 8, 838: 2, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 882: 8, 897: 8, 924: 3, 926: 3, 937: 8, 947: 8, 948: 8, 969: 4, 974: 5, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1098: 8, 1100: 8, 1537: 8, 1538: 8, 1562: 8}, ], CAR.PACIFICA_2018_HYBRID: [ - {68: 8, 168: 8, 257: 5, 258: 8, 264: 8, 268: 8, 270: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 291: 8, 292: 8, 294: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 368: 8, 376: 3, 384: 8, 388: 4, 448: 6, 456: 4, 464: 8, 469: 8, 480: 8, 500: 8, 501: 8, 512: 8, 514: 8, 520: 8, 528: 8, 532: 8, 544: 8, 557: 8, 559: 8, 560: 4, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 624: 8, 625: 8, 632: 8, 639: 8, 653: 8, 654: 8, 655: 8, 660: 8, 669: 3, 671: 8, 672: 8, 680: 8, 701: 8, 704: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 736: 8, 737: 8, 746: 5, 760: 8, 764: 8, 766: 8, 770: 8, 773: 8, 779: 8, 782: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 808: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 832: 8, 838: 2, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 878: 8, 882: 8, 897: 8, 908: 8, 924: 8, 926: 3, 929: 8, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 958: 8, 959: 8, 969: 4, 974: 5, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1082: 8, 1083: 8, 1098: 8, 1100: 8}, + {68: 8, 168: 8, 257: 5, 258: 8, 264: 8, 268: 8, 270: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 291: 8, 292: 8, 294: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 368: 8, 376: 3, 384: 8, 388: 4, 448: 6, 456: 4, 464: 8, 469: 8, 480: 8, 500: 8, 501: 8, 512: 8, 514: 8, 520: 8, 528: 8, 532: 8, 544: 8, 557: 8, 559: 8, 560: 4, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 624: 8, 625: 8, 632: 8, 639: 8, 653: 8, 654: 8, 655: 8, 658: 6, 660: 8, 669: 3, 671: 8, 672: 8, 680: 8, 701: 8, 704: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 736: 8, 737: 8, 746: 5, 760: 8, 764: 8, 766: 8, 770: 8, 773: 8, 779: 8, 782: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 808: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 832: 8, 838: 2, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 878: 8, 882: 8, 897: 8, 908: 8, 924: 8, 926: 3, 929: 8, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 958: 8, 959: 8, 969: 4, 974: 5, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1082: 8, 1083: 8, 1098: 8, 1100: 8}, # based on 9ae7821dc4e92455|2019-07-01--16-42-55 {168: 8, 257: 5, 258: 8, 264: 8, 268: 8, 270: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 291: 8, 292: 8, 294: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 368: 8, 376: 3, 384: 8, 388: 4, 448: 6, 456: 4, 464: 8, 469: 8, 480: 8, 500: 8, 501: 8, 512: 8, 514: 8, 515: 7, 516: 7, 517: 7, 518: 7, 520: 8, 528: 8, 532: 8, 542: 8, 544: 8, 557: 8, 559: 8, 560: 4, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 624: 8, 625: 8, 632: 8, 639: 8, 653: 8, 654: 8, 655: 8, 658: 6, 660: 8, 669: 3, 671: 8, 672: 8, 678: 8, 680: 8, 701: 8, 704: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 729: 5, 736: 8, 737: 8, 746: 5, 760: 8, 764: 8, 766: 8, 770: 8, 773: 8, 779: 8, 782: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 808: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 832: 8, 838: 2, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 878: 8, 882: 8, 897: 8, 908: 8, 924: 8, 926: 3, 929: 8, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 958: 8, 959: 8, 969: 4, 974: 5, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1082: 8, 1083: 8, 1098: 8, 1100: 8, 1216: 8, 1218: 8, 1220: 8, 1225: 8, 1235: 8, 1242: 8, 1246: 8, 1250: 8, 1251: 8, 1252: 8, 1258: 8, 1259: 8, 1260: 8, 1262: 8, 1284: 8, 1537: 8, 1538: 8, 1562: 8, 1568: 8, 1856: 8, 1858: 8, 1860: 8, 1865: 8, 1875: 8, 1882: 8, 1886: 8, 1890: 8, 1891: 8, 1892: 8, 1898: 8, 1899: 8, 1900: 8, 1902: 8, 2016: 8, 2018: 8, 2019: 8, 2020: 8, 2023: 8, 2024: 8, 2026: 8, 2027: 8, 2028: 8, 2031: 8}, ], CAR.PACIFICA_2019_HYBRID: [ - {168: 8, 257: 5, 258: 8, 264: 8, 268: 8, 270: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 291: 8, 292: 8, 294: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 368: 8, 376: 3, 384: 8, 388: 4, 448: 6, 456: 4, 464: 8, 469: 8, 480: 8, 500: 8, 501: 8, 512: 8, 514: 8, 515: 7, 516: 7, 517: 7, 518: 7, 520: 8, 528: 8, 532: 8, 542: 8, 544: 8, 557: 8, 559: 8, 560: 8, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 624: 8, 625: 8, 632: 8, 639: 8, 653: 8, 654: 8, 655: 8, 660: 8, 669: 3, 671: 8, 672: 8, 680: 8, 701: 8, 703: 8, 704: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 736: 8, 737: 8, 746: 5, 752: 2, 754: 8, 760: 8, 764: 8, 766: 8, 770:8, 773: 8, 779: 8, 782: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 832: 8, 838: 2, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 878: 8, 882: 8, 897: 8, 906: 8, 908: 8, 924: 8, 926: 3, 929: 8, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 958: 8, 959: 8, 962: 8, 969: 4, 973: 8, 974: 5, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1082: 8, 1083: 8, 1098: 8, 1100: 8, 1538: 8}, + {168: 8, 257: 5, 258: 8, 264: 8, 268: 8, 270: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 291: 8, 292: 8, 294: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 368: 8, 376: 3, 384: 8, 388: 4, 448: 6, 456: 4, 464: 8, 469: 8, 480: 8, 500: 8, 501: 8, 512: 8, 514: 8, 515: 7, 516: 7, 517: 7, 518: 7, 520: 8, 528: 8, 532: 8, 542: 8, 544: 8, 557: 8, 559: 8, 560: 8, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 624: 8, 625: 8, 632: 8, 639: 8, 653: 8, 654: 8, 655: 8, 658: 6, 660: 8, 669: 3, 671: 8, 672: 8, 680: 8, 701: 8, 703: 8, 704: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 736: 8, 737: 8, 746: 5, 752: 2, 754: 8, 760: 8, 764: 8, 766: 8, 770:8, 773: 8, 779: 8, 782: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 832: 8, 838: 2, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 878: 8, 882: 8, 897: 8, 906: 8, 908: 8, 924: 8, 926: 3, 929: 8, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 958: 8, 959: 8, 962: 8, 969: 4, 973: 8, 974: 5, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1082: 8, 1083: 8, 1098: 8, 1100: 8, 1538: 8}, # Based on 0607d2516fc2148f|2019-02-13--23-03-16 { 168: 8, 257: 5, 258: 8, 264: 8, 268: 8, 270: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 291: 8, 292: 8, 294: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 368: 8, 376: 3, 384: 8, 388: 4, 448: 6, 456: 4, 464: 8, 469: 8, 480: 8, 500: 8, 501: 8, 512: 8, 514: 8, 520: 8, 528: 8, 532: 8, 544: 8, 557: 8, 559: 8, 560: 8, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 624: 8, 625: 8, 632: 8, 639: 8, 653: 8, 654: 8, 655: 8, 658: 6, 660: 8, 669: 3, 671: 8, 672: 8, 678: 8, 680: 8, 701: 8, 703: 8, 704: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 729: 5, 736: 8, 737: 8, 746: 5, 752: 2, 754: 8, 760: 8, 764: 8, 766: 8, 770: 8, 773: 8, 779: 8, 782: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 832: 8, 838: 2, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 878: 8, 882: 8, 897: 8, 906: 8, 908: 8, 924: 8, 926: 3, 929: 8, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 958: 8, 959: 8, 962: 8, 969: 4, 973: 8, 974: 5, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1082: 8, 1083: 8, 1098: 8, 1100: 8, 1537: 8 @@ -46,12 +47,12 @@ class CAR: # JEEP GRAND CHEROKEE V6 2018 {55: 8, 168: 8, 181: 8, 256: 4, 257: 5, 258: 8, 264: 8, 268: 8, 272: 6, 273: 6, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 292: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 352: 8, 362: 8, 368: 8, 376: 3, 384: 8, 388: 4, 416: 7, 448: 6, 456: 4, 464: 8, 500: 8, 501: 8, 512: 8, 514: 8, 520: 8, 532: 8, 544: 8, 557: 8, 559: 8, 560: 4, 564: 4, 571: 3, 579: 8, 584: 8, 608: 8, 618: 8, 624: 8, 625: 8, 632: 8, 639: 8, 656: 4, 658: 6, 660: 8, 671: 8, 672: 8, 676: 8, 678: 8, 680: 8, 683: 8, 684: 8, 703: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 729: 5, 736: 8, 737: 8, 738: 8, 746: 5, 752: 2, 754: 8, 760: 8, 761: 8, 764: 8, 766: 8, 773: 8, 776: 8, 779: 8, 782: 8, 783: 8, 784: 8, 785: 8, 788: 3, 792: 8, 799: 8, 800: 8, 804: 8, 806: 2, 808: 8, 810: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 831: 6, 832: 8, 838: 2, 844: 5, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 882: 8, 897: 8, 906: 8, 924: 8, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 956: 8, 968: 8, 969: 4, 970: 8, 973: 8, 974: 5, 976: 8, 977: 4, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1062: 8, 1098: 8, 1100: 8}, # Jeep Grand Cherokee 2017 Trailhawk - {257: 5, 258: 8, 264: 8, 268: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 292: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 352: 8, 362: 8, 368: 8, 376: 3, 384: 8, 388: 4, 416: 7, 448: 6, 456: 4, 464: 8, 500: 8, 501: 8, 512: 8, 514: 8, 520: 8, 532: 8, 544: 8, 557: 8, 559: 8, 560: 4, 564: 4, 571: 3, 584: 8, 608: 8, 618: 8, 624: 8, 625: 8, 632: 8, 639: 8, 660: 8, 671: 8, 672: 8, 680: 8, 684: 8, 703: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 736: 8, 737: 8, 746: 5, 752: 2, 760: 8, 761: 8, 764: 8, 766: 8, 773: 8, 776: 8, 779: 8, 783: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 806: 2, 808: 8, 810: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 831: 6, 832: 8, 838: 2, 844: 5, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 882: 8, 897: 8, 924: 3, 937: 8, 947: 8, 948: 8, 969: 4, 974: 5, 977: 4, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1062: 8, 1098: 8, 1100: 8}, + {257: 5, 258: 8, 264: 8, 268: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 292: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 352: 8, 362: 8, 368: 8, 376: 3, 384: 8, 388: 4, 416: 7, 448: 6, 456: 4, 464: 8, 500: 8, 501: 8, 512: 8, 514: 8, 520: 8, 532: 8, 544: 8, 557: 8, 559: 8, 560: 4, 564: 4, 571: 3, 584: 8, 608: 8, 618: 8, 624: 8, 625: 8, 632: 8, 639: 8, 658: 6, 660: 8, 671: 8, 672: 8, 680: 8, 684: 8, 703: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 736: 8, 737: 8, 746: 5, 752: 2, 760: 8, 761: 8, 764: 8, 766: 8, 773: 8, 776: 8, 779: 8, 783: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 806: 2, 808: 8, 810: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 831: 6, 832: 8, 838: 2, 844: 5, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 882: 8, 897: 8, 924: 3, 937: 8, 947: 8, 948: 8, 969: 4, 974: 5, 977: 4, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1062: 8, 1098: 8, 1100: 8}, ], CAR.JEEP_CHEROKEE_2019: [ # Jeep Grand Cherokee 2019 from Switzerland # 530: 8 is so far only in this Jeep. - {55: 8, 181: 8, 256: 4, 257: 5, 258: 8, 264: 8, 268: 8, 272: 6, 273: 6, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 292: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 352: 8, 362: 8, 368: 8, 376: 3, 384: 8, 388: 4, 416: 7, 448: 6, 456: 4, 464: 8, 500: 8, 501: 8, 512: 8, 514: 8, 520: 8, 530: 8, 532: 8, 544: 8, 557: 8, 559: 8, 560: 8, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 618: 8, 624: 8, 625: 8, 632: 8, 639: 8, 660: 8, 671: 8, 672: 8, 676: 8, 680: 8, 683: 8, 684: 8, 703: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 736: 8, 737: 8, 738: 8, 746: 5, 752: 2, 754: 8, 760: 8, 761: 8, 764: 8, 773: 8, 776: 8, 779: 8, 782: 8, 783: 8, 784: 8, 792: 8, 799: 8, 804: 8, 806: 2, 808: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 831: 6, 832: 8, 838: 2, 844: 5, 848: 8, 853: 8, 856: 4, 860: 6, 882: 8, 897: 8, 906: 8, 924: 8, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 968: 8, 969: 4, 970: 8, 973: 8, 974: 5, 977: 4, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1062: 8, 1098: 8, 1100: 8}, + {55: 8, 181: 8, 256: 4, 257: 5, 258: 8, 264: 8, 268: 8, 272: 6, 273: 6, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 292: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 352: 8, 362: 8, 368: 8, 376: 3, 384: 8, 388: 4, 416: 7, 448: 6, 456: 4, 464: 8, 500: 8, 501: 8, 512: 8, 514: 8, 520: 8, 530: 8, 532: 8, 544: 8, 557: 8, 559: 8, 560: 8, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 618: 8, 624: 8, 625: 8, 632: 8, 639: 8, 658: 6, 660: 8, 671: 8, 672: 8, 676: 8, 680: 8, 683: 8, 684: 8, 703: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 736: 8, 737: 8, 738: 8, 746: 5, 752: 2, 754: 8, 760: 8, 761: 8, 764: 8, 773: 8, 776: 8, 779: 8, 782: 8, 783: 8, 784: 8, 792: 8, 799: 8, 804: 8, 806: 2, 808: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 831: 6, 832: 8, 838: 2, 844: 5, 848: 8, 853: 8, 856: 4, 860: 6, 882: 8, 897: 8, 906: 8, 924: 8, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 968: 8, 969: 4, 970: 8, 973: 8, 974: 5, 977: 4, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1062: 8, 1098: 8, 1100: 8}, ], } @@ -85,10 +86,5 @@ class ECU: ECU_FINGERPRINT = { - ECU.CAM: 0x2d9, # steer torque cmd + ECU.CAM: [0x292], # lkas cmd } - - -def check_ecu_msgs(fingerprint, ecu): - # return True if fingerprint contains messages normally sent by a given ecu - return ECU_FINGERPRINT[ecu] in fingerprint diff --git a/common/fingerprints.py b/selfdrive/car/fingerprints.py similarity index 100% rename from common/fingerprints.py rename to selfdrive/car/fingerprints.py diff --git a/selfdrive/car/ford/carcontroller.py b/selfdrive/car/ford/carcontroller.py index 3566fd5e75f1c7..b466f03ea04964 100644 --- a/selfdrive/car/ford/carcontroller.py +++ b/selfdrive/car/ford/carcontroller.py @@ -7,7 +7,7 @@ MAX_STEER_DELTA = 1 TOGGLE_DEBUG = False -class CarController(object): +class CarController(): def __init__(self, dbc_name, enable_camera, vehicle_model): self.packer = CANPacker(dbc_name) self.enable_camera = enable_camera @@ -48,7 +48,7 @@ def update(self, enabled, CS, frame, actuators, visual_alert, pcm_cancel): if (frame % 100) == 0: - can_sends.append(make_can_msg(973, '\x00\x00\x00\x00\x00\x00\x00\x00', 0, False)) + can_sends.append(make_can_msg(973, b'\x00\x00\x00\x00\x00\x00\x00\x00', 0, False)) #can_sends.append(make_can_msg(984, '\x00\x00\x00\x00\x80\x45\x60\x30', 0, False)) if (frame % 100) == 0 or (self.enabled_last != enabled) or (self.main_on_last != CS.main_on) or \ @@ -56,29 +56,29 @@ def update(self, enabled, CS, frame, actuators, visual_alert, pcm_cancel): can_sends.append(create_lkas_ui(self.packer, CS.main_on, enabled, steer_alert)) if (frame % 200) == 0: - can_sends.append(make_can_msg(1875, '\x80\xb0\x55\x55\x78\x90\x00\x00', 1, False)) + can_sends.append(make_can_msg(1875, b'\x80\xb0\x55\x55\x78\x90\x00\x00', 1, False)) if (frame % 10) == 0: - can_sends.append(make_can_msg(1648, '\x00\x00\x00\x40\x00\x00\x50\x00', 1, False)) - can_sends.append(make_can_msg(1649, '\x10\x10\xf1\x70\x04\x00\x00\x00', 1, False)) + can_sends.append(make_can_msg(1648, b'\x00\x00\x00\x40\x00\x00\x50\x00', 1, False)) + can_sends.append(make_can_msg(1649, b'\x10\x10\xf1\x70\x04\x00\x00\x00', 1, False)) - can_sends.append(make_can_msg(1664, '\x00\x00\x03\xe8\x00\x01\xa9\xb2', 1, False)) - can_sends.append(make_can_msg(1674, '\x08\x00\x00\xff\x0c\xfb\x6a\x08', 1, False)) - can_sends.append(make_can_msg(1675, '\x00\x00\x3b\x60\x37\x00\x00\x00', 1, False)) - can_sends.append(make_can_msg(1690, '\x70\x00\x00\x55\x86\x1c\xe0\x00', 1, False)) + can_sends.append(make_can_msg(1664, b'\x00\x00\x03\xe8\x00\x01\xa9\xb2', 1, False)) + can_sends.append(make_can_msg(1674, b'\x08\x00\x00\xff\x0c\xfb\x6a\x08', 1, False)) + can_sends.append(make_can_msg(1675, b'\x00\x00\x3b\x60\x37\x00\x00\x00', 1, False)) + can_sends.append(make_can_msg(1690, b'\x70\x00\x00\x55\x86\x1c\xe0\x00', 1, False)) - can_sends.append(make_can_msg(1910, '\x06\x4b\x06\x4b\x42\xd3\x11\x30', 1, False)) - can_sends.append(make_can_msg(1911, '\x48\x53\x37\x54\x48\x53\x37\x54', 1, False)) - can_sends.append(make_can_msg(1912, '\x31\x34\x47\x30\x38\x31\x43\x42', 1, False)) - can_sends.append(make_can_msg(1913, '\x31\x34\x47\x30\x38\x32\x43\x42', 1, False)) - can_sends.append(make_can_msg(1969, '\xf4\x40\x00\x00\x00\x00\x00\x00', 1, False)) - can_sends.append(make_can_msg(1971, '\x0b\xc0\x00\x00\x00\x00\x00\x00', 1, False)) + can_sends.append(make_can_msg(1910, b'\x06\x4b\x06\x4b\x42\xd3\x11\x30', 1, False)) + can_sends.append(make_can_msg(1911, b'\x48\x53\x37\x54\x48\x53\x37\x54', 1, False)) + can_sends.append(make_can_msg(1912, b'\x31\x34\x47\x30\x38\x31\x43\x42', 1, False)) + can_sends.append(make_can_msg(1913, b'\x31\x34\x47\x30\x38\x32\x43\x42', 1, False)) + can_sends.append(make_can_msg(1969, b'\xf4\x40\x00\x00\x00\x00\x00\x00', 1, False)) + can_sends.append(make_can_msg(1971, b'\x0b\xc0\x00\x00\x00\x00\x00\x00', 1, False)) static_msgs = range(1653, 1658) for addr in static_msgs: cnt = (frame % 10) + 1 - can_sends.append(make_can_msg(addr, chr(cnt<<4) + '\x00\x00\x00\x00\x00\x00\x00', 1, False)) + can_sends.append(make_can_msg(addr, (cnt<<4).to_bytes(1, 'little') + b'\x00\x00\x00\x00\x00\x00\x00', 1, False)) self.enabled_last = enabled self.main_on_last = CS.main_on diff --git a/selfdrive/car/ford/carstate.py b/selfdrive/car/ford/carstate.py index 5e87a2c87812f1..b6ddf4525981f3 100644 --- a/selfdrive/car/ford/carstate.py +++ b/selfdrive/car/ford/carstate.py @@ -1,8 +1,8 @@ from selfdrive.can.parser import CANParser +from common.numpy_fast import mean from selfdrive.config import Conversions as CV from selfdrive.car.ford.values import DBC from common.kalman.simple_kalman import KF1D -import numpy as np WHEEL_RADIUS = 0.33 @@ -32,7 +32,7 @@ def get_can_parser(CP): return CANParser(DBC[CP.carFingerprint]['pt'], signals, checks, 0) -class CarState(object): +class CarState(): def __init__(self, CP): self.CP = CP @@ -62,7 +62,7 @@ def update(self, cp): self.v_wheel_fr = cp.vl["WheelSpeed_CG1"]['WhlRl_W_Meas'] * WHEEL_RADIUS self.v_wheel_rl = cp.vl["WheelSpeed_CG1"]['WhlFr_W_Meas'] * WHEEL_RADIUS self.v_wheel_rr = cp.vl["WheelSpeed_CG1"]['WhlFl_W_Meas'] * WHEEL_RADIUS - v_wheel = float(np.mean([self.v_wheel_fl, self.v_wheel_fr, self.v_wheel_rl, self.v_wheel_rr])) + v_wheel = mean([self.v_wheel_fl, self.v_wheel_fr, self.v_wheel_rl, self.v_wheel_rr]) # Kalman filter if abs(v_wheel - self.v_ego) > 2.0: # Prevent large accelerations when car starts at non zero speed diff --git a/selfdrive/car/ford/interface.py b/selfdrive/car/ford/interface.py index efc7301f36a828..a05144c133d347 100755 --- a/selfdrive/car/ford/interface.py +++ b/selfdrive/car/ford/interface.py @@ -1,15 +1,16 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 from cereal import car from selfdrive.swaglog import cloudlog from selfdrive.config import Conversions as CV from selfdrive.controls.lib.drive_helpers import EventTypes as ET, create_event from selfdrive.controls.lib.vehicle_model import VehicleModel from selfdrive.car.ford.carstate import CarState, get_can_parser -from selfdrive.car.ford.values import MAX_ANGLE -from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness +from selfdrive.car.ford.values import MAX_ANGLE, ECU, ECU_FINGERPRINT, FINGERPRINTS +from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, is_ecu_disconnected, gen_empty_fingerprint +from selfdrive.car.interfaces import CarInterfaceBase -class CarInterface(object): +class CarInterface(CarInterfaceBase): def __init__(self, CP, CarController): self.CP = CP self.VM = VehicleModel(CP) @@ -33,18 +34,14 @@ def compute_gb(accel, speed): return float(accel) / 3.0 @staticmethod - def calc_accel_override(a_ego, a_target, v_ego, v_target): - return 1.0 - - @staticmethod - def get_params(candidate, fingerprint, vin="", is_panda_black=False): + def get_params(candidate, fingerprint=gen_empty_fingerprint(), vin="", has_relay=False): ret = car.CarParams.new_message() ret.carName = "ford" ret.carFingerprint = candidate ret.carVin = vin - ret.isPandaBlack = is_panda_black + ret.isPandaBlack = has_relay ret.safetyModel = car.CarParams.SafetyModel.ford ret.dashcamOnly = True @@ -88,9 +85,9 @@ def get_params(candidate, fingerprint, vin="", is_panda_black=False): ret.brakeMaxBP = [5., 20.] ret.brakeMaxV = [1., 0.8] - ret.enableCamera = not any(x for x in [970, 973, 984] if x in fingerprint) or is_panda_black + ret.enableCamera = is_ecu_disconnected(fingerprint[0], FINGERPRINTS, ECU_FINGERPRINT, candidate, ECU.CAM) or has_relay ret.openpilotLongitudinalControl = False - cloudlog.warn("ECU Camera Simulated: %r", ret.enableCamera) + cloudlog.warning("ECU Camera Simulated: %r", ret.enableCamera) ret.steerLimitAlert = False ret.stoppingControl = False diff --git a/selfdrive/car/ford/radar_interface.py b/selfdrive/car/ford/radar_interface.py index be408da03fe7db..2538a185de05d0 100755 --- a/selfdrive/car/ford/radar_interface.py +++ b/selfdrive/car/ford/radar_interface.py @@ -1,32 +1,32 @@ -#!/usr/bin/env python -import os -import numpy as np -from selfdrive.can.parser import CANParser +#!/usr/bin/env python3 from cereal import car +from selfdrive.can.parser import CANParser +from selfdrive.car.ford.values import DBC +from selfdrive.config import Conversions as CV +from selfdrive.car.interfaces import RadarInterfaceBase -RADAR_MSGS = range(0x500, 0x540) +RADAR_MSGS = list(range(0x500, 0x540)) -def _create_radar_can_parser(): - dbc_f = 'ford_fusion_2018_adas.dbc' +def _create_radar_can_parser(car_fingerprint): + dbc_f = DBC[car_fingerprint]['radar'] msg_n = len(RADAR_MSGS) signals = list(zip(['X_Rel'] * msg_n + ['Angle'] * msg_n + ['V_Rel'] * msg_n, RADAR_MSGS * 3, [0] * msg_n + [0] * msg_n + [0] * msg_n)) checks = list(zip(RADAR_MSGS, [20]*msg_n)) - return CANParser(os.path.splitext(dbc_f)[0], signals, checks, 1) + return CANParser(dbc_f, signals, checks, 1) -class RadarInterface(object): +class RadarInterface(RadarInterfaceBase): def __init__(self, CP): # radar self.pts = {} self.validCnt = {key: 0 for key in RADAR_MSGS} self.track_id = 0 - self.delay = 0.0 # Delay of radar + self.delay = 0 # Delay of radar - # Nidec - self.rcp = _create_radar_can_parser() + self.rcp = _create_radar_can_parser(CP.carFingerprint) self.trigger_msg = 0x53f self.updated_messages = set() @@ -44,7 +44,7 @@ def update(self, can_strings): errors.append("canError") ret.errors = errors - for ii in self.updated_messages: + for ii in sorted(self.updated_messages): cpt = self.rcp.vl[ii] if cpt['X_Rel'] > 0.00001: @@ -63,7 +63,7 @@ def update(self, can_strings): self.pts[ii].trackId = self.track_id self.track_id += 1 self.pts[ii].dRel = cpt['X_Rel'] # from front of car - self.pts[ii].yRel = cpt['X_Rel'] * cpt['Angle'] * np.pi / 180. # in car frame's y axis, left is positive + self.pts[ii].yRel = cpt['X_Rel'] * cpt['Angle'] * CV.DEG_TO_RAD # in car frame's y axis, left is positive self.pts[ii].vRel = cpt['V_Rel'] self.pts[ii].aRel = float('nan') self.pts[ii].yvRel = float('nan') @@ -72,6 +72,6 @@ def update(self, can_strings): if ii in self.pts: del self.pts[ii] - ret.points = self.pts.values() + ret.points = list(self.pts.values()) self.updated_messages.clear() return ret diff --git a/selfdrive/car/ford/values.py b/selfdrive/car/ford/values.py index 6ab0b3750bf52d..a3fb576a3b704c 100644 --- a/selfdrive/car/ford/values.py +++ b/selfdrive/car/ford/values.py @@ -11,6 +11,13 @@ class CAR: }], } +class ECU: + CAM = 0 + +ECU_FINGERPRINT = { + ECU.CAM: [970, 973, 984] +} + DBC = { CAR.FUSION: dbc_dict('ford_fusion_2018_pt', 'ford_fusion_2018_adas'), } diff --git a/selfdrive/car/gm/carcontroller.py b/selfdrive/car/gm/carcontroller.py index da820864f0d93a..c4647c8228d9cd 100644 --- a/selfdrive/car/gm/carcontroller.py +++ b/selfdrive/car/gm/carcontroller.py @@ -68,7 +68,7 @@ def process_hud_alert(hud_alert): steer = 1 return steer -class CarController(object): +class CarController(): def __init__(self, canbus, car_fingerprint): self.pedal_steady = 0. self.start_time = 0. diff --git a/selfdrive/car/gm/carstate.py b/selfdrive/car/gm/carstate.py index 2501598dd6cf7d..7da8d6527257c6 100644 --- a/selfdrive/car/gm/carstate.py +++ b/selfdrive/car/gm/carstate.py @@ -1,5 +1,5 @@ -import numpy as np from cereal import car +from common.numpy_fast import mean from common.kalman.simple_kalman import KF1D from selfdrive.config import Conversions as CV from selfdrive.can.parser import CANParser @@ -50,7 +50,7 @@ def get_powertrain_can_parser(CP, canbus): return CANParser(DBC[CP.carFingerprint]['pt'], signals, [], canbus.powertrain) -class CarState(object): +class CarState(): def __init__(self, CP, canbus): self.CP = CP # initialize can parser @@ -78,7 +78,7 @@ def update(self, pt_cp): self.v_wheel_fr = pt_cp.vl["EBCMWheelSpdFront"]['FRWheelSpd'] * CV.KPH_TO_MS self.v_wheel_rl = pt_cp.vl["EBCMWheelSpdRear"]['RLWheelSpd'] * CV.KPH_TO_MS self.v_wheel_rr = pt_cp.vl["EBCMWheelSpdRear"]['RRWheelSpd'] * CV.KPH_TO_MS - v_wheel = float(np.mean([self.v_wheel_fl, self.v_wheel_fr, self.v_wheel_rl, self.v_wheel_rr])) + v_wheel = mean([self.v_wheel_fl, self.v_wheel_fr, self.v_wheel_rl, self.v_wheel_rr]) if abs(v_wheel - self.v_ego) > 2.0: # Prevent large accelerations when car starts at non zero speed self.v_ego_kf.x = [[v_wheel], [0.0]] diff --git a/selfdrive/car/gm/gmcan.py b/selfdrive/car/gm/gmcan.py index 6919de3bd12f26..ada05658ba7b28 100644 --- a/selfdrive/car/gm/gmcan.py +++ b/selfdrive/car/gm/gmcan.py @@ -24,7 +24,7 @@ def create_steering_control_ct6(packer, canbus, apply_steer, v_ego, idx, enabled dat = packer.make_can_msg("ASCMLKASteeringCmd", 0, values)[2] # the checksum logic is weird values['LKASteeringCmdChecksum'] = (0x2a + - sum([ord(i) for i in dat][:4]) + + sum(dat[:4]) + values['LKASMode']) & 0x3ff # pack again with checksum dat = packer.make_can_msg("ASCMLKASteeringCmd", 0, values)[2] @@ -36,7 +36,7 @@ def create_steering_control_ct6(packer, canbus, apply_steer, v_ego, idx, enabled def create_adas_keepalive(bus): - dat = "\x00\x00\x00\x00\x00\x00\x00" + dat = b"\x00\x00\x00\x00\x00\x00\x00" return [[0x409, 0, dat, bus], [0x40a, 0, dat, bus]] def create_gas_regen_command(packer, bus, throttle, idx, acc_engaged, at_full_stop): @@ -52,9 +52,9 @@ def create_gas_regen_command(packer, bus, throttle, idx, acc_engaged, at_full_st } dat = packer.make_can_msg("ASCMGasRegenCmd", bus, values)[2] - values["GasRegenChecksum"] = (((0xff - ord(dat[1])) & 0xff) << 16) | \ - (((0xff - ord(dat[2])) & 0xff) << 8) | \ - ((0x100 - ord(dat[3]) - idx) & 0xff) + values["GasRegenChecksum"] = (((0xff -dat[1]) & 0xff) << 16) | \ + (((0xff - dat[2]) & 0xff) << 8) | \ + ((0x100 - dat[3] - idx) & 0xff) return packer.make_can_msg("ASCMGasRegenCmd", bus, values) @@ -106,13 +106,13 @@ def create_adas_time_status(bus, tt, idx): chksum = 0x1000 - dat[0] - dat[1] - dat[2] - dat[3] chksum = chksum & 0xfff dat += [0x40 + (chksum >> 8), chksum & 0xff, 0x12] - return [0xa1, 0, "".join(map(chr, dat)), bus] + return [0xa1, 0, bytes(dat), bus] def create_adas_steering_status(bus, idx): dat = [idx << 6, 0xf0, 0x20, 0, 0, 0] chksum = 0x60 + sum(dat) dat += [chksum >> 8, chksum & 0xff] - return [0x306, 0, "".join(map(chr, dat)), bus] + return [0x306, 0, bytes(dat), bus] def create_adas_accelerometer_speed_status(bus, speed_ms, idx): spd = int(speed_ms * 16) & 0xfff @@ -125,24 +125,24 @@ def create_adas_accelerometer_speed_status(bus, speed_ms, idx): dat = [0x08, spd >> 4, ((spd & 0xf) << 4) | (accel >> 8), accel & 0xff, 0] chksum = 0x62 + far_range_mode + (idx << 2) + dat[0] + dat[1] + dat[2] + dat[3] + dat[4] dat += [(idx << 5) + (far_range_mode << 4) + (near_range_mode << 3) + (chksum >> 8), chksum & 0xff] - return [0x308, 0, "".join(map(chr, dat)), bus] + return [0x308, 0, bytes(dat), bus] def create_adas_headlights_status(bus): - return [0x310, 0, "\x42\x04", bus] + return [0x310, 0, b"\x42\x04", bus] def create_lka_icon_command(bus, active, critical, steer): if active and steer == 1: if critical: - dat = "\x50\xc0\x14" + dat = b"\x50\xc0\x14" else: - dat = "\x50\x40\x18" + dat = b"\x50\x40\x18" elif active: if critical: - dat = "\x40\xc0\x14" + dat = b"\x40\xc0\x14" else: - dat = "\x40\x40\x18" + dat = b"\x40\x40\x18" else: - dat = "\x00\x00\x00" + dat = b"\x00\x00\x00" return [0x104c006c, 0, dat, bus] # TODO: WIP diff --git a/selfdrive/car/gm/interface.py b/selfdrive/car/gm/interface.py index b3e82e5e617c15..2390997bcb596c 100755 --- a/selfdrive/car/gm/interface.py +++ b/selfdrive/car/gm/interface.py @@ -1,23 +1,24 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 from cereal import car from selfdrive.config import Conversions as CV from selfdrive.controls.lib.drive_helpers import create_event, EventTypes as ET from selfdrive.controls.lib.vehicle_model import VehicleModel -from selfdrive.car.gm.values import DBC, CAR, STOCK_CONTROL_MSGS, \ - SUPERCRUISE_CARS, AccState +from selfdrive.car.gm.values import DBC, CAR, ECU, ECU_FINGERPRINT, \ + SUPERCRUISE_CARS, AccState, FINGERPRINTS from selfdrive.car.gm.carstate import CarState, CruiseButtons, get_powertrain_can_parser -from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness +from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, is_ecu_disconnected, gen_empty_fingerprint +from selfdrive.car.interfaces import CarInterfaceBase ButtonType = car.CarState.ButtonEvent.Type -class CanBus(object): +class CanBus(CarInterfaceBase): def __init__(self): self.powertrain = 0 self.obstacle = 1 self.chassis = 2 self.sw_gmlan = 3 -class CarInterface(object): +class CarInterface(CarInterfaceBase): def __init__(self, CP, CarController): self.CP = CP @@ -42,24 +43,22 @@ def compute_gb(accel, speed): return float(accel) / 4.0 @staticmethod - def calc_accel_override(a_ego, a_target, v_ego, v_target): - return 1.0 - - @staticmethod - def get_params(candidate, fingerprint, vin="", is_panda_black=False): + def get_params(candidate, fingerprint=gen_empty_fingerprint(), vin="", has_relay=False): ret = car.CarParams.new_message() ret.carName = "gm" ret.carFingerprint = candidate ret.carVin = vin - ret.isPandaBlack = is_panda_black + ret.isPandaBlack = has_relay ret.enableCruise = False # Presence of a camera on the object bus is ok. # Have to go to read_only if ASCM is online (ACC-enabled cars), # or camera is on powertrain bus (LKA cars without ACC). - ret.enableCamera = not any(x for x in STOCK_CONTROL_MSGS[candidate] if x in fingerprint) or is_panda_black + ret.enableCamera = is_ecu_disconnected(fingerprint[0], FINGERPRINTS, ECU_FINGERPRINT, candidate, ECU.CAM) or \ + has_relay or \ + candidate == CAR.CADILLAC_CT6 ret.openpilotLongitudinalControl = ret.enableCamera tire_stiffness_factor = 0.444 # not optimized yet ret.safetyModelPassive = car.CarParams.SafetyModel.gmPassive diff --git a/selfdrive/car/gm/radar_interface.py b/selfdrive/car/gm/radar_interface.py index 4f54c82756c5c9..1fb39c5c439921 100755 --- a/selfdrive/car/gm/radar_interface.py +++ b/selfdrive/car/gm/radar_interface.py @@ -1,11 +1,13 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 +from __future__ import print_function import math import time -import numpy as np from cereal import car from selfdrive.can.parser import CANParser from selfdrive.car.gm.interface import CanBus from selfdrive.car.gm.values import DBC, CAR +from selfdrive.config import Conversions as CV +from selfdrive.car.interfaces import RadarInterfaceBase RADAR_HEADER_MSG = 1120 SLOT_1_MSG = RADAR_HEADER_MSG + 1 @@ -20,7 +22,7 @@ def create_radar_can_parser(canbus, car_fingerprint): dbc_f = DBC[car_fingerprint]['radar'] if car_fingerprint in (CAR.VOLT, CAR.MALIBU, CAR.HOLDEN_ASTRA, CAR.ACADIA, CAR.CADILLAC_ATS): # C1A-ARS3-A by Continental - radar_targets = range(SLOT_1_MSG, SLOT_1_MSG + NUM_SLOTS) + radar_targets = list(range(SLOT_1_MSG, SLOT_1_MSG + NUM_SLOTS)) signals = list(zip(['FLRRNumValidTargets', 'FLRRSnsrBlckd', 'FLRRYawRtPlsblityFlt', 'FLRRHWFltPrsntInt', 'FLRRAntTngFltPrsnt', @@ -40,15 +42,15 @@ def create_radar_can_parser(canbus, car_fingerprint): else: return None -class RadarInterface(object): +class RadarInterface(RadarInterfaceBase): def __init__(self, CP): # radar self.pts = {} - self.delay = 0.0 # Delay of radar + self.delay = 0 # Delay of radar canbus = CanBus() - print "Using %d as obstacle CAN bus ID" % canbus.obstacle + print("Using %d as obstacle CAN bus ID" % canbus.obstacle) self.rcp = create_radar_can_parser(canbus, CP.carFingerprint) self.trigger_msg = LAST_RADAR_MSG @@ -65,7 +67,6 @@ def update(self, can_strings): if self.trigger_msg not in self.updated_messages: return None - ret = car.RadarData.new_message() header = self.rcp.vl[RADAR_HEADER_MSG] fault = header['FLRRSnsrBlckd'] or header['FLRRSnstvFltPrsntInt'] or \ @@ -101,16 +102,15 @@ def update(self, can_strings): distance = cpt['TrkRange'] self.pts[targetId].dRel = distance # from front of car # From driver's pov, left is positive - deg_to_rad = np.pi/180. - self.pts[targetId].yRel = math.sin(deg_to_rad * cpt['TrkAzimuth']) * distance + self.pts[targetId].yRel = math.sin(cpt['TrkAzimuth'] * CV.DEG_TO_RAD) * distance self.pts[targetId].vRel = cpt['TrkRangeRate'] self.pts[targetId].aRel = float('nan') self.pts[targetId].yvRel = float('nan') - for oldTarget in self.pts.keys(): + for oldTarget in list(self.pts.keys()): if not oldTarget in currentTargets: del self.pts[oldTarget] - ret.points = self.pts.values() + ret.points = list(self.pts.values()) self.updated_messages.clear() return ret diff --git a/selfdrive/car/gm/values.py b/selfdrive/car/gm/values.py index 1aa5a64b13f9d0..126ae9e40b0cac 100644 --- a/selfdrive/car/gm/values.py +++ b/selfdrive/car/gm/values.py @@ -48,12 +48,12 @@ def parse_gear_shifter(can_gear): FINGERPRINTS = { # Astra BK MY17, ASCM unplugged CAR.HOLDEN_ASTRA: [{ - 190: 8, 193: 8, 197: 8, 199: 4, 201: 8, 209: 7, 211: 8, 241: 6, 249: 8, 288: 5, 298: 8, 304: 1, 309: 8, 311: 8, 313: 8, 320: 3, 328: 1, 352: 5, 381: 6, 386: 8, 388: 8, 393: 8, 398: 8, 401: 8, 413: 8, 417: 8, 419: 8, 422: 1, 426: 7, 431: 8, 442: 8, 451: 8, 452: 8, 453: 8, 455: 7, 456: 8, 458: 5, 479: 8, 481: 7, 485: 8, 489: 8, 497: 8, 499: 3, 500: 8, 501: 8, 508: 8, 528: 5, 532: 6, 554: 3, 560: 8, 562: 8, 563: 5, 564: 5, 565: 5, 567: 5, 647: 5, 707: 8, 723: 8, 753: 5, 761: 7, 806: 1, 810: 8, 840: 5, 842: 5, 844: 8, 866: 4, 961: 8, 969: 8, 977: 8, 979: 8, 985: 5, 1001: 8, 1009: 8, 1011: 6, 1017: 8, 1019: 3, 1020: 8, 1105: 6, 1217: 8, 1221: 5, 1225: 8, 1233: 8, 1249: 8, 1257: 6, 1259: 8, 1261: 7, 1263: 4, 1265: 8, 1267: 8, 1280: 4, 1300: 8, 1328: 4, 1417: 8, 1906: 7, 1907: 7, 1908: 7, 1912: 7, 1919: 7, + 190: 8, 193: 8, 197: 8, 199: 4, 201: 8, 209: 7, 211: 8, 241: 6, 249: 8, 288: 5, 298: 8, 304: 1, 309: 8, 311: 8, 313: 8, 320: 3, 328: 1, 352: 5, 381: 6, 384: 4, 386: 8, 388: 8, 393: 8, 398: 8, 401: 8, 413: 8, 417: 8, 419: 8, 422: 1, 426: 7, 431: 8, 442: 8, 451: 8, 452: 8, 453: 8, 455: 7, 456: 8, 458: 5, 479: 8, 481: 7, 485: 8, 489: 8, 497: 8, 499: 3, 500: 8, 501: 8, 508: 8, 528: 5, 532: 6, 554: 3, 560: 8, 562: 8, 563: 5, 564: 5, 565: 5, 567: 5, 647: 5, 707: 8, 715: 8, 723: 8, 753: 5, 761: 7, 806: 1, 810: 8, 840: 5, 842: 5, 844: 8, 866: 4, 961: 8, 969: 8, 977: 8, 979: 8, 985: 5, 1001: 8, 1009: 8, 1011: 6, 1017: 8, 1019: 3, 1020: 8, 1105: 6, 1217: 8, 1221: 5, 1225: 8, 1233: 8, 1249: 8, 1257: 6, 1259: 8, 1261: 7, 1263: 4, 1265: 8, 1267: 8, 1280: 4, 1300: 8, 1328: 4, 1417: 8, 1906: 7, 1907: 7, 1908: 7, 1912: 7, 1919: 7, }], CAR.VOLT: [ # Volt Premier w/ ACC 2017 { - 170: 8, 171: 8, 189: 7, 190: 6, 193: 8, 197: 8, 199: 4, 201: 8, 209: 7, 211: 2, 241: 6, 288: 5, 289: 8, 298: 8, 304: 1, 308: 4, 309: 8, 311: 8, 313: 8, 320: 3, 328: 1, 352: 5, 381: 6, 386: 8, 388: 8, 389: 2, 390: 7, 417: 7, 419: 1, 426: 7, 451: 8, 452: 8, 453: 6, 454: 8, 456: 8, 479: 3, 481: 7, 485: 8, 489: 8, 493: 8, 495: 4, 497: 8, 499: 3, 500: 6, 501: 8, 508: 8, 528: 4, 532: 6, 546: 7, 550: 8, 554: 3, 558: 8, 560: 8, 562: 8, 563: 5, 564: 5, 565: 5, 566: 5, 567: 3, 568: 1, 573: 1, 577: 8, 647: 3, 707: 8, 711: 6, 761: 7, 810: 8, 840: 5, 842: 5, 844: 8, 866: 4, 961: 8, 969: 8, 977: 8, 979: 7, 988: 6, 989: 8, 995: 7, 1001: 8, 1005: 6, 1009: 8, 1017: 8, 1019: 2, 1020: 8, 1105: 6, 1187: 4, 1217: 8, 1221: 5, 1223: 3, 1225: 7, 1227: 4, 1233: 8, 1249: 8, 1257: 6, 1265: 8, 1267: 1, 1273: 3, 1275: 3, 1280: 4, 1300: 8, 1322: 6, 1323: 4, 1328: 4, 1417: 8, 1601: 8, 1905: 7, 1906: 7, 1907: 7, 1910: 7, 1912: 7, 1922: 7, 1927: 7, 1928: 7, 2016: 8, 2020: 8, 2024: 8, 2028: 8 + 170: 8, 171: 8, 189: 7, 190: 6, 193: 8, 197: 8, 199: 4, 201: 8, 209: 7, 211: 2, 241: 6, 288: 5, 289: 8, 298: 8, 304: 1, 308: 4, 309: 8, 311: 8, 313: 8, 320: 3, 328: 1, 352: 5, 381: 6, 384: 4, 386: 8, 388: 8, 389: 2, 390: 7, 417: 7, 419: 1, 426: 7, 451: 8, 452: 8, 453: 6, 454: 8, 456: 8, 479: 3, 481: 7, 485: 8, 489: 8, 493: 8, 495: 4, 497: 8, 499: 3, 500: 6, 501: 8, 508: 8, 528: 4, 532: 6, 546: 7, 550: 8, 554: 3, 558: 8, 560: 8, 562: 8, 563: 5, 564: 5, 565: 5, 566: 5, 567: 3, 568: 1, 573: 1, 577: 8, 647: 3, 707: 8, 711: 6, 715: 8, 761: 7, 810: 8, 840: 5, 842: 5, 844: 8, 866: 4, 961: 8, 969: 8, 977: 8, 979: 7, 988: 6, 989: 8, 995: 7, 1001: 8, 1005: 6, 1009: 8, 1017: 8, 1019: 2, 1020: 8, 1105: 6, 1187: 4, 1217: 8, 1221: 5, 1223: 3, 1225: 7, 1227: 4, 1233: 8, 1249: 8, 1257: 6, 1265: 8, 1267: 1, 1273: 3, 1275: 3, 1280: 4, 1300: 8, 1322: 6, 1323: 4, 1328: 4, 1417: 8, 1601: 8, 1905: 7, 1906: 7, 1907: 7, 1910: 7, 1912: 7, 1922: 7, 1927: 7, 1928: 7, 2016: 8, 2020: 8, 2024: 8, 2028: 8 }, # Volt Premier w/ ACC 2018 { @@ -86,14 +86,11 @@ def parse_gear_shifter(can_gear): STEER_THRESHOLD = 1.0 -STOCK_CONTROL_MSGS = { - CAR.HOLDEN_ASTRA: [384, 715], - CAR.VOLT: [384, 715], # 384 = "ASCMLKASteeringCmd", 715 = "ASCMGasRegenCmd" - CAR.MALIBU: [384, 715], # 384 = "ASCMLKASteeringCmd", 715 = "ASCMGasRegenCmd" - CAR.ACADIA: [384, 715], # 384 = "ASCMLKASteeringCmd", 715 = "ASCMGasRegenCmd" - CAR.CADILLAC_ATS: [384, 715], # 384 = "ASCMLKASteeringCmd", 715 = "ASCMGasRegenCmd" - CAR.BUICK_REGAL: [384, 715], # 384 = "ASCMLKASteeringCmd", 715 = "ASCMGasRegenCmd" - CAR.CADILLAC_CT6: [], # CT6 does not require ASCMs to be disconnected +class ECU: + CAM = 0 + +ECU_FINGERPRINT = { + ECU.CAM: [384, 715] # 384 = "ASCMLKASteeringCmd", 715 = "ASCMGasRegenCmd" } DBC = { diff --git a/selfdrive/car/honda/carcontroller.py b/selfdrive/car/honda/carcontroller.py index 8b96e511c28175..1058e2f21a972c 100644 --- a/selfdrive/car/honda/carcontroller.py +++ b/selfdrive/car/honda/carcontroller.py @@ -73,7 +73,7 @@ def process_hud_alert(hud_alert): "lanes", "fcw", "acc_alert", "steer_required"]) -class CarController(object): +class CarController(): def __init__(self, dbc_name): self.braking = False self.brake_steady = 0. diff --git a/selfdrive/car/honda/carstate.py b/selfdrive/car/honda/carstate.py index 87ecdb34ef0b47..bb974b3d14d4d6 100644 --- a/selfdrive/car/honda/carstate.py +++ b/selfdrive/car/honda/carstate.py @@ -1,4 +1,5 @@ from cereal import car +from collections import defaultdict from common.numpy_fast import interp from common.kalman.simple_kalman import KF1D from selfdrive.can.can_define import CANDefine @@ -178,11 +179,12 @@ def get_cam_can_parser(CP): bus_cam = 1 if CP.carFingerprint in HONDA_BOSCH and not CP.isPandaBlack else 2 return CANParser(DBC[CP.carFingerprint]['pt'], signals, checks, bus_cam) -class CarState(object): +class CarState(): def __init__(self, CP): self.CP = CP self.can_define = CANDefine(DBC[CP.carFingerprint]['pt']) self.shifter_values = self.can_define.dv["GEARBOX"]["GEAR_SHIFTER"] + self.steer_status_values = defaultdict(lambda: "UNKNOWN", self.can_define.dv["STEER_STATUS"]["STEER_STATUS"]) self.user_gas, self.user_gas_pressed = 0., 0 self.brake_switch_prev = 0 @@ -224,7 +226,6 @@ def update(self, cp, cp_cam): self.prev_right_blinker_on = self.right_blinker_on # ******************* parse out can ******************* - if self.CP.carFingerprint in (CAR.ACCORD, CAR.ACCORD_15, CAR.ACCORDH, CAR.CIVIC_BOSCH, CAR.CRV_HYBRID): # TODO: find wheels moving bit in dbc self.standstill = cp.vl["ENGINE_DATA"]['XMISSION_SPEED'] < 0.1 self.door_all_closed = not cp.vl["SCM_FEEDBACK"]['DRIVERS_DOOR_OPEN'] @@ -237,11 +238,13 @@ def update(self, cp, cp_cam): cp.vl["DOORS_STATUS"]['DOOR_OPEN_RL'], cp.vl["DOORS_STATUS"]['DOOR_OPEN_RR']]) self.seatbelt = not cp.vl["SEATBELT_STATUS"]['SEATBELT_DRIVER_LAMP'] and cp.vl["SEATBELT_STATUS"]['SEATBELT_DRIVER_LATCHED'] - # 2 = temporary; 3 = TBD; 4 = significant steering wheel torque; 5 = (permanent); 6 = temporary; 7 = (permanent) - # TODO: Use values from DBC to parse this field - self.steer_error = cp.vl["STEER_STATUS"]['STEER_STATUS'] not in [0, 2, 3, 4, 6] - self.steer_not_allowed = cp.vl["STEER_STATUS"]['STEER_STATUS'] not in [0, 4] # 4 can be caused by bump OR steering nudge from driver - self.steer_warning = cp.vl["STEER_STATUS"]['STEER_STATUS'] not in [0, 3, 4] # 3 is low speed lockout, not worth a warning + steer_status = self.steer_status_values[cp.vl["STEER_STATUS"]['STEER_STATUS']] + self.steer_error = steer_status not in ['NORMAL', 'NO_TORQUE_ALERT_1', 'NO_TORQUE_ALERT_2', 'LOW_SPEED_LOCKOUT', 'TMP_FAULT'] + # NO_TORQUE_ALERT_2 can be caused by bump OR steering nudge from driver + self.steer_not_allowed = steer_status not in ['NORMAL', 'NO_TORQUE_ALERT_2'] + # LOW_SPEED_LOCKOUT is not worth a warning + self.steer_warning = steer_status not in ['NORMAL', 'LOW_SPEED_LOCKOUT', 'NO_TORQUE_ALERT_2'] + if self.CP.radarOffCan: self.brake_error = 0 else: @@ -357,7 +360,7 @@ def update(self, cp, cp_cam): import zmq context = zmq.Context() - class CarParams(object): + class CarParams(): def __init__(self): self.carFingerprint = "HONDA CIVIC 2016 TOURING" self.enableGasInterceptor = 0 diff --git a/selfdrive/car/honda/hondacan.py b/selfdrive/car/honda/hondacan.py index b66b6c8c53b42b..c6b9a12e8362c7 100644 --- a/selfdrive/car/honda/hondacan.py +++ b/selfdrive/car/honda/hondacan.py @@ -6,7 +6,6 @@ def can_cksum(mm): s = 0 for c in mm: - c = ord(c) s += (c>>4) s += c & 0xF s = 8-s @@ -15,19 +14,19 @@ def can_cksum(mm): def fix(msg, addr): - msg2 = msg[0:-1] + chr(ord(msg[-1]) | can_cksum(struct.pack("I", addr)+msg)) + msg2 = msg[0:-1] + (msg[-1] | can_cksum(struct.pack("I", addr)+msg)).to_bytes(1, 'little') return msg2 -def get_pt_bus(car_fingerprint, is_panda_black): - return 1 if car_fingerprint in HONDA_BOSCH and is_panda_black else 0 +def get_pt_bus(car_fingerprint, has_relay): + return 1 if car_fingerprint in HONDA_BOSCH and has_relay else 0 -def get_lkas_cmd_bus(car_fingerprint, is_panda_black): - return 2 if car_fingerprint in HONDA_BOSCH and not is_panda_black else 0 +def get_lkas_cmd_bus(car_fingerprint, has_relay): + return 2 if car_fingerprint in HONDA_BOSCH and not has_relay else 0 -def create_brake_command(packer, apply_brake, pump_on, pcm_override, pcm_cancel_cmd, fcw, idx, car_fingerprint, is_panda_black): +def create_brake_command(packer, apply_brake, pump_on, pcm_override, pcm_cancel_cmd, fcw, idx, car_fingerprint, has_relay): # TODO: do we loose pressure if we keep pump off for long? brakelights = apply_brake > 0 brake_rq = apply_brake > 0 @@ -49,23 +48,23 @@ def create_brake_command(packer, apply_brake, pump_on, pcm_override, pcm_cancel_ "AEB_REQ_2": 0, "AEB_STATUS": 0, } - bus = get_pt_bus(car_fingerprint, is_panda_black) + bus = get_pt_bus(car_fingerprint, has_relay) return packer.make_can_msg("BRAKE_COMMAND", bus, values, idx) -def create_steering_control(packer, apply_steer, lkas_active, car_fingerprint, idx, is_panda_black): +def create_steering_control(packer, apply_steer, lkas_active, car_fingerprint, idx, has_relay): values = { "STEER_TORQUE": apply_steer if lkas_active else 0, "STEER_TORQUE_REQUEST": lkas_active, } - bus = get_lkas_cmd_bus(car_fingerprint, is_panda_black) + bus = get_lkas_cmd_bus(car_fingerprint, has_relay) return packer.make_can_msg("STEERING_CONTROL", bus, values, idx) -def create_ui_commands(packer, pcm_speed, hud, car_fingerprint, is_metric, idx, is_panda_black): +def create_ui_commands(packer, pcm_speed, hud, car_fingerprint, is_metric, idx, has_relay): commands = [] - bus_pt = get_pt_bus(car_fingerprint, is_panda_black) - bus_lkas = get_lkas_cmd_bus(car_fingerprint, is_panda_black) + bus_pt = get_pt_bus(car_fingerprint, has_relay) + bus_lkas = get_lkas_cmd_bus(car_fingerprint, has_relay) if car_fingerprint not in HONDA_BOSCH: acc_hud_values = { @@ -101,10 +100,10 @@ def create_ui_commands(packer, pcm_speed, hud, car_fingerprint, is_metric, idx, return commands -def spam_buttons_command(packer, button_val, idx, car_fingerprint, is_panda_black): +def spam_buttons_command(packer, button_val, idx, car_fingerprint, has_relay): values = { 'CRUISE_BUTTONS': button_val, 'CRUISE_SETTING': 0, } - bus = get_pt_bus(car_fingerprint, is_panda_black) + bus = get_pt_bus(car_fingerprint, has_relay) return packer.make_can_msg("SCM_BUTTONS", bus, values, idx) diff --git a/selfdrive/car/honda/interface.py b/selfdrive/car/honda/interface.py index 13f399310a07d2..3c2ecfa8ddd4f8 100755 --- a/selfdrive/car/honda/interface.py +++ b/selfdrive/car/honda/interface.py @@ -1,5 +1,4 @@ -#!/usr/bin/env python -import os +#!/usr/bin/env python3 import numpy as np from cereal import car from common.numpy_fast import clip, interp @@ -9,11 +8,12 @@ from selfdrive.controls.lib.drive_helpers import create_event, EventTypes as ET, get_events from selfdrive.controls.lib.vehicle_model import VehicleModel from selfdrive.car.honda.carstate import CarState, get_can_parser, get_cam_can_parser -from selfdrive.car.honda.values import CruiseButtons, CAR, HONDA_BOSCH, VISUAL_HUD, CAMERA_MSGS -from selfdrive.car import STD_CARGO_KG, CivicParams, scale_rot_inertia, scale_tire_stiffness -from selfdrive.controls.lib.planner import _A_CRUISE_MAX_V_FOLLOWING +from selfdrive.car.honda.values import CruiseButtons, CAR, HONDA_BOSCH, VISUAL_HUD, ECU, ECU_FINGERPRINT, FINGERPRINTS +from selfdrive.car import STD_CARGO_KG, CivicParams, scale_rot_inertia, scale_tire_stiffness, is_ecu_disconnected, gen_empty_fingerprint +from selfdrive.controls.lib.planner import _A_CRUISE_MAX_V +from selfdrive.car.interfaces import CarInterfaceBase -A_ACC_MAX = max(_A_CRUISE_MAX_V_FOLLOWING) +A_ACC_MAX = max(_A_CRUISE_MAX_V) ButtonType = car.CarState.ButtonEvent.Type GearShifter = car.CarState.GearShifter @@ -72,7 +72,7 @@ def _compute_gb_acura(accel, speed): return _compute_gb_acura -class CarInterface(object): +class CarInterface(CarInterfaceBase): def __init__(self, CP, CarController): self.CP = CP @@ -131,27 +131,28 @@ def calc_accel_override(a_ego, a_target, v_ego, v_target): return float(max(max_accel, a_target / A_ACC_MAX)) * min(speedLimiter, accelLimiter) @staticmethod - def get_params(candidate, fingerprint, vin="", is_panda_black=False): + def get_params(candidate, fingerprint=gen_empty_fingerprint(), vin="", has_relay=False): ret = car.CarParams.new_message() ret.carName = "honda" ret.carFingerprint = candidate ret.carVin = vin - ret.isPandaBlack = is_panda_black + ret.isPandaBlack = has_relay if candidate in HONDA_BOSCH: ret.safetyModel = car.CarParams.SafetyModel.hondaBosch - ret.enableCamera = True + rdr_bus = 0 if has_relay else 2 + ret.enableCamera = is_ecu_disconnected(fingerprint[rdr_bus], FINGERPRINTS, ECU_FINGERPRINT, candidate, ECU.CAM) or has_relay ret.radarOffCan = True ret.openpilotLongitudinalControl = False else: ret.safetyModel = car.CarParams.SafetyModel.honda - ret.enableCamera = not any(x for x in CAMERA_MSGS if x in fingerprint) or is_panda_black - ret.enableGasInterceptor = 0x201 in fingerprint + ret.enableCamera = is_ecu_disconnected(fingerprint[0], FINGERPRINTS, ECU_FINGERPRINT, candidate, ECU.CAM) or has_relay + ret.enableGasInterceptor = 0x201 in fingerprint[0] ret.openpilotLongitudinalControl = ret.enableCamera - cloudlog.warn("ECU Camera Simulated: %r", ret.enableCamera) - cloudlog.warn("ECU Gas Interceptor: %r", ret.enableGasInterceptor) + cloudlog.warning("ECU Camera Simulated: %r", ret.enableCamera) + cloudlog.warning("ECU Gas Interceptor: %r", ret.enableGasInterceptor) ret.enableCruise = not ret.enableGasInterceptor @@ -172,12 +173,8 @@ def get_params(candidate, fingerprint, vin="", is_panda_black=False): ret.centerToFront = CivicParams.CENTER_TO_FRONT ret.steerRatio = 15.38 # 10.93 is end-to-end spec tire_stiffness_factor = 1. - # Civic at comma has modified steering FW, so different tuning for the Neo in that car - is_fw_modified = os.getenv("DONGLE_ID") in ['5b7c365c50084530'] - if is_fw_modified: - ret.lateralTuning.pid.kf = 0.00004 - ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.4], [0.12]] if is_fw_modified else [[0.8], [0.24]] + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.8], [0.24]] ret.longitudinalTuning.kpBP = [0., 5., 35.] ret.longitudinalTuning.kpV = [3.6, 2.4, 1.5] ret.longitudinalTuning.kiBP = [0., 35.] diff --git a/selfdrive/car/honda/radar_interface.py b/selfdrive/car/honda/radar_interface.py index 6943d3563469cf..2415e95a35f734 100755 --- a/selfdrive/car/honda/radar_interface.py +++ b/selfdrive/car/honda/radar_interface.py @@ -1,23 +1,25 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import os import time from cereal import car from selfdrive.can.parser import CANParser +from common.realtime import DT_RDR +from selfdrive.car.interfaces import RadarInterfaceBase def _create_nidec_can_parser(): dbc_f = 'acura_ilx_2016_nidec.dbc' - radar_messages = [0x400] + range(0x430, 0x43A) + range(0x440, 0x446) + radar_messages = [0x400] + list(range(0x430, 0x43A)) + list(range(0x440, 0x446)) signals = list(zip(['RADAR_STATE'] + ['LONG_DIST'] * 16 + ['NEW_TRACK'] * 16 + ['LAT_DIST'] * 16 + ['REL_SPEED'] * 16, [0x400] + radar_messages[1:] * 4, [0] + [255] * 16 + [1] * 16 + [0] * 16 + [0] * 16)) checks = list(zip([0x445], [20])) + fn = os.path.splitext(dbc_f)[0].encode('utf8') + return CANParser(fn, signals, checks, 1) - return CANParser(os.path.splitext(dbc_f)[0], signals, checks, 1) - -class RadarInterface(object): +class RadarInterface(RadarInterfaceBase): def __init__(self, CP): # radar self.pts = {} @@ -26,7 +28,7 @@ def __init__(self, CP): self.radar_wrong_config = False self.radar_off_can = CP.radarOffCan - self.delay = 0.1 # Delay of radar + self.delay = int(0.1 / DT_RDR) # 0.1s delay of radar # Nidec self.rcp = _create_nidec_can_parser() @@ -55,7 +57,7 @@ def update(self, can_strings): def _update(self, updated_messages): ret = car.RadarData.new_message() - for ii in updated_messages: + for ii in sorted(updated_messages): cpt = self.rcp.vl[ii] if ii == 0x400: # check for radar faults @@ -85,6 +87,6 @@ def _update(self, updated_messages): errors.append("wrongConfig") ret.errors = errors - ret.points = self.pts.values() + ret.points = list(self.pts.values()) return ret diff --git a/selfdrive/car/honda/values.py b/selfdrive/car/honda/values.py index 5e704515fa6327..ab940681300c8d 100644 --- a/selfdrive/car/honda/values.py +++ b/selfdrive/car/honda/values.py @@ -30,6 +30,9 @@ class AH: VisualAlert.seatbeltUnbuckled: AH.SEATBELT, VisualAlert.speedTooHigh: AH.SPEED_TOO_HIGH} +class ECU: + CAM = 0 + class CAR: ACCORD = "HONDA ACCORD 2018 SPORT 2T" ACCORD_15 = "HONDA ACCORD 2018 LX 1.5T" @@ -72,8 +75,8 @@ class CAR: 57: 3, 148: 8, 228: 5, 304: 8, 330: 8, 344: 8, 380: 8, 399: 7, 401: 8, 420: 8, 427: 3, 428: 8, 432: 7, 450: 8, 464: 8, 470: 2, 476: 7, 487: 4, 490: 8, 493: 5, 506: 8, 512: 6, 513: 6, 545: 6, 597: 8, 662: 4, 773: 7, 777: 8, 780: 8, 795: 8, 800: 8, 804: 8, 806: 8, 808: 8, 829: 5, 862: 8, 884: 8, 891: 8, 892: 8, 927: 8, 929: 8, 985: 3, 1024: 5, 1027: 5, 1029: 8, 1036: 8, 1039: 8, 1108: 8, 1302: 8, 1322: 5, 1361: 5, 1365: 5, 1424: 5, 1633: 8, }], CAR.CIVIC_BOSCH: [{ - # 2017 Civic Hatchback EX and 2019 Civic Sedan Touring Canadian - 57: 3, 148: 8, 228: 5, 304: 8, 330: 8, 344: 8, 380: 8, 399: 7, 401: 8, 420: 8, 427: 3, 428: 8, 432: 7, 441: 5, 450: 8, 464: 8, 470: 2, 476: 7, 477: 8, 479: 8, 490: 8, 493: 5, 495: 8, 506: 8, 545: 6, 597: 8, 662: 4, 773: 7, 777: 8, 780: 8, 795: 8, 800: 8, 804: 8, 806: 8, 808: 8, 829: 5, 862: 8, 884: 8, 891: 8, 892: 8, 927: 8, 929: 8, 985: 3, 1024: 5, 1027: 5, 1029: 8, 1036: 8, 1039: 8, 1108: 8, 1302: 8, 1322: 5, 1361: 5, 1365: 5, 1424: 5, 1600: 5, 1601: 8, 1633: 8, + # 2017 Civic Hatchback EX, 2019 Civic Sedan Touring Canadian, and 2018 Civic Hatchback Executive Premium 1.0L CVT European + 57: 3, 148: 8, 228: 5, 304: 8, 330: 8, 344: 8, 380: 8, 399: 7, 401: 8, 420: 8, 427: 3, 428: 8, 432: 7, 441: 5, 450: 8, 460: 3, 464: 8, 470: 2, 476: 7, 477: 8, 479: 8, 490: 8, 493: 5, 495: 8, 506: 8, 545: 6, 597: 8, 662: 4, 773: 7, 777: 8, 780: 8, 795: 8, 800: 8, 804: 8, 806: 8, 808: 8, 829: 5, 862: 8, 884: 8, 891: 8, 892: 8, 927: 8, 929: 8, 985: 3, 1024: 5, 1027: 5, 1029: 8, 1036: 8, 1039: 8, 1108: 8, 1302: 8, 1322: 5, 1361: 5, 1365: 5, 1424: 5, 1600: 5, 1601: 8, 1625: 5, 1629: 5, 1633: 8, }], CAR.CRV: [{ 57: 3, 145: 8, 316: 8, 340: 8, 342: 6, 344: 8, 380: 8, 398: 3, 399: 6, 401: 8, 404: 4, 420: 8, 422: 8, 426: 8, 432: 7, 464: 8, 474: 5, 476: 4, 487: 4, 490: 8, 493: 3, 506: 8, 507: 1, 512: 6, 513: 6, 542: 7, 545: 4, 597: 8, 660: 8, 661: 4, 773: 7, 777: 8, 780: 8, 800: 8, 804: 8, 808: 8, 829: 5, 882: 2, 884: 7, 888: 8, 891: 8, 892: 8, 923: 2, 929: 8, 983: 8, 985: 3, 1024: 5, 1027: 5, 1029: 8, 1033: 5, 1036: 8, 1039: 8, 1057: 5, 1064: 7, 1108: 8, 1125: 8, 1296: 8, 1365: 5, 1424: 5, 1600: 5, 1601: 8, @@ -116,7 +119,7 @@ class CAR: }, # 2019 Ridgeline { - 57: 3, 145: 8, 229: 4, 308: 5, 316: 8, 339: 7, 342: 6, 344: 8, 380: 8, 392: 6, 399: 7, 419: 8, 420: 8, 422:8, 425: 8, 426: 8, 427: 3, 432: 7, 464: 8, 476: 4, 490: 8, 545: 5, 546: 3, 597: 8, 660: 8, 773: 7, 777: 8, 795: 8, 800: 8, 804: 8, 808: 8, 819: 7, 821: 5, 871: 8, 882: 2, 884: 7, 892: 8, 923: 2, 929: 8, 963: 8, 965: 8, 966: 8, 967: 8, 983: 8, 985: 3, 1027: 5, 1029: 8, 1036: 8, 1039: 8, 1064: 7, 1088: 8, 1089: 8, 1092: 1, 1108: 8, 1125: 8, 1296: 8, 1365: 5, 424: 5, 1613: 5, 1616: 5, 1618: 5, 1623: 5, 1668: 5 + 57: 3, 145: 8, 228: 5, 229: 4, 308: 5, 316: 8, 339: 7, 342: 6, 344: 8, 380: 8, 392: 6, 399: 7, 419: 8, 420: 8, 422:8, 425: 8, 426: 8, 427: 3, 432: 7, 464: 8, 476: 4, 490: 8, 545: 5, 546: 3, 597: 8, 660: 8, 773: 7, 777: 8, 795: 8, 800: 8, 804: 8, 808: 8, 819: 7, 821: 5, 871: 8, 882: 2, 884: 7, 892: 8, 923: 2, 929: 8, 963: 8, 965: 8, 966: 8, 967: 8, 983: 8, 985: 3, 1027: 5, 1029: 8, 1036: 8, 1039: 8, 1064: 7, 1088: 8, 1089: 8, 1092: 1, 1108: 8, 1125: 8, 1296: 8, 1365: 5, 424: 5, 1613: 5, 1616: 5, 1618: 5, 1623: 5, 1668: 5 }] } @@ -185,7 +188,8 @@ class CAR: # msgs sent for steering controller by camera module on can 0. # those messages are mutually exclusive on CRV and non-CRV cars -CAMERA_MSGS = [0xe4, 0x194] +ECU_FINGERPRINT = { + ECU.CAM: [0xE4, 0x194], # steer torque cmd +} -# TODO: get these from dbc file HONDA_BOSCH = [CAR.ACCORD, CAR.ACCORD_15, CAR.ACCORDH, CAR.CIVIC_BOSCH, CAR.CRV_5G, CAR.CRV_HYBRID] diff --git a/selfdrive/car/hyundai/carcontroller.py b/selfdrive/car/hyundai/carcontroller.py index a1a688ff5ef7c8..729c853628a792 100644 --- a/selfdrive/car/hyundai/carcontroller.py +++ b/selfdrive/car/hyundai/carcontroller.py @@ -16,7 +16,7 @@ class SteerLimitParams: STEER_DRIVER_MULTIPLIER = 2 STEER_DRIVER_FACTOR = 1 -class CarController(object): +class CarController(): def __init__(self, dbc_name, car_fingerprint): self.apply_steer_last = 0 self.car_fingerprint = car_fingerprint diff --git a/selfdrive/car/hyundai/carstate.py b/selfdrive/car/hyundai/carstate.py index f993bd2a0f6959..a7e3448a0e2759 100644 --- a/selfdrive/car/hyundai/carstate.py +++ b/selfdrive/car/hyundai/carstate.py @@ -1,8 +1,10 @@ +from cereal import car from selfdrive.car.hyundai.values import DBC, STEER_THRESHOLD from selfdrive.can.parser import CANParser from selfdrive.config import Conversions as CV from common.kalman.simple_kalman import KF1D +GearShifter = car.CarState.GearShifter def get_can_parser(CP): @@ -31,7 +33,7 @@ def get_can_parser(CP): ("CYL_PRES", "ESP12", 0), ("CF_Clu_CruiseSwState", "CLU11", 0), - ("CF_Clu_CruiseSwMain" , "CLU11", 0), + ("CF_Clu_CruiseSwMain", "CLU11", 0), ("CF_Clu_SldMainSW", "CLU11", 0), ("CF_Clu_ParityBit1", "CLU11", 0), ("CF_Clu_VanzDecimal" , "CLU11", 0), @@ -48,7 +50,7 @@ def get_can_parser(CP): ("CF_Clu_InhibitN", "CLU15", 0), ("CF_Clu_InhibitR", "CLU15", 0), - ("CF_Lvr_Gear","LVR12",0), + ("CF_Lvr_Gear", "LVR12",0), ("CUR_GR", "TCU12",0), ("ACCEnable", "TCS13", 0), @@ -122,7 +124,7 @@ def get_camera_parser(CP): return CANParser(DBC[CP.carFingerprint]['pt'], signals, checks, 2) -class CarState(object): +class CarState(): def __init__(self, CP): self.CP = CP @@ -211,38 +213,38 @@ def update(self, cp, cp_cam): # Gear Selecton - This is not compatible with all Kia/Hyundai's, But is the best way for those it is compatible with gear = cp.vl["LVR12"]["CF_Lvr_Gear"] if gear == 5: - self.gear_shifter = "drive" + self.gear_shifter = GearShifter.drive elif gear == 6: - self.gear_shifter = "neutral" + self.gear_shifter = GearShifter.neutral elif gear == 0: - self.gear_shifter = "park" + self.gear_shifter = GearShifter.park elif gear == 7: - self.gear_shifter = "reverse" + self.gear_shifter = GearShifter.reverse else: - self.gear_shifter = "unknown" + self.gear_shifter = GearShifter.unknown # Gear Selection via Cluster - For those Kia/Hyundai which are not fully discovered, we can use the Cluster Indicator for Gear Selection, as this seems to be standard over all cars, but is not the preferred method. if cp.vl["CLU15"]["CF_Clu_InhibitD"] == 1: - self.gear_shifter_cluster = "drive" + self.gear_shifter_cluster = GearShifter.drive elif cp.vl["CLU15"]["CF_Clu_InhibitN"] == 1: - self.gear_shifter_cluster = "neutral" + self.gear_shifter_cluster = GearShifter.neutral elif cp.vl["CLU15"]["CF_Clu_InhibitP"] == 1: - self.gear_shifter_cluster = "park" + self.gear_shifter_cluster = GearShifter.park elif cp.vl["CLU15"]["CF_Clu_InhibitR"] == 1: - self.gear_shifter_cluster = "reverse" + self.gear_shifter_cluster = GearShifter.reverse else: - self.gear_shifter_cluster = "unknown" + self.gear_shifter_cluster = GearShifter.unknown # Gear Selecton via TCU12 gear2 = cp.vl["TCU12"]["CUR_GR"] if gear2 == 0: - self.gear_tcu = "park" + self.gear_tcu = GearShifter.park elif gear2 == 14: - self.gear_tcu = "reverse" + self.gear_tcu = GearShifter.reverse elif gear2 > 0 and gear2 < 9: # unaware of anything over 8 currently - self.gear_tcu = "drive" + self.gear_tcu = GearShifter.drive else: - self.gear_tcu = "unknown" + self.gear_tcu = GearShifter.unknown # save the entire LKAS11 and CLU11 self.lkas11 = cp_cam.vl["LKAS11"] diff --git a/selfdrive/car/hyundai/hyundaican.py b/selfdrive/car/hyundai/hyundaican.py index d9e7cf3a92a64d..8783932055f2bf 100644 --- a/selfdrive/car/hyundai/hyundaican.py +++ b/selfdrive/car/hyundai/hyundaican.py @@ -34,15 +34,13 @@ def create_lkas11(packer, car_fingerprint, apply_steer, steer_req, cnt, enabled, if car_fingerprint in CHECKSUM["crc8"]: # CRC Checksum as seen on 2019 Hyundai Santa Fe - dat = dat[:6] + dat[7] + dat = dat[:6] + dat[7:8] checksum = hyundai_checksum(dat) elif car_fingerprint in CHECKSUM["6B"]: # Checksum of first 6 Bytes, as seen on 2018 Kia Sorento - dat = [ord(i) for i in dat] checksum = sum(dat[:6]) % 256 elif car_fingerprint in CHECKSUM["7B"]: # Checksum of first 6 Bytes and last Byte as seen on 2018 Kia Stinger - dat = [ord(i) for i in dat] checksum = (sum(dat[:6]) + dat[7]) % 256 values["CF_Lkas_Chksum"] = checksum @@ -50,15 +48,15 @@ def create_lkas11(packer, car_fingerprint, apply_steer, steer_req, cnt, enabled, return packer.make_can_msg("LKAS11", 0, values) def create_lkas12(): - return make_can_msg(1342, "\x00\x00\x00\x00\x60\x05", 0) + return make_can_msg(1342, b"\x00\x00\x00\x00\x60\x05", 0) def create_1191(): - return make_can_msg(1191, "\x01\x00", 0) + return make_can_msg(1191, b"\x01\x00", 0) def create_1156(): - return make_can_msg(1156, "\x08\x20\xfe\x3f\x00\xe0\xfd\x3f", 0) + return make_can_msg(1156, b"\x08\x20\xfe\x3f\x00\xe0\xfd\x3f", 0) def create_clu11(packer, clu11, button): values = { diff --git a/selfdrive/car/hyundai/interface.py b/selfdrive/car/hyundai/interface.py index b39f07d6f151ac..7d6e372cf68fe8 100644 --- a/selfdrive/car/hyundai/interface.py +++ b/selfdrive/car/hyundai/interface.py @@ -1,16 +1,17 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 from cereal import car from selfdrive.config import Conversions as CV from selfdrive.controls.lib.drive_helpers import EventTypes as ET, create_event from selfdrive.controls.lib.vehicle_model import VehicleModel from selfdrive.car.hyundai.carstate import CarState, get_can_parser, get_camera_parser -from selfdrive.car.hyundai.values import CAMERA_MSGS, CAR, get_hud_alerts, FEATURES -from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness +from selfdrive.car.hyundai.values import ECU, ECU_FINGERPRINT, CAR, get_hud_alerts, FEATURES, FINGERPRINTS +from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, is_ecu_disconnected, gen_empty_fingerprint +from selfdrive.car.interfaces import CarInterfaceBase GearShifter = car.CarState.GearShifter ButtonType = car.CarState.ButtonEvent.Type -class CarInterface(object): +class CarInterface(CarInterfaceBase): def __init__(self, CP, CarController): self.CP = CP self.VM = VehicleModel(CP) @@ -37,18 +38,14 @@ def compute_gb(accel, speed): return float(accel) / 3.0 @staticmethod - def calc_accel_override(a_ego, a_target, v_ego, v_target): - return 1.0 - - @staticmethod - def get_params(candidate, fingerprint, vin="", is_panda_black=False): + def get_params(candidate, fingerprint=gen_empty_fingerprint(), vin="", has_relay=False): ret = car.CarParams.new_message() ret.carName = "hyundai" ret.carFingerprint = candidate ret.carVin = vin - ret.isPandaBlack = is_panda_black + ret.isPandaBlack = has_relay ret.radarOffCan = True ret.safetyModel = car.CarParams.SafetyModel.hyundai ret.enableCruise = True # stock acc @@ -143,7 +140,7 @@ def get_params(candidate, fingerprint, vin="", is_panda_black=False): ret.brakeMaxBP = [0.] ret.brakeMaxV = [1.] - ret.enableCamera = not any(x for x in CAMERA_MSGS if x in fingerprint) or is_panda_black + ret.enableCamera = is_ecu_disconnected(fingerprint[0], FINGERPRINTS, ECU_FINGERPRINT, candidate, ECU.CAM) or has_relay ret.openpilotLongitudinalControl = False ret.steerLimitAlert = False diff --git a/selfdrive/car/hyundai/radar_interface.py b/selfdrive/car/hyundai/radar_interface.py index 04c1005947e231..b2f76511360320 100644 --- a/selfdrive/car/hyundai/radar_interface.py +++ b/selfdrive/car/hyundai/radar_interface.py @@ -1,18 +1,5 @@ -#!/usr/bin/env python -import os -import time -from cereal import car +#!/usr/bin/env python3 +from selfdrive.car.interfaces import RadarInterfaceBase -class RadarInterface(object): - def __init__(self, CP): - # radar - self.pts = {} - self.delay = 0.1 - - def update(self, can_strings): - ret = car.RadarData.new_message() - - if 'NO_RADAR_SLEEP' not in os.environ: - time.sleep(0.05) # radard runs on RI updates - - return ret +class RadarInterface(RadarInterfaceBase): + pass diff --git a/selfdrive/car/hyundai/values.py b/selfdrive/car/hyundai/values.py index 6380ca446318e9..e801260a9538c8 100644 --- a/selfdrive/car/hyundai/values.py +++ b/selfdrive/car/hyundai/values.py @@ -25,7 +25,7 @@ class Buttons: FINGERPRINTS = { CAR.ELANTRA: [{ - 66: 8, 67: 8, 68: 8, 127: 8, 273: 8, 274: 8, 275: 8, 339: 8, 356: 4, 399: 8, 512: 6, 544: 8, 593: 8, 608: 8, 688: 5, 790: 8, 809: 8, 897: 8, 899: 8, 902: 8, 903: 8, 905: 8, 909: 8, 916: 8, 1040: 8, 1056: 8, 1057: 8, 1078: 4, 1170: 8, 1265: 4, 1280: 1, 1282: 4, 1287: 4, 1290: 8, 1292: 8, 1294: 8, 1312: 8, 1314: 8, 1322: 8, 1345: 8, 1349: 8, 1351: 8, 1353: 8, 1363: 8, 1366: 8, 1367: 8, 1369: 8, 1407: 8, 1415: 8, 1419: 8, 1425: 2, 1427: 6, 1440: 8, 1456: 4, 1472: 8, 1486: 8, 1487: 8, 1491: 8, 1530: 8, 1532: 5, 2001: 8, 2003: 8, 2004: 8, 2009: 8, 2012: 8, 2016: 8, 2017: 8, 2024: 8, 2025: 8 + 66: 8, 67: 8, 68: 8, 127: 8, 273: 8, 274: 8, 275: 8, 339: 8, 356: 4, 399: 8, 512: 6, 544: 8, 593: 8, 608: 8, 688: 5, 790: 8, 809: 8, 897: 8, 832: 8, 899: 8, 902: 8, 903: 8, 905: 8, 909: 8, 916: 8, 1040: 8, 1056: 8, 1057: 8, 1078: 4, 1170: 8, 1265: 4, 1280: 1, 1282: 4, 1287: 4, 1290: 8, 1292: 8, 1294: 8, 1312: 8, 1314: 8, 1322: 8, 1345: 8, 1349: 8, 1351: 8, 1353: 8, 1363: 8, 1366: 8, 1367: 8, 1369: 8, 1407: 8, 1415: 8, 1419: 8, 1425: 2, 1427: 6, 1440: 8, 1456: 4, 1472: 8, 1486: 8, 1487: 8, 1491: 8, 1530: 8, 1532: 5, 2001: 8, 2003: 8, 2004: 8, 2009: 8, 2012: 8, 2016: 8, 2017: 8, 2024: 8, 2025: 8 }], CAR.GENESIS: [{ 67: 8, 68: 8, 304: 8, 320: 8, 339: 8, 356: 4, 544: 7, 593: 8, 608: 8, 688: 5, 809: 8, 832: 8, 854: 7, 870: 7, 871: 8, 872: 5, 897: 8, 902: 8, 903: 6, 916: 8, 1024: 2, 1040: 8, 1056: 8, 1057: 8, 1078: 4, 1107: 5, 1136: 8, 1151: 6, 1168: 7, 1170: 8, 1173: 8, 1184: 8, 1265: 4, 1280: 1, 1287: 4, 1292: 8, 1312: 8, 1322: 8, 1331: 8, 1332: 8, 1333: 8, 1334: 8, 1335: 8, 1342: 6, 1345: 8, 1363: 8, 1369: 8, 1370: 8, 1371: 8, 1378: 4, 1384: 5, 1407: 8, 1419: 8, 1427: 6, 1434: 2, 1456: 4 @@ -46,12 +46,17 @@ class Buttons: 67: 8, 127: 8, 304: 8, 320: 8, 339: 8, 356: 4, 544: 8, 593: 8, 608: 8, 688: 6, 809: 8, 832: 8, 854: 7, 870: 7, 871: 8, 872: 8, 897: 8, 902: 8, 903: 8, 905: 8, 909: 8, 916: 8, 1040: 8, 1042: 8, 1056: 8, 1057: 8, 1078: 4, 1107: 5, 1136: 8, 1151: 6, 1155: 8, 1156: 8, 1162: 8, 1164: 8, 1168: 7, 1170: 8, 1173: 8, 1183: 8, 1186: 2, 1191: 2, 1227: 8, 1265: 4, 1280: 1, 1287: 4, 1290: 8, 1292: 8, 1294: 8, 1312: 8, 1322: 8, 1342: 6, 1345: 8, 1348: 8, 1363: 8, 1369: 8, 1379: 8, 1384: 8, 1407: 8, 1414: 3, 1419: 8, 1427: 6, 1456: 4, 1470: 8 }, { - 67: 8, 127: 8, 304: 8, 320: 8, 339: 8, 356: 4, 544: 8, 593: 8, 608: 8, 688: 6, 764: 8, 809: 8, 854: 7, 870: 7, 871: 8, 872: 8, 897: 8, 902: 8, 903: 8, 905: 8, 909: 8, 916: 8, 1040: 8, 1042: 8, 1056: 8, 1057: 8, 1064: 8, 1078: 4, 1107: 5, 1136: 8, 1151: 6, 1155: 8, 1162: 8, 1164: 8, 1168: 7, 1170: 8, 1173: 8, 1180: 8, 1183: 8, 1186: 2, 1227: 8, 1265: 4, 1280: 1, 1287: 4, 1290: 8, 1292: 8, 1294: 8, 1312: 8, 1322: 8, 1345: 8, 1348: 8, 1363: 8, 1369: 8, 1371: 8, 1378: 8, 1384: 8, 1407: 8, 1414: 3, 1419: 8, 1427: 6, 1456: 4, 1470: 8, 1988: 8, 2000: 8, 2004: 8, 2008: 8, 2012: 8 + 67: 8, 127: 8, 304: 8, 320: 8, 339: 8, 356: 4, 544: 8, 593: 8, 608: 8, 688: 6, 764: 8, 809: 8, 832: 8, 854: 7, 870: 7, 871: 8, 872: 8, 897: 8, 902: 8, 903: 8, 905: 8, 909: 8, 916: 8, 1040: 8, 1042: 8, 1056: 8, 1057: 8, 1064: 8, 1078: 4, 1107: 5, 1136: 8, 1151: 6, 1155: 8, 1162: 8, 1164: 8, 1168: 7, 1170: 8, 1173: 8, 1180: 8, 1183: 8, 1186: 2, 1227: 8, 1265: 4, 1280: 1, 1287: 4, 1290: 8, 1292: 8, 1294: 8, 1312: 8, 1322: 8, 1345: 8, 1348: 8, 1363: 8, 1369: 8, 1371: 8, 1378: 8, 1384: 8, 1407: 8, 1414: 3, 1419: 8, 1427: 6, 1456: 4, 1470: 8, 1988: 8, 2000: 8, 2004: 8, 2008: 8, 2012: 8 } ], } -CAMERA_MSGS = [832, 1156, 1191, 1342] +class ECU: + CAM = 0 + +ECU_FINGERPRINT = { + ECU.CAM: [832, 1156, 1191, 1342] +} CHECKSUM = { "crc8": [CAR.SANTA_FE], diff --git a/selfdrive/car/interfaces.py b/selfdrive/car/interfaces.py new file mode 100644 index 00000000000000..0d619cb9504b11 --- /dev/null +++ b/selfdrive/car/interfaces.py @@ -0,0 +1,39 @@ +import os +import time +from cereal import car +from selfdrive.car import gen_empty_fingerprint + +# generic car and radar interfaces + +class CarInterfaceBase(): + def __init__(self, CP, CarController): + pass + + @staticmethod + def calc_accel_override(a_ego, a_target, v_ego, v_target): + return 1. + + @staticmethod + def get_params(candidate, fingerprint=gen_empty_fingerprint(), vin="", has_relay=False): + raise NotImplementedError + + # returns a car.CarState, pass in car.CarControl + def update(self, c, can_strings): + raise NotImplementedError + + # return sendcan, pass in a car.CarControl + def apply(self, c): + raise NotImplementedError + +class RadarInterfaceBase(): + def __init__(self, CP): + self.pts = {} + self.delay = 0 + + def update(self, can_strings): + ret = car.RadarData.new_message() + + if 'NO_RADAR_SLEEP' not in os.environ: + time.sleep(0.05) # radard runs on RI updates + + return ret diff --git a/selfdrive/car/mock/interface.py b/selfdrive/car/mock/interface.py index b703776c0b5e0c..3b768d2838d137 100755 --- a/selfdrive/car/mock/interface.py +++ b/selfdrive/car/mock/interface.py @@ -1,9 +1,11 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 from cereal import car from selfdrive.config import Conversions as CV from selfdrive.services import service_list from selfdrive.swaglog import cloudlog import selfdrive.messaging as messaging +from selfdrive.car import gen_empty_fingerprint +from selfdrive.car.interfaces import CarInterfaceBase # mocked car interface to work with chffrplus TS = 0.01 # 100Hz @@ -12,7 +14,7 @@ LPG = 2 * 3.1415 * YAW_FR * TS / (1 + 2 * 3.1415 * YAW_FR * TS) -class CarInterface(object): +class CarInterface(CarInterfaceBase): def __init__(self, CP, CarController): self.CP = CP @@ -34,11 +36,7 @@ def compute_gb(accel, speed): return accel @staticmethod - def calc_accel_override(a_ego, a_target, v_ego, v_target): - return 1.0 - - @staticmethod - def get_params(candidate, fingerprint, vin="", is_panda_black=False): + def get_params(candidate, fingerprint=gen_empty_fingerprint(), vin="", has_relay=False): ret = car.CarParams.new_message() diff --git a/selfdrive/car/mock/radar_interface.py b/selfdrive/car/mock/radar_interface.py index 8e5f7b7fcaf150..b2f76511360320 100755 --- a/selfdrive/car/mock/radar_interface.py +++ b/selfdrive/car/mock/radar_interface.py @@ -1,15 +1,5 @@ -#!/usr/bin/env python -from cereal import car -import time +#!/usr/bin/env python3 +from selfdrive.car.interfaces import RadarInterfaceBase - -class RadarInterface(object): - def __init__(self, CP): - # radar - self.pts = {} - self.delay = 0.1 - - def update(self, can_strings): - ret = car.RadarData.new_message() - time.sleep(0.05) # radard runs on RI updates - return ret +class RadarInterface(RadarInterfaceBase): + pass diff --git a/selfdrive/car/subaru/carcontroller.py b/selfdrive/car/subaru/carcontroller.py index 95e0013faa9e37..6005976faefb02 100644 --- a/selfdrive/car/subaru/carcontroller.py +++ b/selfdrive/car/subaru/carcontroller.py @@ -18,7 +18,7 @@ def __init__(self, car_fingerprint): -class CarController(object): +class CarController(): def __init__(self, car_fingerprint): self.lkas_active = False self.steer_idx = 0 diff --git a/selfdrive/car/subaru/carstate.py b/selfdrive/car/subaru/carstate.py index 6c5f6782662bc7..cc24f63d2acde5 100644 --- a/selfdrive/car/subaru/carstate.py +++ b/selfdrive/car/subaru/carstate.py @@ -82,7 +82,7 @@ def get_camera_can_parser(CP): return CANParser(DBC[CP.carFingerprint]['pt'], signals, checks, 2) -class CarState(object): +class CarState(): def __init__(self, CP): # initialize can parser self.CP = CP diff --git a/selfdrive/car/subaru/interface.py b/selfdrive/car/subaru/interface.py index 5c91c95463ffe6..0fa12cf7d9bb89 100644 --- a/selfdrive/car/subaru/interface.py +++ b/selfdrive/car/subaru/interface.py @@ -1,15 +1,16 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 from cereal import car from selfdrive.config import Conversions as CV from selfdrive.controls.lib.drive_helpers import create_event, EventTypes as ET from selfdrive.controls.lib.vehicle_model import VehicleModel -from selfdrive.car.subaru.values import CAR +from selfdrive.car.subaru.values import CAR, FINGERPRINTS, ECU_FINGERPRINT, ECU from selfdrive.car.subaru.carstate import CarState, get_powertrain_can_parser, get_camera_can_parser -from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness +from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint, is_ecu_disconnected +from selfdrive.car.interfaces import CarInterfaceBase ButtonType = car.CarState.ButtonEvent.Type -class CarInterface(object): +class CarInterface(CarInterfaceBase): def __init__(self, CP, CarController): self.CP = CP @@ -34,24 +35,20 @@ def compute_gb(accel, speed): return float(accel) / 4.0 @staticmethod - def calc_accel_override(a_ego, a_target, v_ego, v_target): - return 1.0 - - @staticmethod - def get_params(candidate, fingerprint, vin="", is_panda_black=False): + def get_params(candidate, fingerprint=gen_empty_fingerprint(), vin="", has_relay=False): ret = car.CarParams.new_message() ret.carName = "subaru" ret.radarOffCan = True ret.carFingerprint = candidate ret.carVin = vin - ret.isPandaBlack = is_panda_black + ret.isPandaBlack = has_relay ret.safetyModel = car.CarParams.SafetyModel.subaru ret.enableCruise = True ret.steerLimitAlert = True - ret.enableCamera = True + ret.enableCamera = is_ecu_disconnected(fingerprint[0], FINGERPRINTS, ECU_FINGERPRINT, candidate, ECU.CAM) or has_relay ret.steerRateCost = 0.7 diff --git a/selfdrive/car/subaru/radar_interface.py b/selfdrive/car/subaru/radar_interface.py index 6c4e7a16a1080f..b2f76511360320 100644 --- a/selfdrive/car/subaru/radar_interface.py +++ b/selfdrive/car/subaru/radar_interface.py @@ -1,18 +1,5 @@ -#!/usr/bin/env python -import os -import time -from cereal import car +#!/usr/bin/env python3 +from selfdrive.car.interfaces import RadarInterfaceBase -class RadarInterface(object): - def __init__(self, CP): - # radar - self.pts = {} - self.delay = 0.1 - - def update(self, can_strings): - ret = car.RadarData.new_message() - - if 'NO_RADAR_SLEEP' not in os.environ: - time.sleep(0.05) # radard runs on RI updates - - return ret +class RadarInterface(RadarInterfaceBase): + pass diff --git a/selfdrive/car/subaru/subarucan.py b/selfdrive/car/subaru/subarucan.py index 922012f318dd42..96abfaafb3d698 100644 --- a/selfdrive/car/subaru/subarucan.py +++ b/selfdrive/car/subaru/subarucan.py @@ -6,7 +6,6 @@ def subaru_checksum(packer, values, addr): dat = packer.make_can_msg(addr, 0, values)[2] - dat = [ord(i) for i in dat] return (sum(dat[1:]) + (addr >> 8) + addr) & 0xff def create_steering_control(packer, car_fingerprint, apply_steer, frame, steer_step): diff --git a/selfdrive/car/subaru/values.py b/selfdrive/car/subaru/values.py index 0e444d736157e6..9abbaef3c80daf 100644 --- a/selfdrive/car/subaru/values.py +++ b/selfdrive/car/subaru/values.py @@ -17,6 +17,13 @@ class CAR: CAR.IMPREZA: 80, } +class ECU: + CAM = 0 + +ECU_FINGERPRINT = { + ECU.CAM: [290, 356], # steer torque cmd +} + DBC = { CAR.IMPREZA: dbc_dict('subaru_global_2017', None), } diff --git a/selfdrive/car/toyota/carcontroller.py b/selfdrive/car/toyota/carcontroller.py index 0cfd67b9ea8ffb..094588d57e616b 100644 --- a/selfdrive/car/toyota/carcontroller.py +++ b/selfdrive/car/toyota/carcontroller.py @@ -89,7 +89,7 @@ def ipas_state_transition(steer_angle_enabled, enabled, ipas_active, ipas_reset_ return False, 0 -class CarController(object): +class CarController(): def __init__(self, dbc_name, car_fingerprint, enable_camera, enable_dsu, enable_apg): self.braking = False # redundant safety check with the board @@ -257,14 +257,14 @@ def update(self, enabled, CS, frame, actuators, # special cases if fr_step == 5 and ecu == ECU.CAM and bus == 1: cnt = (((frame // 5) % 7) + 1) << 5 - vl = chr(cnt) + vl + vl = bytes([cnt]) + vl elif addr in (0x489, 0x48a) and bus == 0: # add counter for those 2 messages (last 4 bits) cnt = ((frame // 100) % 0xf) + 1 if addr == 0x48a: # 0x48a has a 8 preceding the counter cnt += 1 << 7 - vl += chr(cnt) + vl += bytes([cnt]) can_sends.append(make_can_msg(addr, vl, bus, False)) diff --git a/selfdrive/car/toyota/carstate.py b/selfdrive/car/toyota/carstate.py index f36738f8ee1c0a..fc0260ef562408 100644 --- a/selfdrive/car/toyota/carstate.py +++ b/selfdrive/car/toyota/carstate.py @@ -1,5 +1,5 @@ -import numpy as np from cereal import car +from common.numpy_fast import mean from common.kalman.simple_kalman import KF1D from selfdrive.can.can_define import CANDefine from selfdrive.can.parser import CANParser @@ -15,7 +15,7 @@ def parse_gear_shifter(gear, vals): try: return val_to_capnp[vals[gear]] except KeyError: - return "unknown" + return GearShifter.unknown def get_can_parser(CP): @@ -94,7 +94,7 @@ def get_cam_can_parser(CP): return CANParser(DBC[CP.carFingerprint]['pt'], signals, checks, 2) -class CarState(object): +class CarState(): def __init__(self, CP): self.CP = CP @@ -140,7 +140,7 @@ def update(self, cp): self.v_wheel_fr = cp.vl["WHEEL_SPEEDS"]['WHEEL_SPEED_FR'] * CV.KPH_TO_MS self.v_wheel_rl = cp.vl["WHEEL_SPEEDS"]['WHEEL_SPEED_RL'] * CV.KPH_TO_MS self.v_wheel_rr = cp.vl["WHEEL_SPEEDS"]['WHEEL_SPEED_RR'] * CV.KPH_TO_MS - v_wheel = float(np.mean([self.v_wheel_fl, self.v_wheel_fr, self.v_wheel_rl, self.v_wheel_rr])) + v_wheel = mean([self.v_wheel_fl, self.v_wheel_fr, self.v_wheel_rl, self.v_wheel_rr]) # Kalman filter if abs(v_wheel - self.v_ego) > 2.0: # Prevent large accelerations when car starts at non zero speed diff --git a/selfdrive/car/toyota/interface.py b/selfdrive/car/toyota/interface.py index 457169c4d65741..1063f556a73717 100755 --- a/selfdrive/car/toyota/interface.py +++ b/selfdrive/car/toyota/interface.py @@ -1,17 +1,18 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 from cereal import car from selfdrive.config import Conversions as CV from selfdrive.controls.lib.drive_helpers import EventTypes as ET, create_event from selfdrive.controls.lib.vehicle_model import VehicleModel from selfdrive.car.toyota.carstate import CarState, get_can_parser, get_cam_can_parser -from selfdrive.car.toyota.values import ECU, check_ecu_msgs, CAR, NO_STOP_TIMER_CAR, TSS2_CAR -from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness +from selfdrive.car.toyota.values import ECU, ECU_FINGERPRINT, CAR, NO_STOP_TIMER_CAR, TSS2_CAR, FINGERPRINTS +from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, is_ecu_disconnected, gen_empty_fingerprint from selfdrive.swaglog import cloudlog +from selfdrive.car.interfaces import CarInterfaceBase ButtonType = car.CarState.ButtonEvent.Type GearShifter = car.CarState.GearShifter -class CarInterface(object): +class CarInterface(CarInterfaceBase): def __init__(self, CP, CarController): self.CP = CP self.VM = VehicleModel(CP) @@ -38,18 +39,14 @@ def compute_gb(accel, speed): return float(accel) / 3.0 @staticmethod - def calc_accel_override(a_ego, a_target, v_ego, v_target): - return 1.0 - - @staticmethod - def get_params(candidate, fingerprint, vin="", is_panda_black=False): + def get_params(candidate, fingerprint=gen_empty_fingerprint(), vin="", has_relay=False): ret = car.CarParams.new_message() ret.carName = "toyota" ret.carFingerprint = candidate ret.carVin = vin - ret.isPandaBlack = is_panda_black + ret.isPandaBlack = has_relay ret.safetyModel = car.CarParams.SafetyModel.toyota @@ -219,16 +216,19 @@ def get_params(candidate, fingerprint, vin="", is_panda_black=False): ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.3], [0.05]] ret.lateralTuning.pid.kf = 0.00006 + elif candidate == CAR.LEXUS_CTH: + stop_and_go = True + ret.safetyParam = 100 + ret.wheelbase = 2.60 + ret.steerRatio = 18.6 + tire_stiffness_factor = 0.517 + ret.mass = 3108 * CV.LB_TO_KG + STD_CARGO_KG # mean between min and max + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.3], [0.05]] + ret.lateralTuning.pid.kf = 0.00007 + ret.steerRateCost = 1. ret.centerToFront = ret.wheelbase * 0.44 - #detect the Pedal address - ret.enableGasInterceptor = 0x201 in fingerprint - - # min speed to enable ACC. if car can do stop and go, then set enabling speed - # to a negative value, so it won't matter. - ret.minEnableSpeed = -1. if (stop_and_go or ret.enableGasInterceptor) else 19. * CV.MPH_TO_MS - # TODO: get actual value, for now starting with reasonable value for # civic and scaling by mass and wheelbase ret.rotationalInertia = scale_rot_inertia(ret.mass, ret.wheelbase) @@ -248,14 +248,19 @@ def get_params(candidate, fingerprint, vin="", is_panda_black=False): ret.brakeMaxBP = [0.] ret.brakeMaxV = [1.] - ret.enableCamera = not check_ecu_msgs(fingerprint, ECU.CAM, candidate) or is_panda_black - ret.enableDsu = not check_ecu_msgs(fingerprint, ECU.DSU, candidate) or (is_panda_black and candidate in TSS2_CAR) - ret.enableApgs = False #not check_ecu_msgs(fingerprint, ECU.APGS) + ret.enableCamera = is_ecu_disconnected(fingerprint[0], FINGERPRINTS, ECU_FINGERPRINT, candidate, ECU.CAM) or has_relay + ret.enableDsu = is_ecu_disconnected(fingerprint[0], FINGERPRINTS, ECU_FINGERPRINT, candidate, ECU.DSU) or (has_relay and candidate in TSS2_CAR) + ret.enableApgs = False # is_ecu_disconnected(fingerprint[0], FINGERPRINTS, ECU_FINGERPRINT, candidate, ECU.APGS) + ret.enableGasInterceptor = 0x201 in fingerprint[0] ret.openpilotLongitudinalControl = ret.enableCamera and ret.enableDsu - cloudlog.warn("ECU Camera Simulated: %r", ret.enableCamera) - cloudlog.warn("ECU DSU Simulated: %r", ret.enableDsu) - cloudlog.warn("ECU APGS Simulated: %r", ret.enableApgs) - cloudlog.warn("ECU Gas Interceptor: %r", ret.enableGasInterceptor) + cloudlog.warning("ECU Camera Simulated: %r", ret.enableCamera) + cloudlog.warning("ECU DSU Simulated: %r", ret.enableDsu) + cloudlog.warning("ECU APGS Simulated: %r", ret.enableApgs) + cloudlog.warning("ECU Gas Interceptor: %r", ret.enableGasInterceptor) + + # min speed to enable ACC. if car can do stop and go, then set enabling speed + # to a negative value, so it won't matter. + ret.minEnableSpeed = -1. if (stop_and_go or ret.enableGasInterceptor) else 19. * CV.MPH_TO_MS ret.steerLimitAlert = False @@ -283,10 +288,7 @@ def get_params(candidate, fingerprint, vin="", is_panda_black=False): def update(self, c, can_strings): # ******************* do can recv ******************* self.cp.update_strings(can_strings) - - # run the cam can update for 10s as we just need to know if the camera is alive - if self.frame < 1000: - self.cp_cam.update_strings(can_strings) + self.cp_cam.update_strings(can_strings) self.CS.update(self.cp) @@ -371,6 +373,8 @@ def update(self, c, can_strings): if self.cp_cam.can_valid: self.forwarding_camera = True + if self.cp_cam.can_invalid_cnt >= 100 and self.CP.enableCamera: + events.append(create_event('invalidGiraffeToyota', [ET.PERMANENT])) if not ret.gearShifter == GearShifter.drive and self.CP.enableDsu: events.append(create_event('wrongGear', [ET.NO_ENTRY, ET.SOFT_DISABLE])) if ret.doorOpen: diff --git a/selfdrive/car/toyota/radar_interface.py b/selfdrive/car/toyota/radar_interface.py index 0a1ce07ea2d7eb..a24a911a44f857 100755 --- a/selfdrive/car/toyota/radar_interface.py +++ b/selfdrive/car/toyota/radar_interface.py @@ -1,9 +1,10 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import os import time from selfdrive.can.parser import CANParser from cereal import car from selfdrive.car.toyota.values import NO_DSU_CAR, DBC, TSS2_CAR +from selfdrive.car.interfaces import RadarInterfaceBase def _create_radar_can_parser(car_fingerprint): dbc_f = DBC[car_fingerprint]['radar'] @@ -18,22 +19,22 @@ def _create_radar_can_parser(car_fingerprint): msg_a_n = len(RADAR_A_MSGS) msg_b_n = len(RADAR_B_MSGS) - signals = zip(['LONG_DIST'] * msg_a_n + ['NEW_TRACK'] * msg_a_n + ['LAT_DIST'] * msg_a_n + + signals = list(zip(['LONG_DIST'] * msg_a_n + ['NEW_TRACK'] * msg_a_n + ['LAT_DIST'] * msg_a_n + ['REL_SPEED'] * msg_a_n + ['VALID'] * msg_a_n + ['SCORE'] * msg_b_n, RADAR_A_MSGS * 5 + RADAR_B_MSGS, - [255] * msg_a_n + [1] * msg_a_n + [0] * msg_a_n + [0] * msg_a_n + [0] * msg_a_n + [0] * msg_b_n) + [255] * msg_a_n + [1] * msg_a_n + [0] * msg_a_n + [0] * msg_a_n + [0] * msg_a_n + [0] * msg_b_n)) - checks = zip(RADAR_A_MSGS + RADAR_B_MSGS, [20]*(msg_a_n + msg_b_n)) + checks = list(zip(RADAR_A_MSGS + RADAR_B_MSGS, [20]*(msg_a_n + msg_b_n))) return CANParser(os.path.splitext(dbc_f)[0], signals, checks, 1) -class RadarInterface(object): +class RadarInterface(RadarInterfaceBase): def __init__(self, CP): # radar self.pts = {} self.track_id = 0 - self.delay = 0.0 # Delay of radar + self.delay = 0 # Delay of radar if CP.carFingerprint in TSS2_CAR: self.RADAR_A_MSGS = list(range(0x180, 0x190)) @@ -75,7 +76,7 @@ def _update(self, updated_messages): errors.append("canError") ret.errors = errors - for ii in updated_messages: + for ii in sorted(updated_messages): if ii in self.RADAR_A_MSGS: cpt = self.rcp.vl[ii] @@ -105,5 +106,5 @@ def _update(self, updated_messages): if ii in self.pts: del self.pts[ii] - ret.points = self.pts.values() + ret.points = list(self.pts.values()) return ret diff --git a/selfdrive/car/toyota/toyotacan.py b/selfdrive/car/toyota/toyotacan.py index b886b1c6758d29..7125ecbf3e634f 100644 --- a/selfdrive/car/toyota/toyotacan.py +++ b/selfdrive/car/toyota/toyotacan.py @@ -10,7 +10,7 @@ def fix(msg, addr): checksum = idh + idl + len(msg) + 1 for d_byte in msg: - checksum += ord(d_byte) + checksum += d_byte #return msg + chr(checksum & 0xFF) return msg + struct.pack("B", checksum & 0xFF) diff --git a/selfdrive/car/toyota/values.py b/selfdrive/car/toyota/values.py index 1cb32ccf1812f2..4ec85d51e277ed 100644 --- a/selfdrive/car/toyota/values.py +++ b/selfdrive/car/toyota/values.py @@ -18,6 +18,7 @@ class CAR: LEXUS_ESH_TSS2 = "LEXUS ES 300H 2019" SIENNA = "TOYOTA SIENNA XLE 2018" LEXUS_IS = "LEXUS IS300 2018" + LEXUS_CTH = "LEXUS CT 200H 2018" class ECU: @@ -28,62 +29,56 @@ class ECU: # addr: (ecu, cars, bus, 1/freq*100, vl) STATIC_MSGS = [ - (0x130, ECU.CAM, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON), 1, 100, '\x00\x00\x00\x00\x00\x00\x38'), - (0x240, ECU.CAM, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON), 1, 5, '\x00\x10\x01\x00\x10\x01\x00'), - (0x241, ECU.CAM, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON), 1, 5, '\x00\x10\x01\x00\x10\x01\x00'), - (0x244, ECU.CAM, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON), 1, 5, '\x00\x10\x01\x00\x10\x01\x00'), - (0x245, ECU.CAM, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON), 1, 5, '\x00\x10\x01\x00\x10\x01\x00'), - (0x248, ECU.CAM, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON), 1, 5, '\x00\x00\x00\x00\x00\x00\x01'), - (0x367, ECU.CAM, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON), 0, 40, '\x06\x00'), - (0x414, ECU.CAM, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON), 0, 100, '\x00\x00\x00\x00\x00\x00\x17\x00'), - (0x466, ECU.CAM, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.HIGHLANDER, CAR.HIGHLANDERH), 1, 100, '\x20\x20\xAD'), - (0x466, ECU.CAM, (CAR.COROLLA, CAR.AVALON), 1, 100, '\x24\x20\xB1'), - (0x489, ECU.CAM, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON), 0, 100, '\x00\x00\x00\x00\x00\x00\x00'), - (0x48a, ECU.CAM, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON), 0, 100, '\x00\x00\x00\x00\x00\x00\x00'), - (0x48b, ECU.CAM, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON), 0, 100, '\x66\x06\x08\x0a\x02\x00\x00\x00'), - (0x4d3, ECU.CAM, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.AVALON), 0, 100, '\x1C\x00\x00\x01\x00\x00\x00\x00'), + (0x130, ECU.CAM, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON), 1, 100, b'\x00\x00\x00\x00\x00\x00\x38'), + (0x240, ECU.CAM, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON), 1, 5, b'\x00\x10\x01\x00\x10\x01\x00'), + (0x241, ECU.CAM, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON), 1, 5, b'\x00\x10\x01\x00\x10\x01\x00'), + (0x244, ECU.CAM, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON), 1, 5, b'\x00\x10\x01\x00\x10\x01\x00'), + (0x245, ECU.CAM, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON), 1, 5, b'\x00\x10\x01\x00\x10\x01\x00'), + (0x248, ECU.CAM, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON), 1, 5, b'\x00\x00\x00\x00\x00\x00\x01'), + (0x367, ECU.CAM, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON), 0, 40, b'\x06\x00'), + (0x414, ECU.CAM, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON), 0, 100, b'\x00\x00\x00\x00\x00\x00\x17\x00'), + (0x466, ECU.CAM, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.HIGHLANDER, CAR.HIGHLANDERH), 1, 100, b'\x20\x20\xAD'), + (0x466, ECU.CAM, (CAR.COROLLA, CAR.AVALON), 1, 100, b'\x24\x20\xB1'), + (0x489, ECU.CAM, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON), 0, 100, b'\x00\x00\x00\x00\x00\x00\x00'), + (0x48a, ECU.CAM, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON), 0, 100, b'\x00\x00\x00\x00\x00\x00\x00'), + (0x48b, ECU.CAM, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON), 0, 100, b'\x66\x06\x08\x0a\x02\x00\x00\x00'), + (0x4d3, ECU.CAM, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.AVALON), 0, 100, b'\x1C\x00\x00\x01\x00\x00\x00\x00'), - (0x128, ECU.DSU, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.AVALON), 1, 3, '\xf4\x01\x90\x83\x00\x37'), - (0x128, ECU.DSU, (CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.SIENNA), 1, 3, '\x03\x00\x20\x00\x00\x52'), - (0x141, ECU.DSU, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON, CAR.SIENNA), 1, 2, '\x00\x00\x00\x46'), - (0x160, ECU.DSU, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON, CAR.SIENNA), 1, 7, '\x00\x00\x08\x12\x01\x31\x9c\x51'), - (0x161, ECU.DSU, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.AVALON), 1, 7, '\x00\x1e\x00\x00\x00\x80\x07'), - (0X161, ECU.DSU, (CAR.HIGHLANDERH, CAR.HIGHLANDER, CAR.SIENNA), 1, 7, '\x00\x1e\x00\xd4\x00\x00\x5b'), - (0x283, ECU.DSU, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON, CAR.SIENNA), 0, 3, '\x00\x00\x00\x00\x00\x00\x8c'), - (0x2E6, ECU.DSU, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH), 0, 3, '\xff\xf8\x00\x08\x7f\xe0\x00\x4e'), - (0x2E7, ECU.DSU, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH), 0, 3, '\xa8\x9c\x31\x9c\x00\x00\x00\x02'), - (0x33E, ECU.DSU, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH), 0, 20, '\x0f\xff\x26\x40\x00\x1f\x00'), - (0x344, ECU.DSU, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON, CAR.SIENNA), 0, 5, '\x00\x00\x01\x00\x00\x00\x00\x50'), - (0x365, ECU.DSU, (CAR.PRIUS, CAR.LEXUS_RXH, CAR.HIGHLANDERH), 0, 20, '\x00\x00\x00\x80\x03\x00\x08'), - (0x365, ECU.DSU, (CAR.RAV4, CAR.RAV4H, CAR.COROLLA, CAR.HIGHLANDER, CAR.AVALON, CAR.SIENNA), 0, 20, '\x00\x00\x00\x80\xfc\x00\x08'), - (0x366, ECU.DSU, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.HIGHLANDERH), 0, 20, '\x00\x00\x4d\x82\x40\x02\x00'), - (0x366, ECU.DSU, (CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.AVALON, CAR.SIENNA), 0, 20, '\x00\x72\x07\xff\x09\xfe\x00'), - (0x470, ECU.DSU, (CAR.PRIUS, CAR.LEXUS_RXH), 1, 100, '\x00\x00\x02\x7a'), - (0x470, ECU.DSU, (CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.RAV4H, CAR.SIENNA), 1, 100, '\x00\x00\x01\x79'), - (0x4CB, ECU.DSU, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDERH, CAR.HIGHLANDER, CAR.AVALON, CAR.SIENNA), 0, 100, '\x0c\x00\x00\x00\x00\x00\x00\x00'), + (0x128, ECU.DSU, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.AVALON), 1, 3, b'\xf4\x01\x90\x83\x00\x37'), + (0x128, ECU.DSU, (CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.SIENNA, CAR.LEXUS_CTH), 1, 3, b'\x03\x00\x20\x00\x00\x52'), + (0x141, ECU.DSU, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON, CAR.SIENNA, CAR.LEXUS_CTH), 1, 2, b'\x00\x00\x00\x46'), + (0x160, ECU.DSU, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON, CAR.SIENNA, CAR.LEXUS_CTH), 1, 7, b'\x00\x00\x08\x12\x01\x31\x9c\x51'), + (0x161, ECU.DSU, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.AVALON), 1, 7, b'\x00\x1e\x00\x00\x00\x80\x07'), + (0X161, ECU.DSU, (CAR.HIGHLANDERH, CAR.HIGHLANDER, CAR.SIENNA, CAR.LEXUS_CTH), 1, 7, b'\x00\x1e\x00\xd4\x00\x00\x5b'), + (0x283, ECU.DSU, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON, CAR.SIENNA, CAR.LEXUS_CTH), 0, 3, b'\x00\x00\x00\x00\x00\x00\x8c'), + (0x2E6, ECU.DSU, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH), 0, 3, b'\xff\xf8\x00\x08\x7f\xe0\x00\x4e'), + (0x2E7, ECU.DSU, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH), 0, 3, b'\xa8\x9c\x31\x9c\x00\x00\x00\x02'), + (0x33E, ECU.DSU, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH), 0, 20, b'\x0f\xff\x26\x40\x00\x1f\x00'), + (0x344, ECU.DSU, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.AVALON, CAR.SIENNA, CAR.LEXUS_CTH), 0, 5, b'\x00\x00\x01\x00\x00\x00\x00\x50'), + (0x365, ECU.DSU, (CAR.PRIUS, CAR.LEXUS_RXH, CAR.HIGHLANDERH), 0, 20, b'\x00\x00\x00\x80\x03\x00\x08'), + (0x365, ECU.DSU, (CAR.RAV4, CAR.RAV4H, CAR.COROLLA, CAR.HIGHLANDER, CAR.AVALON, CAR.SIENNA, CAR.LEXUS_CTH), 0, 20, b'\x00\x00\x00\x80\xfc\x00\x08'), + (0x366, ECU.DSU, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.HIGHLANDERH), 0, 20, b'\x00\x00\x4d\x82\x40\x02\x00'), + (0x366, ECU.DSU, (CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDER, CAR.AVALON, CAR.SIENNA, CAR.LEXUS_CTH), 0, 20, b'\x00\x72\x07\xff\x09\xfe\x00'), + (0x470, ECU.DSU, (CAR.PRIUS, CAR.LEXUS_RXH), 1, 100, b'\x00\x00\x02\x7a'), + (0x470, ECU.DSU, (CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.RAV4H, CAR.SIENNA, CAR.LEXUS_CTH), 1, 100, b'\x00\x00\x01\x79'), + (0x4CB, ECU.DSU, (CAR.PRIUS, CAR.RAV4H, CAR.LEXUS_RXH, CAR.RAV4, CAR.COROLLA, CAR.HIGHLANDERH, CAR.HIGHLANDER, CAR.AVALON, CAR.SIENNA, CAR.LEXUS_CTH), 0, 100, b'\x0c\x00\x00\x00\x00\x00\x00\x00'), - (0x292, ECU.APGS, (CAR.PRIUS), 0, 3, '\x00\x00\x00\x00\x00\x00\x00\x9e'), - (0x32E, ECU.APGS, (CAR.PRIUS), 0, 20, '\x00\x00\x00\x00\x00\x00\x00\x00'), - (0x396, ECU.APGS, (CAR.PRIUS), 0, 100, '\xBD\x00\x00\x00\x60\x0F\x02\x00'), - (0x43A, ECU.APGS, (CAR.PRIUS), 0, 100, '\x84\x00\x00\x00\x00\x00\x00\x00'), - (0x43B, ECU.APGS, (CAR.PRIUS), 0, 100, '\x00\x00\x00\x00\x00\x00\x00\x00'), - (0x497, ECU.APGS, (CAR.PRIUS), 0, 100, '\x00\x00\x00\x00\x00\x00\x00\x00'), - (0x4CC, ECU.APGS, (CAR.PRIUS), 0, 100, '\x0D\x00\x00\x00\x00\x00\x00\x00'), + (0x292, ECU.APGS, (CAR.PRIUS), 0, 3, b'\x00\x00\x00\x00\x00\x00\x00\x9e'), + (0x32E, ECU.APGS, (CAR.PRIUS), 0, 20, b'\x00\x00\x00\x00\x00\x00\x00\x00'), + (0x396, ECU.APGS, (CAR.PRIUS), 0, 100, b'\xBD\x00\x00\x00\x60\x0F\x02\x00'), + (0x43A, ECU.APGS, (CAR.PRIUS), 0, 100, b'\x84\x00\x00\x00\x00\x00\x00\x00'), + (0x43B, ECU.APGS, (CAR.PRIUS), 0, 100, b'\x00\x00\x00\x00\x00\x00\x00\x00'), + (0x497, ECU.APGS, (CAR.PRIUS), 0, 100, b'\x00\x00\x00\x00\x00\x00\x00\x00'), + (0x4CC, ECU.APGS, (CAR.PRIUS), 0, 100, b'\x0D\x00\x00\x00\x00\x00\x00\x00'), ] ECU_FINGERPRINT = { - ECU.CAM: 0x2e4, # steer torque cmd - ECU.DSU: 0x343, # accel cmd - ECU.APGS: 0x835, # angle cmd + ECU.CAM: [0x2e4], # steer torque cmd + ECU.DSU: [0x343], # accel cmd + ECU.APGS: [0x835], # angle cmd } -def check_ecu_msgs(fingerprint, ecu, car): - # return True if the reference car fingerprint doesn't contain the ecu fingerprint msg or - # fingerprint contains messages normally sent by a given ecu - return any(ECU_FINGERPRINT[ecu] not in finger for finger in FINGERPRINTS[car]) or ECU_FINGERPRINT[ecu] in fingerprint - - FINGERPRINTS = { CAR.RAV4: [{ 36: 8, 37: 8, 170: 8, 180: 8, 186: 4, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 512: 6, 513: 6, 547: 8, 548: 8, 552: 4, 562: 4, 608: 8, 610: 5, 643: 7, 705: 8, 725: 2, 740: 5, 800: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 897: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 3, 918: 7, 921: 8, 933: 8, 944: 8, 945: 8, 951: 8, 955: 4, 956: 8, 979: 2, 998: 5, 999: 7, 1000: 8, 1001: 8, 1005: 2, 1008: 2, 1014: 8, 1017: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1059: 1, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1408: 8, 1409: 8, 1410: 8, 1552: 8, 1553: 8, 1554: 8, 1555: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1596: 8, 1597: 8, 1600: 8, 1656: 8, 1664: 8, 1728: 8, 1745: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8, 2015: 8, 2024: 8 @@ -102,6 +97,10 @@ def check_ecu_msgs(fingerprint, ecu, car): #2019 LE { 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 614: 8, 643: 7, 658: 8, 713: 8, 740: 5, 742: 8, 743: 8, 800: 8, 810: 2, 814: 8, 829: 2, 830: 7, 835: 8, 836: 8, 863: 8, 865: 8, 869: 7, 870: 7, 871: 2, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 5, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1076: 8, 1077: 8, 1082: 8, 1083: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1175: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1279: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1595: 8, 1777: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8 + }, + #2020 Prius Prime Limited + { + 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 614: 8, 643: 7, 658: 8, 713: 8, 740: 5, 742: 8, 743: 8, 800: 8, 810: 2, 814: 8, 824: 2, 829: 2, 830: 7, 835: 8, 836: 8, 863: 8, 865: 8, 869: 7, 870: 7, 871: 2, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 974: 8, 975: 5, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1076: 8, 1077: 8, 1082: 8, 1083: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1175: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1595: 8, 1649: 8, 1777: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8, 2015: 8, 2024: 8, 2026: 8, 2027: 8, 2029: 8, 2030: 8, 2031: 8 }], #Corolla w/ added Pedal Support (512L and 513L) CAR.COROLLA: [{ @@ -149,7 +148,7 @@ def check_ecu_msgs(fingerprint, ecu, car): 36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 643: 7, 658: 8, 713: 8, 728: 8, 740: 5, 761: 8, 764: 8, 800: 8, 810: 2, 812: 8, 814: 8, 818: 8, 824: 8, 829: 2, 830: 7, 835: 8, 836: 8, 869: 7, 870: 7, 871: 2, 888: 8, 889: 8, 898: 8, 900: 6, 902: 6, 905: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 5, 983: 8, 984: 8, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1011: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1076: 8, 1077: 8, 1082: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1228: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1595: 8, 1745: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8 }], CAR.HIGHLANDER: [{ - 36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 238: 4, 355: 5, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 545: 5, 550: 8, 552: 4, 608: 8, 610: 5, 643: 7, 705: 8, 725: 2, 740: 5, 800: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 3, 921: 8, 922: 8, 933: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 979: 2, 998: 5, 999: 7, 1000: 8, 1001: 8, 1008: 2, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1059: 1, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1182: 8, 1183: 8, 1189: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1206: 8, 1207: 8, 1212: 8, 1227: 8, 1235: 8, 1237: 8, 1279: 8, 1408: 8, 1409: 8, 1410: 8, 1552: 8, 1553: 8, 1554: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1599: 8, 1656: 8, 1666: 8, 1667: 8, 1728: 8, 1745: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8 + 36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 238: 4, 355: 5, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 545: 5, 550: 8, 552: 4, 608: 8, 610: 5, 643: 7, 705: 8, 725: 2, 740: 5, 800: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 3, 921: 8, 922: 8, 933: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 979: 2, 998: 5, 999: 7, 1000: 8, 1001: 8, 1008: 2, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1059: 1, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1182: 8, 1183: 8, 1189: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1206: 8, 1207: 8, 1212: 8, 1227: 8, 1235: 8, 1237: 8, 1279: 8, 1408: 8, 1409: 8, 1410: 8, 1552: 8, 1553: 8, 1554: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1599: 8, 1656: 8, 1666: 8, 1667: 8, 1728: 8, 1745: 8, 1779: 8, 1872: 8, 1880: 8, 1904: 8, 1912: 8, 1984: 8, 1988: 8, 1992: 8, 1996: 8, 1990: 8, 1998: 8 }, # 2019 Highlander XLE { @@ -161,6 +160,9 @@ def check_ecu_msgs(fingerprint, ecu, car): }], CAR.HIGHLANDERH: [{ 36: 8, 37: 8, 170: 8, 180: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 581: 5, 608: 8, 610: 5, 643: 7, 713: 8, 740: 5, 800: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 897: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 3, 918: 7, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 3, 955: 8, 956: 8, 979: 2, 998: 5, 999: 7, 1000: 8, 1001: 8, 1005: 2, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1059: 1, 1112: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1184: 8, 1185: 8, 1186: 8, 1189: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1206: 8, 1212: 8, 1227: 8, 1232: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1552: 8, 1553: 8, 1554: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1599: 8, 1656: 8, 1728: 8, 1745: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8 + }, + { + 36: 8, 37: 8, 170: 8, 180: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 581: 5, 608: 8, 610: 5, 643: 7, 713: 8, 740: 5, 800: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 897: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 3, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 3, 955: 8, 956: 8, 979: 2, 992: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1076: 8, 1077: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1184: 8, 1185: 8, 1186: 8, 1189: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1206: 8, 1212: 8, 1227: 8, 1232: 8, 1237: 8, 1279: 8, 1552: 8, 1553: 8, 1554: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1599: 8, 1656: 8, 1728: 8, 1745: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8 }], CAR.AVALON: [{ 36: 8, 37: 8, 170: 8, 180: 8, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 547: 8, 550: 8, 552: 4, 562: 6, 608: 8, 610: 5, 643: 7, 705: 8, 740: 5, 800: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 897: 8, 905: 8, 911: 1, 916: 2, 921: 8, 933: 6, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 979: 2, 1005: 2, 1014: 8, 1017: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1200: 8, 1201: 8, 1202: 8, 1203: 8, 1206: 8, 1227: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1552: 8, 1553: 8, 1554: 8, 1555: 8, 1556: 8, 1557: 8, 1558: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1596: 8, 1597: 8, 1664: 8, 1728: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8 @@ -177,7 +179,7 @@ def check_ecu_msgs(fingerprint, ecu, car): CAR.COROLLA_TSS2: [ # hatch 2019+ and sedan 2020+ { - 36: 8, 37: 8, 114: 5, 170: 8, 180: 8, 186: 4, 401: 8, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 8, 643: 7, 705: 8, 728: 8, 740: 5, 742: 8, 743: 8, 761: 8, 764: 8, 765: 8, 800: 8, 810: 2, 812: 8, 824: 8, 829: 2, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1076: 8, 1077: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1172: 8, 1235: 8, 1237: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1595: 8, 1649: 8, 1745: 8, 1775: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1808: 8, 1809: 8, 1816: 8, 1817: 8, 1840: 8, 1848: 8, 1904: 8, 1912: 8, 1940: 8, 1941: 8, 1948: 8, 1949: 8, 1952: 8, 1960: 8, 1981: 8, 1986: 8, 1990: 8, 1994: 8, 1998: 8, 2004: 8 + 36: 8, 37: 8, 114: 5, 170: 8, 180: 8, 186: 4, 401: 8, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 8, 643: 7, 705: 8, 728: 8, 740: 5, 742: 8, 743: 8, 761: 8, 764: 8, 765: 8, 800: 8, 810: 2, 812: 8, 824: 8, 829: 2, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1076: 8, 1077: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1172: 8, 1235: 8, 1237: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1595: 8, 1649: 8, 1745: 8, 1775: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1808: 8, 1809: 8, 1816: 8, 1817: 8, 1840: 8, 1848: 8, 1904: 8, 1912: 8, 1940: 8, 1941: 8, 1948: 8, 1949: 8, 1952: 8, 1960: 8, 1981: 8, 1986: 8, 1990: 8, 1994: 8, 1998: 8, 2004: 8 }], CAR.LEXUS_ESH_TSS2: [ { @@ -195,6 +197,9 @@ def check_ecu_msgs(fingerprint, ecu, car): { 36: 8, 37: 8, 170: 8, 180: 8, 295: 8, 296: 8, 400: 6, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 581: 5, 608: 8, 610: 5, 643: 7, 713: 8, 740: 5, 800: 8, 836: 8, 845: 5, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 897: 8, 900: 6, 902: 6, 905: 8, 911: 8, 913: 8, 916: 3, 918: 7, 921: 7, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 3, 955: 8, 956: 8, 979: 2, 992: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1009: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1112: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1168: 1, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1184: 8, 1185: 8, 1186: 8, 1187: 8, 1189: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1206: 8, 1208: 8, 1212: 8, 1227: 8, 1232: 8, 1235: 8, 1279: 8, 1408: 8, 1409: 8, 1410: 8, 1552: 8, 1553: 8, 1554: 8, 1555: 8, 1556: 8, 1557: 8, 1561: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1599: 8, 1728: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8 }], + CAR.LEXUS_CTH: [{ + 36: 8, 37: 8, 170: 8, 180: 8, 288: 8, 426: 6, 452: 8, 466: 8, 467: 8, 548: 8, 552: 4, 560: 7, 581: 5, 608: 8, 610: 5, 643: 7, 713: 8, 740: 5, 800: 8, 810: 2, 832: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 897: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 1, 921: 8, 933: 8, 944: 6, 945: 8, 950: 8, 951: 8, 953: 3, 955: 4, 956: 8, 979: 2, 992: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1017: 8, 1041: 8, 1042: 8, 1043: 8, 1056: 8, 1057: 8, 1059: 1, 1076: 8, 1077: 8, 1114: 8, 1116: 8, 1160: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1184: 8, 1185: 8, 1186: 8, 1190: 8, 1191: 8, 1192: 8, 1227: 8, 1235: 8, 1279: 8, 1552: 8, 1553: 8, 1554: 8, 1555: 8, 1556: 8, 1557: 8, 1558: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1664: 8, 1728: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8 + }] } STEER_THRESHOLD = 100 @@ -217,6 +222,7 @@ def check_ecu_msgs(fingerprint, ecu, car): CAR.LEXUS_ESH_TSS2: dbc_dict('toyota_nodsu_hybrid_pt_generated', 'toyota_tss2_adas'), CAR.SIENNA: dbc_dict('toyota_sienna_xle_2018_pt_generated', 'toyota_adas'), CAR.LEXUS_IS: dbc_dict('lexus_is_2018_pt_generated', 'toyota_adas'), + CAR.LEXUS_CTH: dbc_dict('lexus_ct200h_2018_pt_generated', 'toyota_adas'), } NO_DSU_CAR = [CAR.CHR, CAR.CHRH, CAR.CAMRY, CAR.CAMRYH, CAR.RAV4_TSS2, CAR.COROLLA_TSS2, CAR.LEXUS_ESH_TSS2] diff --git a/common/vin.py b/selfdrive/car/vin.py similarity index 83% rename from common/vin.py rename to selfdrive/car/vin.py index 989aa0fa13f5bb..76fd34ca6d80e8 100755 --- a/common/vin.py +++ b/selfdrive/car/vin.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import selfdrive.messaging as messaging from selfdrive.boardd.boardd import can_list_to_can_capnp @@ -6,9 +6,6 @@ # sanity checks on response messages from vin query def is_vin_response_valid(can_dat, step, cnt): - - can_dat = [ord(i) for i in can_dat] - if len(can_dat) != 8: # ISO-TP meesages are all 8 bytes return False @@ -36,17 +33,17 @@ def __init__(self, bus): self.bus = bus # works on standard 11-bit addresses for diagnostic. Tested on Toyota and Subaru; # Honda uses the extended 29-bit addresses, and unfortunately only works from OBDII - self.query_ext_msgs = [[0x18DB33F1, 0, '\x02\x09\x02'.ljust(8, "\x00"), bus], - [0x18DA10f1, 0, '\x30'.ljust(8, "\x00"), bus]] - self.query_nor_msgs = [[0x7df, 0, '\x02\x09\x02'.ljust(8, "\x00"), bus], - [0x7e0, 0, '\x30'.ljust(8, "\x00"), bus]] + self.query_ext_msgs = [[0x18DB33F1, 0, b'\x02\x09\x02'.ljust(8, b"\x00"), bus], + [0x18DA10f1, 0, b'\x30'.ljust(8, b"\x00"), bus]] + self.query_nor_msgs = [[0x7df, 0, b'\x02\x09\x02'.ljust(8, b"\x00"), bus], + [0x7e0, 0, b'\x30'.ljust(8, b"\x00"), bus]] self.cnts = [1, 2] # number of messages to wait for at each iteration self.step = 0 self.cnt = 0 self.responded = False self.never_responded = True - self.dat = [] + self.dat = b"" self.vin = VIN_UNKNOWN def check_response(self, msg): @@ -55,7 +52,7 @@ def check_response(self, msg): self.never_responded = False # basic sanity checks on ISO-TP response if is_vin_response_valid(msg.dat, self.step, self.cnt): - self.dat += msg.dat[2:] if self.step == 0 else msg.dat[1:] + self.dat += bytes(msg.dat[2:]) if self.step == 0 else bytes(msg.dat[1:]) self.cnt += 1 if self.cnt == self.cnts[self.step]: self.responded = True @@ -73,7 +70,7 @@ def send_query(self, sendcan): def get_vin(self): # only report vin if procedure is finished if self.step == len(self.cnts) and self.cnt == self.cnts[-1]: - self.vin = "".join(self.dat[3:]) + self.vin = self.dat[3:].decode('utf8') return self.vin @@ -98,4 +95,4 @@ def get_vin(logcan, sendcan, bus, query_time=1.): from selfdrive.services import service_list logcan = messaging.sub_sock(service_list['can'].port) sendcan = messaging.pub_sock(service_list['sendcan'].port) - print get_vin(logcan, sendcan, 0) + print(get_vin(logcan, sendcan, 0)) diff --git a/selfdrive/common/params.cc b/selfdrive/common/params.cc index 723b06d9212d94..0bdf6118a6616e 100644 --- a/selfdrive/common/params.cc +++ b/selfdrive/common/params.cc @@ -16,6 +16,7 @@ #include "common/util.h" #include "common/utilpp.h" + namespace { template @@ -28,8 +29,42 @@ static const char* default_params_path = null_coalesce( } // namespace +static int fsync_dir(const char* path){ + int result = 0; + int fd = open(path, O_RDONLY); + + if (fd < 0){ + result = -1; + goto cleanup; + } + + result = fsync(fd); + if (result < 0) { + goto cleanup; + } + + cleanup: + int result_close = 0; + if (fd >= 0){ + result_close = close(fd); + } + + if (result_close < 0) { + return result_close; + } else { + return result; + } +} + int write_db_value(const char* params_path, const char* key, const char* value, size_t value_size) { + // Information about safely and atomically writing a file: https://lwn.net/Articles/457667/ + // 1) Create temp file + // 2) Write data to temp file + // 3) fsync() the temp file + // 4) rename the temp file to the real name + // 5) fsync() the containing directory + int lock_fd = -1; int tmp_fd = -1; int result; @@ -55,12 +90,14 @@ int write_db_value(const char* params_path, const char* key, const char* value, goto cleanup; } + // Build lock path result = snprintf(path, sizeof(path), "%s/.lock", params_path); if (result < 0) { goto cleanup; } lock_fd = open(path, 0); + // Build key path result = snprintf(path, sizeof(path), "%s/d/%s", params_path, key); if (result < 0) { goto cleanup; @@ -80,6 +117,20 @@ int write_db_value(const char* params_path, const char* key, const char* value, // Move temp into place. result = rename(tmp_path, path); + if (result < 0) { + goto cleanup; + } + + // fsync parent directory + result = snprintf(path, sizeof(path), "%s/d", params_path); + if (result < 0) { + goto cleanup; + } + + result = fsync_dir(path); + if (result < 0) { + goto cleanup; + } cleanup: // Release lock. @@ -95,6 +146,60 @@ int write_db_value(const char* params_path, const char* key, const char* value, return result; } +int delete_db_value(const char* params_path, const char* key) { + int lock_fd = -1; + int result; + char path[1024]; + + if (params_path == NULL) { + params_path = default_params_path; + } + + // Build lock path, and open lockfile + result = snprintf(path, sizeof(path), "%s/.lock", params_path); + if (result < 0) { + goto cleanup; + } + lock_fd = open(path, 0); + + // Take lock. + result = flock(lock_fd, LOCK_EX); + if (result < 0) { + goto cleanup; + } + + // Build key path + result = snprintf(path, sizeof(path), "%s/d/%s", params_path, key); + if (result < 0) { + goto cleanup; + } + + // Delete value. + result = remove(path); + if (result != 0) { + result = ERR_NO_VALUE; + goto cleanup; + } + + // fsync parent directory + result = snprintf(path, sizeof(path), "%s/d", params_path); + if (result < 0) { + goto cleanup; + } + + result = fsync_dir(path); + if (result < 0) { + goto cleanup; + } + +cleanup: + // Release lock. + if (lock_fd >= 0) { + close(lock_fd); + } + return result; +} + int read_db_value(const char* params_path, const char* key, char** value, size_t* value_sz) { int lock_fd = -1; diff --git a/selfdrive/common/params.h b/selfdrive/common/params.h index 299dcccd0a412d..6dcd36145e0d28 100644 --- a/selfdrive/common/params.h +++ b/selfdrive/common/params.h @@ -7,6 +7,8 @@ extern "C" { #endif +#define ERR_NO_VALUE -33 + int write_db_value(const char* params_path, const char* key, const char* value, size_t value_size); @@ -23,6 +25,10 @@ int write_db_value(const char* params_path, const char* key, const char* value, int read_db_value(const char* params_path, const char* key, char** value, size_t* value_sz); +// Delete a value from the params database. +// Inputs are the same as read_db_value, without value and value_sz. +int delete_db_value(const char* params_path, const char* key); + // Reads a value from the params database, blocking until successful. // Inputs are the same as read_db_value. void read_db_value_blocking(const char* params_path, const char* key, diff --git a/selfdrive/common/spinner.c b/selfdrive/common/spinner.c new file mode 100644 index 00000000000000..abae7cc1352009 --- /dev/null +++ b/selfdrive/common/spinner.c @@ -0,0 +1,184 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "nanovg.h" +#define NANOVG_GLES3_IMPLEMENTATION +#include "nanovg_gl.h" +#include "nanovg_gl_utils.h" + +#include "framebuffer.h" +#include "spinner.h" + +#define SPINTEXT_LENGTH 128 + +// external resources linked in +extern const unsigned char _binary_opensans_semibold_ttf_start[]; +extern const unsigned char _binary_opensans_semibold_ttf_end[]; + +extern const unsigned char _binary_img_spinner_track_png_start[]; +extern const unsigned char _binary_img_spinner_track_png_end[]; + +extern const unsigned char _binary_img_spinner_comma_png_start[]; +extern const unsigned char _binary_img_spinner_comma_png_end[]; + +bool stdin_input_available() { + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + + fd_set fds; + FD_ZERO(&fds); + FD_SET(STDIN_FILENO, &fds); + select(STDIN_FILENO+1, &fds, NULL, NULL, &timeout); + return (FD_ISSET(0, &fds)); +} + +int spin(int argc, char** argv) { + int err; + + bool draw_progress = false; + float progress_val = 0.0; + + char spintext[SPINTEXT_LENGTH]; + spintext[0] = 0; + + const char* spintext_arg = NULL; + if (argc >= 2) { + strncpy(spintext, argv[1], SPINTEXT_LENGTH); + } + + // spinner + int fb_w, fb_h; + EGLDisplay display; + EGLSurface surface; + FramebufferState *fb = framebuffer_init("spinner", 0x00001000, false, + &display, &surface, &fb_w, &fb_h); + assert(fb); + + NVGcontext *vg = nvgCreateGLES3(NVG_ANTIALIAS | NVG_STENCIL_STROKES); + assert(vg); + + int font = nvgCreateFontMem(vg, "Bold", (unsigned char*)_binary_opensans_semibold_ttf_start, _binary_opensans_semibold_ttf_end-_binary_opensans_semibold_ttf_start, 0); + assert(font >= 0); + + int spinner_img = nvgCreateImageMem(vg, 0, (unsigned char*)_binary_img_spinner_track_png_start, _binary_img_spinner_track_png_end - _binary_img_spinner_track_png_start); + assert(spinner_img >= 0); + int spinner_img_s = 360; + int spinner_img_x = ((fb_w/2)-(spinner_img_s/2)); + int spinner_img_y = 260; + int spinner_img_xc = (fb_w/2); + int spinner_img_yc = (fb_h/2)-100; + int spinner_comma_img = nvgCreateImageMem(vg, 0, (unsigned char*)_binary_img_spinner_comma_png_start, _binary_img_spinner_comma_png_end - _binary_img_spinner_comma_png_start); + assert(spinner_comma_img >= 0); + + for (int cnt = 0; ; cnt++) { + // Check stdin for new text + if (stdin_input_available()){ + fgets(spintext, SPINTEXT_LENGTH, stdin); + spintext[strcspn(spintext, "\n")] = 0; + + // Check if number (update progress bar) + size_t len = strlen(spintext); + bool is_number = len > 0; + for (int i = 0; i < len; i++){ + if (!isdigit(spintext[i])){ + is_number = false; + break; + } + } + + if (is_number) { + progress_val = (float)(atoi(spintext)) / 100.0; + progress_val = fmin(1.0, progress_val); + progress_val = fmax(0.0, progress_val); + } + + draw_progress = is_number; + } + + glClearColor(0.1, 0.1, 0.1, 1.0); + glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + nvgBeginFrame(vg, fb_w, fb_h, 1.0f); + + // background + nvgBeginPath(vg); + NVGpaint bg = nvgLinearGradient(vg, fb_w, 0, fb_w, fb_h, + nvgRGBA(0, 0, 0, 175), nvgRGBA(0, 0, 0, 255)); + nvgFillPaint(vg, bg); + nvgRect(vg, 0, 0, fb_w, fb_h); + nvgFill(vg); + + // spin track + nvgSave(vg); + nvgTranslate(vg, spinner_img_xc, spinner_img_yc); + nvgRotate(vg, (3.75*M_PI * cnt/120.0)); + nvgTranslate(vg, -spinner_img_xc, -spinner_img_yc); + NVGpaint spinner_imgPaint = nvgImagePattern(vg, spinner_img_x, spinner_img_y, + spinner_img_s, spinner_img_s, 0, spinner_img, 0.6f); + nvgBeginPath(vg); + nvgFillPaint(vg, spinner_imgPaint); + nvgRect(vg, spinner_img_x, spinner_img_y, spinner_img_s, spinner_img_s); + nvgFill(vg); + nvgRestore(vg); + + // comma + NVGpaint comma_imgPaint = nvgImagePattern(vg, spinner_img_x, spinner_img_y, + spinner_img_s, spinner_img_s, 0, spinner_comma_img, 1.0f); + nvgBeginPath(vg); + nvgFillPaint(vg, comma_imgPaint); + nvgRect(vg, spinner_img_x, spinner_img_y, spinner_img_s, spinner_img_s); + nvgFill(vg); + + if (draw_progress){ + // draw progress bar + int progress_width = 1000; + int progress_x = fb_w/2-progress_width/2; + int progress_y = 775; + int progress_height = 25; + + NVGpaint paint = nvgBoxGradient( + vg, progress_x + 1, progress_y + 1, + progress_width - 2, progress_height, 3, 4, nvgRGB(27, 27, 27), nvgRGB(27, 27, 27)); + nvgBeginPath(vg); + nvgRoundedRect(vg, progress_x, progress_y, progress_width, progress_height, 12); + nvgFillPaint(vg, paint); + nvgFill(vg); + + int bar_pos = ((progress_width - 2) * progress_val); + + paint = nvgBoxGradient( + vg, progress_x, progress_y, + bar_pos+1.5f, progress_height-1, 3, 4, + nvgRGB(245, 245, 245), nvgRGB(105, 105, 105)); + + nvgBeginPath(vg); + nvgRoundedRect( + vg, progress_x+1, progress_y+1, + bar_pos, progress_height-2, 12); + nvgFillPaint(vg, paint); + nvgFill(vg); + } else { + // message + nvgTextAlign(vg, NVG_ALIGN_CENTER | NVG_ALIGN_TOP); + nvgFontSize(vg, 96.0f); + nvgText(vg, fb_w/2, (fb_h*2/3)+24, spintext, NULL); + } + + nvgEndFrame(vg); + eglSwapBuffers(display, surface); + assert(glGetError() == GL_NO_ERROR); + } + + return 0; +} diff --git a/selfdrive/common/spinner.h b/selfdrive/common/spinner.h new file mode 100644 index 00000000000000..fd35dcc7d48c31 --- /dev/null +++ b/selfdrive/common/spinner.h @@ -0,0 +1,14 @@ +#ifndef COMMON_SPINNER_H +#define COMMON_SPINNER_H + +#ifdef __cplusplus +extern "C" { +#endif + +int spin(int argc, char** argv); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/selfdrive/common/version.h b/selfdrive/common/version.h index 10517c6799b4a5..2c4cfa6a842cf7 100644 --- a/selfdrive/common/version.h +++ b/selfdrive/common/version.h @@ -1 +1 @@ -#define COMMA_VERSION "0.6.4-release" +#define COMMA_VERSION "0.6.5-release" diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index 558c1ba15b9af8..2e7753614ae31d 100755 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -1,7 +1,9 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import os import gc +import json import capnp +import zmq from cereal import car, log from common.numpy_fast import clip from common.realtime import sec_since_boot, set_realtime_priority, Ratekeeper, DT_CTRL @@ -31,6 +33,7 @@ ThermalStatus = log.ThermalData.ThermalStatus State = log.ControlsState.OpenpilotState +HwType = log.HealthData.HwType def isActive(state): @@ -52,12 +55,12 @@ def events_to_bytes(events): return ret -def data_sample(CI, CC, sm, can_sock, cal_status, cal_perc, overtemp, free_space, low_battery, +def data_sample(CI, CC, sm, can_poller, can_sock, cal_status, cal_perc, overtemp, free_space, low_battery, driver_status, state, mismatch_counter, params): """Receive data from sockets and create events for battery, temperature and disk space""" # Update carstate from CAN and create events - can_strs = messaging.drain_sock_raw(can_sock, wait_for_one=True) + can_strs = messaging.drain_sock_raw_poller(can_poller, can_sock, wait_for_one=True) CS = CI.update(CC, can_strs) sm.update(0) @@ -87,7 +90,7 @@ def data_sample(CI, CC, sm, can_sock, cal_status, cal_perc, overtemp, free_space is_rhd = is_rhd_region(sm['gpsLocation'].latitude, sm['gpsLocation'].longitude) driver_status.is_rhd_region = is_rhd driver_status.is_rhd_region_checked = True - put_nonblocking("IsRHD", str(int(is_rhd))) + put_nonblocking("IsRHD", "1" if is_rhd else "0") # Handle calibration if sm.updated['liveCalibration']: @@ -217,7 +220,7 @@ def state_transition(frame, CS, CP, state, events, soft_disable_timer, v_cruise_ def state_control(frame, rcv_frame, plan, path_plan, CS, CP, state, events, v_cruise_kph, v_cruise_kph_last, - AM, rk, driver_status, LaC, LoC, VM, read_only, is_metric, cal_perc): + AM, rk, driver_status, LaC, LoC, read_only, is_metric, cal_perc): """Given the state, this function returns an actuators packet""" actuators = car.CarControl.Actuators.new_message() @@ -264,7 +267,7 @@ def state_control(frame, rcv_frame, plan, path_plan, CS, CP, state, events, v_cr actuators.gas, actuators.brake = LoC.update(active, CS.vEgo, CS.brakePressed, CS.standstill, CS.cruiseState.standstill, v_cruise_kph, v_acc_sol, plan.vTargetFuture, a_acc_sol, CP) # Steering PID loop and lateral MPC - actuators.steer, actuators.steerAngle, lac_log = LaC.update(active, CS.vEgo, CS.steeringAngle, CS.steeringRate, CS.steeringTorqueEps, CS.steeringPressed, CP, VM, path_plan) + actuators.steer, actuators.steerAngle, lac_log = LaC.update(active, CS.vEgo, CS.steeringAngle, CS.steeringRate, CS.steeringTorqueEps, CS.steeringPressed, CP, path_plan) # Send a "steering required alert" if saturation count has reached the limit if LaC.sat_flag and CP.steerLimitAlert: @@ -342,7 +345,7 @@ def data_send(sm, pm, CS, CI, CP, VM, state, events, actuators, v_cruise_kph, rk "alertBlinkingRate": AM.alert_rate, "alertType": AM.alert_type, "alertSound": AM.audible_alert, - "awarenessStatus": max(driver_status.awareness, 0.0) if isEnabled(state) else 0.0, + "awarenessStatus": max(driver_status.awareness, -0.1) if isEnabled(state) else 1.0, "driverMonitoringOn": bool(driver_status.face_detected), "canMonoTimes": list(CS.canMonoTimes), "planMonoTime": sm.logMonoTime['plan'], @@ -424,8 +427,11 @@ def controlsd_thread(sm=None, pm=None, can_sock=None): params = Params() - is_metric = params.get("IsMetric") == "1" - passive = params.get("Passive") != "0" + is_metric = params.get("IsMetric", encoding='utf8') == "1" + passive = params.get("Passive", encoding='utf8') == "1" + openpilot_enabled_toggle = params.get("OpenpilotEnabledToggle", encoding='utf8') == "1" + + passive = passive or not openpilot_enabled_toggle # Pub/Sub Sockets if pm is None: @@ -435,17 +441,20 @@ def controlsd_thread(sm=None, pm=None, can_sock=None): sm = messaging.SubMaster(['thermal', 'health', 'liveCalibration', 'driverMonitoring', 'plan', 'pathPlan', \ 'gpsLocation'], ignore_alive=['gpsLocation']) + can_poller = zmq.Poller() + if can_sock is None: can_timeout = None if os.environ.get('NO_CAN_TIMEOUT', False) else 100 can_sock = messaging.sub_sock(service_list['can'].port, timeout=can_timeout) + can_poller.register(can_sock) # wait for health and CAN packets hw_type = messaging.recv_one(sm.sock['health']).health.hwType - is_panda_black = hw_type == log.HealthData.HwType.blackPanda + has_relay = hw_type in [HwType.blackPanda, HwType.uno] print("Waiting for CAN messages...") get_one_can(can_sock) - CI, CP = get_car(can_sock, pm.sock['sendcan'], is_panda_black) + CI, CP = get_car(can_sock, pm.sock['sendcan'], has_relay) car_recognized = CP.carName != 'mock' # If stock camera is disconnected, we loaded car controls and it's not chffrplus @@ -500,6 +509,10 @@ def controlsd_thread(sm=None, pm=None, can_sock=None): # controlsd is driven by can recv, expected at 100Hz rk = Ratekeeper(100, print_delay_threshold=None) + # FIXME: offroad alerts should not be created with negative severity + connectivity_alert = params.get("Offroad_ConnectivityNeeded", encoding='utf8') + internet_needed = connectivity_alert is not None and json.loads(connectivity_alert.replace("'", "\""))["severity"] >= 0 + prof = Profiler(False) # off by default while True: @@ -508,7 +521,7 @@ def controlsd_thread(sm=None, pm=None, can_sock=None): # Sample data and compute car events CS, events, cal_status, cal_perc, overtemp, free_space, low_battery, mismatch_counter =\ - data_sample(CI, CC, sm, can_sock, cal_status, cal_perc, overtemp, free_space, low_battery, + data_sample(CI, CC, sm, can_poller, can_sock, cal_status, cal_perc, overtemp, free_space, low_battery, driver_status, state, mismatch_counter, params) prof.checkpoint("Sample") @@ -531,6 +544,8 @@ def controlsd_thread(sm=None, pm=None, can_sock=None): events.append(create_event('canError', [ET.NO_ENTRY, ET.IMMEDIATE_DISABLE])) if not sounds_available: events.append(create_event('soundsUnavailable', [ET.NO_ENTRY, ET.PERMANENT])) + if internet_needed: + events.append(create_event('internetConnectivityNeeded', [ET.NO_ENTRY, ET.PERMANENT])) # Only allow engagement with brake pressed when stopped behind another stopped car if CS.brakePressed and sm['plan'].vTargetFuture >= STARTING_TARGET_SPEED and not CP.radarOffCan and CS.vEgo < 0.3: @@ -545,7 +560,7 @@ def controlsd_thread(sm=None, pm=None, can_sock=None): # Compute actuators (runs PID loops and lateral MPC) actuators, v_cruise_kph, driver_status, v_acc, a_acc, lac_log = \ state_control(sm.frame, sm.rcv_frame, sm['plan'], sm['pathPlan'], CS, CP, state, events, v_cruise_kph, v_cruise_kph_last, AM, rk, - driver_status, LaC, LoC, VM, read_only, is_metric, cal_perc) + driver_status, LaC, LoC, read_only, is_metric, cal_perc) prof.checkpoint("State Control") diff --git a/selfdrive/controls/lib/alertmanager.py b/selfdrive/controls/lib/alertmanager.py index 77196273b6e402..b6aa97b6fdc8f6 100644 --- a/selfdrive/controls/lib/alertmanager.py +++ b/selfdrive/controls/lib/alertmanager.py @@ -10,7 +10,7 @@ VisualAlert = car.CarControl.HUDControl.VisualAlert AudibleAlert = car.CarControl.HUDControl.AudibleAlert -class AlertManager(object): +class AlertManager(): def __init__(self): self.activealerts = [] diff --git a/selfdrive/controls/lib/alerts.py b/selfdrive/controls/lib/alerts.py index fbef59fe4d02c9..0b0549899478c6 100644 --- a/selfdrive/controls/lib/alerts.py +++ b/selfdrive/controls/lib/alerts.py @@ -14,7 +14,7 @@ class Priority: AudibleAlert = car.CarControl.HUDControl.AudibleAlert VisualAlert = car.CarControl.HUDControl.VisualAlert -class Alert(object): +class Alert(): def __init__(self, alert_type, alert_text_1, @@ -124,7 +124,7 @@ def __gt__(self, alert2): Alert( "preDriverUnresponsive", - "TOUCH STEERING WHEEL: No Driver Monitoring", + "TOUCH STEERING WHEEL: No Face Detected", "", AlertStatus.normal, AlertSize.small, Priority.LOW, VisualAlert.steerRequired, AudibleAlert.none, .0, .1, .1, alert_rate=0.75), @@ -218,7 +218,7 @@ def __gt__(self, alert2): "TAKE CONTROL", "Steer Unavailable Below ", AlertStatus.userPrompt, AlertSize.mid, - Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarning1, 0., 0., .1), + Priority.MID, VisualAlert.steerRequired, AudibleAlert.none, 0., 0.4, .3), Alert( "debugAlert", @@ -633,11 +633,18 @@ def __gt__(self, alert2): Alert( "commIssueNoEntry", - "openpilot unavailable", + "openpilot Unavailable", "Communication Issue between Processes", AlertStatus.normal, AlertSize.mid, Priority.LOW, VisualAlert.none, AudibleAlert.chimeDisengage, .4, 2., 3.), + Alert( + "internetConnectivityNeededNoEntry", + "openpilot Unavailable", + "Internet Connectivity Needed", + AlertStatus.normal, AlertSize.mid, + Priority.LOW, VisualAlert.none, AudibleAlert.chimeDisengage, .4, 2., 3.), + # permanent alerts Alert( "steerUnavailablePermanent", @@ -674,6 +681,20 @@ def __gt__(self, alert2): AlertStatus.normal, AlertSize.mid, Priority.LOW_LOWEST, VisualAlert.none, AudibleAlert.none, 0., 0., .2), + Alert( + "invalidGiraffeToyotaPermanent", + "Unsupported Giraffe Configuration", + "Visit comma.ai/tg", + AlertStatus.normal, AlertSize.mid, + Priority.LOW_LOWEST, VisualAlert.none, AudibleAlert.none, 0., 0., .2), + + Alert( + "internetConnectivityNeededPermanent", + "Internet Connectivity Needed", + "Check for Updates to Be Able to Engage", + AlertStatus.normal, AlertSize.mid, + Priority.LOW_LOWEST, VisualAlert.none, AudibleAlert.none, 0., 0., .2), + Alert( "sensorDataInvalidPermanent", "No Data from EON Sensors", diff --git a/selfdrive/controls/lib/alerts_offroad.json b/selfdrive/controls/lib/alerts_offroad.json new file mode 100644 index 00000000000000..52a55f23a6684d --- /dev/null +++ b/selfdrive/controls/lib/alerts_offroad.json @@ -0,0 +1,19 @@ +{ + "Offroad_ChargeDisabled": { + "text": "EON charging disabled after car being off for more than 3 days. Turn ignition on to start charging again.", + "severity": 0 + }, + "Offroad_TemperatureTooHigh": { + "text": "EON temperature too high. System won't start.", + "severity": 1 + }, + "Offroad_ConnectivityNeededPrompt": { + "text": "Connect to internet to check for updates. openpilot won't engage in ", + "severity": 0, + "_comment": "Append the number of days at the end of the text" + }, + "Offroad_ConnectivityNeeded": { + "text": "Connect to internet to check for updates. openpilot won't engage.", + "severity": 1 + } +} diff --git a/selfdrive/controls/lib/driver_monitor.py b/selfdrive/controls/lib/driver_monitor.py index f76102ee9fd463..9e94c4fe623ba1 100644 --- a/selfdrive/controls/lib/driver_monitor.py +++ b/selfdrive/controls/lib/driver_monitor.py @@ -13,7 +13,7 @@ _FACE_THRESHOLD = 0.4 _EYE_THRESHOLD = 0.4 -_BLINK_THRESHOLD = 0.2 # 0.225 +_BLINK_THRESHOLD = 0.5 # 0.225 _PITCH_WEIGHT = 1.35 # 1.5 # pitch matters a lot more _METRIC_THRESHOLD = 0.4 _PITCH_POS_ALLOWANCE = 0.04 # 0.08 # rad, to not be too sensitive on positive pitch @@ -29,13 +29,13 @@ _RECOVERY_FACTOR_MAX = 5. # relative to minus step change _RECOVERY_FACTOR_MIN = 1.25 # relative to minus step change -MAX_TERMINAL_ALERTS = 3 # not allowed to engage after 3 terminal alerts +MAX_TERMINAL_ALERTS = 3 # not allowed to engage after 3 terminal alerts # model output refers to center of cropped image, so need to apply the x displacement offset RESIZED_FOCAL = 320.0 H, W, FULL_W = 320, 160, 426 -class DistractedType(object): +class DistractedType(): NOT_DISTRACTED = 0 BAD_POSE = 1 BAD_BLINK = 2 @@ -49,8 +49,8 @@ def head_orientation_from_descriptor(angles_desc, pos_desc, rpy_calib): roll_prnet = angles_desc[2] face_pixel_position = ((pos_desc[0] + .5)*W - W + FULL_W, (pos_desc[1]+.5)*H) - yaw_focal_angle = np.arctan2(face_pixel_position[0] - FULL_W/2, RESIZED_FOCAL) - pitch_focal_angle = np.arctan2(face_pixel_position[1] - H/2, RESIZED_FOCAL) + yaw_focal_angle = np.arctan2(face_pixel_position[0] - FULL_W//2, RESIZED_FOCAL) + pitch_focal_angle = np.arctan2(face_pixel_position[1] - H//2, RESIZED_FOCAL) roll = roll_prnet pitch = pitch_prnet + pitch_focal_angle @@ -82,6 +82,7 @@ def __init__(self): self.blink = DriverBlink() self.awareness = 1. self.awareness_active = 1. + self.awareness_passive = 1. self.driver_distracted = False self.driver_distraction_filter = FirstOrderFilter(0., _DISTRACTED_FILTER_TS, DT_DMON) self.face_detected = False @@ -108,6 +109,7 @@ def _set_timers(self, active_monitoring): if active_monitoring: # when falling back from passive mode to active mode, reset awareness to avoid false alert if not self.active_monitoring_mode: + self.awareness_passive = self.awareness self.awareness = self.awareness_active self.threshold_pre = _DISTRACTED_PRE_TIME_TILL_TERMINAL / _DISTRACTED_TIME @@ -117,6 +119,7 @@ def _set_timers(self, active_monitoring): else: if self.active_monitoring_mode: self.awareness_active = self.awareness + self.awareness = self.awareness_passive self.threshold_pre = _AWARENESS_PRE_TIME_TILL_TERMINAL / _AWARENESS_TIME self.threshold_prompt = _AWARENESS_PROMPT_TIME_TILL_TERMINAL / _AWARENESS_TIME @@ -139,7 +142,7 @@ def _is_driver_distracted(self, pose, blink): if pose_metric > _METRIC_THRESHOLD: return DistractedType.BAD_POSE - elif blink.left_blink>_BLINK_THRESHOLD and blink.right_blink>_BLINK_THRESHOLD: + elif (blink.left_blink + blink.right_blink)*0.5 > _BLINK_THRESHOLD: return DistractedType.BAD_BLINK else: return DistractedType.NOT_DISTRACTED @@ -174,6 +177,7 @@ def update(self, events, driver_engaged, ctrl_active, standstill): # reset only when on disengagement if red reached self.awareness = 1. self.awareness_active = 1. + self.awareness_passive = 1. return events driver_attentive = self.driver_distraction_filter.x < 0.37 @@ -182,6 +186,8 @@ def update(self, events, driver_engaged, ctrl_active, standstill): if (driver_attentive and self.face_detected and self.awareness > 0): # only restore awareness when paying attention and alert is not red self.awareness = min(self.awareness + ((_RECOVERY_FACTOR_MAX-_RECOVERY_FACTOR_MIN)*(1.-self.awareness)+_RECOVERY_FACTOR_MIN)*self.step_change, 1.) + if self.awareness == 1.: + self.awareness_passive = min(self.awareness_passive + self.step_change, 1.) # don't display alert banner when awareness is recovering and has cleared orange if self.awareness > self.threshold_prompt: return events diff --git a/selfdrive/controls/lib/fcw.py b/selfdrive/controls/lib/fcw.py index c080fecb4a5b2f..93570a41dbf821 100644 --- a/selfdrive/controls/lib/fcw.py +++ b/selfdrive/controls/lib/fcw.py @@ -7,7 +7,7 @@ _FCW_A_ACT_BP = [0., 30.] -class FCWChecker(object): +class FCWChecker(): def __init__(self): self.reset_lead(0.0) diff --git a/selfdrive/controls/lib/lane_planner.py b/selfdrive/controls/lib/lane_planner.py index 9363631e45b8b2..06c298e98e4639 100644 --- a/selfdrive/controls/lib/lane_planner.py +++ b/selfdrive/controls/lib/lane_planner.py @@ -32,7 +32,7 @@ def calc_d_poly(l_poly, r_poly, p_poly, l_prob, r_prob, lane_width): return lr_prob * d_poly_lane + (1.0 - lr_prob) * p_poly -class LanePlanner(object): +class LanePlanner(): def __init__(self): self.l_poly = [0., 0., 0., 0.] self.r_poly = [0., 0., 0., 0.] diff --git a/selfdrive/controls/lib/latcontrol_indi.py b/selfdrive/controls/lib/latcontrol_indi.py index 38ba8883b9f64d..82bd6e6d79540c 100644 --- a/selfdrive/controls/lib/latcontrol_indi.py +++ b/selfdrive/controls/lib/latcontrol_indi.py @@ -9,7 +9,7 @@ from selfdrive.controls.lib.drive_helpers import get_steer_max -class LatControlINDI(object): +class LatControlINDI(): def __init__(self, CP): self.angle_steers_des = 0. @@ -47,7 +47,7 @@ def reset(self): self.output_steer = 0. self.counter = 0 - def update(self, active, v_ego, angle_steers, angle_steers_rate, eps_torque, steer_override, CP, VM, path_plan): + def update(self, active, v_ego, angle_steers, angle_steers_rate, eps_torque, steer_override, CP, path_plan): # Update Kalman filter y = np.matrix([[math.radians(angle_steers)], [math.radians(angle_steers_rate)]]) self.x = np.dot(self.A_K, self.x) + np.dot(self.K, y) diff --git a/selfdrive/controls/lib/latcontrol_lqr.py b/selfdrive/controls/lib/latcontrol_lqr.py index 23d91cae43d43f..1badf2d26822e8 100644 --- a/selfdrive/controls/lib/latcontrol_lqr.py +++ b/selfdrive/controls/lib/latcontrol_lqr.py @@ -4,7 +4,7 @@ from cereal import log -class LatControlLQR(object): +class LatControlLQR(): def __init__(self, CP, rate=100): self.sat_flag = False self.scale = CP.lateralTuning.lqr.scale @@ -29,7 +29,7 @@ def reset(self): self.i_lqr = 0.0 self.output_steer = 0.0 - def update(self, active, v_ego, angle_steers, angle_steers_rate, eps_torque, steer_override, CP, VM, path_plan): + def update(self, active, v_ego, angle_steers, angle_steers_rate, eps_torque, steer_override, CP, path_plan): lqr_log = log.ControlsState.LateralLQRState.new_message() steers_max = get_steer_max(CP, v_ego) diff --git a/selfdrive/controls/lib/latcontrol_pid.py b/selfdrive/controls/lib/latcontrol_pid.py index 5fe456d8817f0f..461203dec5950d 100644 --- a/selfdrive/controls/lib/latcontrol_pid.py +++ b/selfdrive/controls/lib/latcontrol_pid.py @@ -4,7 +4,7 @@ from cereal import log -class LatControlPID(object): +class LatControlPID(): def __init__(self, CP): self.pid = PIController((CP.lateralTuning.pid.kpBP, CP.lateralTuning.pid.kpV), (CP.lateralTuning.pid.kiBP, CP.lateralTuning.pid.kiV), @@ -14,7 +14,7 @@ def __init__(self, CP): def reset(self): self.pid.reset() - def update(self, active, v_ego, angle_steers, angle_steers_rate, eps_torque, steer_override, CP, VM, path_plan): + def update(self, active, v_ego, angle_steers, angle_steers_rate, eps_torque, steer_override, CP, path_plan): pid_log = log.ControlsState.LateralPIDState.new_message() pid_log.steerAngle = float(angle_steers) pid_log.steerRate = float(angle_steers_rate) diff --git a/selfdrive/controls/lib/lateral_mpc/lateral_mpc.d b/selfdrive/controls/lib/lateral_mpc/lateral_mpc.d new file mode 100644 index 00000000000000..6cac7c2e148128 --- /dev/null +++ b/selfdrive/controls/lib/lateral_mpc/lateral_mpc.d @@ -0,0 +1,3 @@ +lateral_mpc.o: lateral_mpc.c lib_mpc_export/acado_common.h \ + lib_mpc_export/acado_qpoases_interface.hpp \ + lib_mpc_export/acado_auxiliary_functions.h diff --git a/selfdrive/controls/lib/lateral_mpc/lateral_mpc.o b/selfdrive/controls/lib/lateral_mpc/lateral_mpc.o new file mode 100644 index 00000000000000..e6990f56968567 Binary files /dev/null and b/selfdrive/controls/lib/lateral_mpc/lateral_mpc.o differ diff --git a/selfdrive/controls/lib/lateral_mpc/lib_mpc_export/acado_auxiliary_functions.d b/selfdrive/controls/lib/lateral_mpc/lib_mpc_export/acado_auxiliary_functions.d new file mode 100644 index 00000000000000..50c6a60d1fb846 --- /dev/null +++ b/selfdrive/controls/lib/lateral_mpc/lib_mpc_export/acado_auxiliary_functions.d @@ -0,0 +1,5 @@ +lib_mpc_export/acado_auxiliary_functions.o: \ + lib_mpc_export/acado_auxiliary_functions.c \ + lib_mpc_export/acado_auxiliary_functions.h \ + lib_mpc_export/acado_common.h \ + lib_mpc_export/acado_qpoases_interface.hpp diff --git a/selfdrive/controls/lib/lateral_mpc/lib_mpc_export/acado_auxiliary_functions.o b/selfdrive/controls/lib/lateral_mpc/lib_mpc_export/acado_auxiliary_functions.o new file mode 100644 index 00000000000000..5c17c326853b59 Binary files /dev/null and b/selfdrive/controls/lib/lateral_mpc/lib_mpc_export/acado_auxiliary_functions.o differ diff --git a/selfdrive/controls/lib/lateral_mpc/lib_mpc_export/acado_integrator.d b/selfdrive/controls/lib/lateral_mpc/lib_mpc_export/acado_integrator.d new file mode 100644 index 00000000000000..7c057e5ec0f3a9 --- /dev/null +++ b/selfdrive/controls/lib/lateral_mpc/lib_mpc_export/acado_integrator.d @@ -0,0 +1,3 @@ +lib_mpc_export/acado_integrator.o: lib_mpc_export/acado_integrator.c \ + lib_mpc_export/acado_common.h \ + lib_mpc_export/acado_qpoases_interface.hpp diff --git a/selfdrive/controls/lib/lateral_mpc/lib_mpc_export/acado_integrator.o b/selfdrive/controls/lib/lateral_mpc/lib_mpc_export/acado_integrator.o new file mode 100644 index 00000000000000..e09d5c89864869 Binary files /dev/null and b/selfdrive/controls/lib/lateral_mpc/lib_mpc_export/acado_integrator.o differ diff --git a/selfdrive/controls/lib/lateral_mpc/lib_mpc_export/acado_qpoases_interface.d b/selfdrive/controls/lib/lateral_mpc/lib_mpc_export/acado_qpoases_interface.d new file mode 100644 index 00000000000000..ba3c6ef1c831b7 --- /dev/null +++ b/selfdrive/controls/lib/lateral_mpc/lib_mpc_export/acado_qpoases_interface.d @@ -0,0 +1,24 @@ +lib_mpc_export/acado_qpoases_interface.o: \ + lib_mpc_export/acado_qpoases_interface.cpp \ + lib_mpc_export/acado_common.h \ + lib_mpc_export/acado_qpoases_interface.hpp \ + ../../../../phonelibs/qpoases/INCLUDE/QProblem.hpp \ + ../../../../phonelibs/qpoases/INCLUDE/QProblemB.hpp \ + ../../../../phonelibs/qpoases/INCLUDE/Bounds.hpp \ + ../../../../phonelibs/qpoases/INCLUDE/SubjectTo.hpp \ + ../../../../phonelibs/qpoases/INCLUDE/Indexlist.hpp \ + ../../../../phonelibs/qpoases/INCLUDE/Utils.hpp \ + ../../../../phonelibs/qpoases/INCLUDE/MessageHandling.hpp \ + ../../../../phonelibs/qpoases/INCLUDE/Types.hpp \ + ../../../../phonelibs/qpoases/INCLUDE/Constants.hpp \ + ../../../../phonelibs/qpoases/SRC/MessageHandling.ipp \ + ../../../../phonelibs/qpoases/SRC/Utils.ipp \ + ../../../../phonelibs/qpoases/SRC/Indexlist.ipp \ + ../../../../phonelibs/qpoases/SRC/SubjectTo.ipp \ + ../../../../phonelibs/qpoases/SRC/Bounds.ipp \ + ../../../../phonelibs/qpoases/SRC/QProblemB.ipp \ + ../../../../phonelibs/qpoases/INCLUDE/Constraints.hpp \ + ../../../../phonelibs/qpoases/SRC/Constraints.ipp \ + ../../../../phonelibs/qpoases/INCLUDE/CyclingManager.hpp \ + ../../../../phonelibs/qpoases/SRC/CyclingManager.ipp \ + ../../../../phonelibs/qpoases/SRC/QProblem.ipp diff --git a/selfdrive/controls/lib/lateral_mpc/lib_mpc_export/acado_qpoases_interface.o b/selfdrive/controls/lib/lateral_mpc/lib_mpc_export/acado_qpoases_interface.o new file mode 100644 index 00000000000000..e755f67a5e0d27 Binary files /dev/null and b/selfdrive/controls/lib/lateral_mpc/lib_mpc_export/acado_qpoases_interface.o differ diff --git a/selfdrive/controls/lib/lateral_mpc/lib_mpc_export/acado_solver.d b/selfdrive/controls/lib/lateral_mpc/lib_mpc_export/acado_solver.d new file mode 100644 index 00000000000000..2dae4b94389e48 --- /dev/null +++ b/selfdrive/controls/lib/lateral_mpc/lib_mpc_export/acado_solver.d @@ -0,0 +1,3 @@ +lib_mpc_export/acado_solver.o: lib_mpc_export/acado_solver.c \ + lib_mpc_export/acado_common.h \ + lib_mpc_export/acado_qpoases_interface.hpp diff --git a/selfdrive/controls/lib/lateral_mpc/lib_mpc_export/acado_solver.o b/selfdrive/controls/lib/lateral_mpc/lib_mpc_export/acado_solver.o new file mode 100644 index 00000000000000..5814de21e521ec Binary files /dev/null and b/selfdrive/controls/lib/lateral_mpc/lib_mpc_export/acado_solver.o differ diff --git a/selfdrive/controls/lib/lateral_mpc/libmpc.so b/selfdrive/controls/lib/lateral_mpc/libmpc.so new file mode 100755 index 00000000000000..fd6ee2d482a435 Binary files /dev/null and b/selfdrive/controls/lib/lateral_mpc/libmpc.so differ diff --git a/selfdrive/controls/lib/long_mpc.py b/selfdrive/controls/lib/long_mpc.py index cb1ab94dc69682..4c71683096e3aa 100644 --- a/selfdrive/controls/lib/long_mpc.py +++ b/selfdrive/controls/lib/long_mpc.py @@ -1,5 +1,5 @@ import os -import numpy as np +import math import selfdrive.messaging as messaging from selfdrive.swaglog import cloudlog @@ -11,7 +11,7 @@ LOG_MPC = os.environ.get('LOG_MPC', False) -class LongitudinalMpc(object): +class LongitudinalMpc(): def __init__(self, mpc_id): self.mpc_id = mpc_id @@ -104,10 +104,9 @@ def update(self, pm, CS, lead, v_cruise_setpoint): self.v_mpc_future = self.mpc_solution[0].v_ego[10] # Reset if NaN or goes through lead car - dls = np.array(list(self.mpc_solution[0].x_l)) - np.array(list(self.mpc_solution[0].x_ego)) - crashing = min(dls) < -50.0 - nans = np.any(np.isnan(list(self.mpc_solution[0].v_ego))) - backwards = min(list(self.mpc_solution[0].v_ego)) < -0.01 + crashing = any(lead - ego < -50 for (lead, ego) in zip(self.mpc_solution[0].x_l, self.mpc_solution[0].x_ego)) + nans = any(math.isnan(x) for x in self.mpc_solution[0].v_ego) + backwards = min(self.mpc_solution[0].v_ego) < -0.01 if ((backwards or crashing) and self.prev_lead_status) or nans: if t > self.last_cloudlog_t + 5.0: diff --git a/selfdrive/controls/lib/longcontrol.py b/selfdrive/controls/lib/longcontrol.py index 84c17ef374380f..8910747cdbaaf1 100644 --- a/selfdrive/controls/lib/longcontrol.py +++ b/selfdrive/controls/lib/longcontrol.py @@ -55,7 +55,7 @@ def long_control_state_trans(active, long_control_state, v_ego, v_target, v_pid, return long_control_state -class LongControl(object): +class LongControl(): def __init__(self, CP, compute_gb): self.long_control_state = LongCtrlState.off # initialized to off self.pid = PIController((CP.longitudinalTuning.kpBP, CP.longitudinalTuning.kpV), diff --git a/selfdrive/controls/lib/longitudinal_mpc/lib_mpc_export/acado_auxiliary_functions.d b/selfdrive/controls/lib/longitudinal_mpc/lib_mpc_export/acado_auxiliary_functions.d new file mode 100644 index 00000000000000..50c6a60d1fb846 --- /dev/null +++ b/selfdrive/controls/lib/longitudinal_mpc/lib_mpc_export/acado_auxiliary_functions.d @@ -0,0 +1,5 @@ +lib_mpc_export/acado_auxiliary_functions.o: \ + lib_mpc_export/acado_auxiliary_functions.c \ + lib_mpc_export/acado_auxiliary_functions.h \ + lib_mpc_export/acado_common.h \ + lib_mpc_export/acado_qpoases_interface.hpp diff --git a/selfdrive/controls/lib/longitudinal_mpc/lib_mpc_export/acado_auxiliary_functions.o b/selfdrive/controls/lib/longitudinal_mpc/lib_mpc_export/acado_auxiliary_functions.o new file mode 100644 index 00000000000000..ac07de5818586f Binary files /dev/null and b/selfdrive/controls/lib/longitudinal_mpc/lib_mpc_export/acado_auxiliary_functions.o differ diff --git a/selfdrive/controls/lib/longitudinal_mpc/lib_mpc_export/acado_integrator.d b/selfdrive/controls/lib/longitudinal_mpc/lib_mpc_export/acado_integrator.d new file mode 100644 index 00000000000000..7c057e5ec0f3a9 --- /dev/null +++ b/selfdrive/controls/lib/longitudinal_mpc/lib_mpc_export/acado_integrator.d @@ -0,0 +1,3 @@ +lib_mpc_export/acado_integrator.o: lib_mpc_export/acado_integrator.c \ + lib_mpc_export/acado_common.h \ + lib_mpc_export/acado_qpoases_interface.hpp diff --git a/selfdrive/controls/lib/longitudinal_mpc/lib_mpc_export/acado_integrator.o b/selfdrive/controls/lib/longitudinal_mpc/lib_mpc_export/acado_integrator.o new file mode 100644 index 00000000000000..f936c84557c3fe Binary files /dev/null and b/selfdrive/controls/lib/longitudinal_mpc/lib_mpc_export/acado_integrator.o differ diff --git a/selfdrive/controls/lib/longitudinal_mpc/lib_mpc_export/acado_qpoases_interface.d b/selfdrive/controls/lib/longitudinal_mpc/lib_mpc_export/acado_qpoases_interface.d new file mode 100644 index 00000000000000..ba3c6ef1c831b7 --- /dev/null +++ b/selfdrive/controls/lib/longitudinal_mpc/lib_mpc_export/acado_qpoases_interface.d @@ -0,0 +1,24 @@ +lib_mpc_export/acado_qpoases_interface.o: \ + lib_mpc_export/acado_qpoases_interface.cpp \ + lib_mpc_export/acado_common.h \ + lib_mpc_export/acado_qpoases_interface.hpp \ + ../../../../phonelibs/qpoases/INCLUDE/QProblem.hpp \ + ../../../../phonelibs/qpoases/INCLUDE/QProblemB.hpp \ + ../../../../phonelibs/qpoases/INCLUDE/Bounds.hpp \ + ../../../../phonelibs/qpoases/INCLUDE/SubjectTo.hpp \ + ../../../../phonelibs/qpoases/INCLUDE/Indexlist.hpp \ + ../../../../phonelibs/qpoases/INCLUDE/Utils.hpp \ + ../../../../phonelibs/qpoases/INCLUDE/MessageHandling.hpp \ + ../../../../phonelibs/qpoases/INCLUDE/Types.hpp \ + ../../../../phonelibs/qpoases/INCLUDE/Constants.hpp \ + ../../../../phonelibs/qpoases/SRC/MessageHandling.ipp \ + ../../../../phonelibs/qpoases/SRC/Utils.ipp \ + ../../../../phonelibs/qpoases/SRC/Indexlist.ipp \ + ../../../../phonelibs/qpoases/SRC/SubjectTo.ipp \ + ../../../../phonelibs/qpoases/SRC/Bounds.ipp \ + ../../../../phonelibs/qpoases/SRC/QProblemB.ipp \ + ../../../../phonelibs/qpoases/INCLUDE/Constraints.hpp \ + ../../../../phonelibs/qpoases/SRC/Constraints.ipp \ + ../../../../phonelibs/qpoases/INCLUDE/CyclingManager.hpp \ + ../../../../phonelibs/qpoases/SRC/CyclingManager.ipp \ + ../../../../phonelibs/qpoases/SRC/QProblem.ipp diff --git a/selfdrive/controls/lib/longitudinal_mpc/lib_mpc_export/acado_qpoases_interface.o b/selfdrive/controls/lib/longitudinal_mpc/lib_mpc_export/acado_qpoases_interface.o new file mode 100644 index 00000000000000..946f501e778d6b Binary files /dev/null and b/selfdrive/controls/lib/longitudinal_mpc/lib_mpc_export/acado_qpoases_interface.o differ diff --git a/selfdrive/controls/lib/longitudinal_mpc/lib_mpc_export/acado_solver.d b/selfdrive/controls/lib/longitudinal_mpc/lib_mpc_export/acado_solver.d new file mode 100644 index 00000000000000..2dae4b94389e48 --- /dev/null +++ b/selfdrive/controls/lib/longitudinal_mpc/lib_mpc_export/acado_solver.d @@ -0,0 +1,3 @@ +lib_mpc_export/acado_solver.o: lib_mpc_export/acado_solver.c \ + lib_mpc_export/acado_common.h \ + lib_mpc_export/acado_qpoases_interface.hpp diff --git a/selfdrive/controls/lib/longitudinal_mpc/lib_mpc_export/acado_solver.o b/selfdrive/controls/lib/longitudinal_mpc/lib_mpc_export/acado_solver.o new file mode 100644 index 00000000000000..865c7d826ab398 Binary files /dev/null and b/selfdrive/controls/lib/longitudinal_mpc/lib_mpc_export/acado_solver.o differ diff --git a/selfdrive/controls/lib/longitudinal_mpc/libmpc1.so b/selfdrive/controls/lib/longitudinal_mpc/libmpc1.so new file mode 100755 index 00000000000000..4cf3782aff93d0 Binary files /dev/null and b/selfdrive/controls/lib/longitudinal_mpc/libmpc1.so differ diff --git a/selfdrive/controls/lib/longitudinal_mpc/longitudinal_mpc.d b/selfdrive/controls/lib/longitudinal_mpc/longitudinal_mpc.d new file mode 100644 index 00000000000000..34a2a0d20ce304 --- /dev/null +++ b/selfdrive/controls/lib/longitudinal_mpc/longitudinal_mpc.d @@ -0,0 +1,3 @@ +longitudinal_mpc.o: longitudinal_mpc.c lib_mpc_export/acado_common.h \ + lib_mpc_export/acado_qpoases_interface.hpp \ + lib_mpc_export/acado_auxiliary_functions.h diff --git a/selfdrive/controls/lib/longitudinal_mpc/longitudinal_mpc.o b/selfdrive/controls/lib/longitudinal_mpc/longitudinal_mpc.o new file mode 100644 index 00000000000000..6000b25f56a480 Binary files /dev/null and b/selfdrive/controls/lib/longitudinal_mpc/longitudinal_mpc.o differ diff --git a/selfdrive/controls/lib/pathplanner.py b/selfdrive/controls/lib/pathplanner.py index b62d9f1107973a..5678cf05f9cfa2 100644 --- a/selfdrive/controls/lib/pathplanner.py +++ b/selfdrive/controls/lib/pathplanner.py @@ -1,8 +1,5 @@ import os import math -import numpy as np - -# from common.numpy_fast import clip from common.realtime import sec_since_boot from selfdrive.swaglog import cloudlog from selfdrive.controls.lib.lateral_mpc import libmpc_py @@ -19,7 +16,7 @@ def calc_states_after_delay(states, v_ego, steer_angle, curvature_factor, steer_ return states -class PathPlanner(object): +class PathPlanner(): def __init__(self, CP): self.LP = LanePlanner() @@ -88,7 +85,7 @@ def update(self, sm, pm, CP, VM): self.angle_steers_des_mpc = float(math.degrees(delta_desired * VM.sR) + angle_offset) # Check for infeasable MPC solution - mpc_nans = np.any(np.isnan(list(self.mpc_solution[0].delta))) + mpc_nans = any(math.isnan(x) for x in self.mpc_solution[0].delta) t = sec_since_boot() if mpc_nans: self.libmpc.init(MPC_COST_LAT.PATH, MPC_COST_LAT.LANE, MPC_COST_LAT.HEADING, CP.steerRateCost) diff --git a/selfdrive/controls/lib/pid.py b/selfdrive/controls/lib/pid.py index b68dc3810eef4b..ce2d34b35937f8 100644 --- a/selfdrive/controls/lib/pid.py +++ b/selfdrive/controls/lib/pid.py @@ -10,7 +10,7 @@ def apply_deadzone(error, deadzone): error = 0. return error -class PIController(object): +class PIController(): def __init__(self, k_p, k_i, k_f=1., pos_limit=None, neg_limit=None, rate=100, sat_limit=0.8, convert=None): self._k_p = k_p # proportional gain self._k_i = k_i # integral gain diff --git a/selfdrive/controls/lib/planner.py b/selfdrive/controls/lib/planner.py index 26230843a846c7..db3fe33217d6c0 100755 --- a/selfdrive/controls/lib/planner.py +++ b/selfdrive/controls/lib/planner.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import math import numpy as np from common.params import Params @@ -27,13 +27,12 @@ # need fast accel at very low speed for stop and go # make sure these accelerations are smaller than mpc limits -_A_CRUISE_MAX_V = [1.1, 1.1, .8, .5, .3] -_A_CRUISE_MAX_V_FOLLOWING = [1.6, 1.6, 1.2, .7, .3] -_A_CRUISE_MAX_BP = [0., 5., 10., 20., 40.] +_A_CRUISE_MAX_V = [1.6, 1.6, 0.65, .4] +_A_CRUISE_MAX_BP = [0., 6.4, 22.5, 40.] # Lookup table for turns -_A_TOTAL_MAX_V = [1.5, 1.9, 3.2] -_A_TOTAL_MAX_BP = [0., 20., 40.] +_A_TOTAL_MAX_V = [1.7, 3.2] +_A_TOTAL_MAX_BP = [20., 40.] # Model speed kalman stuff @@ -46,13 +45,9 @@ SPEED_PERCENTILE_IDX = 7 -def calc_cruise_accel_limits(v_ego, following): +def calc_cruise_accel_limits(v_ego): a_cruise_min = interp(v_ego, _A_CRUISE_MIN_BP, _A_CRUISE_MIN_V) - - if following: - a_cruise_max = interp(v_ego, _A_CRUISE_MAX_BP, _A_CRUISE_MAX_V_FOLLOWING) - else: - a_cruise_max = interp(v_ego, _A_CRUISE_MAX_BP, _A_CRUISE_MAX_V) + a_cruise_max = interp(v_ego, _A_CRUISE_MAX_BP, _A_CRUISE_MAX_V) return np.vstack([a_cruise_min, a_cruise_max]) @@ -69,7 +64,7 @@ def limit_accel_in_turns(v_ego, angle_steers, a_target, CP): return [a_target[0], min(a_target[1], a_x_allowed)] -class Planner(object): +class Planner(): def __init__(self, CP): self.CP = CP @@ -95,7 +90,7 @@ def __init__(self, CP): def choose_solution(self, v_cruise_setpoint, enabled): if enabled: - solutions = {'cruise': self.v_cruise, 'model': self.v_model} + solutions = {'model': self.v_model, 'cruise': self.v_cruise} if self.mpc1.prev_lead_status: solutions['mpc1'] = self.mpc1.v_mpc if self.mpc2.prev_lead_status: @@ -134,7 +129,6 @@ def update(self, sm, pm, CP, VM, PP): lead_2 = sm['radarState'].leadTwo enabled = (long_control_state == LongCtrlState.pid) or (long_control_state == LongCtrlState.stopping) - following = lead_1.status and lead_1.dRel < 45.0 and lead_1.vLeadK > v_ego and lead_1.aLeadK > 0.0 if len(sm['model'].path.poly): path = list(sm['model'].path.poly) @@ -142,6 +136,7 @@ def update(self, sm, pm, CP, VM, PP): # Curvature of polynomial https://en.wikipedia.org/wiki/Curvature#Curvature_of_the_graph_of_a_function # y = a x^3 + b x^2 + c x + d, y' = 3 a x^2 + 2 b x + c, y'' = 6 a x + 2 b # k = y'' / (1 + y'^2)^1.5 + # TODO: compute max speed without using a list of points and without numpy y_p = 3 * path[0] * self.path_x**2 + 2 * path[1] * self.path_x + path[2] y_pp = 6 * path[0] * self.path_x + 2 * path[1] curv = y_pp / (1. + y_p**2)**1.5 @@ -149,14 +144,13 @@ def update(self, sm, pm, CP, VM, PP): a_y_max = 2.975 - v_ego * 0.0375 # ~1.85 @ 75mph, ~2.6 @ 25mph v_curvature = np.sqrt(a_y_max / np.clip(np.abs(curv), 1e-4, None)) model_speed = np.min(v_curvature) - # print(model_speed * CV.MS_TO_MPH, model_speed) model_speed = max(20.0 * CV.MPH_TO_MS, model_speed) # Don't slow down below 20mph else: model_speed = MAX_SPEED # Calculate speed for normal cruise control if enabled: - accel_limits = [float(x) for x in calc_cruise_accel_limits(v_ego, following)] + accel_limits = [float(x) for x in calc_cruise_accel_limits(v_ego)] jerk_limits = [min(-0.1, accel_limits[0]), max(0.1, accel_limits[1])] # TODO: make a separate lookup for jerk tuning accel_limits_turns = limit_accel_in_turns(v_ego, sm['carState'].steeringAngle, accel_limits, self.CP) diff --git a/selfdrive/controls/lib/radar_helpers.py b/selfdrive/controls/lib/radar_helpers.py index d246d5d8caf08c..557679e5dcacb1 100644 --- a/selfdrive/controls/lib/radar_helpers.py +++ b/selfdrive/controls/lib/radar_helpers.py @@ -22,7 +22,7 @@ _VLEAD_K = [[0.1988689], [0.28555364]] -class Track(object): +class Track(): def __init__(self): self.ekf = None self.cnt = 0 @@ -67,7 +67,7 @@ def mean(l): return sum(l) / len(l) -class Cluster(object): +class Cluster(): def __init__(self): self.tracks = set() diff --git a/selfdrive/controls/lib/vehicle_model.py b/selfdrive/controls/lib/vehicle_model.py index 1dc77bf375afb6..1559a893e8cedd 100755 --- a/selfdrive/controls/lib/vehicle_model.py +++ b/selfdrive/controls/lib/vehicle_model.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import numpy as np from numpy.linalg import solve @@ -90,7 +90,7 @@ def calc_slip_factor(VM): return VM.m * (VM.cF * VM.aF - VM.cR * VM.aR) / (VM.l**2 * VM.cF * VM.cR) -class VehicleModel(object): +class VehicleModel(): def __init__(self, CP): """ Args: @@ -140,7 +140,7 @@ def calc_curvature(self, sa, u): u: Speed [m/s] Returns: - Curvature factor [rad/m] + Curvature factor [1/m] """ return self.curvature_factor(u) * sa / self.sR @@ -161,7 +161,7 @@ def get_steer_from_curvature(self, curv, u): """Calculates the required steering wheel angle for a given curvature Args: - curv: Desired curvature [rad/s] + curv: Desired curvature [1/m] u: Speed [m/s] Returns: @@ -170,6 +170,19 @@ def get_steer_from_curvature(self, curv, u): return curv * self.sR * 1.0 / self.curvature_factor(u) + def get_steer_from_yaw_rate(self, yaw_rate, u): + """Calculates the required steering wheel angle for a given yaw_rate + + Args: + yaw_rate: Desired yaw rate [rad/s] + u: Speed [m/s] + + Returns: + Steering wheel angle [rad] + """ + curv = yaw_rate / u + return self.get_steer_from_curvature(curv, u) + def yaw_rate(self, sa, u): """Calculate yaw rate @@ -188,6 +201,6 @@ def yaw_rate(self, sa, u): from selfdrive.car.honda.interface import CarInterface from selfdrive.car.honda.values import CAR - CP = CarInterface.get_params(CAR.CIVIC, {}) + CP = CarInterface.get_params(CAR.CIVIC) VM = VehicleModel(CP) print(VM.yaw_rate(math.radians(20), 10.)) diff --git a/selfdrive/controls/plannerd.py b/selfdrive/controls/plannerd.py index 7a5742b3e540f9..59fe51aaca284d 100755 --- a/selfdrive/controls/plannerd.py +++ b/selfdrive/controls/plannerd.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import gc from cereal import car diff --git a/selfdrive/controls/radard.py b/selfdrive/controls/radard.py index d51631633297f0..2a36d9a0ab1845 100755 --- a/selfdrive/controls/radard.py +++ b/selfdrive/controls/radard.py @@ -1,18 +1,20 @@ -#!/usr/bin/env python -import numpy as np -import numpy.matlib +#!/usr/bin/env python3 import importlib +import math from collections import defaultdict, deque +import zmq + import selfdrive.messaging as messaging -from selfdrive.services import service_list -from selfdrive.controls.lib.radar_helpers import Track, Cluster -from selfdrive.config import RADAR_TO_CENTER -from selfdrive.controls.lib.cluster.fastcluster_py import cluster_points_centroid -from selfdrive.swaglog import cloudlog from cereal import car from common.params import Params -from common.realtime import set_realtime_priority, Ratekeeper, DT_MDL +from common.realtime import DT_RDR, Ratekeeper, set_realtime_priority +from selfdrive.config import RADAR_TO_CAMERA +from selfdrive.controls.lib.cluster.fastcluster_py import \ + cluster_points_centroid +from selfdrive.controls.lib.radar_helpers import Cluster, Track +from selfdrive.services import service_list +from selfdrive.swaglog import cloudlog DEBUG = False @@ -22,33 +24,34 @@ VISION_POINT = -1 # Time-alignment -rate = 1. / DT_MDL # model and radar are both at 20Hz v_len = 20 # how many speed data points to remember for t alignment with rdr data def laplacian_cdf(x, mu, b): - b = np.max([b, 1e-4]) - return np.exp(-abs(x-mu)/b) + b = max(b, 1e-4) + return math.exp(-abs(x-mu)/b) def match_vision_to_cluster(v_ego, lead, clusters): # match vision point to best statistical cluster match - probs = [] - offset_vision_dist = lead.dist - RADAR_TO_CENTER - for c in clusters: + offset_vision_dist = lead.dist - RADAR_TO_CAMERA + + def prob(c): prob_d = laplacian_cdf(c.dRel, offset_vision_dist, lead.std) prob_y = laplacian_cdf(c.yRel, lead.relY, lead.relYStd) prob_v = laplacian_cdf(c.vRel, lead.relVel, lead.relVelStd) + # This is isn't exactly right, but good heuristic - combined_prob = prob_d * prob_y * prob_v - probs.append(combined_prob) - idx = np.argmax(probs) + return prob_d * prob_y * prob_v + + cluster = max(clusters, key=prob) + # if no 'sane' match is found return -1 # stationary radar points can be false positives - dist_sane = abs(clusters[idx].dRel - offset_vision_dist) < max([(offset_vision_dist)*.25, 5.0]) - vel_sane = (abs(clusters[idx].vRel - lead.relVel) < 10) or (v_ego + clusters[idx].vRel > 2) + dist_sane = abs(cluster.dRel - offset_vision_dist) < max([(offset_vision_dist)*.25, 5.0]) + vel_sane = (abs(cluster.vRel - lead.relVel) < 10) or (v_ego + cluster.vRel > 2) if dist_sane and vel_sane: - return idx + return cluster else: return None @@ -56,28 +59,30 @@ def match_vision_to_cluster(v_ego, lead, clusters): def get_lead(v_ego, ready, clusters, lead_msg, low_speed_override=True): # Determine leads, this is where the essential logic happens if len(clusters) > 0 and ready and lead_msg.prob > .5: - lead_idx = match_vision_to_cluster(v_ego, lead_msg, clusters) + cluster = match_vision_to_cluster(v_ego, lead_msg, clusters) else: - lead_idx = None + cluster = None lead_dict = {'status': False} - if lead_idx is not None: - lead_dict = clusters[lead_idx].get_RadarState(lead_msg.prob) - elif (lead_idx is None) and ready and (lead_msg.prob > .5): + if cluster is not None: + lead_dict = cluster.get_RadarState(lead_msg.prob) + elif (cluster is None) and ready and (lead_msg.prob > .5): lead_dict = Cluster().get_RadarState_from_vision(lead_msg, v_ego) if low_speed_override: low_speed_clusters = [c for c in clusters if c.potential_low_speed_lead(v_ego)] if len(low_speed_clusters) > 0: - lead_idx = np.argmin([c.dRel for c in low_speed_clusters]) - if (not lead_dict['status']) or (low_speed_clusters[lead_idx].dRel < lead_dict['dRel']): - lead_dict = low_speed_clusters[lead_idx].get_RadarState() + closest_cluster = min(low_speed_clusters, key=lambda c: c.dRel) + + # Only choose new cluster if it is actually closer than the previous one + if (not lead_dict['status']) or (closest_cluster.dRel < lead_dict['dRel']): + lead_dict = closest_cluster.get_RadarState() return lead_dict -class RadarD(object): - def __init__(self, mocked): +class RadarD(): + def __init__(self, mocked, delay=0): self.current_time = 0 self.mocked = mocked @@ -90,19 +95,18 @@ def __init__(self, mocked): # v_ego self.v_ego = 0. - self.v_ego_hist_t = deque([0], maxlen=v_len) - self.v_ego_hist_v = deque([0], maxlen=v_len) + self.v_ego_hist = deque([0], maxlen=delay+1) + self.v_ego_t_aligned = 0. self.ready = False - def update(self, frame, delay, sm, rr, has_radar): + def update(self, frame, sm, rr, has_radar): self.current_time = 1e-9*max([sm.logMonoTime[key] for key in sm.logMonoTime.keys()]) if sm.updated['controlsState']: self.active = sm['controlsState'].active self.v_ego = sm['controlsState'].vEgo - self.v_ego_hist_v.append(self.v_ego) - self.v_ego_hist_t.append(float(frame)/rate) + self.v_ego_hist.append(self.v_ego) if sm.updated['model']: self.ready = True @@ -111,7 +115,7 @@ def update(self, frame, delay, sm, rr, has_radar): ar_pts[pt.trackId] = [pt.dRel, pt.yRel, pt.vRel, pt.measured] # *** remove missing points from meta data *** - for ids in self.tracks.keys(): + for ids in list(self.tracks.keys()): if ids not in ar_pts: self.tracks.pop(ids, None) @@ -120,16 +124,15 @@ def update(self, frame, delay, sm, rr, has_radar): rpt = ar_pts[ids] # align v_ego by a fixed time to align it with the radar measurement - cur_time = float(frame)/rate - self.v_ego_t_aligned = np.interp(cur_time - delay, self.v_ego_hist_t, self.v_ego_hist_v) + self.v_ego_t_aligned = self.v_ego_hist[0] # create the track if it doesn't exist or it's a new track if ids not in self.tracks: self.tracks[ids] = Track() self.tracks[ids].update(rpt[0], rpt[1], rpt[2], self.v_ego_t_aligned, rpt[3]) - idens = list(self.tracks.keys()) - track_pts = np.array([self.tracks[iden].get_key_for_cluster() for iden in idens]) + idens = list(sorted(self.tracks.keys())) + track_pts = list([self.tracks[iden].get_key_for_cluster() for iden in idens]) # If we have multiple points, cluster them @@ -137,7 +140,7 @@ def update(self, frame, delay, sm, rr, has_radar): cluster_idxs = cluster_points_centroid(track_pts, 2.5) clusters = [None] * (max(cluster_idxs) + 1) - for idx in xrange(len(track_pts)): + for idx in range(len(track_pts)): cluster_i = cluster_idxs[idx] if clusters[cluster_i] is None: clusters[cluster_i] = Cluster() @@ -151,7 +154,7 @@ def update(self, frame, delay, sm, rr, has_radar): clusters = [] # if a new point, reset accel to the rest of the cluster - for idx in xrange(len(track_pts)): + for idx in range(len(track_pts)): if self.tracks[idens[idx]].cnt <= 1: aLeadK = clusters[cluster_idxs[idx]].aLeadK aLeadTau = clusters[cluster_idxs[idx]].aLeadTau @@ -186,8 +189,11 @@ def radard_thread(sm=None, pm=None, can_sock=None): cloudlog.info("radard is importing %s", CP.carName) RadarInterface = importlib.import_module('selfdrive.car.%s.radar_interface' % CP.carName).RadarInterface + can_poller = zmq.Poller() + if can_sock is None: can_sock = messaging.sub_sock(service_list['can'].port) + can_poller.register(can_sock) if sm is None: sm = messaging.SubMaster(['model', 'controlsState', 'liveParameters']) @@ -198,13 +204,13 @@ def radard_thread(sm=None, pm=None, can_sock=None): RI = RadarInterface(CP) - rk = Ratekeeper(rate, print_delay_threshold=None) - RD = RadarD(mocked) + rk = Ratekeeper(1.0 / DT_RDR, print_delay_threshold=None) + RD = RadarD(mocked, RI.delay) has_radar = not CP.radarOffCan while 1: - can_strings = messaging.drain_sock_raw(can_sock, wait_for_one=True) + can_strings = messaging.drain_sock_raw_poller(can_poller, can_sock, wait_for_one=True) rr = RI.update(can_strings) if rr is None: @@ -212,7 +218,7 @@ def radard_thread(sm=None, pm=None, can_sock=None): sm.update(0) - dat = RD.update(rk.frame, RI.delay, sm, rr, has_radar) + dat = RD.update(rk.frame, sm, rr, has_radar) dat.radarState.cumLagMs = -rk.remaining*1000. pm.send('radarState', dat) @@ -222,7 +228,7 @@ def radard_thread(sm=None, pm=None, can_sock=None): dat = messaging.new_message() dat.init('liveTracks', len(tracks)) - for cnt, ids in enumerate(tracks.keys()): + for cnt, ids in enumerate(sorted(tracks.keys())): dat.liveTracks[cnt] = { "trackId": ids, "dRel": float(tracks[ids].dRel), diff --git a/selfdrive/controls/tests/test_clustering.py b/selfdrive/controls/tests/test_clustering.py index 14c0e23fe335ce..e899ff7d5788b1 100644 --- a/selfdrive/controls/tests/test_clustering.py +++ b/selfdrive/controls/tests/test_clustering.py @@ -88,7 +88,7 @@ def test_pdist(self): pts_ptr = ffi.cast("double *", pts.ctypes.data) n, m = pts.shape - out = np.zeros((n * (n - 1) / 2, ), dtype=np.float64) + out = np.zeros((n * (n - 1) // 2, ), dtype=np.float64) out_ptr = ffi.cast("double *", out.ctypes.data) hclust.hclust_pdist(n, m, pts_ptr, out_ptr) diff --git a/selfdrive/controls/tests/test_following_distance.py b/selfdrive/controls/tests/test_following_distance.py index bcc67c42a39274..331cb14eacb4ab 100644 --- a/selfdrive/controls/tests/test_following_distance.py +++ b/selfdrive/controls/tests/test_following_distance.py @@ -15,7 +15,7 @@ def RW(v_ego, v_l): return (v_ego * TR - (v_l - v_ego) * TR + v_ego * v_ego / (2 * G) - v_l * v_l / (2 * G)) -class FakePubMaster(object): +class FakePubMaster(): def send(self, s, data): assert data @@ -38,7 +38,7 @@ def run_following_distance_simulation(v_lead, t_end=200.0): first = True while t < t_end: # Run cruise control - accel_limits = [float(x) for x in calc_cruise_accel_limits(v_ego, False)] + accel_limits = [float(x) for x in calc_cruise_accel_limits(v_ego)] jerk_limits = [min(-0.1, accel_limits[0]), max(0.1, accel_limits[1])] v_cruise, a_cruise = speed_smoother(v_ego, a_ego, v_cruise_setpoint, accel_limits[1], accel_limits[0], diff --git a/selfdrive/controls/tests/test_lateral_mpc.py b/selfdrive/controls/tests/test_lateral_mpc.py index 4bd65713485156..8dfff81ad40b59 100644 --- a/selfdrive/controls/tests/test_lateral_mpc.py +++ b/selfdrive/controls/tests/test_lateral_mpc.py @@ -27,15 +27,15 @@ def run_mpc(v_ref=30., x_init=0., y_init=0., psi_init=0., delta_init=0., d_poly = calc_d_poly(p_l, p_r, p_p, l_prob, r_prob, lane_width) - CP = CarInterface.get_params("HONDA CIVIC 2016 TOURING", {}) + CP = CarInterface.get_params("HONDA CIVIC 2016 TOURING") VM = VehicleModel(CP) v_ref = v_ref curvature_factor = VM.curvature_factor(v_ref) - l_poly = libmpc_py.ffi.new("double[4]", map(float, p_l)) - r_poly = libmpc_py.ffi.new("double[4]", map(float, p_r)) - d_poly = libmpc_py.ffi.new("double[4]", map(float, d_poly)) + l_poly = libmpc_py.ffi.new("double[4]", list(map(float, p_l))) + r_poly = libmpc_py.ffi.new("double[4]", list(map(float, p_r))) + d_poly = libmpc_py.ffi.new("double[4]", list(map(float, d_poly))) cur_state = libmpc_py.ffi.new("state_t *") cur_state[0].x = x_init diff --git a/selfdrive/controls/tests/test_monitoring.py b/selfdrive/controls/tests/test_monitoring.py index eccc97402692c1..d5c14d663dedc5 100644 --- a/selfdrive/controls/tests/test_monitoring.py +++ b/selfdrive/controls/tests/test_monitoring.py @@ -138,20 +138,27 @@ def test_biggest_comma_fan(self): self.assertEqual(events_output[int((_DISTRACTED_SECONDS_TO_RED+2*_invisible_time+1.5)/DT_DMON)][0].name, 'driverDistracted') self.assertTrue(len(events_output[int((_DISTRACTED_SECONDS_TO_RED+2*_invisible_time+3.5)/DT_DMON)])==0) - # 5. op engaged, invisible driver, down to orange, driver appears; then down to orange again, driver touches wheel - # - both actions should clear the alert + # 5. op engaged, invisible driver, down to orange, driver touches wheel; then down to orange again, driver appears + # - both actions should clear the alert, but momentary appearence should not def test_sometimes_transparent_commuter(self): - _visible_time = 2 # seconds - ds_vector = always_no_face[:]*2 - interaction_vector = always_false[:]*2 - ds_vector[int(_INVISIBLE_SECONDS_TO_ORANGE/DT_DMON):int((_INVISIBLE_SECONDS_TO_ORANGE+_visible_time)/DT_DMON)] = [msg_ATTENTIVE] * int(_visible_time/DT_DMON) - interaction_vector[int((2*_INVISIBLE_SECONDS_TO_ORANGE+_visible_time)/DT_DMON):int((2*_INVISIBLE_SECONDS_TO_ORANGE+_visible_time+1)/DT_DMON)] = [True] * int(1/DT_DMON) - events_output = run_DState_seq(ds_vector, interaction_vector, 2*always_true, 2*always_false) - self.assertTrue(len(events_output[int(_INVISIBLE_SECONDS_TO_ORANGE*0.5/DT_DMON)])==0) - self.assertEqual(events_output[int((_INVISIBLE_SECONDS_TO_ORANGE-0.1)/DT_DMON)][0].name, 'promptDriverUnresponsive') - self.assertTrue(len(events_output[int((_INVISIBLE_SECONDS_TO_ORANGE*1.5+_visible_time)/DT_DMON)])==0) - self.assertEqual(events_output[int((_INVISIBLE_SECONDS_TO_ORANGE*2+_visible_time-0.5)/DT_DMON)][0].name, 'promptDriverUnresponsive') - self.assertTrue(len(events_output[int((_INVISIBLE_SECONDS_TO_ORANGE*2+_visible_time+0.1)/DT_DMON)])==0) + _visible_time = np.random.choice([1,10]) # seconds + # print _visible_time + ds_vector = always_no_face[:]*2 + interaction_vector = always_false[:]*2 + ds_vector[int((2*_INVISIBLE_SECONDS_TO_ORANGE+1)/DT_DMON):int((2*_INVISIBLE_SECONDS_TO_ORANGE+1+_visible_time)/DT_DMON)] = [msg_ATTENTIVE] * int(_visible_time/DT_DMON) + interaction_vector[int((_INVISIBLE_SECONDS_TO_ORANGE)/DT_DMON):int((_INVISIBLE_SECONDS_TO_ORANGE+1)/DT_DMON)] = [True] * int(1/DT_DMON) + events_output = run_DState_seq(ds_vector, interaction_vector, 2*always_true, 2*always_false) + self.assertTrue(len(events_output[int(_INVISIBLE_SECONDS_TO_ORANGE*0.5/DT_DMON)])==0) + self.assertEqual(events_output[int((_INVISIBLE_SECONDS_TO_ORANGE-0.1)/DT_DMON)][0].name, 'promptDriverUnresponsive') + self.assertTrue(len(events_output[int((_INVISIBLE_SECONDS_TO_ORANGE+0.1)/DT_DMON)])==0) + if _visible_time == 1: + self.assertEqual(events_output[int((_INVISIBLE_SECONDS_TO_ORANGE*2+1-0.1)/DT_DMON)][0].name, 'promptDriverUnresponsive') + self.assertEqual(events_output[int((_INVISIBLE_SECONDS_TO_ORANGE*2+1+0.1+_visible_time)/DT_DMON)][0].name, 'preDriverUnresponsive') + elif _visible_time == 10: + self.assertEqual(events_output[int((_INVISIBLE_SECONDS_TO_ORANGE*2+1-0.1)/DT_DMON)][0].name, 'promptDriverUnresponsive') + self.assertTrue(len(events_output[int((_INVISIBLE_SECONDS_TO_ORANGE*2+1+0.1+_visible_time)/DT_DMON)])==0) + else: + pass # 6. op engaged, invisible driver, down to red, driver appears and then touches wheel, then disengages/reengages # - only disengage will clear the alert @@ -189,5 +196,5 @@ def test_long_traffic_light_victim(self): self.assertEqual(events_output[int((_redlight_time+0.5)/DT_DMON)][0].name, 'promptDriverDistracted') if __name__ == "__main__": - print 'MAX_TERMINAL_ALERTS', MAX_TERMINAL_ALERTS + print('MAX_TERMINAL_ALERTS', MAX_TERMINAL_ALERTS) unittest.main() diff --git a/selfdrive/debug/can_printer.py b/selfdrive/debug/can_printer.py index daa0500b2f20e6..6b5d188be39d00 100755 --- a/selfdrive/debug/can_printer.py +++ b/selfdrive/debug/can_printer.py @@ -1,9 +1,11 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 +import binascii import os import sys from collections import defaultdict -from common.realtime import sec_since_boot + import selfdrive.messaging as messaging +from common.realtime import sec_since_boot from selfdrive.services import service_list @@ -24,9 +26,9 @@ def can_printer(bus=0, max_msg=None, addr="127.0.0.1"): if sec_since_boot() - lp > 0.1: dd = chr(27) + "[2J" dd += "%5.2f\n" % (sec_since_boot() - start) - for k,v in sorted(zip(msgs.keys(), map(lambda x: x[-1].encode("hex"), msgs.values()))): + for k,v in sorted(zip(msgs.keys(), map(lambda x: binascii.hexlify(x[-1]), msgs.values()))): if max_msg is None or k < max_msg: - dd += "%s(%6d) %s\n" % ("%04X(%4d)" % (k,k),len(msgs[k]), v) + dd += "%s(%6d) %s\n" % ("%04X(%4d)" % (k,k),len(msgs[k]), v.decode('ascii')) print(dd) lp = sec_since_boot() @@ -39,4 +41,3 @@ def can_printer(bus=0, max_msg=None, addr="127.0.0.1"): can_printer(int(sys.argv[1])) else: can_printer() - diff --git a/selfdrive/debug/compare_fingerprints.py b/selfdrive/debug/compare_fingerprints.py new file mode 100755 index 00000000000000..a0c80a740e8ae9 --- /dev/null +++ b/selfdrive/debug/compare_fingerprints.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 + +# put 2 fingeprints and print the diffs +f1 = { +168: 8, 257: 5, 258: 8, 264: 8, 268: 8, 270: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 291: 8, 292: 8, 294: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 368: 8, 376: 3, 384: 8, 388: 4, 448: 6, 456: 4, 464: 8, 469: 8, 480: 8, 500: 8, 501: 8, 512: 8, 514: 8, 520: 8, 528: 8, 532: 8, 544: 8, 557: 8, 559: 8, 560: 8, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 624: 8, 625: 8, 632: 8, 639: 8, 653: 8, 654: 8, 655: 8, 658: 6, 660: 8, 669: 3, 671: 8, 672: 8, 678: 8, 680: 8, 701: 8, 703: 8, 704: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 729: 5, 736: 8, 737: 8, 746: 5, 752: 2, 754: 8, 760: 8, 764: 8, 766: 8, 770: 8, 773: 8, 779: 8, 782: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 832: 8, 838: 2, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 878: 8, 882: 8, 897: 8, 906: 8, 908: 8, 924: 8, 926: 3, 929: 8, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 958: 8, 959: 8, 962: 8, 969: 4, 973: 8, 974: 5, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1082: 8, 1083: 8, 1098: 8, 1100: 8, 1537: 8, 1538: 8, 1562: 8 +} + +f2 = { +168: 8, 257: 5, 258: 8, 264: 8, 268: 8, 270: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 291: 8, 292: 8, 294: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 368: 8, 376: 3, 384: 8, 388: 4, 448: 6, 456: 4, 464: 8, 469: 8, 480: 8, 500: 8, 501: 8, 512: 8, 514: 8, 515: 7, 516: 7, 517: 7, 518: 7, 520: 8, 528: 8, 532: 8, 542: 8, 544: 8, 557: 8, 559: 8, 560: 8, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 624: 8, 625: 8, 632: 8, 639: 8, 653: 8, 654: 8, 655: 8, 658: 6, 660: 8, 669: 3, 671: 8, 672: 8, 678: 8, 680: 8, 701: 8, 703: 8, 704: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 729: 5, 736: 8, 737: 8, 746: 5, 752: 2, 754: 8, 760: 8, 764: 8, 766: 8, 770: 8, 773: 8, 779: 8, 782: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 832: 8, 838: 2, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 878: 8, 882: 8, 897: 8, 906: 8, 908: 8, 924: 8, 926: 3, 929: 8, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 958: 8, 959: 8, 962: 8, 969: 4, 973: 8, 974: 5, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1082: 8, 1083: 8, 1098: 8, 1100: 8 +} + +for k in f1: + if k not in f2 or f1[k] != f2[k]: + print(k, "not in f2") + +for k in f2: + if k not in f1 or f2[k] != f1[k]: + print(k, "not in f1") diff --git a/selfdrive/debug/cpu_usage_stat.py b/selfdrive/debug/cpu_usage_stat.py index 7adf7ef78ee02f..e1a6ac35d49fe5 100755 --- a/selfdrive/debug/cpu_usage_stat.py +++ b/selfdrive/debug/cpu_usage_stat.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import psutil import time import os @@ -94,7 +94,7 @@ def get_arg_parser(): for k, stat in stats.items(): if len(stat['cpu_samples']) <= 0: continue - for name, samples in stat['cpu_samples'].iteritems(): + for name, samples in stat['cpu_samples'].items(): samples = np.array(samples) avg = samples.mean() c = samples.size diff --git a/selfdrive/debug/dump.py b/selfdrive/debug/dump.py index 7fd8a7cf4fc8b2..84846a17a675fe 100755 --- a/selfdrive/debug/dump.py +++ b/selfdrive/debug/dump.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import sys import argparse import zmq diff --git a/selfdrive/debug/get_fingerprint.py b/selfdrive/debug/get_fingerprint.py index e528d9826c3734..286b71a132dd4f 100755 --- a/selfdrive/debug/get_fingerprint.py +++ b/selfdrive/debug/get_fingerprint.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # simple script to get a vehicle fingerprint. diff --git a/selfdrive/debug/live_cpu_and_temp.py b/selfdrive/debug/live_cpu_and_temp.py new file mode 100755 index 00000000000000..0cc62ef7c54677 --- /dev/null +++ b/selfdrive/debug/live_cpu_and_temp.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +import numpy as np + +from selfdrive.messaging import SubMaster + +def cputime_total(ct): + return ct.user + ct.nice + ct.system + ct.idle + ct.iowait + ct.irq + ct.softirq + + +def cputime_busy(ct): + return ct.user + ct.nice + ct.system + ct.irq + ct.softirq + + + +sm = SubMaster(['thermal', 'procLog']) + +last_temp = 0.0 +total_times = [0., 0., 0., 0.] +busy_times = [0., 0., 0.0, 0.] + + +while True: + sm.update() + + if sm.updated['thermal']: + t = sm['thermal'] + last_temp = np.mean([t.cpu0, t.cpu1, t.cpu2, t.cpu3]) / 10. + + if sm.updated['procLog']: + m = sm['procLog'] + + cores = [0., 0., 0., 0.] + total_times_new = [0., 0., 0., 0.] + busy_times_new = [0., 0., 0.0, 0.] + + for c in m.cpuTimes: + n = c.cpuNum + total_times_new[n] = cputime_total(c) + busy_times_new[n] = cputime_busy(c) + + for n in range(4): + t_busy = busy_times_new[n] - busy_times[n] + t_total = total_times_new[n] - total_times[n] + cores[n] = t_busy / t_total + + total_times = total_times_new[:] + busy_times = busy_times_new[:] + + print("CPU %.2f%% - Temp %.2f" % (100. * np.mean(cores), last_temp )) diff --git a/selfdrive/debug/mpc/live_lateral_mpc.py b/selfdrive/debug/mpc/live_lateral_mpc.py new file mode 100755 index 00000000000000..f4ee7a18435836 --- /dev/null +++ b/selfdrive/debug/mpc/live_lateral_mpc.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 +import matplotlib +matplotlib.use('TkAgg') + +import sys +from selfdrive.services import service_list +import selfdrive.messaging as messaging +import numpy as np +import matplotlib.pyplot as plt + +# debug liateral MPC by plotting its trajectory. To receive liveLongitudinalMpc packets, +# set on LOG_MPC env variable and run plannerd on a replay + + +def mpc_vwr_thread(addr="127.0.0.1"): + + plt.ion() + fig = plt.figure(figsize=(15, 20)) + ax = fig.add_subplot(131) + aa = fig.add_subplot(132, sharey=ax) + ap = fig.add_subplot(133, sharey=ax) + + ax.set_xlim([-10, 10]) + ax.set_ylim([0., 100.]) + aa.set_xlim([-20., 20]) + ap.set_xlim([-5, 5]) + + ax.set_xlabel('x [m]') + ax.set_ylabel('y [m]') + aa.set_xlabel('steer_angle [deg]') + ap.set_xlabel('asset angle [deg]') + ax.grid(True) + aa.grid(True) + ap.grid(True) + + path_x = np.arange(0, 100) + mpc_path_x = np.arange(0, 49) + + p_path_y = np.zeros(100) + + l_path_y = np.zeros(100) + r_path_y = np.zeros(100) + mpc_path_y = np.zeros(49) + mpc_steer_angle = np.zeros(49) + mpc_psi = np.zeros(49) + + line1, = ax.plot(mpc_path_y, mpc_path_x) + # line1b, = ax.plot(mpc_path_y, mpc_path_x, 'o') + + lineP, = ax.plot(p_path_y, path_x) + lineL, = ax.plot(l_path_y, path_x) + lineR, = ax.plot(r_path_y, path_x) + line3, = aa.plot(mpc_steer_angle, mpc_path_x) + line4, = ap.plot(mpc_psi, mpc_path_x) + ax.invert_xaxis() + aa.invert_xaxis() + plt.show() + + + # *** log *** + livempc = messaging.sub_sock(service_list['liveMpc'].port, addr=addr) + model = messaging.sub_sock(service_list['model'].port, addr=addr) + path_plan_sock = messaging.sub_sock(service_list['pathPlan'].port, addr=addr) + + while 1: + lMpc = messaging.recv_sock(livempc, wait=True) + md = messaging.recv_sock(model) + pp = messaging.recv_sock(path_plan_sock) + + if md is not None: + p_poly = np.array(md.model.path.poly) + l_poly = np.array(md.model.leftLane.poly) + r_poly = np.array(md.model.rightLane.poly) + + p_path_y = np.polyval(p_poly, path_x) + l_path_y = np.polyval(r_poly, path_x) + r_path_y = np.polyval(l_poly, path_x) + + if pp is not None: + p_path_y = np.polyval(pp.pathPlan.dPoly, path_x) + lineP.set_xdata(p_path_y) + lineP.set_ydata(path_x) + + if lMpc is not None: + mpc_path_x = list(lMpc.liveMpc.x)[1:] + mpc_path_y = list(lMpc.liveMpc.y)[1:] + mpc_steer_angle = list(lMpc.liveMpc.delta)[1:] + mpc_psi = list(lMpc.liveMpc.psi)[1:] + + line1.set_xdata(mpc_path_y) + line1.set_ydata(mpc_path_x) + lineL.set_xdata(l_path_y) + lineL.set_ydata(path_x) + lineR.set_xdata(r_path_y) + lineR.set_ydata(path_x) + line3.set_xdata(np.asarray(mpc_steer_angle)*180./np.pi * 14) + line3.set_ydata(mpc_path_x) + line4.set_xdata(np.asarray(mpc_psi)*180./np.pi) + line4.set_ydata(mpc_path_x) + + aa.relim() + aa.autoscale_view(True, scaley=True, scalex=True) + + fig.canvas.draw() + fig.canvas.flush_events() + +if __name__ == "__main__": + if len(sys.argv) > 1: + mpc_vwr_thread(sys.argv[1]) + else: + mpc_vwr_thread() diff --git a/selfdrive/debug/mpc/live_longitudinal_mpc.py b/selfdrive/debug/mpc/live_longitudinal_mpc.py new file mode 100755 index 00000000000000..e72a37585fb8e8 --- /dev/null +++ b/selfdrive/debug/mpc/live_longitudinal_mpc.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 + +import matplotlib +matplotlib.use('TkAgg') + +import sys +from selfdrive.services import service_list +import selfdrive.messaging as messaging +import numpy as np +import matplotlib.pyplot as plt + +N = 21 + +# debug longitudinal MPC by plotting its trajectory. To receive liveLongitudinalMpc packets, +# set on LOG_MPC env variable and run plannerd on a replay + +def plot_longitudinal_mpc(addr="127.0.0.1"): + # *** log *** + livempc = messaging.sub_sock(service_list['liveLongitudinalMpc'].port, addr=addr, conflate=True) + radarstate = messaging.sub_sock(service_list['radarState'].port, addr=addr, conflate=True) + + plt.ion() + fig = plt.figure() + + t = np.hstack([np.arange(0.0, 0.8, 0.2), np.arange(0.8, 10.6, 0.6)]) + + p_x_ego = fig.add_subplot(3, 2, 1) + p_v_ego = fig.add_subplot(3, 2, 3) + p_a_ego = fig.add_subplot(3, 2, 5) + # p_x_l = fig.add_subplot(3, 2, 2) + # p_a_l = fig.add_subplot(3, 2, 6) + p_d_l = fig.add_subplot(3, 2, 2) + p_d_l_v = fig.add_subplot(3, 2, 4) + p_d_l_vv = fig.add_subplot(3, 2, 6) + + p_v_ego.set_ylim([0, 30]) + p_a_ego.set_ylim([-4, 4]) + p_d_l.set_ylim([-1, 10]) + + p_x_ego.set_title('x') + p_v_ego.set_title('v') + p_a_ego.set_title('a') + p_d_l.set_title('rel dist') + + l_x_ego, = p_x_ego.plot(t, np.zeros(N)) + l_v_ego, = p_v_ego.plot(t, np.zeros(N)) + l_a_ego, = p_a_ego.plot(t, np.zeros(N)) + l_x_l, = p_x_ego.plot(t, np.zeros(N)) + l_v_l, = p_v_ego.plot(t, np.zeros(N)) + l_a_l, = p_a_ego.plot(t, np.zeros(N)) + l_d_l, = p_d_l.plot(t, np.zeros(N)) + l_d_l_v, = p_d_l_v.plot(np.zeros(N)) + l_d_l_vv, = p_d_l_vv.plot(np.zeros(N)) + p_x_ego.legend(['ego', 'l']) + p_v_ego.legend(['ego', 'l']) + p_a_ego.legend(['ego', 'l']) + p_d_l_v.set_xlabel('d_rel') + p_d_l_v.set_ylabel('v_rel') + p_d_l_v.set_ylim([-20, 20]) + p_d_l_v.set_xlim([0, 100]) + p_d_l_vv.set_xlabel('d_rel') + p_d_l_vv.set_ylabel('v_rel') + p_d_l_vv.set_ylim([-5, 5]) + p_d_l_vv.set_xlim([10, 40]) + + while True: + lMpc = messaging.recv_sock(livempc, wait=True) + rs = messaging.recv_sock(radarstate, wait=True) + + if lMpc is not None: + + if lMpc.liveLongitudinalMpc.mpcId != 1: + continue + + x_ego = list(lMpc.liveLongitudinalMpc.xEgo) + v_ego = list(lMpc.liveLongitudinalMpc.vEgo) + a_ego = list(lMpc.liveLongitudinalMpc.aEgo) + x_l = list(lMpc.liveLongitudinalMpc.xLead) + v_l = list(lMpc.liveLongitudinalMpc.vLead) + # a_l = list(lMpc.liveLongitudinalMpc.aLead) + a_l = rs.radarState.leadOne.aLeadK * np.exp(-lMpc.liveLongitudinalMpc.aLeadTau * t**2 / 2) + #print(min(a_ego), lMpc.liveLongitudinalMpc.qpIterations) + + l_x_ego.set_ydata(x_ego) + l_v_ego.set_ydata(v_ego) + l_a_ego.set_ydata(a_ego) + + l_x_l.set_ydata(x_l) + l_v_l.set_ydata(v_l) + l_a_l.set_ydata(a_l) + + l_d_l.set_ydata(np.array(x_l) - np.array(x_ego)) + l_d_l_v.set_ydata(np.array(v_l) - np.array(v_ego)) + l_d_l_v.set_xdata(np.array(x_l) - np.array(x_ego)) + l_d_l_vv.set_ydata(np.array(v_l) - np.array(v_ego)) + l_d_l_vv.set_xdata(np.array(x_l) - np.array(x_ego)) + + p_x_ego.relim() + p_x_ego.autoscale_view(True, scaley=True, scalex=True) + fig.canvas.draw() + fig.canvas.flush_events() + + + + +if __name__ == "__main__": + if len(sys.argv) > 1: + plot_longitudinal_mpc(sys.argv[1]) + else: + plot_longitudinal_mpc() diff --git a/selfdrive/debug/mpc/test_mpc_wobble.py b/selfdrive/debug/mpc/test_mpc_wobble.py new file mode 100755 index 00000000000000..5f9f1b3355bf19 --- /dev/null +++ b/selfdrive/debug/mpc/test_mpc_wobble.py @@ -0,0 +1,129 @@ +#! /usr/bin/env python +import matplotlib.pyplot as plt +from selfdrive.controls.lib.lateral_mpc import libmpc_py +from selfdrive.controls.lib.drive_helpers import MPC_COST_LAT +import math + +libmpc = libmpc_py.libmpc +libmpc.init(MPC_COST_LAT.PATH, MPC_COST_LAT.LANE, MPC_COST_LAT.HEADING, 1.) + +cur_state = libmpc_py.ffi.new("state_t *") +cur_state[0].x = 0.0 +cur_state[0].y = 0.0 +cur_state[0].psi = 0.0 +cur_state[0].delta = 0.0 + +mpc_solution = libmpc_py.ffi.new("log_t *") +xx = [] +yy = [] +deltas = [] +psis = [] +times = [] + +curvature_factor = 0.3 +v_ref = 1.0 * 20.12 # 45 mph + +LANE_WIDTH = 3.7 +p = [0.0, 0.0, 0.0, 0.0] +p_l = p[:] +p_l[3] += LANE_WIDTH / 2.0 + +p_r = p[:] +p_r[3] -= LANE_WIDTH / 2.0 + + +l_poly = libmpc_py.ffi.new("double[4]", p_l) +r_poly = libmpc_py.ffi.new("double[4]", p_r) +p_poly = libmpc_py.ffi.new("double[4]", p) + +l_prob = 1.0 +r_prob = 1.0 +p_prob = 1.0 + +for i in range(1): + cur_state[0].delta = math.radians(510. / 13.) + libmpc.run_mpc(cur_state, mpc_solution, l_poly, r_poly, p_poly, l_prob, r_prob, + curvature_factor, v_ref, LANE_WIDTH) + +timesi = [] +ct = 0 +for i in range(21): + timesi.append(ct) + if i <= 4: + ct += 0.05 + else: + ct += 0.15 + + +xi = list(mpc_solution[0].x) +yi = list(mpc_solution[0].y) +psii = list(mpc_solution[0].psi) +deltai = list(mpc_solution[0].delta) +print("COST: ", mpc_solution[0].cost) + + +plt.figure(0) +plt.subplot(3, 1, 1) +plt.plot(timesi, psii) +plt.ylabel('psi') +plt.grid(True) +plt.subplot(3, 1, 2) +plt.plot(timesi, deltai) +plt.ylabel('delta') +plt.grid(True) +plt.subplot(3, 1, 3) +plt.plot(timesi, yi) +plt.ylabel('y') +plt.grid(True) +plt.show() + + +#### UNCOMMENT TO CHECK ITERATIVE SOLUTION +#### +####for i in range(100): +#### libmpc.run_mpc(cur_state, mpc_solution, l_poly, r_poly, p_poly, l_prob, r_prob, +#### curvature_factor, v_ref, LANE_WIDTH) +#### print "x", list(mpc_solution[0].x) +#### print "y", list(mpc_solution[0].y) +#### print "delta", list(mpc_solution[0].delta) +#### print "psi", list(mpc_solution[0].psi) +#### # cur_state[0].x = mpc_solution[0].x[1] +#### # cur_state[0].y = mpc_solution[0].y[1] +#### # cur_state[0].psi = mpc_solution[0].psi[1] +#### cur_state[0].delta = radians(200 / 13.)#mpc_solution[0].delta[1] +#### +#### xx.append(cur_state[0].x) +#### yy.append(cur_state[0].y) +#### psis.append(cur_state[0].psi) +#### deltas.append(cur_state[0].delta) +#### times.append(i * 0.05) +#### +#### +####def f(x): +#### return p_poly[0] * x**3 + p_poly[1] * x**2 + p_poly[2] * x + p_poly[3] +#### +#### +##### planned = map(f, xx) +##### plt.figure(1) +##### plt.plot(yy, xx, 'r-') +##### plt.plot(planned, xx, 'b--', linewidth=0.5) +##### plt.axes().set_aspect('equal', 'datalim') +##### plt.gca().invert_xaxis() +#### +##### planned = map(f, map(float, list(mpc_solution[0].x)[1:])) +##### plt.figure(1) +##### plt.plot(map(float, list(mpc_solution[0].y)[1:]), map(float, list(mpc_solution[0].x)[1:]), 'r-') +##### plt.plot(planned, map(float, list(mpc_solution[0].x)[1:]), 'b--', linewidth=0.5) +##### plt.axes().set_aspect('equal', 'datalim') +##### plt.gca().invert_xaxis() +#### +####plt.figure(2) +####plt.subplot(2, 1, 1) +####plt.plot(times, psis) +####plt.ylabel('psi') +####plt.subplot(2, 1, 2) +####plt.plot(times, deltas) +####plt.ylabel('delta') +#### +#### +####plt.show() diff --git a/selfdrive/debug/mpc/tune_lateral.py b/selfdrive/debug/mpc/tune_lateral.py new file mode 100755 index 00000000000000..4a8ec2ce0b97d4 --- /dev/null +++ b/selfdrive/debug/mpc/tune_lateral.py @@ -0,0 +1,186 @@ +#! /usr/bin/env python +import numpy as np +from collections import OrderedDict +import matplotlib.pyplot as plt +from selfdrive.car.honda.interface import CarInterface +from selfdrive.controls.lib.lateral_mpc import libmpc_py +from selfdrive.controls.lib.vehicle_model import VehicleModel + +# plot lateral MPC trajectory by defining boundary conditions: +# lane lines, p_poly and vehicle states. Use this script to tune MPC costs + +libmpc = libmpc_py.libmpc + +mpc_solution = libmpc_py.ffi.new("log_t *") + +points_l = np.array([1.1049711, 1.1053879, 1.1073375, 1.1096942, 1.1124474, 1.1154714, 1.1192677, 1.1245866, 1.1321017, 1.1396152, 1.146443, 1.1555313, 1.1662073, 1.1774249, 1.1888939, 1.2009926, 1.2149779, 1.2300836, 1.2450289, 1.2617753, 1.2785473, 1.2974714, 1.3151019, 1.3331807, 1.3545501, 1.3763691, 1.3983455, 1.4215056, 1.4446729, 1.4691089, 1.4927692, 1.5175346, 1.5429921, 1.568854, 1.5968665, 1.6268958, 1.657122, 1.6853137, 1.7152609, 1.7477539, 1.7793678, 1.8098511, 1.8428392, 1.8746407, 1.9089606, 1.9426043, 1.9775689, 2.0136933, 2.0520134, 2.0891454]) + +points_r = np.array([-2.4442139, -2.4449506, -2.4448867, -2.44377, -2.4422617, -2.4393811, -2.4374201, -2.4334245, -2.4286852, -2.4238286, -2.4177458, -2.4094386, -2.3994849, -2.3904033, -2.380136, -2.3699453, -2.3594661, -2.3474073, -2.3342307, -2.3194637, -2.3046403, -2.2881098, -2.2706163, -2.2530098, -2.235604, -2.2160542, -2.1967411, -2.1758952, -2.1544619, -2.1325269, -2.1091819, -2.0850561, -2.0621953, -2.0364127, -2.0119917, -1.9851667, -1.9590458, -1.9306552, -1.9024918, -1.8745357, -1.8432863, -1.8131843, -1.7822732, -1.7507075, -1.7180918, -1.6845931, -1.650871, -1.6157099, -1.5787286, -1.5418037]) + + +points_c = (points_l + points_r) / 2.0 + +def compute_path_pinv(): + deg = 3 + x = np.arange(50.0) + X = np.vstack(tuple(x**n for n in range(deg, -1, -1))).T + pinv = np.linalg.pinv(X) + return pinv + + +def model_polyfit(points): + path_pinv = compute_path_pinv() + return np.dot(path_pinv, map(float, points)) + + +xx = [] +yy = [] +deltas = [] +psis = [] +times = [] + +CP = CarInterface.get_params("HONDA CIVIC 2016 TOURING") +VM = VehicleModel(CP) + +v_ref = 32.00 # 45 mph +curvature_factor = VM.curvature_factor(v_ref) +print(curvature_factor) + +LANE_WIDTH = 3.9 +p_l = map(float, model_polyfit(points_l)) +p_r = map(float, model_polyfit(points_r)) +p_p = map(float, model_polyfit(points_c)) + +l_poly = libmpc_py.ffi.new("double[4]", p_l) +r_poly = libmpc_py.ffi.new("double[4]", p_r) +p_poly = libmpc_py.ffi.new("double[4]", p_p) +l_prob = 1.0 +r_prob = 1.0 +p_prob = 1.0 # This is always 1 + + +mpc_x_points = np.linspace(0., 2.5*v_ref, num=50) +points_poly_l = np.polyval(p_l, mpc_x_points) +points_poly_r = np.polyval(p_r, mpc_x_points) +points_poly_p = np.polyval(p_p, mpc_x_points) +print(points_poly_l) + +lanes_x = np.linspace(0, 49) + +cur_state = libmpc_py.ffi.new("state_t *") +cur_state[0].x = 0.0 +cur_state[0].y = 0.5 +cur_state[0].psi = 0.0 +cur_state[0].delta = 0.0 + +xs = [] +ys = [] +deltas = [] +titles = [ + 'Steer rate cost', + 'Heading cost', + 'Lane cost', + 'Path cost', +] + +# Steer rate cost +sol_x = OrderedDict() +sol_y = OrderedDict() +delta = OrderedDict() +for cost in np.logspace(-1, 1.0, 5): + libmpc.init(1.0, 3.0, 1.0, cost) + for _ in range(10): + libmpc.run_mpc(cur_state, mpc_solution, l_poly, r_poly, p_poly, l_prob, r_prob, + curvature_factor, v_ref, LANE_WIDTH) + sol_x[cost] = map(float, list(mpc_solution[0].x)) + sol_y[cost] = map(float, list(mpc_solution[0].y)) + delta[cost] = map(float, list(mpc_solution[0].delta)) +xs.append(sol_x) +ys.append(sol_y) +deltas.append(delta) + +# Heading cost +sol_x = OrderedDict() +sol_y = OrderedDict() +delta = OrderedDict() +for cost in np.logspace(-1, 1.0, 5): + libmpc.init(1.0, 3.0, cost, 1.0) + for _ in range(10): + libmpc.run_mpc(cur_state, mpc_solution, l_poly, r_poly, p_poly, l_prob, r_prob, + curvature_factor, v_ref, LANE_WIDTH) + sol_x[cost] = map(float, list(mpc_solution[0].x)) + sol_y[cost] = map(float, list(mpc_solution[0].y)) + delta[cost] = map(float, list(mpc_solution[0].delta)) +xs.append(sol_x) +ys.append(sol_y) +deltas.append(delta) + +# Lane cost +sol_x = OrderedDict() +sol_y = OrderedDict() +delta = OrderedDict() +for cost in np.logspace(-1, 2.0, 5): + libmpc.init(1.0, cost, 1.0, 1.0) + for _ in range(10): + libmpc.run_mpc(cur_state, mpc_solution, l_poly, r_poly, p_poly, l_prob, r_prob, + curvature_factor, v_ref, LANE_WIDTH) + sol_x[cost] = map(float, list(mpc_solution[0].x)) + sol_y[cost] = map(float, list(mpc_solution[0].y)) + delta[cost] = map(float, list(mpc_solution[0].delta)) +xs.append(sol_x) +ys.append(sol_y) +deltas.append(delta) + + +# Path cost +sol_x = OrderedDict() +sol_y = OrderedDict() +delta = OrderedDict() +for cost in np.logspace(-1, 1.0, 5): + libmpc.init(cost, 3.0, 1.0, 1.0) + for _ in range(10): + libmpc.run_mpc(cur_state, mpc_solution, l_poly, r_poly, p_poly, l_prob, r_prob, + curvature_factor, v_ref, LANE_WIDTH) + sol_x[cost] = map(float, list(mpc_solution[0].x)) + sol_y[cost] = map(float, list(mpc_solution[0].y)) + delta[cost] = map(float, list(mpc_solution[0].delta)) +xs.append(sol_x) +ys.append(sol_y) +deltas.append(delta) + + + +plt.figure() + +for i in range(len(xs)): + ax = plt.subplot(2, 2, i + 1) + sol_x = xs[i] + sol_y = ys[i] + for cost in sol_x.keys(): + plt.plot(sol_x[cost], sol_y[cost]) + + plt.plot(lanes_x, points_r, '.b') + plt.plot(lanes_x, points_l, '.b') + plt.plot(lanes_x, (points_l + points_r) / 2.0, '--g') + plt.plot(mpc_x_points, points_poly_l, 'b') + plt.plot(mpc_x_points, points_poly_r, 'b') + plt.plot(mpc_x_points, (points_poly_l + points_poly_r) / 2.0, 'g') + plt.legend(map(lambda x: str(round(x, 2)), sol_x.keys()) + ['right', 'left', 'center'], loc=3) + plt.title(titles[i]) + plt.grid(True) + # ax.set_aspect('equal', 'datalim') + + +plt.figure() +for i in range(len(xs)): + plt.subplot(2, 2, i + 1) + sol_x = xs[i] + delta = deltas[i] + + for cost in sol_x.keys(): + plt.plot(delta[cost]) + plt.title(titles[i]) + plt.legend(map(lambda x: str(round(x, 2)), sol_x.keys()), loc=3) + plt.grid(True) + +plt.show() diff --git a/selfdrive/debug/mpc/tune_longitudinal.py b/selfdrive/debug/mpc/tune_longitudinal.py new file mode 100755 index 00000000000000..0af444631d34e3 --- /dev/null +++ b/selfdrive/debug/mpc/tune_longitudinal.py @@ -0,0 +1,168 @@ +#! /usr/bin/env python +import numpy as np +import matplotlib.pyplot as plt +from selfdrive.controls.lib.longitudinal_mpc import libmpc_py +from selfdrive.controls.lib.drive_helpers import MPC_COST_LONG +import math + +# plot liongitudinal MPC trajectory by defining boundary conditions: +# ego and lead vehicles state. Use this script to tune MPC costs + +def RW(v_ego, v_l): + TR = 1.8 + G = 9.81 + return (v_ego * TR - (v_l - v_ego) * TR + v_ego*v_ego/(2*G) - v_l*v_l / (2*G)) + + +def NORM_RW_ERROR(v_ego, v_l, p): + return (RW(v_ego, v_l) + 4.0 - p) + return (RW(v_ego, v_l) + 4.0 - p) / (np.sqrt(v_ego + 0.5) + 0.1) + + +v_ego = 20.0 +a_ego = 0 + +x_lead = 10.0 +v_lead = 20.0 +a_lead = -3.0 +a_lead_tau = 0. + +# v_ego = 7.02661012716 +# a_ego = -1.26143024772 + +# x_lead = 29.625 + 20 +# v_lead = 0.725235462189 + 1 +# a_lead = -1.00025629997 + +# a_lead_tau = 2.90729817665 + +min_a_lead_tau = (a_lead**2 * math.pi) / (2 * (v_lead + 0.01)**2) +min_a_lead_tau = 0.0 + +print(a_lead_tau, min_a_lead_tau) +a_lead_tau = max(a_lead_tau, min_a_lead_tau) + +ffi, libmpc = libmpc_py.get_libmpc(1) +libmpc.init(MPC_COST_LONG.TTC, MPC_COST_LONG.DISTANCE, MPC_COST_LONG.ACCELERATION, MPC_COST_LONG.JERK) +libmpc.init_with_simulation(v_ego, x_lead, v_lead, a_lead, a_lead_tau) + +cur_state = ffi.new("state_t *") +cur_state[0].x_ego = 0.0 +cur_state[0].v_ego = v_ego +cur_state[0].a_ego = a_ego +cur_state[0].x_l = x_lead +cur_state[0].v_l = v_lead + +mpc_solution = ffi.new("log_t *") + +for _ in range(10): + print(libmpc.run_mpc(cur_state, mpc_solution, a_lead_tau, a_lead)) + + +for i in range(21): + print("t: %.2f\t x_e: %.2f\t v_e: %.2f\t a_e: %.2f\t" % (mpc_solution[0].t[i], mpc_solution[0].x_ego[i], mpc_solution[0].v_ego[i], mpc_solution[0].a_ego[i])) + print("x_l: %.2f\t v_l: %.2f\t \t" % (mpc_solution[0].x_l[i], mpc_solution[0].v_l[i])) + +t = np.hstack([np.arange(0., 1.0, 0.2), np.arange(1.0, 10.1, 0.6)]) + +print(map(float, mpc_solution[0].x_ego)[-1]) +print(map(float, mpc_solution[0].x_l)[-1] - map(float, mpc_solution[0].x_ego)[-1]) + +plt.figure(figsize=(8, 8)) + +plt.subplot(4, 1, 1) +x_l = np.array(map(float, mpc_solution[0].x_l)) +plt.plot(t, map(float, mpc_solution[0].x_ego)) +plt.plot(t, x_l) +plt.legend(['ego', 'lead']) +plt.title('x') +plt.grid() + +plt.subplot(4, 1, 2) +v_ego = np.array(map(float, mpc_solution[0].v_ego)) +v_l = np.array(map(float, mpc_solution[0].v_l)) +plt.plot(t, v_ego) +plt.plot(t, v_l) +plt.legend(['ego', 'lead']) +plt.ylim([-1, max(max(v_ego), max(v_l))]) +plt.title('v') +plt.grid() + +plt.subplot(4, 1, 3) +plt.plot(t, map(float, mpc_solution[0].a_ego)) +plt.plot(t, map(float, mpc_solution[0].a_l)) +plt.legend(['ego', 'lead']) +plt.title('a') +plt.grid() + + +plt.subplot(4, 1, 4) +d_l = np.array(map(float, mpc_solution[0].x_l)) - np.array(map(float, mpc_solution[0].x_ego)) +desired = 4.0 + RW(v_ego, v_l) + +plt.plot(t, d_l) +plt.plot(t, desired, '--') +plt.ylim(-1, max(max(desired), max(d_l))) +plt.legend(['relative distance', 'desired distance']) +plt.grid() + +plt.show() + +# c1 = np.exp(0.3 * NORM_RW_ERROR(v_ego, v_l, d_l)) +# c2 = np.exp(4.5 - d_l) +# print(c1) +# print(c2) + +# plt.figure() +# plt.plot(t, c1, label="NORM_RW_ERROR") +# plt.plot(t, c2, label="penalty function") +# plt.legend() + +# ## OLD MPC +# a_lead_tau = 1.5 +# a_lead_tau = max(a_lead_tau, -a_lead / (v_lead + 0.01)) + +# ffi, libmpc = libmpc_py.get_libmpc(1) +# libmpc.init(MPC_COST_LONG.TTC, MPC_COST_LONG.DISTANCE, MPC_COST_LONG.ACCELERATION, MPC_COST_LONG.JERK) +# libmpc.init_with_simulation(v_ego, x_lead, v_lead, a_lead, a_lead_tau) + +# cur_state = ffi.new("state_t *") +# cur_state[0].x_ego = 0.0 +# cur_state[0].v_ego = v_ego +# cur_state[0].a_ego = a_ego +# cur_state[0].x_lead = x_lead +# cur_state[0].v_lead = v_lead +# cur_state[0].a_lead = a_lead + +# mpc_solution = ffi.new("log_t *") + +# for _ in range(10): +# print libmpc.run_mpc(cur_state, mpc_solution, a_lead_tau) + +# t = np.hstack([np.arange(0., 1.0, 0.2), np.arange(1.0, 10.1, 0.6)]) + +# print(map(float, mpc_solution[0].x_ego)[-1]) +# print(map(float, mpc_solution[0].x_lead)[-1] - map(float, mpc_solution[0].x_ego)[-1]) +# plt.subplot(4, 2, 2) +# plt.plot(t, map(float, mpc_solution[0].x_ego)) +# plt.plot(t, map(float, mpc_solution[0].x_lead)) +# plt.legend(['ego', 'lead']) +# plt.title('x') + +# plt.subplot(4, 2, 4) +# plt.plot(t, map(float, mpc_solution[0].v_ego)) +# plt.plot(t, map(float, mpc_solution[0].v_lead)) +# plt.legend(['ego', 'lead']) +# plt.title('v') + +# plt.subplot(4, 2, 6) +# plt.plot(t, map(float, mpc_solution[0].a_ego)) +# plt.plot(t, map(float, mpc_solution[0].a_lead)) +# plt.legend(['ego', 'lead']) +# plt.title('a') + + +# plt.subplot(4, 2, 8) +# plt.plot(t, np.array(map(float, mpc_solution[0].x_lead)) - np.array(map(float, mpc_solution[0].x_ego))) + +# plt.show() diff --git a/selfdrive/debug/show_matching_cars.py b/selfdrive/debug/show_matching_cars.py new file mode 100755 index 00000000000000..424e89887d262a --- /dev/null +++ b/selfdrive/debug/show_matching_cars.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +from selfdrive.car.fingerprints import eliminate_incompatible_cars, all_known_cars +import selfdrive.messaging as messaging + + +# Prius and Leuxs es 300H +fingerprint = {898: 8, 905: 8, 810: 2, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 921: 8, 800: 8, 944: 8, 1570: 8, 1059: 1, 36: 8, 37: 8, 550: 8, 295: 8, 296: 8, 170: 8, 1071: 8, 560: 7, 945: 8, 562: 6, 180: 8, 1077: 8, 950: 8, 951: 8, 953: 8, 1595: 8, 1084: 8, 829: 2, 1086: 8, 1568: 8, 452: 8, 581: 5, 1057: 8, 713: 8, 971: 7, 975: 5, 1571: 8, 466: 8, 467: 8, 1572: 8, 1114: 8, 933: 8, 863: 8, 608: 8, 993: 8, 610: 8, 955: 8, 166: 8, 1056: 8, 956: 8, 1132: 8, 1085: 8, 552: 4, 1779: 8, 1017: 8, 1020: 8, 426: 6, 1279: 8} + +# rav4 2019 and corolla tss2 +fingerprint = {896: 8, 898: 8, 976: 1, 1541: 8, 905: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1552: 8, 1553: 8, 1556: 8, 921: 8, 1056: 8, 544: 4, 1570: 8, 1059: 1, 36: 8, 37: 8, 550: 8, 552: 4, 170: 8, 812: 8, 944: 8, 945: 8, 562: 6, 180: 8, 1077: 8, 951: 8, 824: 8, 1076: 8, 186: 4, 955: 8, 956: 8, 705: 8, 452: 8, 1592: 8, 464: 8, 1571: 8, 466: 8, 467: 8, 761: 8, 728: 8, 1572: 8, 1114: 8, 933: 8, 800: 8, 608: 8, 865: 8, 610: 8, 1595: 8, 1745: 8, 764: 8, 1002: 8, 1649: 8, 1779: 8, 1568: 8, 1017: 8, 1279: 8, 1020: 8, 810: 2, 426: 6} + +# rav4 2019 and corolla tss2 +fingerprint = {896: 8, 898: 8, 900: 6, 976: 1, 1541: 8, 902: 6, 905: 8, 810: 2, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1552: 8, 1553: 8, 1556: 8, 1571: 8, 921: 8, 1056: 8, 544: 4, 1570: 8, 1059: 1, 36: 8, 37: 8, 550: 8, 935: 8, 552: 4, 170: 8, 812: 8, 944: 8, 945: 8, 562: 6, 180: 8, 1077: 8, 951: 8, 1592: 8, 1076: 8, 186: 4, 955: 8, 956: 8, 1001: 8, 705: 8, 452: 8, 1788: 8, 464: 8, 824: 8, 466: 8, 467: 8, 761: 8, 728: 8, 1572: 8, 1114: 8, 933: 8, 800: 8, 608: 8, 865: 8, 610: 8, 1595: 8, 934: 8, 998: 5, 1745: 8, 1000: 8, 764: 8, 1002: 8, 999: 7, 1789: 8, 1649: 8, 1779: 8, 1568: 8, 1017: 8, 1786: 8, 1787: 8, 1020: 8, 426: 6, 1279: 8} + +candidate_cars = all_known_cars() + + +for addr, l in fingerprint.items(): + dat = messaging.new_message() + dat.init('can', 1) + + msg = dat.can[0] + msg.address = addr + msg.dat = " " * l + + candidate_cars = eliminate_incompatible_cars(msg, candidate_cars) + print(candidate_cars) diff --git a/selfdrive/debug/tuner.py b/selfdrive/debug/tuner.py index 066b0841aba5bc..b8a023ba29967f 100755 --- a/selfdrive/debug/tuner.py +++ b/selfdrive/debug/tuner.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 """ This tool can be used to quickly changes the values in a JSON file used for tuning Keys like in vim: diff --git a/selfdrive/locationd/calibrationd.py b/selfdrive/locationd/calibrationd.py index db4b0c2266fee6..50cc9d0157a090 100755 --- a/selfdrive/locationd/calibrationd.py +++ b/selfdrive/locationd/calibrationd.py @@ -1,4 +1,5 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 + import os import copy import json @@ -6,7 +7,7 @@ import selfdrive.messaging as messaging from selfdrive.locationd.calibration_helpers import Calibration from selfdrive.swaglog import cloudlog -from common.params import Params +from common.params import Params, put_nonblocking from common.transformations.model import model_height from common.transformations.camera import view_frame_from_device_frame, get_view_frame_from_road_frame, \ eon_intrinsics, get_calib_from_vp, H, W @@ -30,7 +31,7 @@ def is_calibration_valid(vp): vp[1] > VP_VALIDITY_CORNERS[0,1] and vp[1] < VP_VALIDITY_CORNERS[1,1] -class Calibrator(object): +class Calibrator(): def __init__(self, param_put=False): self.param_put = param_put self.vp = copy.copy(VP_INIT) @@ -38,8 +39,9 @@ def __init__(self, param_put=False): self.cal_status = Calibration.UNCALIBRATED self.write_counter = 0 self.just_calibrated = False - self.params = Params() - calibration_params = self.params.get("CalibrationParams") + + # Read calibration + calibration_params = Params().get("CalibrationParams") if calibration_params: try: calibration_params = json.loads(calibration_params) @@ -49,7 +51,6 @@ def __init__(self, param_put=False): except Exception: cloudlog.exception("CalibrationParams file found but error encountered") - def update_status(self): start_status = self.cal_status if len(self.vps) < INPUTS_NEEDED: @@ -75,7 +76,7 @@ def handle_cam_odom(self, log): if self.param_put and (self.write_counter % WRITE_CYCLES == 0 or self.just_calibrated): cal_params = {"vanishing_point": list(self.vp), "valid_points": len(self.vps)} - self.params.put("CalibrationParams", json.dumps(cal_params)) + put_nonblocking("CalibrationParams", json.dumps(cal_params).encode('utf8')) return new_vp else: return None @@ -109,7 +110,7 @@ def calibrationd_thread(sm=None, pm=None): new_vp = calibrator.handle_cam_odom(sm['cameraOdometry']) if DEBUG and new_vp is not None: - print 'got new vp', new_vp + print('got new vp', new_vp) calibrator.send_data(pm) diff --git a/selfdrive/locationd/paramsd.cc b/selfdrive/locationd/paramsd.cc index b9b4a9c1adeebb..a38729dcd12d91 100644 --- a/selfdrive/locationd/paramsd.cc +++ b/selfdrive/locationd/paramsd.cc @@ -1,17 +1,20 @@ +#include #include + #include #include #include -#include "locationd_yawrate.h" +#include "json11.hpp" #include "cereal/gen/cpp/log.capnp.h" #include "common/swaglog.h" #include "common/messaging.h" #include "common/params.h" #include "common/timing.h" + +#include "locationd_yawrate.h" #include "params_learner.h" -#include "json11.hpp" const int num_polls = 3; @@ -162,7 +165,6 @@ int main(int argc, char *argv[]) { zmq_send(live_parameters_sock_raw, bytes.begin(), bytes.size(), ZMQ_DONTWAIT); // Save parameters every minute - // TODO: Save in seperate thread if (save_counter % 6000 == 0) { json11::Json json = json11::Json::object { {"carVin", vin}, @@ -173,7 +175,10 @@ int main(int argc, char *argv[]) { }; std::string out = json.dump(); - write_db_value(NULL, "LiveParameters", out.c_str(), out.length()); + std::async(std::launch::async, + [out]{ + write_db_value(NULL, "LiveParameters", out.c_str(), out.length()); + }); } } } diff --git a/selfdrive/locationd/test/ci_test.py b/selfdrive/locationd/test/ci_test.py index 7e151093b4a73c..847dcf635f55c7 100755 --- a/selfdrive/locationd/test/ci_test.py +++ b/selfdrive/locationd/test/ci_test.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import subprocess import os import sys diff --git a/selfdrive/locationd/test/test_params_learner.py b/selfdrive/locationd/test/test_params_learner.py index b29f591e7e57bd..c1b75c5af95970 100755 --- a/selfdrive/locationd/test/test_params_learner.py +++ b/selfdrive/locationd/test/test_params_learner.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import numpy as np import unittest @@ -12,7 +12,7 @@ class TestParamsLearner(unittest.TestCase): def setUp(self): - self.CP = CarInterface.get_params(CAR.CIVIC, {}) + self.CP = CarInterface.get_params(CAR.CIVIC) bts = self.CP.to_bytes() self.params_learner = liblocationd.params_learner_init(len(bts), bts, 0.0, 1.0, self.CP.steerRatio, 1.0) diff --git a/selfdrive/locationd/test/ublox.py b/selfdrive/locationd/test/ublox.py index 175316fd8144d6..82d775930142d3 100644 --- a/selfdrive/locationd/test/ublox.py +++ b/selfdrive/locationd/test/ublox.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 ''' UBlox binary protocol handling @@ -10,6 +10,7 @@ for ublox version 8, not all functions may work. ''' + import struct import time, os @@ -534,7 +535,7 @@ class UBloxMessage: '''UBlox message class - holds a UBX binary message''' def __init__(self): - self._buf = "" + self._buf = b"" self._fields = {} self._recs = [] self._unpacked = False @@ -613,11 +614,11 @@ def name(self): def msg_class(self): '''return the message class''' - return ord(self._buf[2]) + return self._buf[2] def msg_id(self): '''return the message id within the class''' - return ord(self._buf[3]) + return self._buf[3] def msg_type(self): '''return the message type tuple (class, id)''' @@ -630,9 +631,9 @@ def msg_length(self): def valid_so_far(self): '''check if the message is valid so far''' - if len(self._buf) > 0 and ord(self._buf[0]) != PREAMBLE1: + if len(self._buf) > 0 and self._buf[0] != PREAMBLE1: return False - if len(self._buf) > 1 and ord(self._buf[1]) != PREAMBLE2: + if len(self._buf) > 1 and self._buf[1] != PREAMBLE2: self.debug(1, "bad pre2") return False if self.needed_bytes() == 0 and not self.valid(): @@ -661,7 +662,7 @@ def checksum(self, data=None): ck_a = 0 ck_b = 0 for i in data: - ck_a = (ck_a + ord(i)) & 0xFF + ck_a = (ck_a + i) & 0xFF ck_b = (ck_b + ck_a) & 0xFF return (ck_a, ck_b) @@ -713,7 +714,7 @@ def __init__(self, port, baudrate=115200, timeout=0, panda=False, grey=False): self.dev = PandaSerial(self.panda, 1, self.baudrate) self.baudrate = 460800 - print "upping baud:",self.baudrate + print("upping baud:",self.baudrate) self.send_nmea("$PUBX,41,1,0007,0003,%u,0" % self.baudrate) time.sleep(0.1) @@ -722,7 +723,7 @@ def __init__(self, port, baudrate=115200, timeout=0, panda=False, grey=False): from selfdrive.services import service_list import selfdrive.messaging as messaging - class BoarddSerial(object): + class BoarddSerial(): def __init__(self): self.ubloxRaw = messaging.sub_sock(service_list['ubloxRaw'].port) self.buf = "" diff --git a/selfdrive/locationd/test/ubloxd.py b/selfdrive/locationd/test/ubloxd.py index 388a69bf429bed..409bfc331ce222 100755 --- a/selfdrive/locationd/test/ubloxd.py +++ b/selfdrive/locationd/test/ubloxd.py @@ -1,4 +1,5 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 + import os import serial from selfdrive.locationd.test import ublox @@ -210,7 +211,7 @@ def gen_raw(msg): cnos = {} for meas in measurements_parsed: cnos[meas['svId']] = meas['cno'] - print 'Carrier to noise ratio for each sat: \n', cnos, '\n' + print('Carrier to noise ratio for each sat: \n', cnos, '\n') receiverStatus_bools = int_to_bool_list(msg_meta_data['recStat']) receiverStatus = {'leapSecValid': receiverStatus_bools[0], 'clkReset': receiverStatus_bools[2]} @@ -254,7 +255,7 @@ def handle_msg(dev, msg, nav_frame_buffer): ubloxGnss.send(nav.to_bytes()) else: - print "UNKNNOWN MESSAGE:", msg.name() + print("UNKNNOWN MESSAGE:", msg.name()) except ublox.UBloxError as e: print(e) @@ -265,7 +266,7 @@ def main(gctx=None): global gpsLocationExternal, ubloxGnss nav_frame_buffer = {} nav_frame_buffer[0] = {} - for i in xrange(1,33): + for i in range(1,33): nav_frame_buffer[0][i] = {} diff --git a/selfdrive/locationd/test/ubloxd_easy.py b/selfdrive/locationd/test/ubloxd_easy.py index 8bb16d403a3d6b..b936badd57bb4d 100755 --- a/selfdrive/locationd/test/ubloxd_easy.py +++ b/selfdrive/locationd/test/ubloxd_easy.py @@ -1,4 +1,5 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 + import os from selfdrive.locationd.test import ublox from common import realtime @@ -46,7 +47,7 @@ def main(gctx=None): raw.logMonoTime = int(realtime.sec_since_boot() * 1e9) ubloxGnss.send(raw.to_bytes()) else: - print "INVALID MESSAGE" + print("INVALID MESSAGE") if __name__ == "__main__": diff --git a/selfdrive/locationd/test/ubloxd_py_test.py b/selfdrive/locationd/test/ubloxd_py_test.py index 81040811834f6d..bca9ddc421564d 100755 --- a/selfdrive/locationd/test/ubloxd_py_test.py +++ b/selfdrive/locationd/test/ubloxd_py_test.py @@ -17,7 +17,7 @@ def mkdirs_exists_ok(path): def parser_test(fn, prefix): nav_frame_buffer = {} nav_frame_buffer[0] = {} - for i in xrange(1, 33): + for i in range(1, 33): nav_frame_buffer[0][i] = {} if not os.path.exists(prefix): diff --git a/selfdrive/locationd/test/ubloxd_regression_test.py b/selfdrive/locationd/test/ubloxd_regression_test.py index 94d6b4fe206388..29210bf545cd55 100644 --- a/selfdrive/locationd/test/ubloxd_regression_test.py +++ b/selfdrive/locationd/test/ubloxd_regression_test.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import os import sys import argparse diff --git a/selfdrive/locationd/ubloxd_main.cc b/selfdrive/locationd/ubloxd_main.cc index 3ea080ad9d9da9..df3b3aa8bcf571 100644 --- a/selfdrive/locationd/ubloxd_main.cc +++ b/selfdrive/locationd/ubloxd_main.cc @@ -25,7 +25,7 @@ #include "ublox_msg.h" -volatile int do_exit = 0; // Flag for process exit on signal +volatile sig_atomic_t do_exit = 0; // Flag for process exit on signal void set_do_exit(int sig) { do_exit = 1; diff --git a/selfdrive/loggerd/deleter.py b/selfdrive/loggerd/deleter.py index b1e1ffcd04a5ca..5669e2342d2318 100644 --- a/selfdrive/loggerd/deleter.py +++ b/selfdrive/loggerd/deleter.py @@ -1,10 +1,10 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import os import shutil import threading from selfdrive.swaglog import cloudlog from selfdrive.loggerd.config import ROOT, get_available_percent -from selfdrive.loggerd.uploader import listdir_by_creation_date +from selfdrive.loggerd.uploader import listdir_by_creation def deleter_thread(exit_event): @@ -13,7 +13,7 @@ def deleter_thread(exit_event): if available_percent < 10.0: # remove the earliest directory we can - dirs = listdir_by_creation_date(ROOT) + dirs = listdir_by_creation(ROOT) for delete_dir in dirs: delete_path = os.path.join(ROOT, delete_dir) diff --git a/selfdrive/loggerd/loggerd.cc b/selfdrive/loggerd/loggerd.cc index db59780f0b3bba..ec4c1140e1e858 100644 --- a/selfdrive/loggerd/loggerd.cc +++ b/selfdrive/loggerd/loggerd.cc @@ -63,7 +63,7 @@ double randrange(double a, double b) { } -volatile int do_exit = 0; +volatile sig_atomic_t do_exit = 0; static void set_do_exit(int sig) { do_exit = 1; } @@ -126,7 +126,7 @@ void encoder_thread(bool is_streaming, bool raw_clips, bool front) { if (!encoder_inited) { LOGD("encoder init %dx%d", buf_info.width, buf_info.height); - encoder_init(&encoder, front ? "dcamera" : "fcamera", buf_info.width, buf_info.height, CAMERA_FPS, front ? 1000000 : 5000000); + encoder_init(&encoder, front ? "dcamera" : "fcamera", buf_info.width, buf_info.height, CAMERA_FPS, front ? 2500000 : 5000000); encoder_inited = true; if (is_streaming) { encoder.stream_sock_raw = zmq_socket(s.ctx, ZMQ_PUB); diff --git a/selfdrive/loggerd/tests/fill_eon.py b/selfdrive/loggerd/tests/fill_eon.py index 8ebc5ceb2a82d3..f273ea89ec7e9f 100755 --- a/selfdrive/loggerd/tests/fill_eon.py +++ b/selfdrive/loggerd/tests/fill_eon.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 """Script to fill up EON with fake data""" import os diff --git a/selfdrive/loggerd/tests/loggerd_tests_common.py b/selfdrive/loggerd/tests/loggerd_tests_common.py index dd48381d8efecd..9db75a7f59783e 100644 --- a/selfdrive/loggerd/tests/loggerd_tests_common.py +++ b/selfdrive/loggerd/tests/loggerd_tests_common.py @@ -7,7 +7,6 @@ import selfdrive.loggerd.uploader as uploader - def create_random_file(file_path, size_mb, lock=False): try: os.mkdir(os.path.dirname(file_path)) @@ -28,6 +27,30 @@ def create_random_file(file_path, size_mb, lock=False): if not lock: os.remove(lock_path) +class MockResponse(): + def __init__(self, text): + self.text = text + +class MockApi(): + def __init__(self, dongle_id): + pass + + def get(self, *args, **kwargs): + return MockResponse('{"url": "http://localhost/does/not/exist", "headers": {}}') + + def get_token(self): + return "fake-token" + +class MockParams(): + def __init__(self): + self.params = { + "DongleId": b"0000000000000000", + "IsUploadRawEnabled": b"1", + "IsUploadVideoOverCellularEnabled": b"1" + } + + def get(self, k): + return self.params[k] class UploaderTestCase(unittest.TestCase): f_type = "UNKNOWN" @@ -35,8 +58,14 @@ class UploaderTestCase(unittest.TestCase): def setUp(self): self.root = tempfile.mkdtemp() uploader.ROOT = self.root # Monkey patch root dir + uploader.Api = MockApi + uploader.Params = MockParams + uploader.fake_upload = 1 + uploader.is_on_hotspot = lambda *args: False + uploader.is_on_wifi = lambda *args: False self.seg_num = random.randint(1, 300) self.seg_format = "2019-04-18--12-52-54--{}" + self.seg_format2 = "2019-05-18--11-22-33--{}" self.seg_dir = self.seg_format.format(self.seg_num) def tearDown(self): @@ -48,6 +77,6 @@ def tearDown(self): def make_file_with_data(self, f_dir, fn, size_mb=.1, lock=False): file_path = os.path.join(self.root, f_dir, fn) - create_random_file(file_path, size_mb) + create_random_file(file_path, size_mb, lock) return file_path diff --git a/selfdrive/loggerd/tests/test_deleter.py b/selfdrive/loggerd/tests/test_deleter.py index 6e62db600f5b01..adbb0f0316fc21 100644 --- a/selfdrive/loggerd/tests/test_deleter.py +++ b/selfdrive/loggerd/tests/test_deleter.py @@ -6,22 +6,19 @@ import selfdrive.loggerd.deleter as deleter from common.timeout import Timeout, TimeoutException -from loggerd_tests_common import UploaderTestCase +from selfdrive.loggerd.tests.loggerd_tests_common import UploaderTestCase Stats = namedtuple("Stats", ['f_bavail', 'f_blocks']) -fake_stats = Stats(f_bavail=0, f_blocks=10) - - -def fake_statvfs(d): - return fake_stats - - class TestDeleter(UploaderTestCase): + def fake_statvfs(self, d): + return self.fake_stats + def setUp(self): self.f_type = "fcamera.hevc" super(TestDeleter, self).setUp() - deleter.os.statvfs = fake_statvfs + self.fake_stats = Stats(f_bavail=0, f_blocks=10) + deleter.os.statvfs = self.fake_statvfs deleter.ROOT = self.root def tearDown(self): @@ -69,10 +66,9 @@ def test_delete_files_in_create_order(self): self.assertTrue(os.path.exists(f_path_2), "Newer file deleted before older file") def test_no_delete_when_available_space(self): - global fake_stats f_path = self.make_file_with_data(self.seg_dir, self.f_type) - fake_stats = Stats(f_bavail=10, f_blocks=10) + self.fake_stats = Stats(f_bavail=10, f_blocks=10) self.start_thread() diff --git a/selfdrive/loggerd/tests/test_uploader.py b/selfdrive/loggerd/tests/test_uploader.py new file mode 100644 index 00000000000000..ed9a9722208ca9 --- /dev/null +++ b/selfdrive/loggerd/tests/test_uploader.py @@ -0,0 +1,116 @@ +import os +import time +import threading +import logging +import json + +from selfdrive.swaglog import cloudlog +import selfdrive.loggerd.uploader as uploader + +from common.timeout import Timeout + +from selfdrive.loggerd.tests.loggerd_tests_common import UploaderTestCase + +class TestLogHandler(logging.Handler): + def __init__(self): + logging.Handler.__init__(self) + self.reset() + + def reset(self): + self.upload_order = list() + + def emit(self, record): + try: + j = json.loads(record.message) + if j["event"] == "upload_success": + self.upload_order.append(j["key"]) + except BaseException: + pass + +log_handler = TestLogHandler() +cloudlog.addHandler(log_handler) + +class TestUploader(UploaderTestCase): + def setUp(self): + super(TestUploader, self).setUp() + log_handler.reset() + + def tearDown(self): + super(TestUploader, self).tearDown() + + def start_thread(self): + self.end_event = threading.Event() + self.up_thread = threading.Thread(target=uploader.uploader_fn, args=[self.end_event]) + self.up_thread.daemon = True + self.up_thread.start() + + def join_thread(self): + self.end_event.set() + self.up_thread.join() + + def gen_files(self, lock=False): + f_paths = list() + for t in ["bootlog.bz2", "qlog.bz2", "rlog.bz2", "dcamera.hevc", "fcamera.hevc"]: + f_paths.append(self.make_file_with_data(self.seg_dir, t, 1, lock=lock)) + return f_paths + + def gen_order(self, seg1, seg2): + keys = [f"{self.seg_format.format(i)}/qlog.bz2" for i in seg1] + keys += [f"{self.seg_format2.format(i)}/qlog.bz2" for i in seg2] + for i in seg1: + keys += [f"{self.seg_format.format(i)}/{f}" for f in ['rlog.bz2','fcamera.hevc','dcamera.hevc']] + for i in seg2: + keys += [f"{self.seg_format2.format(i)}/{f}" for f in ['rlog.bz2','fcamera.hevc','dcamera.hevc']] + keys += [f"{self.seg_format.format(i)}/bootlog.bz2" for i in seg1] + keys += [f"{self.seg_format2.format(i)}/bootlog.bz2" for i in seg2] + return keys + + def test_upload(self): + f_paths = self.gen_files(lock=False) + + self.start_thread() + + with Timeout(5, "Timeout waiting for file to be uploaded"): + while len(os.listdir(self.root)): + time.sleep(0.01) + self.join_thread() + + for f_path in f_paths: + self.assertFalse(os.path.exists(f_path), "All files not uploaded") + exp_order = self.gen_order([self.seg_num], []) + self.assertTrue(log_handler.upload_order == exp_order, "Files uploaded in wrong order") + + def test_upload_files_in_create_order(self): + f_paths = list() + seg1_nums = [0,1,2,10,20] + for i in seg1_nums: + self.seg_dir = self.seg_format.format(i) + f_paths += self.gen_files() + seg2_nums = [5,50,51] + for i in seg2_nums: + self.seg_dir = self.seg_format2.format(i) + f_paths += self.gen_files() + + self.start_thread() + + with Timeout(5, "Timeout waiting for file to be upload"): + while len(os.listdir(self.root)): + time.sleep(0.01) + + self.join_thread() + + for f_path in f_paths: + self.assertFalse(os.path.exists(f_path), "All files not uploaded") + exp_order = self.gen_order(seg1_nums, seg2_nums) + self.assertTrue(log_handler.upload_order == exp_order, "Files uploaded in wrong order") + + def test_no_upload_with_lock_file(self): + f_paths = self.gen_files(lock=True) + + self.start_thread() + # allow enough time that files should have been uploaded if they would be uploaded + time.sleep(5) + self.join_thread() + + for f_path in f_paths: + self.assertTrue(os.path.exists(f_path), "File upload when locked") diff --git a/selfdrive/loggerd/uploader.py b/selfdrive/loggerd/uploader.py index 38887f4ad2b279..dc9a2765f4856d 100644 --- a/selfdrive/loggerd/uploader.py +++ b/selfdrive/loggerd/uploader.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import os import re import time -import stat import json import random import ctypes @@ -12,7 +11,6 @@ import threading import subprocess -from collections import Counter from selfdrive.swaglog import cloudlog from selfdrive.loggerd.config import ROOT @@ -43,20 +41,17 @@ def raise_on_thread(t, exctype): ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0) raise SystemError("PyThreadState_SetAsyncExc failed") -def listdir_with_creation_date(d): - lst = os.listdir(d) - for fn in lst: - try: - st = os.stat(os.path.join(d, fn)) - ctime = st[stat.ST_CTIME] - yield (ctime, fn) - except OSError: - cloudlog.exception("listdir_with_creation_date: stat failed?") - yield (None, fn) +def get_directory_sort(d): + return list(map(lambda s: s.rjust(10, '0'), d.rsplit('--', 1))) -def listdir_by_creation_date(d): - times_and_paths = list(listdir_with_creation_date(d)) - return [path for _, path in sorted(times_and_paths)] +def listdir_by_creation(d): + try: + paths = os.listdir(d) + paths = sorted(paths, key=get_directory_sort) + return paths + except OSError: + cloudlog.exception("listdir_by_creation failed") + return list() def clear_locks(root): for logname in os.listdir(root): @@ -71,17 +66,20 @@ def clear_locks(root): def is_on_wifi(): # ConnectivityManager.getActiveNetworkInfo() try: - result = subprocess.check_output(["service", "call", "connectivity", "2"]).strip().split("\n") + result = subprocess.check_output(["service", "call", "connectivity", "2"], encoding='utf8').strip().split("\n") # pylint: disable=unexpected-keyword-arg except subprocess.CalledProcessError: return False - data = ''.join(''.join(w.decode("hex")[::-1] for w in l[14:49].split()) for l in result[1:]) + # Concatenate all ascii parts + r = "" + for line in result[1:]: + r += line[51:67] - return "\x00".join("WIFI") in data + return "W.I.F.I" in r def is_on_hotspot(): try: - result = subprocess.check_output(["ifconfig", "wlan0"]) + result = subprocess.check_output(["ifconfig", "wlan0"], encoding='utf8') # pylint: disable=unexpected-keyword-arg result = re.findall(r"inet addr:((\d+\.){3}\d+)", result)[0][0] is_android = result.startswith('192.168.43.') @@ -92,7 +90,7 @@ def is_on_hotspot(): except: return False -class Uploader(object): +class Uploader(): def __init__(self, dongle_id, root): self.dongle_id = dongle_id self.api = Api(dongle_id) @@ -103,6 +101,9 @@ def __init__(self, dongle_id, root): self.last_resp = None self.last_exc = None + self.immediate_priority = {"qlog.bz2": 0} + self.high_priority = {"rlog.bz2": 0, "fcamera.hevc": 1, "dcamera.hevc": 2} + def clean_dirs(self): try: for logname in os.listdir(self.root): @@ -113,10 +114,17 @@ def clean_dirs(self): except OSError: cloudlog.exception("clean_dirs failed") + def get_upload_sort(self, name): + if name in self.immediate_priority: + return self.immediate_priority[name] + if name in self.high_priority: + return self.high_priority[name] + 100 + return 1000 + def gen_upload_files(self): if not os.path.isdir(self.root): return - for logname in listdir_by_creation_date(self.root): + for logname in listdir_by_creation(self.root): path = os.path.join(self.root, logname) try: names = os.listdir(path) @@ -125,44 +133,32 @@ def gen_upload_files(self): if any(name.endswith(".lock") for name in names): continue - for name in names: + for name in sorted(names, key=self.get_upload_sort): key = os.path.join(logname, name) fn = os.path.join(path, name) yield (name, key, fn) - def get_data_stats(self): - name_counts = Counter() - total_size = 0 - for name, key, fn in self.gen_upload_files(): - name_counts[name] += 1 - total_size += os.stat(fn).st_size - return dict(name_counts), total_size - def next_file_to_upload(self, with_raw): + upload_files = list(self.gen_upload_files()) # try to upload qlog files first - for name, key, fn in self.gen_upload_files(): - if name == "qlog.bz2": - return (key, fn, 0) + for name, key, fn in upload_files: + if name in self.immediate_priority: + return (key, fn) if with_raw: # then upload the full log files, rear and front camera files - for name, key, fn in self.gen_upload_files(): - if name == "rlog.bz2": - return (key, fn, 1) - elif name == "fcamera.hevc": - return (key, fn, 2) - elif name == "dcamera.hevc": - return (key, fn, 3) + for name, key, fn in upload_files: + if name in self.high_priority: + return (key, fn) # then upload other files - for name, key, fn in self.gen_upload_files(): + for name, key, fn in upload_files: if not name.endswith('.lock') and not name.endswith(".tmp"): - return (key, fn, 4) + return (key, fn) return None - def do_upload(self, key, fn): try: url_resp = self.api.get("v1.3/"+self.dongle_id+"/upload_url/", timeout=10, path=key, access_token=self.api.get_token()) @@ -173,7 +169,7 @@ def do_upload(self, key, fn): if fake_upload: cloudlog.info("*** WARNING, THIS IS A FAKE UPLOAD TO %s ***" % url) - class FakeResponse(object): + class FakeResponse(): def __init__(self): self.status_code = 200 self.last_resp = FakeResponse() @@ -231,13 +227,11 @@ def upload(self, key, fn): return success - - def uploader_fn(exit_event): cloudlog.info("uploader_fn") params = Params() - dongle_id = params.get("DongleId") + dongle_id = params.get("DongleId").decode('utf8') if dongle_id is None: cloudlog.info("uploader missing dongle_id") @@ -247,8 +241,8 @@ def uploader_fn(exit_event): backoff = 0.1 while True: - allow_raw_upload = (params.get("IsUploadRawEnabled") != "0") - allow_cellular = (params.get("IsUploadVideoOverCellularEnabled") != "0") + allow_raw_upload = (params.get("IsUploadRawEnabled") != b"0") + allow_cellular = (params.get("IsUploadVideoOverCellularEnabled") != b"0") on_hotspot = is_on_hotspot() on_wifi = is_on_wifi() should_upload = allow_cellular or (on_wifi and not on_hotspot) @@ -261,7 +255,7 @@ def uploader_fn(exit_event): time.sleep(5) continue - key, fn, _ = d + key, fn = d cloudlog.event("uploader_netcheck", allow_cellular=allow_cellular, is_on_hotspot=on_hotspot, is_on_wifi=on_wifi) cloudlog.info("to upload %r", d) diff --git a/selfdrive/logmessaged.py b/selfdrive/logmessaged.py index c2c583dfc55444..57e5416aa5f3dd 100755 --- a/selfdrive/logmessaged.py +++ b/selfdrive/logmessaged.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import zmq from logentries import LogentriesHandler from selfdrive.services import service_list @@ -19,7 +19,8 @@ def main(gctx=None): pub_sock = messaging.pub_sock(service_list['logMessage'].port) while True: - dat = ''.join(sock.recv_multipart()) + dat = b''.join(sock.recv_multipart()) + dat = dat.decode('utf8') # print "RECV", repr(dat) diff --git a/selfdrive/manager.py b/selfdrive/manager.py index 62bf834b68f369..fb8b92e1667cec 100755 --- a/selfdrive/manager.py +++ b/selfdrive/manager.py @@ -1,10 +1,12 @@ -#!/usr/bin/env python2.7 +#!/usr/bin/env python3.7 import os import sys import fcntl import errno import signal import subprocess +import datetime +from common.spinner import Spinner from common.basedir import BASEDIR sys.path.append(os.path.join(BASEDIR, "pyextra")) @@ -34,53 +36,24 @@ def unblock_stdout(): break try: - sys.stdout.write(dat) + sys.stdout.write(dat.decode('utf8')) except (OSError, IOError): pass os._exit(os.wait()[1]) if __name__ == "__main__": - is_neos = os.path.isfile("/init.qcom.rc") - neos_update_required = False - - if is_neos: - version = int(open("/VERSION").read()) if os.path.isfile("/VERSION") else 0 - revision = int(open("/REVISION").read()) if version >= 10 else 0 # Revision only present in NEOS 10 and up - neos_update_required = version < 10 or (version == 10 and revision < 4) - - if neos_update_required: - # update continue.sh before updating NEOS - if os.path.isfile(os.path.join(BASEDIR, "scripts", "continue.sh")): - from shutil import copyfile - copyfile(os.path.join(BASEDIR, "scripts", "continue.sh"), "/data/data/com.termux/files/continue.sh") - - # run the updater - print("Starting NEOS updater") - subprocess.check_call(["git", "clean", "-xdf"], cwd=BASEDIR) - updater_dir = os.path.join(BASEDIR, "installer", "updater") - manifest_path = os.path.realpath(os.path.join(updater_dir, "update.json")) - os.system(os.path.join(updater_dir, "updater") + " file://" + manifest_path) - raise Exception("NEOS outdated") - elif os.path.isdir("/data/neoupdate"): - from shutil import rmtree - rmtree("/data/neoupdate") - unblock_stdout() import glob import shutil import hashlib import importlib -import re -import stat -import subprocess import traceback from multiprocessing import Process from setproctitle import setproctitle #pylint: disable=no-name-in-module -from common.file_helpers import atomic_write_in_dir_neos from common.params import Params import cereal ThermalStatus = cereal.log.ThermalData.ThermalStatus @@ -134,7 +107,7 @@ def get_running(): interrupt_processes = [] # processes to end with SIGKILL instead of SIGTERM -kill_processes = ['sensord'] +kill_processes = ['sensord', 'paramsd'] persistent_processes = [ 'thermald', @@ -405,7 +378,7 @@ def manager_thread(): break def get_installed_apks(): - dat = subprocess.check_output(["pm", "list", "packages", "-f"]).strip().split("\n") + dat = subprocess.check_output(["pm", "list", "packages", "-f"], encoding='utf8').strip().split("\n") # pylint: disable=unexpected-keyword-arg ret = {} for x in dat: if x.startswith("package:"): @@ -440,10 +413,10 @@ def update_apks(): if not os.path.exists(apk_path): continue - h1 = hashlib.sha1(open(apk_path).read()).hexdigest() + h1 = hashlib.sha1(open(apk_path, 'rb').read()).hexdigest() h2 = None if installed[app] is not None: - h2 = hashlib.sha1(open(installed[app]).read()).hexdigest() + h2 = hashlib.sha1(open(installed[app], 'rb').read()).hexdigest() cloudlog.info("comparing version of %s %s vs %s" % (app, h1, h2)) if h2 is None or h1 != h2: @@ -457,46 +430,7 @@ def update_apks(): assert success -def update_ssh(): - ssh_home_dirpath = "/system/comma/home/.ssh/" - auth_keys_path = os.path.join(ssh_home_dirpath, "authorized_keys") - auth_keys_persist_path = os.path.join(ssh_home_dirpath, "authorized_keys.persist") - auth_keys_mode = stat.S_IREAD | stat.S_IWRITE - - params = Params() - github_keys = params.get("GithubSshKeys") or '' - - old_keys = open(auth_keys_path).read() - has_persisted_keys = os.path.exists(auth_keys_persist_path) - if has_persisted_keys: - persisted_keys = open(auth_keys_persist_path).read() - else: - # add host filter - persisted_keys = re.sub(r'^(?!.+?from.+? )(ssh|ecdsa)', 'from="10.0.0.0/8,172.16.0.0/12,192.168.0.0/16" \\1', old_keys, flags=re.MULTILINE) - - new_keys = persisted_keys + '\n' + github_keys - - if has_persisted_keys and new_keys == old_keys and os.stat(auth_keys_path)[stat.ST_MODE] == auth_keys_mode: - # nothing to do - let's avoid remount - return - - try: - subprocess.check_call(["mount", "-o", "rw,remount", "/system"]) - if not has_persisted_keys: - atomic_write_in_dir_neos(auth_keys_persist_path, persisted_keys, mode=auth_keys_mode) - - atomic_write_in_dir_neos(auth_keys_path, new_keys, mode=auth_keys_mode) - finally: - try: - subprocess.check_call(["mount", "-o", "ro,remount", "/system"]) - except: - cloudlog.exception("Failed to remount as read-only") - # this can fail due to "Device busy" - reboot if so - os.system("reboot") - raise RuntimeError - def manager_update(): - update_ssh() update_apks() uninstall = [app for app in get_installed_apks().keys() if app in ("com.spotify.music", "com.waze")] @@ -504,13 +438,16 @@ def manager_update(): cloudlog.info("uninstalling %s" % app) os.system("pm uninstall % s" % app) -def manager_prepare(): +def manager_prepare(spinner=None): # build cereal first subprocess.check_call(["make", "-j4"], cwd=os.path.join(BASEDIR, "cereal")) # build all processes os.chdir(os.path.dirname(os.path.abspath(__file__))) - for p in managed_processes: + + for i, p in enumerate(managed_processes): + if spinner is not None: + spinner.update("%d" % (100.0 * (i + 1) / len(managed_processes),)) prepare_managed_process(p) def uninstall(): @@ -557,12 +494,16 @@ def main(): params.manager_start() # set unset params + if params.get("CompletedTrainingVersion") is None: + params.put("CompletedTrainingVersion", "0") if params.get("IsMetric") is None: params.put("IsMetric", "0") if params.get("RecordFront") is None: params.put("RecordFront", "0") if params.get("HasAcceptedTerms") is None: params.put("HasAcceptedTerms", "0") + if params.get("HasCompletedSetup") is None: + params.put("HasCompletedSetup", "0") if params.get("IsUploadRawEnabled") is None: params.put("IsUploadRawEnabled", "1") if params.get("IsUploadVideoOverCellularEnabled") is None: @@ -577,6 +518,11 @@ def main(): params.put("LimitSetSpeed", "0") if params.get("LimitSetSpeedNeural") is None: params.put("LimitSetSpeedNeural", "0") + if params.get("LastUpdateTime") is None: + t = datetime.datetime.now().isoformat() + params.put("LastUpdateTime", t.encode('utf8')) + if params.get("OpenpilotEnabledToggle") is None: + params.put("OpenpilotEnabledToggle", "1") # is this chffrplus? if os.getenv("PASSIVE") is not None: @@ -585,21 +531,11 @@ def main(): if params.get("Passive") is None: raise Exception("Passive must be set to continue") - # put something on screen while we set things up - if os.getenv("PREPAREONLY") is not None: - spinner_proc = None - else: - spinner_text = "chffrplus" if params.get("Passive")=="1" else "openpilot" - spinner_proc = subprocess.Popen(["./spinner", "loading %s"%spinner_text], - cwd=os.path.join(BASEDIR, "selfdrive", "ui", "spinner"), - close_fds=True) - try: - manager_update() - manager_init() - manager_prepare() - finally: - if spinner_proc: - spinner_proc.terminate() + with Spinner() as spinner: + spinner.update("0") # Show progress bar + manager_update() + manager_init() + manager_prepare(spinner) if os.getenv("PREPAREONLY") is not None: return diff --git a/selfdrive/messaging.py b/selfdrive/messaging.py index 13fb41efebd754..3310ff0785bfa5 100644 --- a/selfdrive/messaging.py +++ b/selfdrive/messaging.py @@ -31,6 +31,24 @@ def sub_sock(port, poller=None, addr="127.0.0.1", conflate=False, timeout=None): poller.register(sock, zmq.POLLIN) return sock + +def drain_sock_raw_poller(poller, sock, wait_for_one=False): + ret = [] + + if wait_for_one: + try: + ret.append(sock.recv()) + except zmq.error.Again: # Thrown when there is timeout on the socket + return ret + + while True: + if not poller.poll(0): + break # Socket has no more messages + + ret.append(sock.recv()) + + return ret + def drain_sock_raw(sock, wait_for_one=False): ret = [] while 1: @@ -84,7 +102,7 @@ def recv_one_or_none(sock): return None -class SubMaster(object): +class SubMaster(): def __init__(self, services, ignore_alive=None, addr="127.0.0.1"): self.poller = zmq.Poller() self.frame = -1 @@ -108,8 +126,14 @@ def __init__(self, services, ignore_alive=None, addr="127.0.0.1"): if addr is not None: self.sock[s] = sub_sock(service_list[s].port, poller=self.poller, addr=addr, conflate=True) self.freq[s] = service_list[s].frequency + data = new_message() - data.init(s) + if s in ['can', 'sensorEvents', 'liveTracks', 'sendCan', + 'ethernetData', 'cellInfo', 'wifiScan', + 'trafficEvents', 'orbObservation', 'carEvents']: + data.init(s, 0) + else: + data.init(s) self.data[s] = getattr(data, s) self.logMonoTime[s] = 0 self.valid[s] = data.valid @@ -168,6 +192,6 @@ def __init__(self, services): def send(self, s, dat): # accept either bytes or capnp builder - if not isinstance(dat, str): + if not isinstance(dat, bytes): dat = dat.to_bytes() self.sock[s].send(dat) diff --git a/selfdrive/pandad.py b/selfdrive/pandad.py index 09f2e717f9f24b..eac0ea92d133ad 100755 --- a/selfdrive/pandad.py +++ b/selfdrive/pandad.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # simple boardd wrapper that updates the panda first import os import time @@ -32,11 +32,15 @@ def update_panda(): panda_dfu = PandaDFU(panda_dfu[0]) panda_dfu.recover() - print "waiting for board..." + print("waiting for board...") time.sleep(1) - current_version = "bootstub" if panda.bootstub else str(panda.get_version()) - cloudlog.info("Panda connected, version: %s, expected %s" % (current_version, repo_version)) + try: + serial = panda.get_serial()[0].decode("utf-8") + except Exception: + serial = None + current_version = "bootstub" if panda.bootstub else panda.get_version() + cloudlog.warning("Panda %s connected, version: %s, expected %s" % (serial, current_version, repo_version)) if panda.bootstub or not current_version.startswith(repo_version): cloudlog.info("Panda firmware out of date, update required") @@ -60,7 +64,7 @@ def update_panda(): cloudlog.info("Panda still not booting, exiting") raise AssertionError - version = str(panda.get_version()) + version = panda.get_version() if not version.startswith(repo_version): cloudlog.info("Version mismatch after flashing, exiting") raise AssertionError diff --git a/selfdrive/registration.py b/selfdrive/registration.py index 5d45b11292759d..1c85e40b2204a8 100644 --- a/selfdrive/registration.py +++ b/selfdrive/registration.py @@ -1,42 +1,50 @@ import os import json +import binascii import subprocess -import struct +import itertools from datetime import datetime, timedelta from selfdrive.swaglog import cloudlog from selfdrive.version import version, terms_version, training_version, get_git_commit, get_git_branch, get_git_remote from common.api import api_get from common.params import Params -from common.file_helpers import mkdirs_exists_ok def get_imei(): - ret = subprocess.check_output(["getprop", "oem.device.imeicache"]).strip() + ret = subprocess.check_output(["getprop", "oem.device.imeicache"], encoding='utf8').strip() # pylint: disable=unexpected-keyword-arg if ret == "": ret = "000000000000000" return ret def get_serial(): - return subprocess.check_output(["getprop", "ro.serialno"]).strip() + return subprocess.check_output(["getprop", "ro.serialno"], encoding='utf8').strip() # pylint: disable=unexpected-keyword-arg # TODO: move this to a library def parse_service_call(call): - ret = subprocess.check_output(call).strip() + ret = subprocess.check_output(call, encoding='utf8').strip() # pylint: disable=unexpected-keyword-arg if 'Parcel' not in ret: return None + try: - def fh(x): - if len(x) != 8: - return [] - return [x[6:8], x[4:6], x[2:4], x[0:2]] - hd = [] - for x in ret.split("\n")[1:]: - for k in map(fh, x.split(": ")[1].split(" '")[0].split(" ")): - hd.extend(k) - return ''.join([chr(int(x, 16)) for x in hd]) + r = b"" + for line in ret.split("\n")[1:]: # Skip 'Parcel(' + line_hex = line[14:49].replace(' ', '') + r += binascii.unhexlify(line_hex) + + r = r[8:] # Cut off length field + r = r.decode('utf_16_be') + + # All pairs of two characters seem to be swapped. Not sure why + result = "" + for a, b, in itertools.zip_longest(r[::2], r[1::2], fillvalue='\x00'): + result += b + a + + result = result.replace('\x00', '') + + return result except Exception: return None @@ -45,9 +53,7 @@ def get_subscriber_info(): ret = parse_service_call(["service", "call", "iphonesubinfo", "7"]) if ret is None or len(ret) < 8: return "" - if struct.unpack("I", ret[4:8]) == -1: - return "" - return ret[8:-2:2] + return ret def register(): @@ -60,22 +66,11 @@ def register(): params.put("GitRemote", get_git_remote()) params.put("SubscriberInfo", get_subscriber_info()) - # create a key for auth - # your private key is kept on your device persist partition and never sent to our servers - # do not erase your persist partition - if not os.path.isfile("/persist/comma/id_rsa.pub"): - cloudlog.warning("generating your personal RSA key") - mkdirs_exists_ok("/persist/comma") - assert os.system("openssl genrsa -out /persist/comma/id_rsa.tmp 2048") == 0 - assert os.system("openssl rsa -in /persist/comma/id_rsa.tmp -pubout -out /persist/comma/id_rsa.tmp.pub") == 0 - os.rename("/persist/comma/id_rsa.tmp", "/persist/comma/id_rsa") - os.rename("/persist/comma/id_rsa.tmp.pub", "/persist/comma/id_rsa.pub") - # make key readable by app users (ai.comma.plus.offroad) os.chmod('/persist/comma/', 0o755) os.chmod('/persist/comma/id_rsa', 0o744) - dongle_id, access_token = params.get("DongleId"), params.get("AccessToken") + dongle_id, access_token = params.get("DongleId", encoding='utf8'), params.get("AccessToken", encoding='utf8') public_key = open("/persist/comma/id_rsa.pub").read() # create registration token @@ -91,7 +86,7 @@ def register(): resp = api_get("v2/pilotauth/", method='POST', timeout=15, imei=get_imei(), serial=get_serial(), public_key=public_key, register_token=register_token) dongleauth = json.loads(resp.text) - dongle_id, access_token = dongleauth["dongle_id"].encode('ascii'), dongleauth["access_token"].encode('ascii') + dongle_id, access_token = dongleauth["dongle_id"], dongleauth["access_token"] params.put("DongleId", dongle_id) params.put("AccessToken", access_token) diff --git a/selfdrive/sensord/gpsd.cc b/selfdrive/sensord/gpsd.cc index 6bf7a6a9e1861b..0a8cd1bffc72a6 100644 --- a/selfdrive/sensord/gpsd.cc +++ b/selfdrive/sensord/gpsd.cc @@ -28,7 +28,7 @@ #include "rawgps.h" -volatile int do_exit = 0; +volatile sig_atomic_t do_exit = 0; namespace { @@ -219,7 +219,7 @@ void* clock_thread(void* args) { cereal::Event::Builder event = msg.initRoot(); event.setLogMonoTime(boottime); auto clocks = event.initClocks(); - + clocks.setBootTimeNanos(boottime); clocks.setMonotonicNanos(monotonic); clocks.setMonotonicRawNanos(monotonic_raw); @@ -248,7 +248,7 @@ int main() { signal(SIGTERM, (sighandler_t)set_do_exit); gps_init(); - + rawgps_init(); err = pthread_create(&clock_thread_handle, NULL, diff --git a/selfdrive/sensord/rawgps.cc b/selfdrive/sensord/rawgps.cc index 91e5562c7df934..7f5206a06c0cb4 100644 --- a/selfdrive/sensord/rawgps.cc +++ b/selfdrive/sensord/rawgps.cc @@ -18,8 +18,6 @@ #include "libdiag.h" -extern volatile int do_exit; - #define NV_GNSS_OEM_FEATURE_MASK 7165 # define NV_GNSS_OEM_FEATURE_MASK_OEMDRE 1 #define NV_CGPS_DPO_CONTROL 5596 @@ -376,7 +374,7 @@ struct __attribute__((packed)) GNSSOemdreMeasurement { float doppler_acceleration; float fine_speed; float fine_speed_uncertainty; - + uint64_t carrier_phase; uint32_t f_count; @@ -428,7 +426,7 @@ struct __attribute__((packed)) GNSSOemdreMeasurementReportv2 { uint8_t source; GNSSOemdreMeasurement measurements[16]; - + }; _Static_assert(sizeof(GNSSOemdreMeasurementReportv2) == 1851, "error"); @@ -590,7 +588,7 @@ static void handle_log(uint8_t *ptr, int len) { assert(len >= sizeof(GNSSGpsMeasurementReportv0)); const GNSSGpsMeasurementReportv0* report = (const GNSSGpsMeasurementReportv0*)ptr; assert(len >= sizeof(sizeof(GNSSGpsMeasurementReportv0))+sizeof(GNSSGpsMeasurementReportv0_SV) * report->sv_count); - + auto lreport = qcomGnss.initMeasurementReport(); lreport.setSource(cereal::QcomGnss::MeasurementSource::GPS); lreport.setFCount(report->f_count); @@ -646,9 +644,9 @@ static void handle_log(uint8_t *ptr, int len) { #ifdef RAWGPS_TEST // if (sv->measurement_status & (1 << 27)) printf("%d\n", sv->unfiltered_measurement_integral); - printf("GPS %03d %d %d 0x%08X o: %02x go: %02x fs: %02x cn: %02x pd: %02x cs: %02x po: %02x ms: %08x ms2: %08x me: %08x az: %08x el: %08x fc: %08x\n", + printf("GPS %03d %d %d 0x%08X o: %02x go: %02x fs: %02x cn: %02x pd: %02x cs: %02x po: %02x ms: %08x ms2: %08x me: %08x az: %08x el: %08x fc: %08x\n", sv->sv_id, - !!(sv->measurement_status & (1 << 27)), + !!(sv->measurement_status & (1 << 27)), sv->unfiltered_measurement_integral, sv->unfiltered_measurement_integral, sv->observations, sv->good_observations, @@ -731,9 +729,9 @@ static void handle_log(uint8_t *ptr, int len) { #ifdef RAWGPS_TEST // if (sv->measurement_status & (1 << 27)) printf("%d\n", sv->unfiltered_measurement_integral); - printf("GLO %03d %02x %d %d 0x%08X o: %02x go: %02x fs: %02x cn: %02x pd: %02x cs: %02x po: %02x ms: %08x ms2: %08x me: %08x az: %08x el: %08x fc: %08x\n", + printf("GLO %03d %02x %d %d 0x%08X o: %02x go: %02x fs: %02x cn: %02x pd: %02x cs: %02x po: %02x ms: %08x ms2: %08x me: %08x az: %08x el: %08x fc: %08x\n", sv->sv_id, sv->frequency_index & 0xff, - !!(sv->measurement_status & (1 << 27)), + !!(sv->measurement_status & (1 << 27)), sv->unfiltered_measurement_integral, sv->unfiltered_measurement_integral, sv->observations, sv->good_observations, @@ -779,7 +777,7 @@ static void handle_log(uint8_t *ptr, int len) { lreport.setGpsLeapSecondsUncertainty(report->gps_leap_seconds_uncertainty); lreport.setGpsToGlonassTimeBiasMilliseconds(report->gps_to_glonass_time_bias_milliseconds); lreport.setGpsToGlonassTimeBiasMillisecondsUncertainty(report->gps_to_glonass_time_bias_milliseconds_uncertainty); - + lreport.setGpsWeek(report->gps_week); lreport.setGpsMilliseconds(report->gps_milliseconds); lreport.setGpsTimeBiasMs(report->gps_time_bias); @@ -869,7 +867,7 @@ static void handle_log(uint8_t *ptr, int len) { lreport.setSvId(report->sv_id); lreport.setFrequencyIndex(report->frequency_index); - + lreport.setHasPosition(report->flags & 1); lreport.setHasIono(report->flags & 2); lreport.setHasTropo(report->flags & 4); @@ -986,7 +984,7 @@ static int oemdre_on(int client_id) { int res_len = diag_send_sync(client_id, (unsigned char*)&req_pkt, sizeof(req_pkt), res_pkt, sizeof(res_pkt)); GpsOemControlResp *resp = (GpsOemControlResp*)res_pkt; - + if (res_len != sizeof(GpsOemControlResp) || resp->cmd_code != DIAG_SUBSYS_CMD || resp->subsys_id != DIAG_SUBSYS_GPS @@ -1060,7 +1058,7 @@ static bool nv_write_u32(int client_id, uint16_t nv_id, uint32_t val) { .nv_id = nv_id, }; *(uint32_t*)req.data = val; - + NvPacket resp = {0}; int res_len = diag_send_sync(client_id, (unsigned char*)&req, sizeof(req), (unsigned char*)&resp, sizeof(resp)); @@ -1072,7 +1070,7 @@ static bool nv_write_u32(int client_id, uint16_t nv_id, uint32_t val) { LOGW("nv_write_u32: diag command failed"); return false; } - + if (resp.status != NV_DONE) { LOGW("nv_write_u32: write failed: %d", resp.status); return false; @@ -1186,4 +1184,4 @@ int main() { rawgps_destroy(); return 0; } -#endif \ No newline at end of file +#endif diff --git a/selfdrive/sensord/sensors.cc b/selfdrive/sensord/sensors.cc index 5717458f7215f4..ded2b88c44d740 100644 --- a/selfdrive/sensord/sensors.cc +++ b/selfdrive/sensord/sensors.cc @@ -38,7 +38,7 @@ #define SENSOR_PROXIMITY 6 #define SENSOR_LIGHT 7 -volatile int do_exit = 0; +volatile sig_atomic_t do_exit = 0; namespace { diff --git a/selfdrive/sensord/start_gpsd.py b/selfdrive/sensord/start_gpsd.py index ada2687158a4db..287ead295998d0 100755 --- a/selfdrive/sensord/start_gpsd.py +++ b/selfdrive/sensord/start_gpsd.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import os assert os.system("make") == 0 diff --git a/selfdrive/sensord/start_sensord.py b/selfdrive/sensord/start_sensord.py index d6d6564113a09e..bd0cbed82b7bbf 100755 --- a/selfdrive/sensord/start_sensord.py +++ b/selfdrive/sensord/start_sensord.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import os assert os.system("make") == 0 diff --git a/selfdrive/service_list.yaml b/selfdrive/service_list.yaml index ec8b0b9d448211..a38c6ad714ac60 100644 --- a/selfdrive/service_list.yaml +++ b/selfdrive/service_list.yaml @@ -40,7 +40,7 @@ lidarPts: [8030, true, 0.] procLog: [8031, true, 0.5] gpsLocationExternal: [8032, true, 10., 1] ubloxGnss: [8033, true, 10.] -clocks: [8034, true, 1.] +clocks: [8034, true, 1., 1] liveMpc: [8035, false, 20.] liveLongitudinalMpc: [8036, false, 20.] plusFrame: [8037, false, 0.] diff --git a/selfdrive/services.py b/selfdrive/services.py index 18d43ff76a3448..24a96c4eb2e4e1 100644 --- a/selfdrive/services.py +++ b/selfdrive/services.py @@ -1,15 +1,20 @@ import os import yaml -class Service(object): - def __init__(self, port, should_log, frequency): +class Service(): + def __init__(self, port, should_log, frequency, decimation=None): self.port = port self.should_log = should_log self.frequency = frequency + self.decimation = decimation service_list_path = os.path.join(os.path.dirname(__file__), "service_list.yaml") service_list = {} with open(service_list_path, "r") as f: for k, v in yaml.safe_load(f).items(): - service_list[k] = Service(v[0], v[1], v[2]) + decimation = None + if len(v) == 4: + decimation = v[3] + + service_list[k] = Service(v[0], v[1], v[2], decimation) diff --git a/selfdrive/swaglog.py b/selfdrive/swaglog.py index 169898637a901f..90962cb5d84933 100644 --- a/selfdrive/swaglog.py +++ b/selfdrive/swaglog.py @@ -14,6 +14,7 @@ def __init__(self, formatter): def connect(self): self.zctx = zmq.Context() self.sock = self.zctx.socket(zmq.PUSH) + self.sock.setsockopt(zmq.LINGER, 10) self.sock.connect("ipc:///tmp/logmessage") self.pid = os.getpid() @@ -24,7 +25,8 @@ def emit(self, record): msg = self.format(record).rstrip('\n') # print("SEND".format(repr(msg))) try: - self.sock.send(chr(record.levelno)+msg, zmq.NOBLOCK) + s = chr(record.levelno)+msg + self.sock.send(s.encode('utf8'), zmq.NOBLOCK) except zmq.error.Again: # drop :/ pass diff --git a/selfdrive/debug/getframes/__init__.py b/selfdrive/test/longitudinal_maneuvers/__init__.py similarity index 100% rename from selfdrive/debug/getframes/__init__.py rename to selfdrive/test/longitudinal_maneuvers/__init__.py diff --git a/selfdrive/test/plant/maneuver.py b/selfdrive/test/longitudinal_maneuvers/maneuver.py similarity index 94% rename from selfdrive/test/plant/maneuver.py rename to selfdrive/test/longitudinal_maneuvers/maneuver.py index ea5ebdd9ee2579..e79cf61d26a65a 100644 --- a/selfdrive/test/plant/maneuver.py +++ b/selfdrive/test/longitudinal_maneuvers/maneuver.py @@ -1,10 +1,10 @@ from collections import defaultdict -from selfdrive.test.plant.maneuverplots import ManeuverPlot -from selfdrive.test.plant.plant import Plant +from selfdrive.test.longitudinal_maneuvers.maneuverplots import ManeuverPlot +from selfdrive.test.longitudinal_maneuvers.plant import Plant import numpy as np -class Maneuver(object): +class Maneuver(): def __init__(self, title, duration, **kwargs): # Was tempted to make a builder class self.distance_lead = kwargs.get("initial_distance_lead", 200.0) @@ -79,7 +79,7 @@ def evaluate(self): for check in self.checks: c = check(logs) if not c: - print check.__name__ + " not valid!" + print(check.__name__ + " not valid!") valid = valid and c print("maneuver end", valid) diff --git a/selfdrive/test/plant/maneuverplots.py b/selfdrive/test/longitudinal_maneuvers/maneuverplots.py similarity index 99% rename from selfdrive/test/plant/maneuverplots.py rename to selfdrive/test/longitudinal_maneuvers/maneuverplots.py index 36b3e5bf8372e0..3d52588100ffb7 100644 --- a/selfdrive/test/plant/maneuverplots.py +++ b/selfdrive/test/longitudinal_maneuvers/maneuverplots.py @@ -6,7 +6,7 @@ from selfdrive.config import Conversions as CV -class ManeuverPlot(object): +class ManeuverPlot(): def __init__(self, title = None): self.time_array = [] diff --git a/selfdrive/test/plant/plant.py b/selfdrive/test/longitudinal_maneuvers/plant.py similarity index 92% rename from selfdrive/test/plant/plant.py rename to selfdrive/test/longitudinal_maneuvers/plant.py index 531ad8ad269c39..1a57284697ad57 100755 --- a/selfdrive/test/plant/plant.py +++ b/selfdrive/test/longitudinal_maneuvers/plant.py @@ -1,4 +1,5 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 +import binascii import os import struct import time @@ -24,7 +25,7 @@ honda = dbc(os.path.join(DBC_PATH, "honda_civic_touring_2016_can_generated.dbc")) # Trick: set 0x201 (interceptor) in fingerprints for gas is controlled like if there was an interceptor -CP = CarInterface.get_params(CAR.CIVIC, {0x201}) +CP = CarInterface.get_params(CAR.CIVIC, {0: {0x201: 6}, 1: {}, 2: {}, 3: {}}) def car_plant(pos, speed, grade, gas, brake): @@ -81,12 +82,15 @@ def get_car_can_parser(): return CANParser(dbc_f, signals, checks) def to_3_byte(x): - return struct.pack("!H", int(x)).encode("hex")[1:] + # Convert into 12 bit value + s = struct.pack("!H", int(x)) + return binascii.hexlify(s)[1:] def to_3s_byte(x): - return struct.pack("!h", int(x)).encode("hex")[1:] + s = struct.pack("!h", int(x)) + return binascii.hexlify(s)[1:] -class Plant(object): +class Plant(): messaging_initialized = False def __init__(self, lead_relevancy=False, rate=100, speed=0.0, distance_lead=2.0): @@ -105,6 +109,7 @@ def __init__(self, lead_relevancy=False, rate=100, speed=0.0, distance_lead=2.0) Plant.plan = messaging.sub_sock(service_list['plan'].port) Plant.messaging_initialized = True + self.frame = 0 self.angle_steer = 0. self.gear_choice = 0 self.speed, self.speed_prev = 0., 0. @@ -221,7 +226,7 @@ def step(self, v_lead=0.0, cruise_buttons=None, grade=0.0, publish_model = True) lateral_pos_rel = 0. # print at 5hz - if (self.rk.frame % (self.rate//5)) == 0: + if (self.frame % (self.rate//5)) == 0: print("%6.2f m %6.2f m/s %6.2f m/s2 %.2f ang gas: %.2f brake: %.2f steer: %5.2f lead_rel: %6.2f m %6.2f m/s" % (distance, speed, acceleration, self.angle_steer, gas, brake, steer_torque, d_rel, v_rel)) # ******** publish the car ******** @@ -301,10 +306,10 @@ def step(self, v_lead=0.0, cruise_buttons=None, grade=0.0, publish_model = True) msg_struct[sgs[i]] = getattr(vls, sgs[i]) if "COUNTER" in honda.get_signals(msg): - msg_struct["COUNTER"] = self.rk.frame % 4 + msg_struct["COUNTER"] = self.frame % 4 if "COUNTER_PEDAL" in honda.get_signals(msg): - msg_struct["COUNTER_PEDAL"] = self.rk.frame % 0xf + msg_struct["COUNTER_PEDAL"] = self.frame % 0xf msg = honda.lookup_msg_id(msg) msg_data = honda.encode(msg, msg_struct) @@ -313,24 +318,26 @@ def step(self, v_lead=0.0, cruise_buttons=None, grade=0.0, publish_model = True) msg_data = fix(msg_data, msg) if "CHECKSUM_PEDAL" in honda.get_signals(msg): - msg_struct["CHECKSUM_PEDAL"] = crc8_pedal([ord(i) for i in msg_data][:-1]) + msg_struct["CHECKSUM_PEDAL"] = crc8_pedal(msg_data[:-1]) msg_data = honda.encode(msg, msg_struct) can_msgs.append([msg, 0, msg_data, 0]) # add the radar message # TODO: use the DBC - if self.rk.frame % 5 == 0: - radar_state_msg = '\x79\x00\x00\x00\x00\x00\x00\x00' + if self.frame % 5 == 0: + radar_state_msg = b'\x79\x00\x00\x00\x00\x00\x00\x00' radar_msg = to_3_byte(d_rel*16.0) + \ to_3_byte(int(lateral_pos_rel*16.0)&0x3ff) + \ to_3s_byte(int(v_rel*32.0)) + \ - "0f00000" + b"0f00000" + + radar_msg = binascii.unhexlify(radar_msg) can_msgs.append([0x400, 0, radar_state_msg, 1]) - can_msgs.append([0x445, 0, radar_msg.decode("hex"), 1]) + can_msgs.append([0x445, 0, radar_msg, 1]) # add camera msg so controlsd thinks it's alive - msg_struct["COUNTER"] = self.rk.frame % 4 + msg_struct["COUNTER"] = self.frame % 4 msg = honda.lookup_msg_id(0xe4) msg_data = honda.encode(msg, msg_struct) msg_data = fix(msg_data, 0xe4) @@ -366,7 +373,7 @@ def step(self, v_lead=0.0, cruise_buttons=None, grade=0.0, publish_model = True) # ******** publish a fake model going straight and fake calibration ******** # note that this is worst case for MPC, since model will delay long mpc by one time step - if publish_model and self.rk.frame % 5 == 0: + if publish_model and self.frame % 5 == 0: md = messaging.new_message() cal = messaging.new_message() md.init('model') @@ -406,18 +413,23 @@ def step(self, v_lead=0.0, cruise_buttons=None, grade=0.0, publish_model = True) Plant.logcan.send(can_list_to_can_capnp(can_msgs)) # ******** update prevs ******** - self.speed = speed - self.distance = distance - self.distance_lead = distance_lead - - self.speed_prev = speed - self.distance_prev = distance - self.distance_lead_prev = distance_lead + self.frame += 1 if self.response_seen: self.rk.monitor_time() + + self.speed = speed + self.distance = distance + self.distance_lead = distance_lead + + self.speed_prev = speed + self.distance_prev = distance + self.distance_lead_prev = distance_lead + else: + # Don't advance time when controlsd is not yet ready self.rk.keep_time() + self.rk._frame = 0 return { "distance": distance, diff --git a/selfdrive/test/plant/plant_ui.py b/selfdrive/test/longitudinal_maneuvers/plant_ui.py similarity index 97% rename from selfdrive/test/plant/plant_ui.py rename to selfdrive/test/longitudinal_maneuvers/plant_ui.py index 5fa0ffad247301..e9dd18f37276f7 100755 --- a/selfdrive/test/plant/plant_ui.py +++ b/selfdrive/test/longitudinal_maneuvers/plant_ui.py @@ -1,6 +1,6 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import pygame # pylint: disable=import-error -from selfdrive.test.plant.plant import Plant +from selfdrive.test.longitudinal_maneuvers.plant import Plant from selfdrive.car.honda.values import CruiseButtons import numpy as np import selfdrive.messaging as messaging diff --git a/selfdrive/test/tests/plant/test_longitudinal.py b/selfdrive/test/longitudinal_maneuvers/test_longitudinal.py similarity index 98% rename from selfdrive/test/tests/plant/test_longitudinal.py rename to selfdrive/test/longitudinal_maneuvers/test_longitudinal.py index ca05924200dbb7..bfcbf67f7ba1c0 100755 --- a/selfdrive/test/tests/plant/test_longitudinal.py +++ b/selfdrive/test/longitudinal_maneuvers/test_longitudinal.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import os os.environ['OLD_CAN'] = '1' os.environ['NOCRASH'] = '1' @@ -11,7 +11,7 @@ from selfdrive.config import Conversions as CV from selfdrive.car.honda.values import CruiseButtons as CB -from selfdrive.test.plant.maneuver import Maneuver +from selfdrive.test.longitudinal_maneuvers.maneuver import Maneuver import selfdrive.manager as manager from common.params import Params @@ -332,6 +332,7 @@ def setUpClass(cls): shutil.rmtree('/data/params', ignore_errors=True) params = Params() params.put("Passive", "1" if os.getenv("PASSIVE") else "0") + params.put("OpenpilotEnabledToggle", "1") manager.gctx = {} manager.prepare_managed_process('radard') diff --git a/selfdrive/test/openpilotci_upload.py b/selfdrive/test/openpilotci_upload.py index 85509851dee3c1..df40715716bad7 100755 --- a/selfdrive/test/openpilotci_upload.py +++ b/selfdrive/test/openpilotci_upload.py @@ -1,10 +1,11 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import os import sys import subprocess -from azure.storage.blob import BlockBlobService + def upload_file(path, name): + from azure.storage.blob import BlockBlobService # pylint: disable=no-name-in-module, import-error sas_token = os.getenv("TOKEN", None) if sas_token is not None: service = BlockBlobService(account_name="commadataci", sas_token=sas_token) @@ -18,5 +19,4 @@ def upload_file(path, name): for f in sys.argv[1:]: name = os.path.basename(f) url = upload_file(f, name) - print url - + print(url) diff --git a/selfdrive/test/tests/process_replay/.gitignore b/selfdrive/test/process_replay/.gitignore similarity index 100% rename from selfdrive/test/tests/process_replay/.gitignore rename to selfdrive/test/process_replay/.gitignore diff --git a/selfdrive/test/tests/process_replay/README.md b/selfdrive/test/process_replay/README.md similarity index 100% rename from selfdrive/test/tests/process_replay/README.md rename to selfdrive/test/process_replay/README.md diff --git a/selfdrive/test/plant/__init__.py b/selfdrive/test/process_replay/__init__.py similarity index 100% rename from selfdrive/test/plant/__init__.py rename to selfdrive/test/process_replay/__init__.py diff --git a/selfdrive/test/tests/process_replay/compare_logs.py b/selfdrive/test/process_replay/compare_logs.py similarity index 98% rename from selfdrive/test/tests/process_replay/compare_logs.py rename to selfdrive/test/process_replay/compare_logs.py index 5a1bd3fd7360d3..34f6ded60257f5 100755 --- a/selfdrive/test/tests/process_replay/compare_logs.py +++ b/selfdrive/test/process_replay/compare_logs.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import bz2 import os import sys diff --git a/selfdrive/test/tests/process_replay/process_replay.py b/selfdrive/test/process_replay/process_replay.py similarity index 93% rename from selfdrive/test/tests/process_replay/process_replay.py rename to selfdrive/test/process_replay/process_replay.py index b360aed9723c6f..1676daa142b714 100755 --- a/selfdrive/test/tests/process_replay/process_replay.py +++ b/selfdrive/test/process_replay/process_replay.py @@ -1,7 +1,8 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import os import threading import importlib +import shutil import zmq if "CI" in os.environ: @@ -111,7 +112,7 @@ def __init__(self, services): def send(self, s, dat): self.last_updated = s - if isinstance(dat, str): + if isinstance(dat, bytes): self.data[s] = log.Event.from_bytes(dat) else: self.data[s] = dat.as_reader() @@ -127,11 +128,11 @@ def wait_for_msg(self): return dat def fingerprint(msgs, fsm, can_sock): - print "start fingerprinting" + print("start fingerprinting") fsm.wait_on_getitem = True # populate fake socket with data for fingerprinting - canmsgs = filter(lambda msg: msg.which() == "can", msgs) + canmsgs = [msg for msg in msgs if msg.which() == "can"] can_sock.recv_called.wait() can_sock.recv_called.clear() can_sock.data = [msg.as_builder().to_bytes() for msg in canmsgs[:300]] @@ -147,13 +148,13 @@ def fingerprint(msgs, fsm, can_sock): can_sock.data = [] fsm.update_ready.set() - print "finished fingerprinting" + print("finished fingerprinting") def get_car_params(msgs, fsm, can_sock): can = FakeSocket(wait=False) sendcan = FakeSocket(wait=False) - canmsgs = filter(lambda msg: msg.which() == 'can', msgs) + canmsgs = [msg for msg in msgs if msg.which() == 'can'] for m in canmsgs[:300]: can.send(m.as_builder().to_bytes()) _, CP = get_car(can, sendcan) @@ -225,15 +226,17 @@ def replay_process(cfg, lr): fsm = FakeSubMaster(pub_sockets) fpm = FakePubMaster(sub_sockets) args = (fsm, fpm) - if 'can' in cfg.pub_sub.keys(): + if 'can' in list(cfg.pub_sub.keys()): can_sock = FakeSocket() args = (fsm, fpm, can_sock) all_msgs = sorted(lr, key=lambda msg: msg.logMonoTime) - pub_msgs = filter(lambda msg: msg.which() in cfg.pub_sub.keys(), all_msgs) + pub_msgs = [msg for msg in all_msgs if msg.which() in list(cfg.pub_sub.keys())] + shutil.rmtree('/data/params', ignore_errors=True) params = Params() params.manager_start() + params.put("OpenpilotEnabledToggle", "1") params.put("Passive", "0") os.environ['NO_RADAR_SLEEP'] = "1" @@ -244,14 +247,14 @@ def replay_process(cfg, lr): thread.start() if cfg.init_callback is not None: - if 'can' not in cfg.pub_sub.keys(): + if 'can' not in list(cfg.pub_sub.keys()): can_sock = None cfg.init_callback(all_msgs, fsm, can_sock) CP = car.CarParams.from_bytes(params.get("CarParams", block=True)) # wait for started process to be ready - if 'can' in cfg.pub_sub.keys(): + if 'can' in list(cfg.pub_sub.keys()): can_sock.wait_for_recv() else: fsm.wait_for_update() diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit new file mode 100644 index 00000000000000..557be7d88d35e9 --- /dev/null +++ b/selfdrive/test/process_replay/ref_commit @@ -0,0 +1 @@ +8def7e7391802f2e86498d764c953f487361f6a1 \ No newline at end of file diff --git a/selfdrive/test/tests/process_replay/test_processes.py b/selfdrive/test/process_replay/test_processes.py similarity index 78% rename from selfdrive/test/tests/process_replay/test_processes.py rename to selfdrive/test/process_replay/test_processes.py index 8d70c80a2b0934..6832aba33cca9c 100755 --- a/selfdrive/test/tests/process_replay/test_processes.py +++ b/selfdrive/test/process_replay/test_processes.py @@ -1,11 +1,11 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import os import requests import sys import tempfile -from selfdrive.test.tests.process_replay.compare_logs import compare_logs -from selfdrive.test.tests.process_replay.process_replay import replay_process, CONFIGS +from selfdrive.test.process_replay.compare_logs import compare_logs +from selfdrive.test.process_replay.process_replay import replay_process, CONFIGS from tools.lib.logreader import LogReader segments = [ @@ -36,22 +36,22 @@ def get_segment(segment_name): ref_commit_fn = os.path.join(process_replay_dir, "ref_commit") if not os.path.isfile(ref_commit_fn): - print "couldn't find reference commit" + print("couldn't find reference commit") sys.exit(1) ref_commit = open(ref_commit_fn).read().strip() - print "***** testing against commit %s *****" % ref_commit + print("***** testing against commit %s *****" % ref_commit) results = {} for segment in segments: - print "***** testing route segment %s *****\n" % segment + print("***** testing route segment %s *****\n" % segment) results[segment] = {} rlog_fn = get_segment(segment) if rlog_fn is None: - print "failed to get segment %s" % segment + print("failed to get segment %s" % segment) sys.exit(1) lr = LogReader(rlog_fn) @@ -84,16 +84,16 @@ def get_segment(segment_name): with open(os.path.join(process_replay_dir, "diff.txt"), "w") as f: f.write("***** tested against commit %s *****\n" % ref_commit) - for segment, result in results.items(): + for segment, result in list(results.items()): f.write("***** differences for segment %s *****\n" % segment) - print "***** results for segment %s *****" % segment + print("***** results for segment %s *****" % segment) - for proc, diff in result.items(): + for proc, diff in list(result.items()): f.write("*** process: %s ***\n" % proc) - print "\t%s" % proc + print("\t%s" % proc) if isinstance(diff, str): - print "\t\t%s" % diff + print("\t\t%s" % diff) failed = True elif len(diff): cnt = {} @@ -104,15 +104,15 @@ def get_segment(segment_name): cnt[k] = 1 if k not in cnt else cnt[k] + 1 for k, v in sorted(cnt.items()): - print "\t\t%s: %s" % (k, v) + print("\t\t%s: %s" % (k, v)) failed = True if failed: - print "TEST FAILED" + print("TEST FAILED") else: - print "TEST SUCCEEDED" + print("TEST SUCCEEDED") - print "\n\nTo update the reference logs for this test run:" - print "./update_refs.py" + print("\n\nTo update the reference logs for this test run:") + print("./update_refs.py") sys.exit(int(failed)) diff --git a/selfdrive/test/tests/process_replay/update_refs.py b/selfdrive/test/process_replay/update_refs.py similarity index 73% rename from selfdrive/test/tests/process_replay/update_refs.py rename to selfdrive/test/process_replay/update_refs.py index 4bc2659391a304..e0da25133e009d 100755 --- a/selfdrive/test/tests/process_replay/update_refs.py +++ b/selfdrive/test/process_replay/update_refs.py @@ -1,11 +1,11 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import os import sys from selfdrive.test.openpilotci_upload import upload_file -from selfdrive.test.tests.process_replay.compare_logs import save_log -from selfdrive.test.tests.process_replay.process_replay import replay_process, CONFIGS -from selfdrive.test.tests.process_replay.test_processes import segments, get_segment +from selfdrive.test.process_replay.compare_logs import save_log +from selfdrive.test.process_replay.process_replay import replay_process, CONFIGS +from selfdrive.test.process_replay.test_processes import segments, get_segment from selfdrive.version import get_git_commit from tools.lib.logreader import LogReader @@ -24,7 +24,7 @@ rlog_fn = get_segment(segment) if rlog_fn is None: - print "failed to get segment %s" % segment + print("failed to get segment %s" % segment) sys.exit(1) lr = LogReader(rlog_fn) @@ -39,4 +39,4 @@ os.remove(log_fn) os.remove(rlog_fn) - print "done" + print("done") diff --git a/selfdrive/test/test_car_models.py b/selfdrive/test/test_car_models.py index 317f325918da17..fc4605f94acdf7 100755 --- a/selfdrive/test/test_car_models.py +++ b/selfdrive/test/test_car_models.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import shutil import time import zmq @@ -14,7 +14,7 @@ import selfdrive.messaging as messaging from common.params import Params from common.basedir import BASEDIR -from common.fingerprints import all_known_cars +from selfdrive.car.fingerprints import all_known_cars from selfdrive.car.honda.values import CAR as HONDA from selfdrive.car.toyota.values import CAR as TOYOTA from selfdrive.car.gm.values import CAR as GM @@ -41,6 +41,8 @@ def wait_for_socket(name, timeout=10.0): except zmq.error.Again: pass time.sleep(0.5) + if r is None: + sys.exit(-1) return r def get_route_logs(route_name): @@ -52,10 +54,10 @@ def get_route_logs(route_name): r = requests.get(log_url) if r.status_code == 200: - with open(log_path, "w") as f: + with open(log_path, "wb") as f: f.write(r.content) else: - print "failed to download test log %s" % route_name + print("failed to download test log %s" % route_name) sys.exit(-1) routes = { @@ -435,7 +437,7 @@ def get_route_logs(route_name): tested_cars = [keys["carFingerprint"] for route, keys in routes.items()] for car_model in all_known_cars(): if car_model not in tested_cars: - print "***** WARNING: %s not tested *****" % car_model + print("***** WARNING: %s not tested *****" % car_model) results = {} for route, checks in routes.items(): @@ -454,26 +456,26 @@ def get_route_logs(route_name): else: params.put("Passive", "0") - print "testing ", route, " ", checks['carFingerprint'] - print "Preparing processes" + print("testing ", route, " ", checks['carFingerprint']) + print("Preparing processes") manager.prepare_managed_process("radard") manager.prepare_managed_process("controlsd") manager.prepare_managed_process("plannerd") - print "Starting processes" + print("Starting processes") manager.start_managed_process("radard") manager.start_managed_process("controlsd") manager.start_managed_process("plannerd") time.sleep(2) # Start unlogger - print "Start unlogger" + print("Start unlogger") if route in non_public_routes: unlogger_cmd = [os.path.join(BASEDIR, os.environ['UNLOGGER_PATH']), '%s' % route, '--disable', 'frame,plan,pathPlan,liveLongitudinalMpc,radarState,controlsState,liveTracks,liveMpc,sendcan,carState,carControl', '--no-interactive'] else: unlogger_cmd = [os.path.join(BASEDIR, 'tools/replay/unlogger.py'), '%s' % route, '/tmp', '--disable', 'frame,plan,pathPlan,liveLongitudinalMpc,radarState,controlsState,liveTracks,liveMpc,sendcan,carState,carControl', '--no-interactive'] unlogger = subprocess.Popen(unlogger_cmd, preexec_fn=os.setsid) - print "Check sockets" + print("Check sockets") controls_state_result = wait_for_socket('controlsState', timeout=30) radarstate_result = wait_for_socket('radarState', timeout=30) plan_result = wait_for_socket('plan', timeout=30) @@ -485,7 +487,7 @@ def get_route_logs(route_name): carstate_result = wait_for_socket('carState', timeout=30) - print "Check if everything is running" + print("Check if everything is running") running = manager.get_running() controlsd_running = running['controlsd'].is_alive() radard_running = running['radard'].is_alive() @@ -526,19 +528,20 @@ def get_route_logs(route_name): params_ok = False if sockets_ok and params_ok: - print "Success" + print("Success") results[route] = True, failures break else: - print "Failure" + print("Failure") results[route] = False, failures time.sleep(2) - print results + for route in results: + print(results[route]) params.put("Passive", "0") # put back not passive to not leave the params in an unintended state if not all(passed for passed, _ in results.values()): - print "TEST FAILED" + print("TEST FAILED") sys.exit(1) else: - print "TEST SUCESSFUL" + print("TEST SUCESSFUL") diff --git a/selfdrive/test/test_fingerprints.py b/selfdrive/test/test_fingerprints.py index 721ea163fcc8af..b291ff6a1c1193 100755 --- a/selfdrive/test/test_fingerprints.py +++ b/selfdrive/test/test_fingerprints.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import os import sys from common.basedir import BASEDIR diff --git a/selfdrive/test/test_openpilot.py b/selfdrive/test/test_openpilot.py index 13770f50a5ff6b..0176a7fcd0f11e 100644 --- a/selfdrive/test/test_openpilot.py +++ b/selfdrive/test/test_openpilot.py @@ -43,7 +43,7 @@ def wrap(): #@phone_only #@with_processes(['controlsd', 'radard']) #def test_controls(): -# from selfdrive.test.plant.plant import Plant +# from selfdrive.test.longitudinal_maneuvers.plant import Plant # # # start the fake car for 2 seconds # plant = Plant(100) diff --git a/selfdrive/test/tests/plant/__init__.py b/selfdrive/test/tests/plant/__init__.py deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/selfdrive/test/tests/process_replay/__init__.py b/selfdrive/test/tests/process_replay/__init__.py deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/selfdrive/test/tests/process_replay/ref_commit b/selfdrive/test/tests/process_replay/ref_commit deleted file mode 100644 index 3744386a82e960..00000000000000 --- a/selfdrive/test/tests/process_replay/ref_commit +++ /dev/null @@ -1 +0,0 @@ -8a11bcbc9833e154e10b59a8babb2b4545372f56 \ No newline at end of file diff --git a/selfdrive/thermald.py b/selfdrive/thermald.py index b866521a920c9d..a0548beb6032f3 100755 --- a/selfdrive/thermald.py +++ b/selfdrive/thermald.py @@ -1,19 +1,29 @@ -#!/usr/bin/env python2.7 +#!/usr/bin/env python3.7 import os +import json +import copy +import datetime from smbus2 import SMBus from cereal import log +from common.basedir import BASEDIR +from common.params import Params +from common.realtime import sec_since_boot, DT_TRML +from common.numpy_fast import clip +from common.filter_simple import FirstOrderFilter from selfdrive.version import terms_version, training_version from selfdrive.swaglog import cloudlog import selfdrive.messaging as messaging from selfdrive.services import service_list from selfdrive.loggerd.config import get_available_percent -from common.params import Params -from common.realtime import sec_since_boot, DT_TRML -from common.numpy_fast import clip -from common.filter_simple import FirstOrderFilter ThermalStatus = log.ThermalData.ThermalStatus CURRENT_TAU = 15. # 15s time constant +DAYS_NO_CONNECTIVITY_MAX = 7 # do not allow to engage after a week without internet +DAYS_NO_CONNECTIVITY_PROMPT = 4 # send an offroad prompt after 4 days with no internet + + +with open(BASEDIR + "/selfdrive/controls/lib/alerts_offroad.json") as json_file: + OFFROAD_ALERTS = json.load(json_file) def read_tz(x): with open("/sys/devices/virtual/thermal/thermal_zone%d/temp" % x) as f: @@ -99,27 +109,11 @@ def handle_fan(max_cpu_temp, bat_temp, fan_speed): # no max fan speed unless battery is hot fan_speed = min(fan_speed, _FAN_SPEEDS[-2]) - set_eon_fan(fan_speed/16384) + set_eon_fan(fan_speed//16384) return fan_speed -def check_car_battery_voltage(should_start, health, charging_disabled): - - # charging disallowed if: - # - there are health packets from panda, and; - # - 12V battery voltage is too low, and; - # - onroad isn't started - if charging_disabled and (health is None or health.health.voltage > 11800): - charging_disabled = False - os.system('echo "1" > /sys/class/power_supply/battery/charging_enabled') - elif not charging_disabled and health is not None and health.health.voltage < 11500 and not should_start: - charging_disabled = True - os.system('echo "0" > /sys/class/power_supply/battery/charging_enabled') - - return charging_disabled - - def thermald_thread(): setup_eon_fan() @@ -138,13 +132,13 @@ def thermald_thread(): ignition_seen = False started_seen = False thermal_status = ThermalStatus.green + thermal_status_prev = ThermalStatus.green + usb_power = True + usb_power_prev = True health_sock.RCVTIMEO = int(1000 * 2 * DT_TRML) # 2x the expected health frequency current_filter = FirstOrderFilter(0., CURRENT_TAU, DT_TRML) health_prev = None - - # Make sure charging is enabled - charging_disabled = False - os.system('echo "1" > /sys/class/power_supply/battery/charging_enabled') + current_connectivity_alert = None params = Params() @@ -157,8 +151,12 @@ def thermald_thread(): # clear car params when panda gets disconnected if health is None and health_prev is not None: params.panda_disconnect() + ignition_seen = False health_prev = health + if health is not None: + usb_power = health.health.usbPowerMode != log.HealthData.UsbPowerMode.client + # loggerd is gated based on free space avail = get_available_percent() / 100.0 @@ -207,6 +205,32 @@ def thermald_thread(): # **** starting logic **** + # Check for last update time and display alerts if needed + now = datetime.datetime.now() + try: + last_update = datetime.datetime.fromisoformat(params.get("LastUpdateTime", encoding='utf8')) + except (TypeError, ValueError): + last_update = now + dt = now - last_update + + if dt.days > DAYS_NO_CONNECTIVITY_MAX: + if current_connectivity_alert != "expired": + current_connectivity_alert = "expired" + params.delete("Offroad_ConnectivityNeededPrompt") + params.put("Offroad_ConnectivityNeeded", json.dumps(OFFROAD_ALERTS["Offroad_ConnectivityNeeded"])) + elif dt.days > DAYS_NO_CONNECTIVITY_PROMPT: + remaining_time = str(DAYS_NO_CONNECTIVITY_MAX - dt.days) + if current_connectivity_alert != "prompt" + remaining_time: + current_connectivity_alert = "prompt" + remaining_time + alert_connectivity_prompt = copy.copy(OFFROAD_ALERTS["Offroad_ConnectivityNeededPrompt"]) + alert_connectivity_prompt["text"] += remaining_time + " days." + params.delete("Offroad_ConnectivityNeeded") + params.put("Offroad_ConnectivityNeededPrompt", json.dumps(alert_connectivity_prompt)) + elif current_connectivity_alert is not None: + current_connectivity_alert = None + params.delete("Offroad_ConnectivityNeeded") + params.delete("Offroad_ConnectivityNeededPrompt") + # start constellation of processes when the car starts ignition = health is not None and health.health.started ignition_seen = ignition_seen or ignition @@ -215,7 +239,7 @@ def thermald_thread(): if not ignition_seen and health is not None and health.health.voltage > 13500: ignition = True - do_uninstall = params.get("DoUninstall") == "1" + do_uninstall = params.get("DoUninstall") == b"1" accepted_terms = params.get("HasAcceptedTerms") == terms_version completed_training = params.get("CompletedTrainingVersion") == training_version @@ -233,8 +257,12 @@ def thermald_thread(): # if any CPU gets above 107 or the battery gets above 63, kill all processes # controls will warn with CPU above 95 or battery above 60 if thermal_status >= ThermalStatus.danger: - # TODO: Add a better warning when this is happening should_start = False + if thermal_status_prev < ThermalStatus.danger: + params.put("Offroad_TemperatureTooHigh", json.dumps(OFFROAD_ALERTS["Offroad_TemperatureTooHigh"])) + else: + if thermal_status_prev >= ThermalStatus.danger: + params.delete("Offroad_TemperatureTooHigh") if should_start: off_ts = None @@ -254,15 +282,21 @@ def thermald_thread(): started_seen and (sec_since_boot() - off_ts) > 60: os.system('LD_LIBRARY_PATH="" svc power shutdown') - #charging_disabled = check_car_battery_voltage(should_start, health, charging_disabled) - - msg.thermal.chargingDisabled = charging_disabled msg.thermal.chargingError = current_filter.x > 0. and msg.thermal.batteryPercent < 90 # if current is positive, then battery is being discharged msg.thermal.started = started_ts is not None msg.thermal.startedTs = int(1e9*(started_ts or 0)) msg.thermal.thermalStatus = thermal_status thermal_sock.send(msg.to_bytes()) + + if usb_power_prev and not usb_power: + params.put("Offroad_ChargeDisabled", json.dumps(OFFROAD_ALERTS["Offroad_ChargeDisabled"])) + elif usb_power and not usb_power_prev: + params.delete("Offroad_ChargeDisabled") + + thermal_status_prev = thermal_status + usb_power_prev = usb_power + print(msg) # report to server once per minute diff --git a/selfdrive/tombstoned.py b/selfdrive/tombstoned.py index 3af76818d484cd..292ec0408b7599 100644 --- a/selfdrive/tombstoned.py +++ b/selfdrive/tombstoned.py @@ -16,7 +16,7 @@ def get_tombstones(): def report_tombstone(fn, client): mtime = os.path.getmtime(fn) - with open(fn, "r") as f: + with open(fn, encoding='ISO-8859-1') as f: dat = f.read() # see system/core/debuggerd/tombstone.cpp diff --git a/selfdrive/ui/spinner/spinner b/selfdrive/ui/spinner/spinner index 2b9e634feab1ed..828b4b60a9fa59 100755 Binary files a/selfdrive/ui/spinner/spinner and b/selfdrive/ui/spinner/spinner differ diff --git a/selfdrive/ui/start.py b/selfdrive/ui/start.py index e3e629b545d12c..a1d00ce145da4a 100755 --- a/selfdrive/ui/start.py +++ b/selfdrive/ui/start.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import os assert os.system("make") == 0 diff --git a/selfdrive/ui/ui.c b/selfdrive/ui/ui.c index 1c88d21923faf4..d09061ea638359 100644 --- a/selfdrive/ui/ui.c +++ b/selfdrive/ui/ui.c @@ -331,7 +331,7 @@ static void set_volume(UIState *s, int volume) { int volume_changed = system(volume_change_cmd); } -volatile int do_exit = 0; +volatile sig_atomic_t do_exit = 0; static void set_do_exit(int sig) { do_exit = 1; } @@ -443,7 +443,7 @@ sound_file sound_table[] = { { cereal_CarControl_HUDControl_AudibleAlert_chimeEngage, "../assets/sounds/engaged.wav", false }, { cereal_CarControl_HUDControl_AudibleAlert_chimeWarning1, "../assets/sounds/warning_1.wav", false }, { cereal_CarControl_HUDControl_AudibleAlert_chimeWarning2, "../assets/sounds/warning_2.wav", false }, - { cereal_CarControl_HUDControl_AudibleAlert_chimeWarningRepeat, "../assets/sounds/warning_2.wav", true }, + { cereal_CarControl_HUDControl_AudibleAlert_chimeWarningRepeat, "../assets/sounds/warning_repeat.wav", true }, { cereal_CarControl_HUDControl_AudibleAlert_chimeError, "../assets/sounds/error.wav", false }, { cereal_CarControl_HUDControl_AudibleAlert_chimePrompt, "../assets/sounds/error.wav", false }, { cereal_CarControl_HUDControl_AudibleAlert_none, NULL, false }, @@ -2192,8 +2192,8 @@ int main(int argc, char* argv[]) { float smooth_brightness = BRIGHTNESS_B; - const int MIN_VOLUME = LEON ? 12 : 8; - const int MAX_VOLUME = LEON ? 15 : 13; + const int MIN_VOLUME = LEON ? 12 : 9; + const int MAX_VOLUME = LEON ? 15 : 12; set_volume(s, MIN_VOLUME); #ifdef DEBUG_FPS diff --git a/selfdrive/updated.py b/selfdrive/updated.py index 743eb6f589a33b..d05a9a8fa7ed8e 100755 --- a/selfdrive/updated.py +++ b/selfdrive/updated.py @@ -1,13 +1,18 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # simple service that waits for network access and tries to update every hour -import time +import datetime import subprocess +import time + +from common.params import Params from selfdrive.swaglog import cloudlog NICE_LOW_PRIORITY = ["nice", "-n", "19"] def main(gctx=None): + params = Params() + while True: # try network ping_failed = subprocess.call(["ping", "-W", "4", "-c", "1", "8.8.8.8"]) @@ -17,7 +22,7 @@ def main(gctx=None): # download application update try: - r = subprocess.check_output(NICE_LOW_PRIORITY + ["git", "fetch"], stderr=subprocess.STDOUT) + r = subprocess.check_output(NICE_LOW_PRIORITY + ["git", "fetch"], stderr=subprocess.STDOUT).decode('utf8') except subprocess.CalledProcessError as e: cloudlog.event("git fetch failed", cmd=e.cmd, @@ -27,8 +32,26 @@ def main(gctx=None): continue cloudlog.info("git fetch success: %s", r) + # Write update available param + try: + cur_hash = subprocess.check_output(["git", "rev-parse", "HEAD"]).rstrip() + upstream_hash = subprocess.check_output(["git", "rev-parse", "@{u}"]).rstrip() + params.put("UpdateAvailable", str(int(cur_hash != upstream_hash))) + except: + params.put("UpdateAvailable", "0") + + # Write latest release notes to param + try: + r = subprocess.check_output(["git", "--no-pager", "show", "@{u}:RELEASES.md"]) + r = r[:r.find(b'\n\n')] # Slice latest release notes + params.put("ReleaseNotes", r + b"\n") + except: + params.put("ReleaseNotes", "") + + t = datetime.datetime.now().isoformat() + params.put("LastUpdateTime", t.encode('utf8')) + time.sleep(60*60) if __name__ == "__main__": main() - diff --git a/selfdrive/version.py b/selfdrive/version.py index 2eb39dc9769826..dd78fa4e0bb890 100644 --- a/selfdrive/version.py +++ b/selfdrive/version.py @@ -1,28 +1,29 @@ +#!/usr/bin/env python3 import os import subprocess from selfdrive.swaglog import cloudlog def get_git_commit(): - return subprocess.check_output(["git", "rev-parse", "HEAD"]).strip() + return subprocess.check_output(["git", "rev-parse", "HEAD"], encoding='utf8').strip() # pylint: disable=unexpected-keyword-arg def get_git_branch(): - return subprocess.check_output(["git", "rev-parse", "--abbrev-ref", "HEAD"]).strip() + return subprocess.check_output(["git", "rev-parse", "--abbrev-ref", "HEAD"], encoding='utf8').strip() # pylint: disable=unexpected-keyword-arg def get_git_full_branchname(): - return subprocess.check_output(["git", "rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"]).strip() + return subprocess.check_output(["git", "rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"], encoding='utf8').strip() # pylint: disable=unexpected-keyword-arg def get_git_remote(): try: - local_branch = subprocess.check_output(["git", "name-rev", "--name-only", "HEAD"]).strip() - tracking_remote = subprocess.check_output(["git", "config", "branch." + local_branch + ".remote"]).strip() - return subprocess.check_output(["git", "config", "remote." + tracking_remote + ".url"]).strip() + local_branch = subprocess.check_output(["git", "name-rev", "--name-only", "HEAD"], encoding='utf8').strip() # pylint: disable=unexpected-keyword-arg + tracking_remote = subprocess.check_output(["git", "config", "branch." + local_branch + ".remote"], encoding='utf8').strip() # pylint: disable=unexpected-keyword-arg + return subprocess.check_output(["git", "config", "remote." + tracking_remote + ".url"], encoding='utf8').strip() # pylint: disable=unexpected-keyword-arg except subprocess.CalledProcessError: # Not on a branch, fallback - return subprocess.check_output(["git", "config", "--get", "remote.origin.url"]).strip() + return subprocess.check_output(["git", "config", "--get", "remote.origin.url"], encoding='utf8').strip() # pylint: disable=unexpected-keyword-arg with open(os.path.join(os.path.dirname(os.path.abspath(__file__)), "common", "version.h")) as _versionf: @@ -44,9 +45,9 @@ def get_git_remote(): dirty = subprocess.call(["git", "diff-index", "--quiet", branch, "--"]) != 0 if dirty: - dirty_files = subprocess.check_output(["git", "diff-index", branch, "--"]) - commit = subprocess.check_output(["git", "rev-parse", "--verify", "HEAD"]).rstrip() - origin_commit = subprocess.check_output(["git", "rev-parse", "--verify", branch]).rstrip() + dirty_files = subprocess.check_output(["git", "diff-index", branch, "--"], encoding='utf8') # pylint: disable=unexpected-keyword-arg + commit = subprocess.check_output(["git", "rev-parse", "--verify", "HEAD"], encoding='utf8').rstrip() # pylint: disable=unexpected-keyword-arg + origin_commit = subprocess.check_output(["git", "rev-parse", "--verify", branch], encoding='utf8').rstrip() # pylint: disable=unexpected-keyword-arg cloudlog.event("dirty comma branch", vesion=version, dirty=dirty, origin=origin, branch=branch, dirty_files=dirty_files, commit=commit, origin_commit=origin_commit) else: @@ -58,8 +59,8 @@ def get_git_remote(): pass dirty = True -training_version = "0.1.0" -terms_version = "2" +training_version = b"0.1.0" +terms_version = b"2" if __name__ == "__main__": print("Dirty: %s" % dirty) diff --git a/selfdrive/visiond/cameras/camera_frame_stream.cc b/selfdrive/visiond/cameras/camera_frame_stream.cc index 81b2bd40089eac..ae3c8b14ca1af8 100644 --- a/selfdrive/visiond/cameras/camera_frame_stream.cc +++ b/selfdrive/visiond/cameras/camera_frame_stream.cc @@ -19,7 +19,7 @@ extern "C" { #include } -extern volatile int do_exit; +extern volatile sig_atomic_t do_exit; #define FRAME_WIDTH 1164 #define FRAME_HEIGHT 874 diff --git a/selfdrive/visiond/cameras/camera_qcom.c b/selfdrive/visiond/cameras/camera_qcom.c index ccaee8575fc2d4..39fd189b5a5cf3 100644 --- a/selfdrive/visiond/cameras/camera_qcom.c +++ b/selfdrive/visiond/cameras/camera_qcom.c @@ -44,7 +44,7 @@ typedef struct CameraMsg { float grey_frac; } CameraMsg; -extern volatile int do_exit; +extern volatile sig_atomic_t do_exit; CameraInfo cameras_supported[CAMERA_ID_MAX] = { [CAMERA_ID_IMX298] = { @@ -368,21 +368,6 @@ static void set_exposure(CameraState *s, float exposure_frac, float gain_frac) { integ_lines = min(integ_lines, frame_length-11); } - // done after exposure to not adjust it - if (s->using_pll) { - // can adjust frame length by up to +/- 1 - const int PHASE_DEADZONE = 20000; // 20 us - int phase_max = 1000000000 / s->fps; - int phase_diff = s->phase_actual - s->phase_request; - phase_diff = ((phase_diff + phase_max/2) % phase_max) - phase_max/2; - - if (phase_diff < -PHASE_DEADZONE) { - frame_length += 1; - } else if (phase_diff > PHASE_DEADZONE) { - frame_length -= 1; - } - } - if (gain_frac >= 0) { // ISO200 is minimum gain gain_frac = clamp(gain_frac, 1.0/64, 1.0); @@ -2019,41 +2004,6 @@ static bool acceleration_from_sensor_sock(void* sock, float* vs) { return ret; } -static bool gps_time_from_timing_sock(void* sock, uint64_t *mono_time, double* vs) { - int err; - - zmq_msg_t msg; - err = zmq_msg_init(&msg); - assert(err == 0); - - err = zmq_msg_recv(&msg, sock, 0); - assert(err >= 0); - - struct capn ctx; - capn_init_mem(&ctx, zmq_msg_data(&msg), zmq_msg_size(&msg), 0); - - cereal_Event_ptr eventp; - eventp.p = capn_getp(capn_root(&ctx), 0, 1); - struct cereal_Event eventd; - cereal_read_Event(&eventd, eventp); - - bool ret = false; - - if (eventd.which == cereal_Event_liveLocationTiming) { - struct cereal_LiveLocationData lld; - cereal_read_LiveLocationData(&lld, eventd.liveLocationTiming); - - *mono_time = lld.fixMonoTime; - *vs = lld.timeOfWeek; - ret = true; - } - - capn_free(&ctx); - zmq_msg_close(&msg); - - return ret; -} - static void ops_term() { zsock_t *ops_sock = zsock_new_push(">inproc://cameraops"); assert(ops_sock); @@ -2076,13 +2026,10 @@ static void* ops_thread(void* arg) { zsock_t *sensor_sock = zsock_new_sub(">tcp://127.0.0.1:8003", ""); assert(sensor_sock); - zsock_t *livelocationtiming_sock = zsock_new_sub(">tcp://127.0.0.1:8049", ""); - assert(livelocationtiming_sock); - zsock_t *terminate = zsock_new_sub(">inproc://terminate", ""); assert(terminate); - zpoller_t *poller = zpoller_new(cameraops, sensor_sock, livelocationtiming_sock, terminate, NULL); + zpoller_t *poller = zpoller_new(cameraops, sensor_sock, terminate, NULL); assert(poller); while (!do_exit) { @@ -2130,15 +2077,6 @@ static void* ops_thread(void* arg) { s->rear.last_sag_ts = ts; s->rear.last_sag_acc_z = -vs[2]; } - } else if (which == livelocationtiming_sock) { - uint64_t mono_time; - double gps_time; - if (gps_time_from_timing_sock(sockraw, &mono_time, &gps_time)) { - s->rear.global_time_offset = (uint64_t)(gps_time*1e9) - mono_time; - //LOGW("%f %lld = %lld", gps_time, mono_time, s->rear.global_time_offset); - s->rear.phase_request = 10000000; - s->rear.using_pll = true; - } } } @@ -2228,12 +2166,6 @@ void cameras_run(DualCameraState *s) { // printf("ISP_EVENT_EOF delta %f\n", (t-last_t)/1e6); c->last_t = t; - if (c->using_pll) { - int mod = ((int)1000000000 / c->fps); - c->phase_actual = (((timestamp + c->global_time_offset) % mod) + mod) % mod; - LOGD("phase is %12d request is %12d with offset %lld", c->phase_actual, c->phase_request, c->global_time_offset); - } - pthread_mutex_lock(&c->frame_info_lock); c->frame_metadata[c->frame_metadata_idx] = (FrameMetadata){ .frame_id = isp_event_data->frame_id, @@ -2270,4 +2202,3 @@ void cameras_close(DualCameraState *s) { camera_close(&s->rear); camera_close(&s->front); } - diff --git a/selfdrive/visiond/cameras/camera_qcom.h b/selfdrive/visiond/cameras/camera_qcom.h index 0cc8f844a57477..1a9c31baa3a29f 100644 --- a/selfdrive/visiond/cameras/camera_qcom.h +++ b/selfdrive/visiond/cameras/camera_qcom.h @@ -54,13 +54,6 @@ typedef struct CameraState { uint32_t line_length_pclk; unsigned int max_gain; - // PLL to sync cameras in time - // assumes at least 1 FPS - bool using_pll; - int phase_actual; - int phase_request; - int64_t global_time_offset; - int csid_fd; int csiphy_fd; int sensor_fd; diff --git a/selfdrive/debug/getframes/Makefile b/selfdrive/visiond/snapshot/Makefile similarity index 65% rename from selfdrive/debug/getframes/Makefile rename to selfdrive/visiond/snapshot/Makefile index 932673e208d116..6edde2f822ad74 100644 --- a/selfdrive/debug/getframes/Makefile +++ b/selfdrive/visiond/snapshot/Makefile @@ -18,9 +18,15 @@ visionipc.o: ../../common/visionipc.c ../../common/visionipc.h -I../.. -I../../.. \ -c -o '$@' ../../common/visionipc.c -libvisionipc.so: visionipc.o - $(CC) -shared -fPIC -o '$@' visionipc.o +ipc.o: ../../common/ipc.c ../../common/ipc.h + @echo "[ CC ] $@" + $(CC) $(CFLAGS) -MMD \ + -I../.. -I../../.. \ + -c -o '$@' ../../common/ipc.c + +libvisionipc.so: visionipc.o ipc.o + $(CC) -shared -fPIC -o '$@' visionipc.o ipc.o .PHONY: clean clean: - rm visionipc.o libvisionipc.so + rm visionipc.o ipc.o libvisionipc.so diff --git a/selfdrive/test/tests/__init__.py b/selfdrive/visiond/snapshot/__init__.py similarity index 100% rename from selfdrive/test/tests/__init__.py rename to selfdrive/visiond/snapshot/__init__.py diff --git a/selfdrive/visiond/snapshot/snapshot.py b/selfdrive/visiond/snapshot/snapshot.py new file mode 100755 index 00000000000000..cb24209655878b --- /dev/null +++ b/selfdrive/visiond/snapshot/snapshot.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +import os +import subprocess +from PIL import Image +import time +import signal + +from selfdrive.visiond.snapshot.visionipc import VisionIPC + +def jpeg_write(fn, dat): + img = Image.fromarray(dat) + img.save(fn, "JPEG") + +def snapshot(): + # note: super sketch race condition if you start the car at the same time at this + # TODO: lock car starting? + ps = subprocess.Popen("ps | grep visiond", shell=True, stdout=subprocess.PIPE) + ret = list(filter(lambda x: 'grep ' not in x, ps.communicate()[0].decode('utf-8').strip().split("\n"))) + if len(ret) > 0: + return None + + proc = subprocess.Popen(os.path.join(os.getenv("HOME"), "one/selfdrive/visiond/visiond"), cwd=os.path.join(os.getenv("HOME"), "one/selfdrive/visiond")) + time.sleep(6.0) + + ret = None + try: + ipc = VisionIPC() + pic = ipc.get() + del ipc + + ipc_front = VisionIPC(front=True) + fpic = ipc_front.get() + del ipc_front + + ret = pic, fpic + finally: + proc.send_signal(signal.SIGINT) + proc.communicate() + + return ret + +if __name__ == "__main__": + pic, fpic = snapshot() + jpeg_write("/tmp/back.jpg", pic) + jpeg_write("/tmp/front.jpg", fpic) + diff --git a/selfdrive/debug/getframes/getframes.py b/selfdrive/visiond/snapshot/visionipc.py old mode 100755 new mode 100644 similarity index 65% rename from selfdrive/debug/getframes/getframes.py rename to selfdrive/visiond/snapshot/visionipc.py index 4964841750d339..1129025081948e --- a/selfdrive/debug/getframes/getframes.py +++ b/selfdrive/visiond/snapshot/visionipc.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import os import subprocess from cffi import FFI @@ -9,7 +9,6 @@ subprocess.check_call(["make"], cwd=gf_dir) - ffi = FFI() ffi.cdef(""" @@ -69,33 +68,19 @@ """ ) -clib = ffi.dlopen(os.path.join(gf_dir, "libvisionipc.so")) - - -def getframes(front=False): - s = ffi.new("VisionStream*") - buf_info = ffi.new("VisionStreamBufs*") +class VisionIPC(): + def __init__(self, front=False): + self.clib = ffi.dlopen(os.path.join(gf_dir, "libvisionipc.so")) - if front: - stream_type = clib.VISION_STREAM_RGB_FRONT - else: - stream_type = clib.VISION_STREAM_RGB_BACK + self.s = ffi.new("VisionStream*") + self.buf_info = ffi.new("VisionStreamBufs*") - err = clib.visionstream_init(s, stream_type, True, buf_info) - assert err == 0 - - w = buf_info.width - h = buf_info.height - assert buf_info.stride == w*3 - assert buf_info.buf_len == w*h*3 - - while True: - buf = clib.visionstream_get(s, ffi.NULL) + err = self.clib.visionstream_init(self.s, self.clib.VISION_STREAM_RGB_FRONT if front else self.clib.VISION_STREAM_RGB_BACK, True, self.buf_info) + assert err == 0 + def get(self): + buf = self.clib.visionstream_get(self.s, ffi.NULL) pbuf = ffi.buffer(buf.addr, buf.len) - yield np.frombuffer(pbuf, dtype=np.uint8).reshape((h, w, 3)) - + ret = np.frombuffer(pbuf, dtype=np.uint8).reshape((-1, self.buf_info.stride//3, 3)) + return ret[:self.buf_info.height, :self.buf_info.width, [2,1,0]] -if __name__ == "__main__": - for buf in getframes(): - print("{0} {1}".format(buf.shape, buf[101, 101])) diff --git a/selfdrive/visiond/visiond.cc b/selfdrive/visiond/visiond.cc index 53d1f827775439..62682918c04247 100644 --- a/selfdrive/visiond/visiond.cc +++ b/selfdrive/visiond/visiond.cc @@ -80,7 +80,7 @@ typedef void (*sighandler_t) (int); #endif extern "C" { -volatile int do_exit = 0; +volatile sig_atomic_t do_exit = 0; } namespace { @@ -738,8 +738,8 @@ void* monitoring_thread(void *arg) { } else // use default setting if no face { - s->front_meteringbox_ymin = s->rgb_front_height * 0; - s->front_meteringbox_ymax = s->rgb_front_height * 2 / 3; + s->front_meteringbox_ymin = s->rgb_front_height * 1 / 3; + s->front_meteringbox_ymax = s->rgb_front_height * 1; s->front_meteringbox_xmin = s->rgb_front_width * 3 / 5; s->front_meteringbox_xmax = s->rgb_front_width; } @@ -820,8 +820,8 @@ void* frontview_thread(void *arg) { } else { - y_start = s->rgb_front_height * 0; - y_end = s->rgb_front_height * 2 / 3; + y_start = s->rgb_front_height * 1 / 3; + y_end = s->rgb_front_height * 1; x_start = s->rgb_front_width * 3 / 5; x_end = s->rgb_front_width; } @@ -1301,7 +1301,7 @@ void set_do_exit(int sig) { do_exit = 1; } -void party(VisionState *s, bool nomodel) { +void party(VisionState *s) { int err; s->terminate_pub = zsock_new_pub("@inproc://terminate"); @@ -1390,11 +1390,6 @@ int main(int argc, char **argv) { test_run = true; } - bool no_model = false; - if (argc > 1 && strcmp(argv[1], "--no-model") == 0) { - no_model = true; - } - VisionState state = {0}; VisionState *s = &state; @@ -1443,7 +1438,7 @@ int main(int argc, char **argv) { if (test_run) { do_exit = true; } - party(s, no_model); + party(s); zsock_destroy(&s->recorder_sock); zsock_destroy(&s->monitoring_sock);