openpilot v0.6.5 release
parent
3a04a69cbe
commit
cf80f7a28b
|
@ -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.
|
|
@ -0,0 +1,21 @@
|
|||
Choose one of the templates below:
|
||||
|
||||
# Fingerprint
|
||||
This pull requests adds a fingerprint for <Make - Model - Year - Trim>.
|
||||
|
||||
This is an explorer link to a drive with the stock system enabled: ...
|
||||
|
||||
# Car support
|
||||
This pull requests adds support for <Make - Model - Year - Trim>.
|
||||
|
||||
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.
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
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
|
||||
# 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.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
|
||||
|
|
59
Pipfile
59
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"
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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.
|
||||
|
||||
|
@ -93,6 +93,7 @@ Supported Cars
|
|||
| Kia | Optima 2019 | SCC + LKAS | Yes | Stock | 0mph | 0mph | Custom<sup>6</sup>|
|
||||
| Kia | Sorento 2018 | All | Yes | Stock | 0mph | 0mph | Custom<sup>6</sup>|
|
||||
| Kia | Stinger 2018 | SCC + LKAS | Yes | Stock | 0mph | 0mph | Custom<sup>6</sup>|
|
||||
| Lexus | CT Hybrid 2017-18 | All | Yes | Yes<sup>2</sup>| 0mph | 0mph | Toyota |
|
||||
| Lexus | ES Hybrid 2019 | All | Yes | Yes | 0mph | 0mph | Toyota |
|
||||
| Lexus | RX Hybrid 2016-19 | All | Yes | Yes<sup>2</sup>| 0mph | 0mph | Toyota |
|
||||
| Lexus | IS 2017-2019 | All | Yes | Stock | 22mph | 0mph | Toyota |
|
||||
|
@ -144,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.
|
||||
|
||||
|
|
14
RELEASES.md
14
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
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -4,7 +4,7 @@ from datetime import datetime, timedelta
|
|||
|
||||
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 @@ class Api(object):
|
|||
'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/"
|
||||
|
|
|
@ -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)
|
|
@ -17,10 +17,10 @@ DBCSignal = namedtuple(
|
|||
"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 @@ class dbc(object):
|
|||
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 @@ class dbc(object):
|
|||
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]:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 @@ class AutoMoveTempdir(object):
|
|||
else:
|
||||
shutil.rmtree(self._path)
|
||||
|
||||
class NamedTemporaryDir(object):
|
||||
class NamedTemporaryDir():
|
||||
def __init__(self, temp_dir=None):
|
||||
self._path = tempfile.mkdtemp(dir=temp_dir)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -5,6 +5,6 @@ import subprocess
|
|||
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
|
||||
|
|
|
@ -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]
|
||||
self.x1_0 = x[1][0]
|
||||
|
|
|
@ -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"])))
|
||||
cmdclass={'build_ext': BuildExtWithoutPlatformSuffix},
|
||||
ext_modules=cythonize(Extension("simple_kalman_impl", ["simple_kalman_impl.pyx"])))
|
||||
|
|
|
@ -12,7 +12,10 @@ def interp(x, xp, fp):
|
|||
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)
|
||||
|
|
|
@ -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 @@ keys = {
|
|||
"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 @@ class FileLock(object):
|
|||
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 @@ class Params(object):
|
|||
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 @@ class Params(object):
|
|||
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)
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import time
|
||||
|
||||
class Profiler(object):
|
||||
class Profiler():
|
||||
def __init__(self, enabled=False):
|
||||
self.enabled = enabled
|
||||
self.cp = {}
|
||||
|
|
|
@ -19,6 +19,7 @@ assert sec_since_boot
|
|||
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
|
||||
|
|
|
@ -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)
|
||||
|
|
@ -11,7 +11,7 @@ class RunningStat():
|
|||
self.n = priors[2]
|
||||
self.M_last = self.M
|
||||
self.S_last = self.S
|
||||
|
||||
|
||||
else:
|
||||
self.reset()
|
||||
|
||||
|
@ -70,4 +70,4 @@ class RunningStatFilter():
|
|||
pass
|
||||
# self.filtered_stat.push_data(self.filtered_stat.mean())
|
||||
|
||||
# class SequentialBayesian():
|
||||
# class SequentialBayesian():
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
import sympy as sp
|
||||
import numpy as np
|
||||
|
||||
|
|
|
@ -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 transform_img(base_img,
|
|||
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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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'
|
||||
|
|
Binary file not shown.
|
@ -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 time
|
|||
import threading
|
||||
import traceback
|
||||
import zmq
|
||||
import base64
|
||||
import requests
|
||||
import six.moves.queue
|
||||
from functools import partial
|
||||
|
@ -24,6 +26,7 @@ from common.params import Params
|
|||
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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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<cereal::Event>();
|
||||
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"],
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
|
@ -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 common.realtime import Ratekeeper
|
|||
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 @@ try:
|
|||
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')
|
||||
|
|
|
@ -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 @@ if __name__ == "__main__":
|
|||
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)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import time
|
||||
import signal
|
||||
|
|
|
@ -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 @@ import unittest
|
|||
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 @@ class TestBoarddApiMethods(unittest.TestCase):
|
|||
|
||||
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 @@ class TestBoarddApiMethods(unittest.TestCase):
|
|||
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 @@ class TestBoarddApiMethods(unittest.TestCase):
|
|||
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 @@ class CANDefine(object):
|
|||
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()
|
||||
|
|
|
@ -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 = <canpack_init_func>dlsym(libdbc, 'canpack_init')
|
||||
self.canpack_pack_vector = <canpack_pack_vector_func>dlsym(libdbc, 'canpack_pack_vector')
|
||||
self.dbc_lookup = <dbc_lookup_func>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, (<char *>&val)[:size], bus]
|
||||
|
|
|
@ -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"])))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 = <can_init_with_vectors_func>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 = <unicode>self.address_to_msg_name[cv.address].c_str()
|
||||
cv_name = <unicode>cv.name
|
||||
|
||||
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[cv.address][cv_name] = cv.value
|
||||
self.ts[cv.address][cv_name] = cv.ts
|
||||
|
||||
self.vl[name][cv_name] = cv.value
|
||||
self.ts[name][cv_name] = cv.ts
|
||||
|
||||
updated_val.insert(cv.address)
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -7,7 +7,7 @@ from selfdrive.car.honda.hondacan import fix
|
|||
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 @@ class CANParser(object):
|
|||
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
|
||||
|
|
|
@ -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 @@ from common.dbc import dbc
|
|||
|
||||
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
|
||||
|
|
|
@ -2,8 +2,9 @@ import struct
|
|||
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 @@ class CANPacker(object):
|
|||
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],
|
||||
|
|
|
@ -5,7 +5,7 @@ from selfdrive.can.libdbc_py import libdbc, ffi
|
|||
|
||||
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 @@ class CANParser(object):
|
|||
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 @@ class CANParser(object):
|
|||
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 @@ class CANParser(object):
|
|||
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 @@ class CANParser(object):
|
|||
'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 @@ class CANParser(object):
|
|||
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
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ class TestPackerMethods(unittest.TestCase):
|
|||
|
||||
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)
|
||||
|
|
|
@ -17,7 +17,7 @@ class TestPackerMethods(unittest.TestCase):
|
|||
|
||||
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)
|
||||
|
|
|
@ -15,8 +15,8 @@ class TestPackerMethods(unittest.TestCase):
|
|||
|
||||
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 @@ class TestPackerMethods(unittest.TestCase):
|
|||
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 @@ class TestPackerMethods(unittest.TestCase):
|
|||
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)
|
||||
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ class TestPackerMethods(unittest.TestCase):
|
|||
|
||||
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)
|
||||
|
|
|
@ -14,7 +14,7 @@ class TestPackerMethods(unittest.TestCase):
|
|||
|
||||
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)
|
||||
|
|
|
@ -17,7 +17,7 @@ class TestPackerMethods(unittest.TestCase):
|
|||
|
||||
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 @@ class TestPackerMethods(unittest.TestCase):
|
|||
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
|
||||
|
|
|
@ -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 @@ class TestCanParser(unittest.TestCase):
|
|||
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):
|
||||
|
|
|
@ -4,6 +4,9 @@ from common.numpy_fast import clip
|
|||
# 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])
|
||||
|
|
|
@ -2,11 +2,12 @@ import os
|
|||
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 @@ class CarInterface(object):
|
|||
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 @@ class CarInterface(object):
|
|||
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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
PYTHONPATH=`realpath ../../../` python chryslercan_test.py
|
|
@ -1,55 +1,57 @@
|
|||
from selfdrive.car.chrysler import chryslercan
|
||||
from selfdrive.can.packer import CANPacker
|
||||
import unittest
|
||||
|
||||
from cereal import car
|
||||
VisualAlert = car.CarControl.HUDControl.VisualAlert
|
||||
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))
|
|
@ -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 @@ FINGERPRINTS = {
|
|||
],
|
||||
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 @@ FINGERPRINTS = {
|
|||
# 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
|
||||
|
|
|
@ -7,7 +7,7 @@ from selfdrive.can.packer import CANPacker
|
|||
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 @@ class CarController(object):
|
|||
|
||||
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 @@ class CarController(object):
|
|||
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
|
||||
|
|
|
@ -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 @@ class CarState(object):
|
|||
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
|
||||
|
|
|
@ -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 @@ class CarInterface(object):
|
|||
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 @@ class CarInterface(object):
|
|||
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
|
||||
|
|
|
@ -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 @@ class RadarInterface(object):
|
|||
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 @@ class RadarInterface(object):
|
|||
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 @@ class RadarInterface(object):
|
|||
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
|
||||
|
|
|
@ -11,6 +11,13 @@ FINGERPRINTS = {
|
|||
}],
|
||||
}
|
||||
|
||||
class ECU:
|
||||
CAM = 0
|
||||
|
||||
ECU_FINGERPRINT = {
|
||||
ECU.CAM: [970, 973, 984]
|
||||
}
|
||||
|
||||
DBC = {
|
||||
CAR.FUSION: dbc_dict('ford_fusion_2018_pt', 'ford_fusion_2018_adas'),
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 @@ class CarState(object):
|
|||
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]]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 @@ class CarInterface(object):
|
|||
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
|
||||
|
|
|
@ -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 @@ class RadarInterface(object):
|
|||
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 @@ class RadarInterface(object):
|
|||
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
|
||||
|
|
|
@ -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 @@ FINGERPRINTS = {
|
|||
|
||||
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 = {
|
||||
|
|
|
@ -73,7 +73,7 @@ HUDData = namedtuple("HUDData",
|
|||
"lanes", "fcw", "acc_alert", "steer_required"])
|
||||
|
||||
|
||||
class CarController(object):
|
||||
class CarController():
|
||||
def __init__(self, dbc_name):
|
||||
self.braking = False
|
||||
self.brake_steady = 0.
|
||||
|
|
|
@ -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 @@ class CarState(object):
|
|||
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 @@ class CarState(object):
|
|||
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 @@ if __name__ == '__main__':
|
|||
import zmq
|
||||
context = zmq.Context()
|
||||
|
||||
class CarParams(object):
|
||||
class CarParams():
|
||||
def __init__(self):
|
||||
self.carFingerprint = "HONDA CIVIC 2016 TOURING"
|
||||
self.enableGasInterceptor = 0
|
||||
|
|
|
@ -6,7 +6,6 @@ from selfdrive.car.honda.values import CAR, HONDA_BOSCH
|
|||
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)
|
||||
|
|
|
@ -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.config import Conversions as CV
|
|||
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 get_compute_gb_acura():
|
|||
return _compute_gb_acura
|
||||
|
||||
|
||||
class CarInterface(object):
|
||||
class CarInterface(CarInterfaceBase):
|
||||
def __init__(self, CP, CarController):
|
||||
self.CP = CP
|
||||
|
||||
|
@ -131,27 +131,28 @@ class CarInterface(object):
|
|||
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 @@ class CarInterface(object):
|
|||
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.]
|
||||
|
|
|
@ -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]))
|
||||
|
||||
return CANParser(os.path.splitext(dbc_f)[0], signals, checks, 1)
|
||||
fn = os.path.splitext(dbc_f)[0].encode('utf8')
|
||||
return CANParser(fn, signals, checks, 1)
|
||||
|
||||
|
||||
class RadarInterface(object):
|
||||
class RadarInterface(RadarInterfaceBase):
|
||||
def __init__(self, CP):
|
||||
# radar
|
||||
self.pts = {}
|
||||
|
@ -26,7 +28,7 @@ class RadarInterface(object):
|
|||
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 @@ class RadarInterface(object):
|
|||
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 @@ class RadarInterface(object):
|
|||
errors.append("wrongConfig")
|
||||
ret.errors = errors
|
||||
|
||||
ret.points = self.pts.values()
|
||||
ret.points = list(self.pts.values())
|
||||
|
||||
return ret
|
||||
|
|
|
@ -30,6 +30,9 @@ VISUAL_HUD = {
|
|||
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"
|
||||
|
@ -116,7 +119,7 @@ FINGERPRINTS = {
|
|||
},
|
||||
# 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 @@ SPEED_FACTOR = {
|
|||
|
||||
# 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]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 @@ class CarState(object):
|
|||
# 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"]
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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 @@ class CarInterface(object):
|
|||
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 @@ class CarInterface(object):
|
|||
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 @@ FINGERPRINTS = {
|
|||
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],
|
||||
|
|
|
@ -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
|
|
@ -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 @@ YAW_FR = 0.2 # ~0.8s time constant on yaw rate filter
|
|||
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 @@ class CarInterface(object):
|
|||
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()
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue