Compare commits
59 Commits
latency_lo
...
master
Author | SHA1 | Date |
---|---|---|
Jason Wen | 3a6039e0ff | |
Adeeb Shihadeh | 7a2fd6622c | |
HaraldSchafer | adf34c3414 | |
HaraldSchafer | 7dd9971717 | |
Shane Smiskol | 405ecbced3 | |
Adeeb Shihadeh | bb36a1c8b2 | |
Adeeb Shihadeh | 67e3a2c39a | |
Shane Smiskol | 4802c864d5 | |
Adeeb Shihadeh | aeb98b3937 | |
Jack Huang | db93275d87 | |
Adeeb Shihadeh | 8af20af66d | |
George Hotz | 1df3c86999 | |
Adeeb Shihadeh | ea74a90ca0 | |
Shane Smiskol | e91613bc62 | |
Harald Schafer | d08b52caef | |
Shane Smiskol | c88ced1f10 | |
Adeeb Shihadeh | a55e25d9d2 | |
Shane Smiskol | 85d8997a8a | |
Adeeb Shihadeh | fc2f84759d | |
Adeeb Shihadeh | 53909c1757 | |
Dylan Herman | 9f1c663ae2 | |
HaraldSchafer | 4a8fffd0f4 | |
Adeeb Shihadeh | b57c2f4a14 | |
Robbe Derks | 1035b910f0 | |
mitchellgoffpc | 5c8c6faa9a | |
Adeeb Shihadeh | 7cd8575c74 | |
Robbe Derks | 25219442d1 | |
Adeeb Shihadeh | b079475ad3 | |
Dylan Herman | 604fefa9b1 | |
Comma Device | 03ac5bb4e3 | |
Adeeb Shihadeh | c76434ca9f | |
whokilleddb | 1bdf29dc5b | |
Adeeb Shihadeh | a6d4bb5d01 | |
Cameron Clough | 602cbfcba0 | |
Shane Smiskol | 20085620db | |
Shane Smiskol | 15368ec3d1 | |
Shane Smiskol | 247b66f4a8 | |
Shane Smiskol | 7a2f3c023e | |
Shane Smiskol | 70286766da | |
Shane Smiskol | 99c02bdd29 | |
Adeeb Shihadeh | 7eb9416f6b | |
Adeeb Shihadeh | 2219cb4478 | |
Adeeb Shihadeh | 1af3c52049 | |
George Hotz | 5a11101bcf | |
Shane Smiskol | 6c7d178d96 | |
Gijs Koning | 3d8537ab23 | |
Adeeb Shihadeh | b9c48f12ad | |
Shane Smiskol | 628eecff06 | |
Igor Biletskyy | 62087a6368 | |
Jonathan Frey | 5bc47a294f | |
Adeeb Shihadeh | f7d0ddb9a4 | |
Harald Schafer | db7b49c71c | |
Shane Smiskol | 31a6b141d6 | |
HaraldSchafer | dcece099ff | |
Shane Smiskol | 3a7edeea32 | |
Shane Smiskol | facf6c109d | |
Jason Young | 62bb43b7e2 | |
Adeeb Shihadeh | bae78dd46b | |
Adeeb Shihadeh | 20db4525a2 |
|
@ -22,8 +22,8 @@ Route: [a route with the bug fix]
|
|||
<!--- ***** Template: Car port *****
|
||||
|
||||
**Checklist**
|
||||
- [ ] added to README
|
||||
- [ ] test route added to [test_routes.py](https://github.com/commaai/openpilot/blob/master/selfdrive/test/test_routes.py)
|
||||
- [ ] added entry to CarInfo in selfdrive/car/*/values.py and ran `selfdrive/car/docs.py` to generate new docs
|
||||
- [ ] test route added to [routes.py](https://github.com/commaai/openpilot/blob/master/selfdrive/car/tests/routes.py)
|
||||
- [ ] route with openpilot:
|
||||
- [ ] route with stock system:
|
||||
|
||||
|
|
|
@ -244,7 +244,8 @@ jobs:
|
|||
run: eval "$BUILD"
|
||||
- name: Run unit tests
|
||||
run: |
|
||||
${{ env.RUN }} "scons -j$(nproc) --test && \
|
||||
${{ env.RUN }} "export SKIP_LONG_TESTS=1 && \
|
||||
scons -j$(nproc) --test && \
|
||||
$UNIT_TEST common && \
|
||||
$UNIT_TEST opendbc/can && \
|
||||
$UNIT_TEST selfdrive/boardd && \
|
||||
|
@ -383,7 +384,7 @@ jobs:
|
|||
uses: actions/cache@v2
|
||||
with:
|
||||
path: /tmp/comma_download_cache
|
||||
key: car_models-${{ hashFiles('selfdrive/car/tests/test_models.py', 'selfdrive/test/test_routes.py') }}-${{ matrix.job }}
|
||||
key: car_models-${{ hashFiles('selfdrive/car/tests/test_models.py', 'selfdrive/car/tests/routes.py') }}-${{ matrix.job }}
|
||||
- name: Cache scons
|
||||
id: scons-cache
|
||||
# TODO: Change the version to the released version when https://github.com/actions/cache/pull/489 (or 571) is merged.
|
||||
|
|
|
@ -54,7 +54,7 @@ confidence=
|
|||
# --enable=similarities". If you want to run only the classes checker, but have
|
||||
# no Warning level messages displayed, use"--disable=all --enable=classes
|
||||
# --disable=W"
|
||||
disable=C,R,W0613,W0511,W0212,W0201,W0311,W0106,W0603,W0621,W0703,W1201,W1203,E1136,W1514
|
||||
disable=C,R,W0613,W0511,W0212,W0201,W0106,W0603,W0621,W0703,W1201,W1203,E1136,W1514
|
||||
|
||||
|
||||
# Enable the message, report, category or checker with the given id(s). You can
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
Version 0.8.14 (2022-0X-XX)
|
||||
========================
|
||||
* bigmodel!
|
||||
* Toyota Alphard Hybrid 2021 support
|
||||
* Toyota Avalon Hybrid 2022 support
|
||||
|
||||
Version 0.8.13 (2022-02-18)
|
||||
========================
|
||||
|
|
2
cereal
|
@ -1 +1 @@
|
|||
Subproject commit 64b6014193a69fe2e2b3b7a17f9e228162081ddf
|
||||
Subproject commit a818779f1a55c6bf53fa0692e31111585662b722
|
|
@ -36,8 +36,8 @@ class TestSimpleKalman(unittest.TestCase):
|
|||
self.assertEqual(self.kf.x, [[1.0], [1.0]])
|
||||
|
||||
def update_returns_state(self):
|
||||
x = self.kf.update(100)
|
||||
self.assertEqual(x, self.kf.x)
|
||||
x = self.kf.update(100)
|
||||
self.assertEqual(x, self.kf.x)
|
||||
|
||||
def test_old_equal_new(self):
|
||||
for _ in range(1000):
|
||||
|
|
|
@ -172,33 +172,33 @@ class SwagLogger(logging.Logger):
|
|||
#On some versions of IronPython, currentframe() returns None if
|
||||
#IronPython isn't run with -X:Frames.
|
||||
if f is not None:
|
||||
f = f.f_back
|
||||
f = f.f_back
|
||||
orig_f = f
|
||||
while f and stacklevel > 1:
|
||||
f = f.f_back
|
||||
stacklevel -= 1
|
||||
f = f.f_back
|
||||
stacklevel -= 1
|
||||
if not f:
|
||||
f = orig_f
|
||||
f = orig_f
|
||||
rv = "(unknown file)", 0, "(unknown function)", None
|
||||
while hasattr(f, "f_code"):
|
||||
co = f.f_code
|
||||
filename = os.path.normcase(co.co_filename)
|
||||
co = f.f_code
|
||||
filename = os.path.normcase(co.co_filename)
|
||||
|
||||
# TODO: is this pylint exception correct?
|
||||
if filename == _srcfile: # pylint: disable=comparison-with-callable
|
||||
f = f.f_back
|
||||
continue
|
||||
sinfo = None
|
||||
if stack_info:
|
||||
sio = io.StringIO()
|
||||
sio.write('Stack (most recent call last):\n')
|
||||
traceback.print_stack(f, file=sio)
|
||||
sinfo = sio.getvalue()
|
||||
if sinfo[-1] == '\n':
|
||||
sinfo = sinfo[:-1]
|
||||
sio.close()
|
||||
rv = (co.co_filename, f.f_lineno, co.co_name, sinfo)
|
||||
break
|
||||
# TODO: is this pylint exception correct?
|
||||
if filename == _srcfile: # pylint: disable=comparison-with-callable
|
||||
f = f.f_back
|
||||
continue
|
||||
sinfo = None
|
||||
if stack_info:
|
||||
sio = io.StringIO()
|
||||
sio.write('Stack (most recent call last):\n')
|
||||
traceback.print_stack(f, file=sio)
|
||||
sinfo = sio.getvalue()
|
||||
if sinfo[-1] == '\n':
|
||||
sinfo = sinfo[:-1]
|
||||
sio.close()
|
||||
rv = (co.co_filename, f.f_lineno, co.co_name, sinfo)
|
||||
break
|
||||
return rv
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
394
docs/CARS.md
|
@ -1,186 +1,222 @@
|
|||
# Supported Cars
|
||||
|
||||
## comma.ai supported cars
|
||||
A supported vehicle is one that just works when you install a comma device. Every car performs differently with openpilot, but all supported cars should provide a better experience than any stock system.
|
||||
|
||||
| Make | Model (US Market Reference) | Supported Package | ACC | No ACC accel below | No ALC below |
|
||||
| ----------| ------------------------------| ------------------| -----------------| -------------------| ------------------|
|
||||
| Acura | ILX 2016-19 | AcuraWatch Plus | openpilot | 25mph<sup>1</sup> | 25mph |
|
||||
| Acura | RDX 2016-18 | AcuraWatch Plus | openpilot | 25mph<sup>1</sup> | 12mph |
|
||||
| Acura | RDX 2019-21 | All | Stock | 0mph | 3mph |
|
||||
| Honda | Accord 2018-21 | All | Stock | 0mph | 3mph |
|
||||
| Honda | Accord Hybrid 2018-21 | All | Stock | 0mph | 3mph |
|
||||
| Honda | Civic Hatchback 2017-21 | Honda Sensing | Stock | 0mph | 12mph |
|
||||
| Honda | Civic Coupe 2016-18 | Honda Sensing | openpilot | 0mph | 12mph |
|
||||
| Honda | Civic Coupe 2019-20 | All | Stock | 0mph | 2mph<sup>2</sup> |
|
||||
| Honda | Civic Sedan 2016-18 | Honda Sensing | openpilot | 0mph | 12mph |
|
||||
| Honda | Civic Sedan 2019-20 | All | Stock | 0mph | 2mph<sup>2</sup> |
|
||||
| Honda | CR-V 2015-16 | Touring | openpilot | 25mph<sup>1</sup> | 12mph |
|
||||
| Honda | CR-V 2017-21 | Honda Sensing | Stock | 0mph | 12mph |
|
||||
| Honda | CR-V Hybrid 2017-2019 | Honda Sensing | Stock | 0mph | 12mph |
|
||||
| Honda | e 2020 | All | Stock | 0mph | 3mph |
|
||||
| Honda | Fit 2018-19 | Honda Sensing | openpilot | 25mph<sup>1</sup> | 12mph |
|
||||
| Honda | Freed 2020 | Honda Sensing | openpilot | 25mph<sup>1</sup> | 12mph |
|
||||
| Honda | HR-V 2019-20 | Honda Sensing | openpilot | 25mph<sup>1</sup> | 12mph |
|
||||
| Honda | Insight 2019-21 | All | Stock | 0mph | 3mph |
|
||||
| Honda | Inspire 2018 | All | Stock | 0mph | 3mph |
|
||||
| Honda | Odyssey 2018-20 | Honda Sensing | openpilot | 25mph<sup>1</sup> | 0mph |
|
||||
| Honda | Passport 2019-21 | All | openpilot | 25mph<sup>1</sup> | 12mph |
|
||||
| Honda | Pilot 2016-21 | Honda Sensing | openpilot | 25mph<sup>1</sup> | 12mph |
|
||||
| Honda | Ridgeline 2017-21 | Honda Sensing | openpilot | 25mph<sup>1</sup> | 12mph |
|
||||
| Hyundai | Palisade 2020-21 | All | Stock | 0mph | 0mph |
|
||||
| Hyundai | Sonata 2020-22 | All | Stock | 0mph | 0mph |
|
||||
| Lexus | CT Hybrid 2017-18 | LSS | Stock<sup>3</sup>| 0mph | 0mph |
|
||||
| Lexus | ES 2019-21 | All | openpilot | 0mph | 0mph |
|
||||
| Lexus | ES Hybrid 2017-18 | LSS | Stock<sup>3</sup>| 0mph | 0mph |
|
||||
| Lexus | ES Hybrid 2019-21 | All | openpilot | 0mph | 0mph |
|
||||
| Lexus | IS 2017-2019 | All | Stock | 22mph | 0mph |
|
||||
| Lexus | NX 2018-2019 | All | Stock<sup>3</sup>| 0mph | 0mph |
|
||||
| Lexus | NX 2020 | All | openpilot | 0mph | 0mph |
|
||||
| Lexus | NX Hybrid 2018-19 | All | Stock<sup>3</sup>| 0mph | 0mph |
|
||||
| Lexus | RC 2020 | All | Stock | 22mph | 0mph |
|
||||
| Lexus | RX 2016-18 | All | Stock<sup>3</sup>| 0mph | 0mph |
|
||||
| Lexus | RX 2020-21 | All | openpilot | 0mph | 0mph |
|
||||
| Lexus | RX Hybrid 2016-19 | All | Stock<sup>3</sup>| 0mph | 0mph |
|
||||
| Lexus | RX Hybrid 2020-21 | All | openpilot | 0mph | 0mph |
|
||||
| Lexus | UX Hybrid 2019-21 | All | openpilot | 0mph | 0mph |
|
||||
| Toyota | Alphard 2019-20 | All | openpilot | 0mph | 0mph |
|
||||
| Toyota | Avalon 2016-18 | TSS-P | Stock<sup>3</sup>| 20mph<sup>1</sup> | 0mph |
|
||||
| Toyota | Avalon 2019-21 | TSS-P | Stock<sup>3</sup>| 0mph | 0mph |
|
||||
| Toyota | Avalon 2022 | All | openpilot | 0mph | 0mph |
|
||||
| Toyota | Avalon Hybrid 2019-21 | TSS-P | Stock<sup>3</sup>| 0mph | 0mph |
|
||||
| Toyota | Camry 2018-20 | All | Stock | 0mph<sup>4</sup> | 0mph |
|
||||
| Toyota | Camry 2021-22 | All | openpilot | 0mph<sup>4</sup> | 0mph |
|
||||
| Toyota | Camry Hybrid 2018-20 | All | Stock | 0mph<sup>4</sup> | 0mph |
|
||||
| Toyota | Camry Hybrid 2021-22 | All | openpilot | 0mph | 0mph |
|
||||
| Toyota | C-HR 2017-21 | All | Stock | 0mph | 0mph |
|
||||
| Toyota | C-HR Hybrid 2017-19 | All | Stock | 0mph | 0mph |
|
||||
| Toyota | Corolla 2017-19 | All | Stock<sup>3</sup>| 20mph<sup>1</sup> | 0mph |
|
||||
| Toyota | Corolla 2020-22 | All | openpilot | 0mph | 0mph |
|
||||
| Toyota | Corolla Hatchback 2019-22 | All | openpilot | 0mph | 0mph |
|
||||
| Toyota | Corolla Hybrid 2020-22 | All | openpilot | 0mph | 0mph |
|
||||
| Toyota | Highlander 2017-19 | All | Stock<sup>3</sup>| 0mph | 0mph |
|
||||
| Toyota | Highlander 2020-22 | All | openpilot | 0mph | 0mph |
|
||||
| Toyota | Highlander Hybrid 2017-19 | All | Stock<sup>3</sup>| 0mph | 0mph |
|
||||
| Toyota | Highlander Hybrid 2020-22 | All | openpilot | 0mph | 0mph |
|
||||
| Toyota | Mirai 2021 | All | openpilot | 0mph | 0mph |
|
||||
| Toyota | Prius 2016-20 | TSS-P | Stock<sup>3</sup>| 0mph | 0mph |
|
||||
| Toyota | Prius 2021-22 | All | openpilot | 0mph | 0mph |
|
||||
| Toyota | Prius v 2017 | TSS-P | Stock<sup>3</sup>| 20mph<sup>1</sup> | 0mph |
|
||||
| Toyota | Prius Prime 2017-20 | All | Stock<sup>3</sup>| 0mph | 0mph |
|
||||
| Toyota | Prius Prime 2021-22 | All | openpilot | 0mph | 0mph |
|
||||
| Toyota | Rav4 2016-18 | TSS-P | Stock<sup>3</sup>| 20mph<sup>1</sup> | 0mph |
|
||||
| Toyota | Rav4 2019-21 | All | openpilot | 0mph | 0mph |
|
||||
| Toyota | Rav4 Hybrid 2016-18 | TSS-P | Stock<sup>3</sup>| 0mph | 0mph |
|
||||
| Toyota | Rav4 Hybrid 2019-21 | All | openpilot | 0mph | 0mph |
|
||||
| Toyota | Sienna 2018-20 | All | Stock<sup>3</sup>| 0mph | 0mph |
|
||||
Cars are organized into three tiers:
|
||||
|
||||
<sup>1</sup>[Comma Pedal](https://github.com/commaai/openpilot/wiki/comma-pedal) is used to provide stop-and-go capability to some of the openpilot-supported cars that don't currently support stop-and-go. ***NOTE: The Comma Pedal is not officially supported by [comma](https://comma.ai).*** <br />
|
||||
- Gold - The best openpilot experience. Great highway driving and beyond.
|
||||
- Silver - A solid highway driving experience, but is limited by stock longitudinal. May be upgraded in the future.
|
||||
- Bronze - A good highway experience, but may have limited performance in traffic and on sharp turns.
|
||||
|
||||
How We Rate The Cars
|
||||
---
|
||||
|
||||
### openpilot Adaptive Cruise Control (ACC)
|
||||
- <a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a> - openpilot is able to control the gas and brakes.
|
||||
- <a href="#"><img valign="top" src="assets/icon-star-half.svg" width="22" /></a> - openpilot is able to control the gas and brakes with some restrictions.
|
||||
- <a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a> - The gas and brakes are controlled by the car's stock Adaptive Cruise Control (ACC) system.
|
||||
|
||||
### Stop and Go
|
||||
- <a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a> - Adaptive Cruise Control (ACC) operates down to 0 mph.
|
||||
- <a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a> - Adaptive Cruise Control (ACC) available only above certain speeds. See your car's manual for the minimum speed.
|
||||
|
||||
### Steer to 0
|
||||
- <a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a> - openpilot can control the steering wheel down to 0 mph.
|
||||
- <a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a> - No steering control below certain speeds.
|
||||
|
||||
### Steering Torque
|
||||
- <a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a> - Car has enough steering torque for comfortable highway driving.
|
||||
- <a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a> - Limited ability to make turns.
|
||||
|
||||
### Actively Maintained
|
||||
- <a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a> - Mainline software support, harness hardware sold by comma, lots of users, primary development target.
|
||||
- <a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a> - Low user count, community maintained, harness hardware not sold by comma.
|
||||
|
||||
**All supported cars can move between the tiers as support changes.**
|
||||
|
||||
## Gold Cars
|
||||
|
||||
|Make|Model|Supported Package|openpilot ACC|Stop and Go|Steer to 0|Steering Torque|Actively Maintained|
|
||||
|---|---|---|:---:|:---:|:---:|:---:|:---:|
|
||||
|Genesis|G70 2020|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Hyundai|Palisade 2020-21|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Hyundai|Santa Fe 2019-20|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Hyundai|Sonata 2020-22|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Hyundai|Sonata Hybrid 2021-22|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Kia|Niro Electric 2019-22|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Kia|Telluride 2020|SCC + LKAS|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Lexus|ES 2019-21|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Lexus|ES Hybrid 2019-21|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Lexus|NX 2020|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Lexus|RX 2020-21|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Lexus|RX Hybrid 2020-21|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Lexus|UX Hybrid 2019-21|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Alphard 2019-20|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Alphard Hybrid 2021|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Avalon 2022|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Avalon Hybrid 2022|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Camry 2021-22|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>[<sup>4</sup>](#Footnotes)|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Camry Hybrid 2021-22|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Corolla 2020-22|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Corolla Hatchback 2019-22|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Corolla Hybrid 2020-22|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Highlander 2020-22|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Highlander Hybrid 2020-22|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Mirai 2021|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Prius 2021-22|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Prius Prime 2021-22|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|RAV4 2019-21|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|RAV4 Hybrid 2019-21|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|
||||
## Silver Cars
|
||||
|
||||
|Make|Model|Supported Package|openpilot ACC|Stop and Go|Steer to 0|Steering Torque|Actively Maintained|
|
||||
|---|---|---|:---:|:---:|:---:|:---:|:---:|
|
||||
|Audi|A3 2014-19|ACC + Lane Assist|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Audi|A3 Sportback e-tron 2017-18|ACC + Lane Assist|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Audi|Q2 2018|ACC + Lane Assist|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Audi|Q3 2020-21|ACC + Lane Assist|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Audi|S3 2015-17|ACC + Lane Assist|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Genesis|G70 2018|All|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Genesis|G80 2018|All|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Hyundai|Elantra 2021-22|SCC + LKAS|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Hyundai|Elantra Hybrid 2021|SCC + LKAS|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Hyundai|Ioniq Electric 2020|SCC + LKAS|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Hyundai|Ioniq Hybrid 2020-22|SCC + LFA|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Hyundai|Ioniq Plug-In Hybrid 2020-21|SCC + LKAS|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Hyundai|Kona 2020|SCC + LKAS|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Hyundai|Kona Electric 2018-19|SCC + LKAS|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Hyundai|Kona Hybrid 2020|SCC + LKAS|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Hyundai|Santa Fe 2021-22|All|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Hyundai|Santa Fe Hybrid 2022|All|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Hyundai|Santa Fe Plug-In Hybrid 2022|All|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Hyundai|Sonata 2018-19|SCC + LKAS|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Kia|Ceed 2019|SCC + LKAS|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Kia|Forte 2018-21|SCC + LKAS|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Kia|K5 2021-22|SCC + LFA|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Kia|Niro Hybrid 2021-22|SCC + LKAS|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Kia|Optima 2019|SCC + LKAS|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Kia|Seltos 2021|SCC + LKAS|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Kia|Sorento 2018-19|SCC + LKAS|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Kia|Stinger 2018|SCC + LKAS|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Lexus|CT Hybrid 2017-18|LSS|<a href="#"><img valign="top" src="assets/icon-star-half.svg" width="22" /></a>[<sup>3</sup>](#Footnotes)|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Lexus|ES Hybrid 2017-18|LSS|<a href="#"><img valign="top" src="assets/icon-star-half.svg" width="22" /></a>[<sup>3</sup>](#Footnotes)|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Lexus|NX 2018-19|All|<a href="#"><img valign="top" src="assets/icon-star-half.svg" width="22" /></a>[<sup>3</sup>](#Footnotes)|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Lexus|NX Hybrid 2018-19|All|<a href="#"><img valign="top" src="assets/icon-star-half.svg" width="22" /></a>[<sup>3</sup>](#Footnotes)|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Lexus|RX 2016-18|All|<a href="#"><img valign="top" src="assets/icon-star-half.svg" width="22" /></a>[<sup>3</sup>](#Footnotes)|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Lexus|RX Hybrid 2016-19|All|<a href="#"><img valign="top" src="assets/icon-star-half.svg" width="22" /></a>[<sup>3</sup>](#Footnotes)|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Mazda|CX-5 2022|All|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|SEAT|Ateca 2018|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|SEAT|Leon 2014-20|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Avalon 2019-21|TSS-P|<a href="#"><img valign="top" src="assets/icon-star-half.svg" width="22" /></a>[<sup>3</sup>](#Footnotes)|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Avalon Hybrid 2019-21|TSS-P|<a href="#"><img valign="top" src="assets/icon-star-half.svg" width="22" /></a>[<sup>3</sup>](#Footnotes)|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|C-HR 2017-21|All|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|C-HR Hybrid 2017-19|All|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Camry 2018-20|All|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>[<sup>4</sup>](#Footnotes)|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Camry Hybrid 2018-20|All|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>[<sup>4</sup>](#Footnotes)|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Highlander 2017-19|All|<a href="#"><img valign="top" src="assets/icon-star-half.svg" width="22" /></a>[<sup>3</sup>](#Footnotes)|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Highlander Hybrid 2017-19|All|<a href="#"><img valign="top" src="assets/icon-star-half.svg" width="22" /></a>[<sup>3</sup>](#Footnotes)|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|RAV4 Hybrid 2016-18|TSS-P|<a href="#"><img valign="top" src="assets/icon-star-half.svg" width="22" /></a>[<sup>3</sup>](#Footnotes)|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Sienna 2018-20|All|<a href="#"><img valign="top" src="assets/icon-star-half.svg" width="22" /></a>[<sup>3</sup>](#Footnotes)|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Volkswagen|Arteon 2018, 2021[<sup>8</sup>](#Footnotes)|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Volkswagen|Atlas 2018-19, 2022[<sup>8</sup>](#Footnotes)|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Volkswagen|Golf 2015-20|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Volkswagen|Golf Alltrack 2017-18|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Volkswagen|Golf GTE 2016|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Volkswagen|Golf GTI 2018-20|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Volkswagen|Golf R 2016-19|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Volkswagen|Golf SportWagen 2015|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Volkswagen|Golf SportsVan 2016|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Volkswagen|Jetta 2018-21|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Volkswagen|Jetta GLI 2021|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Volkswagen|Passat 2016-18[<sup>7</sup>](#Footnotes)|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Volkswagen|Polo 2020|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Volkswagen|T-Cross 2021[<sup>8</sup>](#Footnotes)|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Volkswagen|T-Roc 2021[<sup>8</sup>](#Footnotes)|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Volkswagen|Taos 2022[<sup>8</sup>](#Footnotes)|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Volkswagen|Tiguan 2020-22[<sup>8</sup>](#Footnotes)|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Volkswagen|Touran 2017|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Volkswagen|e-Golf 2014, 2019-20|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Ĺ koda|Kamiq 2021[<sup>6</sup>](#Footnotes)|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Ĺ koda|Karoq 2019|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Ĺ koda|Kodiaq 2018-19|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Ĺ koda|Octavia 2015, 2018-19|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Ĺ koda|Octavia RS 2016|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Ĺ koda|Scala 2020|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Ĺ koda|Superb 2015-18|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|
||||
## Bronze Cars
|
||||
|
||||
|Make|Model|Supported Package|openpilot ACC|Stop and Go|Steer to 0|Steering Torque|Actively Maintained|
|
||||
|---|---|---|:---:|:---:|:---:|:---:|:---:|
|
||||
|Acura|ILX 2016-19|AcuraWatch Plus|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Acura|RDX 2016-18|AcuraWatch Plus|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Acura|RDX 2019-21|All|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Cadillac|Escalade ESV 2016[<sup>1</sup>](#Footnotes)|ACC + LKAS|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Chevrolet|Volt 2017-18[<sup>1</sup>](#Footnotes)|Adaptive Cruise|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Chrysler|Pacifica 2017-18|Adaptive Cruise|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Chrysler|Pacifica 2020|Adaptive Cruise|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Chrysler|Pacifica Hybrid 2017-18|Adaptive Cruise|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Chrysler|Pacifica Hybrid 2019-21|Adaptive Cruise|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|GMC|Acadia 2018[<sup>1</sup>](#Footnotes)|Adaptive Cruise|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Genesis|G90 2018|All|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|
|
||||
|Honda|Accord 2018-21|All|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Honda|Accord Hybrid 2018-21|All|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Honda|CR-V 2015-16|Touring|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Honda|CR-V 2017-21|Honda Sensing|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Honda|CR-V Hybrid 2017-19|Honda Sensing|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Honda|Civic 2016-18|Honda Sensing|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Honda|Civic 2019-20|All|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>[<sup>2</sup>](#Footnotes)|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Honda|Civic Hatchback 2017-21|Honda Sensing|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Honda|Fit 2018-19|Honda Sensing|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Honda|Freed 2020|Honda Sensing|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Honda|HR-V 2019-20|Honda Sensing|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Honda|Insight 2019-21|All|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Honda|Inspire 2018|All|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Honda|Odyssey 2018-20|Honda Sensing|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Honda|Passport 2019-21|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Honda|Pilot 2016-21|Honda Sensing|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Honda|Ridgeline 2017-21|Honda Sensing|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Honda|e 2020|All|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Hyundai|Elantra 2017-19|SCC + LKAS|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Hyundai|Genesis 2015-16|SCC + LKAS|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Hyundai|Ioniq Electric 2019|SCC + LKAS|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Hyundai|Ioniq Hybrid 2017-19|SCC + LKAS|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Hyundai|Veloster 2019-20|SCC + LKAS|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Jeep|Grand Cherokee 2016-18|Adaptive Cruise|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Jeep|Grand Cherokee 2019-20|Adaptive Cruise|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Kia|Niro Plug-In Hybrid 2019|SCC + LKAS|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Kia|Optima 2017|SCC + LKAS|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Lexus|IS 2017-19|All|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Lexus|RC 2020|All|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Mazda|CX-9 2021|All|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Nissan|Altima 2019-20|ProPILOT|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Nissan|Leaf 2018-22|ProPILOT|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Nissan|Rogue 2018-20|ProPILOT|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Nissan|X-Trail 2017|ProPILOT|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Subaru|Ascent 2019|EyeSight|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Subaru|Crosstrek 2018-20|EyeSight|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Subaru|Forester 2019-21|EyeSight|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Subaru|Impreza 2017-19|EyeSight|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Avalon 2016-18|TSS-P|<a href="#"><img valign="top" src="assets/icon-star-half.svg" width="22" /></a>[<sup>3</sup>](#Footnotes)|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Corolla 2017-19|All|<a href="#"><img valign="top" src="assets/icon-star-half.svg" width="22" /></a>[<sup>3</sup>](#Footnotes)|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Prius 2016-20|TSS-P|<a href="#"><img valign="top" src="assets/icon-star-half.svg" width="22" /></a>[<sup>3</sup>](#Footnotes)|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-half.svg" width="22" /></a>[<sup>5</sup>](#Footnotes)|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Prius Prime 2017-20|All|<a href="#"><img valign="top" src="assets/icon-star-half.svg" width="22" /></a>[<sup>3</sup>](#Footnotes)|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-half.svg" width="22" /></a>[<sup>5</sup>](#Footnotes)|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|Prius v 2017|TSS-P|<a href="#"><img valign="top" src="assets/icon-star-half.svg" width="22" /></a>[<sup>3</sup>](#Footnotes)|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-half.svg" width="22" /></a>[<sup>5</sup>](#Footnotes)|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Toyota|RAV4 2016-18|TSS-P|<a href="#"><img valign="top" src="assets/icon-star-half.svg" width="22" /></a>[<sup>3</sup>](#Footnotes)|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Volkswagen|California 2021[<sup>8</sup>](#Footnotes)|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|Volkswagen|Caravelle 2020[<sup>8</sup>](#Footnotes)|Driver Assistance|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|
||||
|
||||
|
||||
## Footnotes
|
||||
<sup>1</sup>Requires an <a href="https://comma.ai/shop/products/comma-car-harness">OBD-II car harness</a> and <a href="https://github.com/commaai/openpilot/wiki/GM#hardware">community built ASCM harness</a>. <b><i>NOTE: disconnecting the ASCM disables Automatic Emergency Braking (AEB).</i></b> <br />
|
||||
<sup>2</sup>2019 Honda Civic 1.6L Diesel Sedan does not have ALC below 12mph. <br />
|
||||
<sup>3</sup>When disconnecting the Driver Support Unit (DSU), openpilot ACC will replace stock ACC. ***NOTE: disconnecting the DSU disables Automatic Emergency Braking (AEB).*** <br />
|
||||
<sup>3</sup>When disconnecting the Driver Support Unit (DSU), openpilot Adaptive Cruise Control (ACC) will replace stock Adaptive Cruise Control (ACC). <b><i> NOTE: disconnecting the DSU disables Automatic Emergency Braking (AEB).</i></b> <br />
|
||||
<sup>4</sup>28mph for Camry 4CYL L, 4CYL LE and 4CYL SE which don't have Full-Speed Range Dynamic Radar Cruise Control. <br />
|
||||
<sup>5</sup>An inaccurate steering wheel angle sensor makes precise control difficult. <br />
|
||||
<sup>6</sup>Not including the China market Kamiq, which is based on the (currently) unsupported PQ34 platform. <br />
|
||||
<sup>7</sup>Not including the USA/China market Passat, which is based on the (currently) unsupported PQ35/NMS platform. <br />
|
||||
<sup>8</sup>Model-years 2021 and beyond may have a new camera harness design, which isn't yet available from the comma store. Before ordering, remove the Lane Assist camera cover and check to see if the connector is black (older design) or light brown (newer design). For the newer design, in the interim, choose "VW J533 Development" from the vehicle drop-down for a harness that integrates at the CAN gateway inside the dashboard. <br />
|
||||
|
||||
## Community Maintained Cars and Features
|
||||
|
||||
| Make | Model (US Market Reference) | Supported Package | ACC | No ACC accel below | No ALC below |
|
||||
| ----------| --------------------------------| ------------------| -----------------| -------------------| -------------|
|
||||
| Audi | A3 2014-19 | ACC + Lane Assist | Stock | 0mph | 0mph |
|
||||
| Audi | A3 Sportback e-tron 2017-18 | ACC + Lane Assist | Stock | 0mph | 0mph |
|
||||
| Audi | Q2 2018 | ACC + Lane Assist | Stock | 0mph | 0mph |
|
||||
| Audi | Q3 2020-21 | ACC + Lane Assist | Stock | 0mph | 0mph |
|
||||
| Audi | S3 2015-17 | ACC + Lane Assist | Stock | 0mph | 0mph |
|
||||
| Cadillac | Escalade ESV 2016<sup>1</sup> | ACC + LKAS | openpilot | 0mph | 7mph |
|
||||
| Chevrolet | Volt 2017-18<sup>1</sup> | Adaptive Cruise | openpilot | 0mph | 7mph |
|
||||
| Chrysler | Pacifica 2017-18 | Adaptive Cruise | Stock | 0mph | 9mph |
|
||||
| Chrysler | Pacifica 2020 | Adaptive Cruise | Stock | 0mph | 39mph |
|
||||
| Chrysler | Pacifica Hybrid 2017-18 | Adaptive Cruise | Stock | 0mph | 9mph |
|
||||
| Chrysler | Pacifica Hybrid 2019-21 | Adaptive Cruise | Stock | 0mph | 39mph |
|
||||
| Genesis | G70 2018 | All | Stock | 0mph | 0mph |
|
||||
| Genesis | G70 2020 | All | Stock | 0mph | 0mph |
|
||||
| Genesis | G80 2018 | All | Stock | 0mph | 0mph |
|
||||
| Genesis | G90 2018 | All | Stock | 0mph | 0mph |
|
||||
| GMC | Acadia 2018<sup>1</sup> | Adaptive Cruise | openpilot | 0mph | 7mph |
|
||||
| Hyundai | Elantra 2017-19 | SCC + LKAS | Stock | 19mph | 34mph |
|
||||
| Hyundai | Elantra 2021-22 | SCC + LKAS | Stock | 0mph | 0mph |
|
||||
| Hyundai | Elantra Hybrid 2021 | SCC + LKAS | Stock | 0mph | 0mph |
|
||||
| Hyundai | Genesis 2015-16 | SCC + LKAS | Stock | 19mph | 37mph |
|
||||
| Hyundai | Ioniq Electric 2019 | SCC + LKAS | Stock | 0mph | 32mph |
|
||||
| Hyundai | Ioniq Electric 2020 | SCC + LKAS | Stock | 0mph | 0mph |
|
||||
| Hyundai | Ioniq Hybrid 2017-19 | SCC + LKAS | Stock | 0mph | 32mph |
|
||||
| Hyundai | Ioniq Hybrid 2020-22 | SCC + LFA | Stock | 0mph | 0mph |
|
||||
| Hyundai | Ioniq PHEV 2020-21 | SCC + LKAS | Stock | 0mph | 0mph |
|
||||
| Hyundai | Kona 2020 | SCC + LKAS | Stock | 0mph | 0mph |
|
||||
| Hyundai | Kona EV 2018-19 | SCC + LKAS | Stock | 0mph | 0mph |
|
||||
| Hyundai | Kona Hybrid 2020 | SCC + LKAS | Stock | 0mph | 0mph |
|
||||
| Hyundai | Santa Fe 2019-20 | All | Stock | 0mph | 0mph |
|
||||
| Hyundai | Santa Fe 2021-22 | All | Stock | 0mph | 0mph |
|
||||
| Hyundai | Santa Fe Hybrid 2022 | All | Stock | 0mph | 0mph |
|
||||
| Hyundai | Santa Fe Plug-in Hybrid 2022 | All | Stock | 0mph | 0mph |
|
||||
| Hyundai | Sonata 2018-2019 | SCC + LKAS | Stock | 0mph | 0mph |
|
||||
| Hyundai | Sonata Hybrid 2021-22 | All | Stock | 0mph | 0mph |
|
||||
| Hyundai | Veloster 2019-20 | SCC + LKAS | Stock | 5mph | 0mph |
|
||||
| Jeep | Grand Cherokee 2016-18 | Adaptive Cruise | Stock | 0mph | 9mph |
|
||||
| Jeep | Grand Cherokee 2019-20 | Adaptive Cruise | Stock | 0mph | 39mph |
|
||||
| Kia | Ceed 2019 | SCC + LKAS | Stock | 0mph | 0mph |
|
||||
| Kia | Forte 2018-21 | SCC + LKAS | Stock | 0mph | 0mph |
|
||||
| Kia | K5 2021-22 | SCC + LFA | Stock | 0mph | 0mph |
|
||||
| Kia | Niro EV 2019-22 | All | Stock | 0mph | 0mph |
|
||||
| Kia | Niro Hybrid 2021-22 | SCC + LKAS | Stock | 0mph | 0mph |
|
||||
| Kia | Niro PHEV 2019 | SCC + LKAS | Stock | 10mph | 32mph |
|
||||
| Kia | Optima 2017 | SCC + LKAS | Stock | 0mph | 32mph |
|
||||
| Kia | Optima 2019 | SCC + LKAS | Stock | 0mph | 0mph |
|
||||
| Kia | Seltos 2021 | SCC + LKAS | Stock | 0mph | 0mph |
|
||||
| Kia | Sorento 2018-19 | SCC + LKAS | Stock | 0mph | 0mph |
|
||||
| Kia | Stinger 2018 | SCC + LKAS | Stock | 0mph | 0mph |
|
||||
| Kia | Telluride 2020 | SCC + LKAS | Stock | 0mph | 0mph |
|
||||
| Mazda | CX-5 2022 | All | Stock | 0mph | 0mph |
|
||||
| Mazda | CX-9 2021 | All | Stock | 0mph | 28mph |
|
||||
| Nissan | Altima 2019-20 | ProPILOT | Stock | 0mph | 0mph |
|
||||
| Nissan | Leaf 2018-22 | ProPILOT | Stock | 0mph | 0mph |
|
||||
| Nissan | Rogue 2018-20 | ProPILOT | Stock | 0mph | 0mph |
|
||||
| Nissan | X-Trail 2017 | ProPILOT | Stock | 0mph | 0mph |
|
||||
| SEAT | Ateca 2018 | Driver Assistance | Stock | 0mph | 0mph |
|
||||
| SEAT | Leon 2014-2020 | Driver Assistance | Stock | 0mph | 0mph |
|
||||
| Subaru | Ascent 2019 | EyeSight | Stock | 0mph | 0mph |
|
||||
| Subaru | Crosstrek 2018-20 | EyeSight | Stock | 0mph | 0mph |
|
||||
| Subaru | Forester 2019-21 | EyeSight | Stock | 0mph | 0mph |
|
||||
| Subaru | Impreza 2017-19 | EyeSight | Stock | 0mph | 0mph |
|
||||
| Ĺ koda | Kamiq 2021<sup>2</sup> | Driver Assistance | Stock | 0mph | 0mph |
|
||||
| Ĺ koda | Karoq 2019 | Driver Assistance | Stock | 0mph | 0mph |
|
||||
| Ĺ koda | Kodiaq 2018-19 | Driver Assistance | Stock | 0mph | 0mph |
|
||||
| Ĺ koda | Octavia 2015, 2018-19 | Driver Assistance | Stock | 0mph | 0mph |
|
||||
| Ĺ koda | Octavia RS 2016 | Driver Assistance | Stock | 0mph | 0mph |
|
||||
| Ĺ koda | Scala 2020 | Driver Assistance | Stock | 0mph | 0mph |
|
||||
| Ĺ koda | Superb 2015-18 | Driver Assistance | Stock | 0mph | 0mph |
|
||||
| Volkswagen| Arteon 2018, 2021<sup>4</sup> | Driver Assistance | Stock | 0mph | 0mph |
|
||||
| Volkswagen| Atlas 2018-19, 2022<sup>4</sup> | Driver Assistance | Stock | 0mph | 0mph |
|
||||
| Volkswagen| Caravelle 2020<sup>4</sup> | Driver Assistance | Stock | 0mph | 32mph |
|
||||
| Volkswagen| California 2021<sup>4</sup> | Driver Assistance | Stock | 0mph | 32mph |
|
||||
| Volkswagen| e-Golf 2014, 2019-20 | Driver Assistance | Stock | 0mph | 0mph |
|
||||
| Volkswagen| Golf 2015-20 | Driver Assistance | Stock | 0mph | 0mph |
|
||||
| Volkswagen| Golf Alltrack 2017-18 | Driver Assistance | Stock | 0mph | 0mph |
|
||||
| Volkswagen| Golf GTE 2016 | Driver Assistance | Stock | 0mph | 0mph |
|
||||
| Volkswagen| Golf GTI 2018-20 | Driver Assistance | Stock | 0mph | 0mph |
|
||||
| Volkswagen| Golf R 2016-19 | Driver Assistance | Stock | 0mph | 0mph |
|
||||
| Volkswagen| Golf SportsVan 2016 | Driver Assistance | Stock | 0mph | 0mph |
|
||||
| Volkswagen| Golf SportWagen 2015 | Driver Assistance | Stock | 0mph | 0mph |
|
||||
| Volkswagen| Jetta 2018-20 | Driver Assistance | Stock | 0mph | 0mph |
|
||||
| Volkswagen| Jetta GLI 2021 | Driver Assistance | Stock | 0mph | 0mph |
|
||||
| Volkswagen| Passat 2016-18<sup>3</sup> | Driver Assistance | Stock | 0mph | 0mph |
|
||||
| Volkswagen| Polo 2020 | Driver Assistance | Stock | 0mph | 0mph |
|
||||
| Volkswagen| T-Cross 2021<sup>4</sup> | Driver Assistance | Stock | 0mph | 0mph |
|
||||
| Volkswagen| T-Roc 2021<sup>4</sup> | Driver Assistance | Stock | 0mph | 0mph |
|
||||
| Volkswagen| Taos 2022<sup>4</sup> | Driver Assistance | Stock | 0mph | 0mph |
|
||||
| Volkswagen| Tiguan 2020-22<sup>4</sup> | Driver Assistance | Stock | 0mph | 0mph |
|
||||
| Volkswagen| Touran 2017 | Driver Assistance | Stock | 0mph | 0mph |
|
||||
|
||||
<sup>1</sup>Requires an [OBD-II car harness](https://comma.ai/shop/products/comma-car-harness) and [community built ASCM harness](https://github.com/commaai/openpilot/wiki/GM#hardware). ***NOTE: disconnecting the ASCM disables Automatic Emergency Braking (AEB).*** <br />
|
||||
<sup>2</sup>Not including the China market Kamiq, which is based on the (currently) unsupported PQ34 platform. <br />
|
||||
<sup>3</sup>Not including the USA/China market Passat, which is based on the (currently) unsupported PQ35/NMS platform. <br />
|
||||
<sup>4</sup>Model-years 2021 and beyond may have a new camera harness design, which isn't yet available from the comma store. Before ordering,
|
||||
remove the Lane Assist camera cover and check to see if the connector is black (older design) or light brown (newer design). For the newer design,
|
||||
in the interim, choose "VW J533 Development" from the vehicle drop-down for a harness that integrates at the CAN gateway inside the dashboard.<br />
|
||||
Community Maintained Cars and Features are not verified by comma to meet our [safety model](SAFETY.md). Be extra cautious using them.
|
||||
|
||||
To promote a car from community maintained, it must meet a few requirements. We must own one from the brand, we must sell the harness for it, has full ISO26262 in both panda and openpilot, there must be a path forward for longitudinal control, it must have AEB still enabled, and it must support fingerprinting 2.0
|
||||
|
||||
Although they're not upstream, the community has openpilot running on other makes and models. See the 'Community Supported Models' section of each make [on our wiki](https://wiki.comma.ai/).
|
||||
## Community Maintained Cars
|
||||
Although they're not upstream, the community has openpilot running on other makes and models. See the 'Community Supported Models' section of each make [on our wiki](https://wiki.comma.ai/).
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12.2584 16.8419L12 16.686L11.7416 16.8419L6.57613 19.9596L7.94693 14.0836L8.01549 13.7897L7.78739 13.5921L3.22308 9.63803L9.23227 9.12821L9.5327 9.10272L9.65036 8.82511L12 3.2813L14.3496 8.82511L14.4673 9.10272L14.7677 9.12821L20.7769 9.63803L16.2126 13.5921L15.9845 13.7897L16.0531 14.0836L17.4239 19.9596L12.2584 16.8419Z" stroke="#B7B7B7"/>
|
||||
</svg>
|
After Width: | Height: | Size: 457 B |
|
@ -0,0 +1,3 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12.2584 16.8419L12 16.686L11.7416 16.8419L6.57613 19.9596L7.94693 14.0836L8.01549 13.7897L7.78739 13.5921L3.22308 9.63803L9.23227 9.12821L9.5327 9.10272L9.65036 8.82511L12 3.2813L14.3496 8.82511L14.4673 9.10272L14.7677 9.12821L20.7769 9.63803L16.2126 13.5921L15.9845 13.7897L16.0531 14.0836L17.4239 19.9596L12.2584 16.8419Z" fill="#F5C543" stroke="#F0A43B"/>
|
||||
</svg>
|
After Width: | Height: | Size: 472 B |
|
@ -0,0 +1,5 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 2V17.27L5.82 21L7.46 13.97L2 9.24L9.19 8.63L12 2Z" fill="#F5C543"/>
|
||||
<path d="M12.2584 16.8419L12 16.686L11.7416 16.8419L6.57613 19.9596L7.94693 14.0836L8.01549 13.7897L7.78739 13.5921L3.22308 9.63803L9.23227 9.12821L9.5327 9.10272L9.65036 8.82511L12 3.2813L14.3496 8.82511L14.4673 9.10272L14.7677 9.12821L20.7769 9.63803L16.2126 13.5921L15.9845 13.7897L16.0531 14.0836L17.4239 19.9596L12.2584 16.8419Z" stroke="#B7B7B7"/>
|
||||
<path d="M7.33226 18.9192L11 16.7055L12 16.1V17.27L5.82 21L7.46 13.97L2 9.24L9.19 8.63L12 2V4.6L11 6.92203L9.8754 9.57544L4.44617 10.0361L8.57098 13.6094L7.33226 18.9192Z" fill="#F0A43B"/>
|
||||
</svg>
|
After Width: | Height: | Size: 727 B |
|
@ -104,14 +104,7 @@ function tici_init {
|
|||
sleep 3
|
||||
fi
|
||||
|
||||
# setup governors
|
||||
sudo su -c 'echo "performance" > /sys/class/devfreq/soc:qcom,memlat-cpu0/governor'
|
||||
sudo su -c 'echo "performance" > /sys/class/devfreq/soc:qcom,memlat-cpu4/governor'
|
||||
|
||||
# TODO: move this to agnos
|
||||
# network manager config
|
||||
nmcli connection modify --temporary lte gsm.auto-config yes
|
||||
nmcli connection modify --temporary lte gsm.home-only yes
|
||||
sudo rm -f /data/etc/NetworkManager/system-connections/*.nmmeta
|
||||
|
||||
# set success flag for current boot slot
|
||||
|
|
|
@ -9,6 +9,12 @@ To view the architecture of the ONNX networks, you can use [netron](https://netr
|
|||
* Channels 0,1,2,3 represent the full-res Y channel and are represented in numpy as Y[::2, ::2], Y[::2, 1::2], Y[1::2, ::2], and Y[1::2, 1::2]
|
||||
* Channel 4 represents the half-res U channel
|
||||
* Channel 5 represents the half-res V channel
|
||||
* **wide image stream**
|
||||
* Two consecutive images (256 * 512 * 3 in RGB) recorded at 20 Hz : 393216 = 2 * 6 * 128 * 256
|
||||
* Each 256 * 512 image is represented in YUV420 with 6 channels : 6 * 128 * 256
|
||||
* Channels 0,1,2,3 represent the full-res Y channel and are represented in numpy as Y[::2, ::2], Y[::2, 1::2], Y[1::2, ::2], and Y[1::2, 1::2]
|
||||
* Channel 4 represents the half-res U channel
|
||||
* Channel 5 represents the half-res V channel
|
||||
* **desire**
|
||||
* one-hot encoded vector to command model to execute certain actions, bit only needs to be sent for 1 frame : 8
|
||||
* **traffic convention**
|
||||
|
|
2
panda
|
@ -1 +1 @@
|
|||
Subproject commit e6722c7f99b8f7b9f81bb0216edb88cc2e5ad7c0
|
||||
Subproject commit 7104818e148494523e87fd74736748b6ffd0a7c4
|
|
@ -100,6 +100,7 @@ selfdrive/boardd/set_time.py
|
|||
selfdrive/boardd/pandad.py
|
||||
|
||||
selfdrive/car/__init__.py
|
||||
selfdrive/car/docs_definitions.py
|
||||
selfdrive/car/car_helpers.py
|
||||
selfdrive/car/fingerprints.py
|
||||
selfdrive/car/interfaces.py
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
#!/usr/bin/env python3
|
||||
import os
|
||||
from collections import Counter
|
||||
from pprint import pprint
|
||||
|
||||
from common.basedir import BASEDIR
|
||||
from selfdrive.car.docs import get_tier_car_info
|
||||
|
||||
with open(os.path.join(BASEDIR, "docs/CARS.md")) as f:
|
||||
lines = f.readlines()
|
||||
cars = [l for l in lines if l.strip().startswith("|") and l.strip().endswith("|") and
|
||||
"Make" not in l and any(c.isalpha() for c in l)]
|
||||
if __name__ == "__main__":
|
||||
tiers = get_tier_car_info()
|
||||
cars = [car for tier_cars in tiers.values() for car in tier_cars]
|
||||
|
||||
make_count = Counter(l.split('|')[1].split('|')[0].strip() for l in cars)
|
||||
print("\n", "*"*20, len(cars), "total", "*"*20, "\n")
|
||||
make_count = Counter(l.make for l in cars)
|
||||
print("\n", "*" * 20, len(cars), "total", "*" * 20, "\n")
|
||||
pprint(make_count)
|
||||
|
|
|
@ -2,3 +2,6 @@
|
|||
|
||||
echo "compressing training guide images"
|
||||
optipng -o7 -strip all training/* training_wide/*
|
||||
|
||||
# This can sometimes provide smaller images
|
||||
# mogrify -quality 100 -format jpg training_wide/* training/*
|
||||
|
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 688 KiB After Width: | Height: | Size: 914 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 743 KiB After Width: | Height: | Size: 947 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.5 MiB |
Before Width: | Height: | Size: 708 KiB After Width: | Height: | Size: 919 KiB |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 1.9 MiB After Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 720 KiB After Width: | Height: | Size: 793 KiB |
Before Width: | Height: | Size: 894 KiB After Width: | Height: | Size: 1.0 MiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 718 KiB After Width: | Height: | Size: 818 KiB |
Before Width: | Height: | Size: 612 KiB After Width: | Height: | Size: 707 KiB |
Before Width: | Height: | Size: 821 KiB After Width: | Height: | Size: 871 KiB |
Before Width: | Height: | Size: 1.7 MiB After Width: | Height: | Size: 1.5 MiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 897 KiB After Width: | Height: | Size: 1010 KiB |
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 792 KiB After Width: | Height: | Size: 1.0 MiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 1.6 MiB After Width: | Height: | Size: 1.8 MiB |
Before Width: | Height: | Size: 949 KiB After Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 2.1 MiB After Width: | Height: | Size: 1.6 MiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 821 KiB After Width: | Height: | Size: 944 KiB |
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 1.2 MiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 41 KiB |
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 1.2 MiB |
Before Width: | Height: | Size: 794 KiB After Width: | Height: | Size: 915 KiB |
Before Width: | Height: | Size: 738 KiB After Width: | Height: | Size: 854 KiB |
Before Width: | Height: | Size: 852 KiB After Width: | Height: | Size: 1001 KiB |
|
@ -161,7 +161,7 @@ bool safety_setter_thread(std::vector<Panda *> pandas) {
|
|||
int safety_param;
|
||||
|
||||
auto safety_configs = car_params.getSafetyConfigs();
|
||||
uint16_t unsafe_mode = car_params.getUnsafeMode();
|
||||
uint16_t alternative_experience = car_params.getAlternativeExperience();
|
||||
for (uint32_t i = 0; i < pandas.size(); i++) {
|
||||
auto panda = pandas[i];
|
||||
|
||||
|
@ -174,8 +174,8 @@ bool safety_setter_thread(std::vector<Panda *> pandas) {
|
|||
safety_param = 0;
|
||||
}
|
||||
|
||||
LOGW("panda %d: setting safety model: %d, param: %d, unsafe mode: %d", i, (int)safety_model, safety_param, unsafe_mode);
|
||||
panda->set_unsafe_mode(unsafe_mode);
|
||||
LOGW("panda %d: setting safety model: %d, param: %d, alternative experience: %d", i, (int)safety_model, safety_param, alternative_experience);
|
||||
panda->set_alternative_experience(alternative_experience);
|
||||
panda->set_safety_model(safety_model, safety_param);
|
||||
}
|
||||
|
||||
|
@ -362,7 +362,7 @@ std::optional<bool> send_panda_states(PubMaster *pm, const std::vector<Panda *>
|
|||
ps.setFaultStatus(cereal::PandaState::FaultStatus(health.fault_status_pkt));
|
||||
ps.setPowerSaveEnabled((bool)(health.power_save_enabled_pkt));
|
||||
ps.setHeartbeatLost((bool)(health.heartbeat_lost_pkt));
|
||||
ps.setUnsafeMode(health.unsafe_mode_pkt);
|
||||
ps.setAlternativeExperience(health.alternative_experience_pkt);
|
||||
ps.setHarnessStatus(cereal::PandaState::HarnessStatus(health.car_harness_status_pkt));
|
||||
|
||||
// Convert faults bitset to capnp list
|
||||
|
|
|
@ -251,8 +251,8 @@ void Panda::set_safety_model(cereal::CarParams::SafetyModel safety_model, int sa
|
|||
usb_write(0xdc, (uint16_t)safety_model, safety_param);
|
||||
}
|
||||
|
||||
void Panda::set_unsafe_mode(uint16_t unsafe_mode) {
|
||||
usb_write(0xdf, unsafe_mode, 0);
|
||||
void Panda::set_alternative_experience(uint16_t alternative_experience) {
|
||||
usb_write(0xdf, alternative_experience, 0);
|
||||
}
|
||||
|
||||
cereal::PandaState::PandaType Panda::get_hw_type() {
|
||||
|
|
|
@ -74,7 +74,7 @@ class Panda {
|
|||
// Panda functionality
|
||||
cereal::PandaState::PandaType get_hw_type();
|
||||
void set_safety_model(cereal::CarParams::SafetyModel safety_model, int safety_param=0);
|
||||
void set_unsafe_mode(uint16_t unsafe_mode);
|
||||
void set_alternative_experience(uint16_t alternative_experience);
|
||||
void set_rtc(struct tm sys_time);
|
||||
struct tm get_rtc();
|
||||
void set_fan_speed(uint16_t fan_speed);
|
||||
|
|
|
@ -127,6 +127,7 @@ def main() -> NoReturn:
|
|||
first_run = False
|
||||
|
||||
# run boardd with all connected serials as arguments
|
||||
os.environ['MANAGER_DAEMON'] = 'boardd'
|
||||
os.chdir(os.path.join(BASEDIR, "selfdrive/boardd"))
|
||||
subprocess.run(["./boardd", *panda_serials], check=True)
|
||||
|
||||
|
|
|
@ -74,4 +74,4 @@ class TestBoarddApiMethods(unittest.TestCase):
|
|||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
unittest.main()
|
||||
|
|
|
@ -52,7 +52,7 @@ public:
|
|||
CL_CHECK(clReleaseProgram(prg_debayer));
|
||||
}
|
||||
|
||||
void queue(cl_command_queue q, cl_mem cam_buf_cl, cl_mem buf_cl, int width, int height, float gain, cl_event *debayer_event) {
|
||||
void queue(cl_command_queue q, cl_mem cam_buf_cl, cl_mem buf_cl, int width, int height, float gain, float black_level, cl_event *debayer_event) {
|
||||
CL_CHECK(clSetKernelArg(krnl_, 0, sizeof(cl_mem), &cam_buf_cl));
|
||||
CL_CHECK(clSetKernelArg(krnl_, 1, sizeof(cl_mem), &buf_cl));
|
||||
|
||||
|
@ -62,6 +62,7 @@ public:
|
|||
const size_t globalWorkSize[] = {size_t(width), size_t(height)};
|
||||
const size_t localWorkSize[] = {debayer_local_worksize, debayer_local_worksize};
|
||||
CL_CHECK(clSetKernelArg(krnl_, 2, localMemSize, 0));
|
||||
CL_CHECK(clSetKernelArg(krnl_, 3, sizeof(float), &black_level));
|
||||
CL_CHECK(clEnqueueNDRangeKernel(q, krnl_, 2, NULL, globalWorkSize, localWorkSize, 0, 0, debayer_event));
|
||||
} else {
|
||||
if (hdr_) {
|
||||
|
@ -165,13 +166,15 @@ bool CameraBuf::acquire() {
|
|||
|
||||
if (debayer) {
|
||||
float gain = 0.0;
|
||||
|
||||
float black_level = 42.0;
|
||||
#ifndef QCOM2
|
||||
gain = camera_state->digital_gain;
|
||||
if ((int)gain == 0) gain = 1.0;
|
||||
#else
|
||||
if (camera_state->camera_id == CAMERA_ID_IMX390) black_level = 64.0;
|
||||
#endif
|
||||
|
||||
debayer->queue(q, camrabuf_cl, cur_rgb_buf->buf_cl, rgb_width, rgb_height, gain, &event);
|
||||
debayer->queue(q, camrabuf_cl, cur_rgb_buf->buf_cl, rgb_width, rgb_height, gain, black_level, &event);
|
||||
} else {
|
||||
assert(rgb_stride == camera_state->ci.frame_stride);
|
||||
CL_CHECK(clEnqueueCopyBuffer(q, camrabuf_cl, cur_rgb_buf->buf_cl, 0, 0, cur_rgb_buf->len, 0, 0, &event));
|
||||
|
|
|
@ -25,7 +25,8 @@
|
|||
#define CAMERA_ID_LGC920 6
|
||||
#define CAMERA_ID_LGC615 7
|
||||
#define CAMERA_ID_AR0231 8
|
||||
#define CAMERA_ID_MAX 9
|
||||
#define CAMERA_ID_IMX390 9
|
||||
#define CAMERA_ID_MAX 10
|
||||
|
||||
const int UI_BUF_COUNT = 4;
|
||||
const int YUV_BUFFER_COUNT = Hardware::EON() ? 100 : 40;
|
||||
|
|
|
@ -22,6 +22,9 @@
|
|||
#include "selfdrive/common/swaglog.h"
|
||||
#include "selfdrive/camerad/cameras/sensor2_i2c.h"
|
||||
|
||||
// For debugging:
|
||||
// echo "4294967295" > /sys/module/cam_debug_util/parameters/debug_mdl
|
||||
|
||||
extern ExitHandler do_exit;
|
||||
|
||||
const size_t FRAME_WIDTH = 1928;
|
||||
|
@ -39,6 +42,14 @@ CameraInfo cameras_supported[CAMERA_ID_MAX] = {
|
|||
.bayer_flip = 1,
|
||||
.hdr = false
|
||||
},
|
||||
[CAMERA_ID_IMX390] = {
|
||||
.frame_width = FRAME_WIDTH,
|
||||
.frame_height = FRAME_HEIGHT,
|
||||
.frame_stride = FRAME_STRIDE,
|
||||
.bayer = true,
|
||||
.bayer_flip = 1,
|
||||
.hdr = false
|
||||
},
|
||||
};
|
||||
|
||||
const float DC_GAIN = 2.5;
|
||||
|
@ -160,8 +171,15 @@ void clear_req_queue(int fd, int32_t session_hdl, int32_t link_hdl) {
|
|||
// ************** high level camera helpers ****************
|
||||
|
||||
void CameraState::sensors_start() {
|
||||
int start_reg_len = sizeof(start_reg_array) / sizeof(struct i2c_random_wr_payload);
|
||||
sensors_i2c(start_reg_array, start_reg_len, CAM_SENSOR_PACKET_OPCODE_SENSOR_CONFIG);
|
||||
if (camera_id == CAMERA_ID_AR0231) {
|
||||
int start_reg_len = sizeof(start_reg_array_ar0231) / sizeof(struct i2c_random_wr_payload);
|
||||
sensors_i2c(start_reg_array_ar0231, start_reg_len, CAM_SENSOR_PACKET_OPCODE_SENSOR_CONFIG, true);
|
||||
} else if (camera_id == CAMERA_ID_IMX390) {
|
||||
int start_reg_len = sizeof(start_reg_array_imx390) / sizeof(struct i2c_random_wr_payload);
|
||||
sensors_i2c(start_reg_array_imx390, start_reg_len, CAM_SENSOR_PACKET_OPCODE_SENSOR_CONFIG, false);
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
void CameraState::sensors_poke(int request_id) {
|
||||
|
@ -181,7 +199,7 @@ void CameraState::sensors_poke(int request_id) {
|
|||
release_fd(multi_cam_state->video0_fd, cam_packet_handle);
|
||||
}
|
||||
|
||||
void CameraState::sensors_i2c(struct i2c_random_wr_payload* dat, int len, int op_code) {
|
||||
void CameraState::sensors_i2c(struct i2c_random_wr_payload* dat, int len, int op_code, bool data_word) {
|
||||
// LOGD("sensors_i2c: %d", len);
|
||||
uint32_t cam_packet_handle = 0;
|
||||
int size = sizeof(struct cam_packet)+sizeof(struct cam_cmd_buf_desc)*1;
|
||||
|
@ -199,7 +217,7 @@ void CameraState::sensors_i2c(struct i2c_random_wr_payload* dat, int len, int op
|
|||
i2c_random_wr->header.count = len;
|
||||
i2c_random_wr->header.op_code = 1;
|
||||
i2c_random_wr->header.cmd_type = CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_WR;
|
||||
i2c_random_wr->header.data_type = CAMERA_SENSOR_I2C_TYPE_WORD;
|
||||
i2c_random_wr->header.data_type = data_word ? CAMERA_SENSOR_I2C_TYPE_WORD : CAMERA_SENSOR_I2C_TYPE_BYTE;
|
||||
i2c_random_wr->header.addr_type = CAMERA_SENSOR_I2C_TYPE_WORD;
|
||||
memcpy(i2c_random_wr->random_wr_payload, dat, len*sizeof(struct i2c_random_wr_payload));
|
||||
|
||||
|
@ -220,7 +238,7 @@ static cam_cmd_power *power_set_wait(cam_cmd_power *power, int16_t delay_ms) {
|
|||
return (struct cam_cmd_power *)(unconditional_wait + 1);
|
||||
};
|
||||
|
||||
void CameraState::sensors_init() {
|
||||
int CameraState::sensors_init() {
|
||||
int video0_fd = multi_cam_state->video0_fd;
|
||||
uint32_t cam_packet_handle = 0;
|
||||
int size = sizeof(struct cam_packet)+sizeof(struct cam_cmd_buf_desc)*2;
|
||||
|
@ -239,17 +257,17 @@ void CameraState::sensors_init() {
|
|||
switch (camera_num) {
|
||||
case 0:
|
||||
// port 0
|
||||
i2c_info->slave_addr = 0x20;
|
||||
i2c_info->slave_addr = (camera_id == CAMERA_ID_AR0231) ? 0x20 : 0x34;
|
||||
probe->camera_id = 0;
|
||||
break;
|
||||
case 1:
|
||||
// port 1
|
||||
i2c_info->slave_addr = 0x30;
|
||||
i2c_info->slave_addr = (camera_id == CAMERA_ID_AR0231) ? 0x30 : 0x36;
|
||||
probe->camera_id = 1;
|
||||
break;
|
||||
case 2:
|
||||
// port 2
|
||||
i2c_info->slave_addr = 0x20;
|
||||
i2c_info->slave_addr = (camera_id == CAMERA_ID_AR0231) ? 0x20 : 0x34;
|
||||
probe->camera_id = 2;
|
||||
break;
|
||||
}
|
||||
|
@ -263,8 +281,15 @@ void CameraState::sensors_init() {
|
|||
probe->addr_type = CAMERA_SENSOR_I2C_TYPE_WORD;
|
||||
probe->op_code = 3; // don't care?
|
||||
probe->cmd_type = CAMERA_SENSOR_CMD_TYPE_PROBE;
|
||||
probe->reg_addr = 0x3000; //0x300a; //0x300b;
|
||||
probe->expected_data = 0x354; //0x7750; //0x885a;
|
||||
if (camera_id == CAMERA_ID_AR0231) {
|
||||
probe->reg_addr = 0x3000;
|
||||
probe->expected_data = 0x354;
|
||||
} else if (camera_id == CAMERA_ID_IMX390) {
|
||||
probe->reg_addr = 0x330;
|
||||
probe->expected_data = 0x1538;
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
probe->data_mask = 0;
|
||||
|
||||
//buf_desc[1].size = buf_desc[1].length = 148;
|
||||
|
@ -293,7 +318,7 @@ void CameraState::sensors_init() {
|
|||
power->count = 1;
|
||||
power->cmd_type = CAMERA_SENSOR_CMD_TYPE_PWR_UP;
|
||||
power->power_settings[0].power_seq_type = 0;
|
||||
power->power_settings[0].config_val_low = 19200000; //Hz
|
||||
power->power_settings[0].config_val_low = (camera_id == CAMERA_ID_AR0231) ? 19200000 : 24000000; //Hz
|
||||
power = power_set_wait(power, 10);
|
||||
|
||||
// 8,1 is this reset?
|
||||
|
@ -341,7 +366,6 @@ void CameraState::sensors_init() {
|
|||
|
||||
LOGD("probing the sensor");
|
||||
int ret = do_cam_control(sensor_fd, CAM_SENSOR_PROBE_CMD, (void *)(uintptr_t)cam_packet_handle, 0);
|
||||
assert(ret == 0);
|
||||
|
||||
munmap(i2c_info, buf_desc[0].size);
|
||||
release_fd(video0_fd, buf_desc[0].mem_handle);
|
||||
|
@ -349,6 +373,8 @@ void CameraState::sensors_init() {
|
|||
release_fd(video0_fd, buf_desc[1].mem_handle);
|
||||
munmap(pkt, size);
|
||||
release_fd(video0_fd, cam_packet_handle);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CameraState::config_isp(int io_mem_handle, int fence, int request_id, int buf0_mem_handle, int buf0_offset) {
|
||||
|
@ -561,9 +587,10 @@ void CameraState::enqueue_req_multi(int start, int n, bool dp) {
|
|||
|
||||
// ******************* camera *******************
|
||||
|
||||
void CameraState::camera_init(MultiCameraState *multi_cam_state_, VisionIpcServer * v, int camera_id, int camera_num_, unsigned int fps, cl_device_id device_id, cl_context ctx, VisionStreamType rgb_type, VisionStreamType yuv_type) {
|
||||
void CameraState::camera_init(MultiCameraState *multi_cam_state_, VisionIpcServer * v, int camera_id_, int camera_num_, unsigned int fps, cl_device_id device_id, cl_context ctx, VisionStreamType rgb_type, VisionStreamType yuv_type) {
|
||||
LOGD("camera init %d", camera_num);
|
||||
multi_cam_state = multi_cam_state_;
|
||||
camera_id = camera_id_;
|
||||
assert(camera_id < std::size(cameras_supported));
|
||||
ci = cameras_supported[camera_id];
|
||||
assert(ci.frame_width != 0);
|
||||
|
@ -586,17 +613,24 @@ void CameraState::camera_init(MultiCameraState *multi_cam_state_, VisionIpcServe
|
|||
}
|
||||
|
||||
void CameraState::camera_open() {
|
||||
int ret;
|
||||
sensor_fd = open_v4l_by_name_and_index("cam-sensor-driver", camera_num);
|
||||
assert(sensor_fd >= 0);
|
||||
LOGD("opened sensor for %d", camera_num);
|
||||
|
||||
// probe the sensor
|
||||
LOGD("-- Probing sensor %d", camera_num);
|
||||
sensors_init();
|
||||
ret = sensors_init();
|
||||
if (ret != 0) {
|
||||
LOGD("AR0231 init failed, trying IMX390");
|
||||
camera_id = CAMERA_ID_IMX390;
|
||||
ret = sensors_init();
|
||||
}
|
||||
assert(ret == 0);
|
||||
|
||||
// create session
|
||||
struct cam_req_mgr_session_info session_info = {};
|
||||
int ret = do_cam_control(multi_cam_state->video0_fd, CAM_REQ_MGR_CREATE_SESSION, &session_info, sizeof(session_info));
|
||||
ret = do_cam_control(multi_cam_state->video0_fd, CAM_REQ_MGR_CREATE_SESSION, &session_info, sizeof(session_info));
|
||||
LOGD("get session: %d 0x%X", ret, session_info.session_hdl);
|
||||
session_handle = session_info.session_hdl;
|
||||
|
||||
|
@ -675,10 +709,13 @@ void CameraState::camera_open() {
|
|||
config_isp(0, 0, 1, buf0_handle, 0);
|
||||
|
||||
LOG("-- Configuring sensor");
|
||||
sensors_i2c(init_array_ar0231, std::size(init_array_ar0231), CAM_SENSOR_PACKET_OPCODE_SENSOR_CONFIG);
|
||||
//sensors_i2c(start_reg_array, std::size(start_reg_array), CAM_SENSOR_PACKET_OPCODE_SENSOR_STREAMON);
|
||||
//sensors_i2c(stop_reg_array, std::size(stop_reg_array), CAM_SENSOR_PACKET_OPCODE_SENSOR_STREAMOFF);
|
||||
|
||||
if (camera_id == CAMERA_ID_AR0231) {
|
||||
sensors_i2c(init_array_ar0231, std::size(init_array_ar0231), CAM_SENSOR_PACKET_OPCODE_SENSOR_CONFIG, true);
|
||||
} else if (camera_id == CAMERA_ID_IMX390) {
|
||||
sensors_i2c(init_array_imx390, std::size(init_array_imx390), CAM_SENSOR_PACKET_OPCODE_SENSOR_CONFIG, false);
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
// config csiphy
|
||||
LOG("-- Config CSI PHY");
|
||||
|
@ -1008,14 +1045,28 @@ void CameraState::set_camera_exposure(float grey_frac) {
|
|||
}
|
||||
// LOGE("ae - camera %d, cur_t %.5f, sof %.5f, dt %.5f", camera_num, 1e-9 * nanos_since_boot(), 1e-9 * buf.cur_frame_data.timestamp_sof, 1e-9 * (nanos_since_boot() - buf.cur_frame_data.timestamp_sof));
|
||||
|
||||
uint16_t analog_gain_reg = 0xFF00 | (new_g << 4) | new_g;
|
||||
struct i2c_random_wr_payload exp_reg_array[] = {
|
||||
{0x3366, analog_gain_reg},
|
||||
{0x3362, (uint16_t)(dc_gain_enabled ? 0x1 : 0x0)},
|
||||
{0x3012, (uint16_t)exposure_time},
|
||||
};
|
||||
sensors_i2c(exp_reg_array, sizeof(exp_reg_array)/sizeof(struct i2c_random_wr_payload),
|
||||
CAM_SENSOR_PACKET_OPCODE_SENSOR_CONFIG);
|
||||
if (camera_id == CAMERA_ID_AR0231) {
|
||||
uint16_t analog_gain_reg = 0xFF00 | (new_g << 4) | new_g;
|
||||
struct i2c_random_wr_payload exp_reg_array[] = {
|
||||
{0x3366, analog_gain_reg},
|
||||
{0x3362, (uint16_t)(dc_gain_enabled ? 0x1 : 0x0)},
|
||||
{0x3012, (uint16_t)exposure_time},
|
||||
};
|
||||
sensors_i2c(exp_reg_array, sizeof(exp_reg_array)/sizeof(struct i2c_random_wr_payload), CAM_SENSOR_PACKET_OPCODE_SENSOR_CONFIG, true);
|
||||
} else if (camera_id == CAMERA_ID_IMX390) {
|
||||
// if gain is sub 1, we have to use exposure to mimic sub 1 gains
|
||||
uint32_t real_exposure_time = (gain < 1.0) ? (exposure_time*gain) : exposure_time;
|
||||
// invert real_exposure_time, max exposure is 2
|
||||
real_exposure_time = (exposure_time >= 0x7cf) ? 2 : (0x7cf - exposure_time);
|
||||
uint32_t real_gain = int((10*log10(fmax(1.0, gain)))/0.3);
|
||||
//printf("%d expose: %d gain: %f = %d\n", camera_num, exposure_time, gain, real_gain);
|
||||
struct i2c_random_wr_payload exp_reg_array[] = {
|
||||
{0x000c, real_exposure_time&0xFF}, {0x000d, real_exposure_time>>8},
|
||||
{0x0010, real_exposure_time&0xFF}, {0x0011, real_exposure_time>>8},
|
||||
{0x0018, real_gain&0xFF}, {0x0019, real_gain>>8},
|
||||
};
|
||||
sensors_i2c(exp_reg_array, sizeof(exp_reg_array)/sizeof(struct i2c_random_wr_payload), CAM_SENSOR_PACKET_OPCODE_SENSOR_CONFIG, false);
|
||||
}
|
||||
}
|
||||
|
||||
void camera_autoexposure(CameraState *s, float grey_frac) {
|
||||
|
|
|
@ -40,8 +40,8 @@ public:
|
|||
|
||||
void sensors_start();
|
||||
void sensors_poke(int request_id);
|
||||
void sensors_i2c(struct i2c_random_wr_payload* dat, int len, int op_code);
|
||||
void sensors_init();
|
||||
void sensors_i2c(struct i2c_random_wr_payload* dat, int len, int op_code, bool data_word);
|
||||
int sensors_init();
|
||||
|
||||
void camera_open();
|
||||
void camera_init(MultiCameraState *multi_cam_state, VisionIpcServer * v, int camera_id, int camera_num, unsigned int fps, cl_device_id device_id, cl_context ctx, VisionStreamType rgb_type, VisionStreamType yuv_type);
|
||||
|
@ -62,6 +62,7 @@ public:
|
|||
int frame_id_last;
|
||||
int idx_offset;
|
||||
bool skipped;
|
||||
int camera_id;
|
||||
|
||||
CameraBuf buf;
|
||||
};
|
||||
|
@ -73,7 +74,6 @@ typedef struct MultiCameraState {
|
|||
int device_iommu;
|
||||
int cdm_iommu;
|
||||
|
||||
|
||||
CameraState road_cam;
|
||||
CameraState wide_road_cam;
|
||||
CameraState driver_cam;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#pragma OPENCL EXTENSION cl_khr_fp16 : enable
|
||||
|
||||
const half black_level = 42.0;
|
||||
|
||||
const __constant half3 color_correction[3] = {
|
||||
// post wb CCM
|
||||
(half3)(1.82717181, -0.31231438, 0.07307673),
|
||||
|
@ -39,7 +37,7 @@ half3 color_correct(half3 rgb) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
half val_from_10(const uchar * source, int gx, int gy) {
|
||||
inline half val_from_10(const uchar * source, int gx, int gy, half black_level) {
|
||||
// parse 12bit
|
||||
int start = gy * FRAME_STRIDE + (3 * (gx / 2));
|
||||
int offset = gx % 2;
|
||||
|
@ -49,7 +47,7 @@ half val_from_10(const uchar * source, int gx, int gy) {
|
|||
|
||||
// normalize
|
||||
pv = max(0.0h, pv - black_level);
|
||||
pv *= 0.00101833h; // /= (1024.0f - black_level);
|
||||
pv /= (1024.0f - black_level);
|
||||
|
||||
// correct vignetting
|
||||
if (CAM_NUM == 1) { // fcamera
|
||||
|
@ -89,7 +87,8 @@ half phi(half x) {
|
|||
|
||||
__kernel void debayer10(const __global uchar * in,
|
||||
__global uchar * out,
|
||||
__local half * cached
|
||||
__local half * cached,
|
||||
float black_level
|
||||
)
|
||||
{
|
||||
const int x_global = get_global_id(0);
|
||||
|
@ -102,7 +101,7 @@ __kernel void debayer10(const __global uchar * in,
|
|||
|
||||
int out_idx = 3 * x_global + 3 * y_global * RGB_WIDTH;
|
||||
|
||||
half pv = val_from_10(in, x_global, y_global);
|
||||
half pv = val_from_10(in, x_global, y_global, black_level);
|
||||
cached[localOffset] = pv;
|
||||
|
||||
// don't care
|
||||
|
@ -118,22 +117,22 @@ __kernel void debayer10(const __global uchar * in,
|
|||
if (x_local < 1) {
|
||||
localColOffset = x_local;
|
||||
globalColOffset = -1;
|
||||
cached[(y_local + 1) * localRowLen + x_local] = val_from_10(in, x_global-1, y_global);
|
||||
cached[(y_local + 1) * localRowLen + x_local] = val_from_10(in, x_global-1, y_global, black_level);
|
||||
} else if (x_local >= get_local_size(0) - 1) {
|
||||
localColOffset = x_local + 2;
|
||||
globalColOffset = 1;
|
||||
cached[localOffset + 1] = val_from_10(in, x_global+1, y_global);
|
||||
cached[localOffset + 1] = val_from_10(in, x_global+1, y_global, black_level);
|
||||
}
|
||||
|
||||
if (y_local < 1) {
|
||||
cached[y_local * localRowLen + x_local + 1] = val_from_10(in, x_global, y_global-1);
|
||||
cached[y_local * localRowLen + x_local + 1] = val_from_10(in, x_global, y_global-1, black_level);
|
||||
if (localColOffset != -1) {
|
||||
cached[y_local * localRowLen + localColOffset] = val_from_10(in, x_global+globalColOffset, y_global-1);
|
||||
cached[y_local * localRowLen + localColOffset] = val_from_10(in, x_global+globalColOffset, y_global-1, black_level);
|
||||
}
|
||||
} else if (y_local >= get_local_size(1) - 1) {
|
||||
cached[(y_local + 2) * localRowLen + x_local + 1] = val_from_10(in, x_global, y_global+1);
|
||||
cached[(y_local + 2) * localRowLen + x_local + 1] = val_from_10(in, x_global, y_global+1, black_level);
|
||||
if (localColOffset != -1) {
|
||||
cached[(y_local + 2) * localRowLen + localColOffset] = val_from_10(in, x_global+globalColOffset, y_global+1);
|
||||
cached[(y_local + 2) * localRowLen + localColOffset] = val_from_10(in, x_global+globalColOffset, y_global+1, black_level);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,49 @@
|
|||
struct i2c_random_wr_payload start_reg_array[] = {{0x301A, 0x91C}};
|
||||
struct i2c_random_wr_payload stop_reg_array[] = {{0x301A, 0x918}};
|
||||
struct i2c_random_wr_payload start_reg_array_ar0231[] = {{0x301A, 0x91C}};
|
||||
struct i2c_random_wr_payload stop_reg_array_ar0231[] = {{0x301A, 0x918}};
|
||||
struct i2c_random_wr_payload start_reg_array_imx390[] = {{0x0, 0}};
|
||||
struct i2c_random_wr_payload stop_reg_array_imx390[] = {{0x0, 1}};
|
||||
|
||||
struct i2c_random_wr_payload init_array_imx390[] = {
|
||||
{0x2008, 0xd0}, {0x2009, 0x07}, {0x200a, 0x00}, // MODE_VMAX = time between frames
|
||||
{0x200C, 0xe4}, {0x200D, 0x0c}, // MODE_HMAX
|
||||
|
||||
// crop
|
||||
{0x3410, 0x88}, {0x3411, 0x7}, // CROP_H_SIZE
|
||||
{0x3418, 0xb8}, {0x3419, 0x4}, // CROP_V_SIZE
|
||||
{0x0078, 1}, {0x03c0, 1},
|
||||
|
||||
// external trigger (off)
|
||||
// while images still come in, they are blank with this
|
||||
{0x3650, 0}, // CU_MODE
|
||||
|
||||
// exposure
|
||||
{0x000c, 0xc0}, {0x000d, 0x07},
|
||||
{0x0010, 0xc0}, {0x0011, 0x07},
|
||||
|
||||
// WUXGA mode
|
||||
// not in datasheet, from https://github.com/bogsen/STLinux-Kernel/blob/master/drivers/media/platform/tegra/imx185.c
|
||||
{0x0086, 0xc4}, {0x0087, 0xff}, // WND_SHIFT_V = -60
|
||||
{0x03c6, 0xc4}, {0x03c7, 0xff}, // SM_WND_SHIFT_V_APL = -60
|
||||
|
||||
{0x201c, 0xe1}, {0x201d, 0x12}, // image read amount
|
||||
{0x21ee, 0xc4}, {0x21ef, 0x04}, // image send amount (1220 is the end)
|
||||
{0x21f0, 0xc4}, {0x21f1, 0x04}, // image processing amount
|
||||
|
||||
// disable a bunch of errors causing blanking
|
||||
{0x0390, 0x00}, {0x0391, 0x00}, {0x0392, 0x00},
|
||||
|
||||
// flip bayer
|
||||
{0x2D64, 0x64 + 2},
|
||||
|
||||
// color correction
|
||||
{0x0030, 0xf8}, {0x0031, 0x00}, // red gain
|
||||
{0x0032, 0x9a}, {0x0033, 0x00}, // gr gain
|
||||
{0x0034, 0x9a}, {0x0035, 0x00}, // gb gain
|
||||
{0x0036, 0x22}, {0x0037, 0x01}, // blue gain
|
||||
|
||||
// hdr enable (noise with this on for now)
|
||||
{0x00f9, 0}
|
||||
};
|
||||
|
||||
struct i2c_random_wr_payload init_array_ar0231[] = {
|
||||
{0x301A, 0x0018}, // RESET_REGISTER
|
||||
|
|
|
@ -24,9 +24,9 @@ if __name__ == "__main__":
|
|||
lr = list(LogReader(path))
|
||||
|
||||
for msg in tqdm(lr):
|
||||
if msg.which() == 'thumbnail':
|
||||
with open(os.path.join(out_path, f"{msg.thumbnail.frameId}.jpg"), 'wb') as f:
|
||||
f.write(msg.thumbnail.thumbnail)
|
||||
elif msg.which() == 'navThumbnail':
|
||||
with open(os.path.join(out_path, f"nav_{msg.navThumbnail.frameId}.jpg"), 'wb') as f:
|
||||
f.write(msg.navThumbnail.thumbnail)
|
||||
if msg.which() == 'thumbnail':
|
||||
with open(os.path.join(out_path, f"{msg.thumbnail.frameId}.jpg"), 'wb') as f:
|
||||
f.write(msg.thumbnail.thumbnail)
|
||||
elif msg.which() == 'navThumbnail':
|
||||
with open(os.path.join(out_path, f"nav_{msg.navThumbnail.frameId}.jpg"), 'wb') as f:
|
||||
f.write(msg.navThumbnail.thumbnail)
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
{% set footnote_tag = '[<sup>{}</sup>](#Footnotes)' -%}
|
||||
{% set star_icon = '<a href="#"><img valign="top" src="assets/icon-star-{}.svg" width="22" /></a>' -%}
|
||||
|
||||
# Supported Cars
|
||||
|
||||
A supported vehicle is one that just works when you install a comma device. Every car performs differently with openpilot, but all supported cars should provide a better experience than any stock system.
|
||||
|
||||
Cars are organized into three tiers:
|
||||
|
||||
{% for tier in tiers %}
|
||||
- {{tier.name.title()}} - {{tier.value}}
|
||||
{% endfor %}
|
||||
|
||||
How We Rate The Cars
|
||||
---
|
||||
|
||||
### openpilot Adaptive Cruise Control (ACC)
|
||||
- {{star_icon.format(Star.FULL.value)}} - openpilot is able to control the gas and brakes.
|
||||
- {{star_icon.format(Star.HALF.value)}} - openpilot is able to control the gas and brakes with some restrictions.
|
||||
- {{star_icon.format(Star.EMPTY.value)}} - The gas and brakes are controlled by the car's stock Adaptive Cruise Control (ACC) system.
|
||||
|
||||
### Stop and Go
|
||||
- {{star_icon.format(Star.FULL.value)}} - Adaptive Cruise Control (ACC) operates down to 0 mph.
|
||||
- {{star_icon.format(Star.EMPTY.value)}} - Adaptive Cruise Control (ACC) available only above certain speeds. See your car's manual for the minimum speed.
|
||||
|
||||
### Steer to 0
|
||||
- {{star_icon.format(Star.FULL.value)}} - openpilot can control the steering wheel down to 0 mph.
|
||||
- {{star_icon.format(Star.EMPTY.value)}} - No steering control below certain speeds.
|
||||
|
||||
### Steering Torque
|
||||
- {{star_icon.format(Star.FULL.value)}} - Car has enough steering torque for comfortable highway driving.
|
||||
- {{star_icon.format(Star.EMPTY.value)}} - Limited ability to make turns.
|
||||
|
||||
### Actively Maintained
|
||||
- {{star_icon.format(Star.FULL.value)}} - Mainline software support, harness hardware sold by comma, lots of users, primary development target.
|
||||
- {{star_icon.format(Star.EMPTY.value)}} - Low user count, community maintained, harness hardware not sold by comma.
|
||||
|
||||
**All supported cars can move between the tiers as support changes.**
|
||||
|
||||
{% for tier, cars in tiers.items() %}
|
||||
## {{tier.name.title()}} Cars
|
||||
|
||||
|{{Column | map(attribute='value') | join('|')}}|
|
||||
|---|---|---|:---:|:---:|:---:|:---:|:---:|
|
||||
{% for car_info in cars %}
|
||||
|{% for column in Column %}{{car_info.get_column(column, star_icon, footnote_tag)}}|{% endfor %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
## Footnotes
|
||||
{% for footnote in footnotes %}
|
||||
<sup>{{loop.index}}</sup>{{footnote}} <br />
|
||||
{% endfor %}
|
||||
|
||||
## Community Maintained Cars
|
||||
Although they're not upstream, the community has openpilot running on other makes and models. See the 'Community Supported Models' section of each make [on our wiki](https://wiki.comma.ai/).
|
|
@ -1,4 +1,6 @@
|
|||
import os
|
||||
from typing import Any, Dict, List
|
||||
|
||||
from common.params import Params
|
||||
from common.basedir import BASEDIR
|
||||
from selfdrive.version import is_comma_remote, is_tested_branch
|
||||
|
@ -57,19 +59,25 @@ def load_interfaces(brand_names):
|
|||
return ret
|
||||
|
||||
|
||||
def _get_interface_names():
|
||||
# read all the folders in selfdrive/car and return a dict where:
|
||||
# - keys are all the car names that which we have an interface for
|
||||
# - values are lists of spefic car models for a given car
|
||||
def get_interface_attr(attr: str) -> Dict[str, Any]:
|
||||
# returns given attribute from each interface
|
||||
brand_names = {}
|
||||
for car_folder in [x[0] for x in os.walk(BASEDIR + '/selfdrive/car')]:
|
||||
for car_folder in sorted([x[0] for x in os.walk(BASEDIR + '/selfdrive/car')]):
|
||||
try:
|
||||
brand_name = car_folder.split('/')[-1]
|
||||
model_names = __import__(f'selfdrive.car.{brand_name}.values', fromlist=['CAR']).CAR
|
||||
model_names = [getattr(model_names, c) for c in model_names.__dict__.keys() if not c.startswith("__")]
|
||||
brand_names[brand_name] = model_names
|
||||
attr_data = getattr(__import__(f'selfdrive.car.{brand_name}.values', fromlist=[attr]), attr, None)
|
||||
brand_names[brand_name] = attr_data
|
||||
except (ImportError, OSError):
|
||||
pass
|
||||
return brand_names
|
||||
|
||||
|
||||
def _get_interface_names() -> Dict[str, List[str]]:
|
||||
# returns a dict of brand name and its respective models
|
||||
brand_names = {}
|
||||
for brand_name, model_names in get_interface_attr("CAR").items():
|
||||
model_names = [getattr(model_names, c) for c in model_names.__dict__.keys() if not c.startswith("__")]
|
||||
brand_names[brand_name] = model_names
|
||||
|
||||
return brand_names
|
||||
|
||||
|
@ -173,11 +181,13 @@ def get_car(logcan, sendcan):
|
|||
cloudlog.warning("car doesn't match any fingerprints: %r", fingerprints)
|
||||
candidate = "mock"
|
||||
|
||||
CarInterface, CarController, CarState = interfaces[candidate]
|
||||
car_params = CarInterface.get_params(candidate, fingerprints, car_fw)
|
||||
car_params.carVin = vin
|
||||
car_params.carFw = car_fw
|
||||
car_params.fingerprintSource = source
|
||||
car_params.fuzzyFingerprint = not exact_match
|
||||
disable_radar = Params().get_bool("DisableRadar")
|
||||
|
||||
return CarInterface(car_params, CarController, CarState), car_params
|
||||
CarInterface, CarController, CarState = interfaces[candidate]
|
||||
CP = CarInterface.get_params(candidate, fingerprints, car_fw, disable_radar)
|
||||
CP.carVin = vin
|
||||
CP.carFw = car_fw
|
||||
CP.fingerprintSource = source
|
||||
CP.fuzzyFingerprint = not exact_match
|
||||
|
||||
return CarInterface(CP, CarController, CarState), CP
|
||||
|
|
|
@ -7,6 +7,7 @@ from opendbc.can.packer import CANPacker
|
|||
|
||||
class CarController():
|
||||
def __init__(self, dbc_name, CP, VM):
|
||||
self.CP = CP
|
||||
self.apply_steer_last = 0
|
||||
self.ccframe = 0
|
||||
self.prev_frame = -1
|
||||
|
@ -29,11 +30,11 @@ class CarController():
|
|||
CS.out.steeringTorqueEps, CarControllerParams)
|
||||
self.steer_rate_limited = new_steer != apply_steer
|
||||
|
||||
moving_fast = CS.out.vEgo > CS.CP.minSteerSpeed # for status message
|
||||
if CS.out.vEgo > (CS.CP.minSteerSpeed - 0.5): # for command high bit
|
||||
moving_fast = CS.out.vEgo > self.CP.minSteerSpeed # for status message
|
||||
if CS.out.vEgo > (self.CP.minSteerSpeed - 0.5): # for command high bit
|
||||
self.gone_fast_yet = True
|
||||
elif self.car_fingerprint in (CAR.PACIFICA_2019_HYBRID, CAR.PACIFICA_2020, CAR.JEEP_CHEROKEE_2019):
|
||||
if CS.out.vEgo < (CS.CP.minSteerSpeed - 3.0):
|
||||
if CS.out.vEgo < (self.CP.minSteerSpeed - 3.0):
|
||||
self.gone_fast_yet = False # < 14.5m/s stock turns off this bit, but fine down to 13.5
|
||||
lkas_active = moving_fast and enabled
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ from selfdrive.car.interfaces import CarInterfaceBase
|
|||
|
||||
class CarInterface(CarInterfaceBase):
|
||||
@staticmethod
|
||||
def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None):
|
||||
def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None, disable_radar=False):
|
||||
ret = CarInterfaceBase.get_std_params(candidate, fingerprint)
|
||||
ret.carName = "chrysler"
|
||||
ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.chrysler)]
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
from typing import Dict, List, Union
|
||||
|
||||
from selfdrive.car import dbc_dict
|
||||
from selfdrive.car.docs_definitions import CarInfo
|
||||
from cereal import car
|
||||
Ecu = car.CarParams.Ecu
|
||||
|
||||
|
@ -18,6 +21,16 @@ class CAR:
|
|||
JEEP_CHEROKEE = "JEEP GRAND CHEROKEE V6 2018" # includes 2017 Trailhawk
|
||||
JEEP_CHEROKEE_2019 = "JEEP GRAND CHEROKEE 2019" # includes 2020 Trailhawk
|
||||
|
||||
|
||||
CAR_INFO: Dict[str, Union[CarInfo, List[CarInfo]]] = {
|
||||
CAR.PACIFICA_2017_HYBRID: CarInfo("Chrysler Pacifica Hybrid 2017-18", "Adaptive Cruise"),
|
||||
CAR.PACIFICA_2019_HYBRID: CarInfo("Chrysler Pacifica Hybrid 2019-21", "Adaptive Cruise"),
|
||||
CAR.PACIFICA_2018: CarInfo("Chrysler Pacifica 2017-18", "Adaptive Cruise"),
|
||||
CAR.PACIFICA_2020: CarInfo("Chrysler Pacifica 2020", "Adaptive Cruise"),
|
||||
CAR.JEEP_CHEROKEE: CarInfo("Jeep Grand Cherokee 2016-18", "Adaptive Cruise", "https://www.youtube.com/watch?v=eLR9o2JkuRk"),
|
||||
CAR.JEEP_CHEROKEE_2019: CarInfo("Jeep Grand Cherokee 2019-20", "Adaptive Cruise", "https://www.youtube.com/watch?v=jBe4lWnRSu4"),
|
||||
}
|
||||
|
||||
# Unique CAN messages:
|
||||
# Only the hybrids have 270: 8
|
||||
# Only the gas have 55: 8, 416: 7
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import jinja2
|
||||
import os
|
||||
from enum import Enum
|
||||
from typing import Dict, List
|
||||
|
||||
from common.basedir import BASEDIR
|
||||
from selfdrive.car.docs_definitions import CarInfo, Column, Star, Tier
|
||||
from selfdrive.car.car_helpers import interfaces, get_interface_attr
|
||||
from selfdrive.car.hyundai.radar_interface import RADAR_START_ADDR as HKG_RADAR_START_ADDR
|
||||
from selfdrive.car.tests.routes import non_tested_cars
|
||||
|
||||
|
||||
def get_all_footnotes() -> Dict[Enum, int]:
|
||||
all_footnotes = []
|
||||
for _, footnotes in get_interface_attr("Footnote").items():
|
||||
if footnotes is not None:
|
||||
all_footnotes += footnotes
|
||||
return {fn: idx + 1 for idx, fn in enumerate(all_footnotes)}
|
||||
|
||||
|
||||
ALL_FOOTNOTES: Dict[Enum, int] = get_all_footnotes()
|
||||
CARS_MD_OUT = os.path.join(BASEDIR, "docs", "CARS.md")
|
||||
CARS_MD_TEMPLATE = os.path.join(BASEDIR, "selfdrive", "car", "CARS_template.md")
|
||||
|
||||
|
||||
def get_tier_car_info() -> Dict[Tier, List[CarInfo]]:
|
||||
tier_car_info: Dict[Tier, List[CarInfo]] = {tier: [] for tier in Tier}
|
||||
|
||||
for models in get_interface_attr("CAR_INFO").values():
|
||||
for model, car_info in models.items():
|
||||
# Hyundai exception: those with radar have openpilot longitudinal
|
||||
fingerprint = {0: {}, 1: {HKG_RADAR_START_ADDR: 8}, 2: {}, 3: {}}
|
||||
CP = interfaces[model][0].get_params(model, fingerprint=fingerprint, disable_radar=True)
|
||||
|
||||
if CP.dashcamOnly:
|
||||
continue
|
||||
|
||||
# A platform can include multiple car models
|
||||
if not isinstance(car_info, list):
|
||||
car_info = (car_info,)
|
||||
|
||||
for _car_info in car_info:
|
||||
_car_info.init(CP, non_tested_cars, ALL_FOOTNOTES)
|
||||
tier_car_info[_car_info.tier].append(_car_info)
|
||||
|
||||
# Sort cars by make and model + year
|
||||
for tier, cars in tier_car_info.items():
|
||||
tier_car_info[tier] = sorted(cars, key=lambda x: x.make + x.model)
|
||||
|
||||
return tier_car_info
|
||||
|
||||
|
||||
def generate_cars_md(tier_car_info: Dict[Tier, List[CarInfo]], template_fn: str) -> str:
|
||||
with open(template_fn, "r") as f:
|
||||
template = jinja2.Template(f.read(), trim_blocks=True, lstrip_blocks=True)
|
||||
|
||||
footnotes = [fn.value.text for fn in ALL_FOOTNOTES]
|
||||
return template.render(tiers=tier_car_info, footnotes=footnotes, Star=Star, Column=Column)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Auto generates supported cars documentation",
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||
|
||||
parser.add_argument("--template", default=CARS_MD_TEMPLATE, help="Override default template filename")
|
||||
parser.add_argument("--out", default=CARS_MD_OUT, help="Override default generated filename")
|
||||
args = parser.parse_args()
|
||||
|
||||
with open(args.out, 'w') as f:
|
||||
f.write(generate_cars_md(get_tier_car_info(), args.template))
|
||||
print(f"Generated and written to {args.out}")
|
|
@ -0,0 +1,100 @@
|
|||
from cereal import car
|
||||
from collections import namedtuple
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
from typing import Dict, List, Optional, Union, no_type_check
|
||||
|
||||
|
||||
class Tier(Enum):
|
||||
GOLD = "The best openpilot experience. Great highway driving and beyond."
|
||||
SILVER = "A solid highway driving experience, but is limited by stock longitudinal. May be upgraded in the future."
|
||||
BRONZE = "A good highway experience, but may have limited performance in traffic and on sharp turns."
|
||||
|
||||
|
||||
class Column(Enum):
|
||||
MAKE = "Make"
|
||||
MODEL = "Model"
|
||||
PACKAGE = "Supported Package"
|
||||
LONGITUDINAL = "openpilot ACC"
|
||||
FSR_LONGITUDINAL = "Stop and Go"
|
||||
FSR_STEERING = "Steer to 0"
|
||||
STEERING_TORQUE = "Steering Torque"
|
||||
MAINTAINED = "Actively Maintained"
|
||||
|
||||
|
||||
class Star(Enum):
|
||||
FULL = "full"
|
||||
HALF = "half"
|
||||
EMPTY = "empty"
|
||||
|
||||
|
||||
StarColumns = list(Column)[3:]
|
||||
CarFootnote = namedtuple("CarFootnote", ["text", "column", "star"], defaults=[None])
|
||||
|
||||
|
||||
def get_footnote(footnotes: Optional[List[Enum]], column: Column) -> Optional[Enum]:
|
||||
# Returns applicable footnote given current column
|
||||
if footnotes is not None:
|
||||
for fn in footnotes:
|
||||
if fn.value.column == column:
|
||||
return fn
|
||||
return None
|
||||
|
||||
|
||||
@dataclass
|
||||
class CarInfo:
|
||||
name: str
|
||||
package: str
|
||||
video_link: Optional[str] = None
|
||||
footnotes: Optional[List[Enum]] = None
|
||||
min_steer_speed: Optional[float] = None
|
||||
min_enable_speed: Optional[float] = None
|
||||
good_torque: bool = False
|
||||
|
||||
def init(self, CP: car.CarParams, non_tested_cars: List[str], all_footnotes: Dict[Enum, int]):
|
||||
# TODO: set all the min steer speeds in carParams and remove this
|
||||
min_steer_speed = CP.minSteerSpeed
|
||||
if self.min_steer_speed is not None:
|
||||
min_steer_speed = self.min_steer_speed
|
||||
assert CP.minSteerSpeed == 0, f"Minimum steer speed set in both CarInfo and CarParams for {CP.carFingerprint}"
|
||||
|
||||
# TODO: set all the min enable speeds in carParams correctly and remove this
|
||||
min_enable_speed = CP.minEnableSpeed
|
||||
if self.min_enable_speed is not None:
|
||||
min_enable_speed = self.min_enable_speed
|
||||
|
||||
self.make, self.model = self.name.split(' ', 1)
|
||||
self.row = {
|
||||
Column.MAKE: self.make,
|
||||
Column.MODEL: self.model,
|
||||
Column.PACKAGE: self.package,
|
||||
# StarColumns
|
||||
Column.LONGITUDINAL: CP.openpilotLongitudinalControl and not CP.radarOffCan,
|
||||
Column.FSR_LONGITUDINAL: min_enable_speed <= 0.,
|
||||
Column.FSR_STEERING: min_steer_speed <= 0.,
|
||||
Column.STEERING_TORQUE: self.good_torque,
|
||||
Column.MAINTAINED: CP.carFingerprint not in non_tested_cars,
|
||||
}
|
||||
|
||||
self.all_footnotes = all_footnotes
|
||||
for column in StarColumns:
|
||||
self.row[column] = Star.FULL if self.row[column] else Star.EMPTY
|
||||
|
||||
# Demote if footnote specifies a star
|
||||
footnote = get_footnote(self.footnotes, column)
|
||||
if footnote is not None and footnote.value.star is not None:
|
||||
self.row[column] = footnote.value.star
|
||||
|
||||
self.tier = {5: Tier.GOLD, 4: Tier.SILVER}.get(list(self.row.values()).count(Star.FULL), Tier.BRONZE)
|
||||
|
||||
@no_type_check
|
||||
def get_column(self, column: Column, star_icon: str, footnote_tag: str) -> str:
|
||||
item: Union[str, Star] = self.row[column]
|
||||
if column in StarColumns:
|
||||
item = star_icon.format(item.value)
|
||||
|
||||
footnote = get_footnote(self.footnotes, column)
|
||||
if footnote is not None:
|
||||
item += footnote_tag.format(self.all_footnotes[footnote])
|
||||
|
||||
return item
|
|
@ -8,7 +8,7 @@ from selfdrive.car.interfaces import CarInterfaceBase
|
|||
|
||||
class CarInterface(CarInterfaceBase):
|
||||
@staticmethod
|
||||
def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None):
|
||||
def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None, disable_radar=False):
|
||||
ret = CarInterfaceBase.get_std_params(candidate, fingerprint)
|
||||
ret.carName = "ford"
|
||||
ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.ford)]
|
||||
|
|
|
@ -1,12 +1,21 @@
|
|||
from selfdrive.car import dbc_dict
|
||||
from typing import Dict, List, Union
|
||||
|
||||
from cereal import car
|
||||
from selfdrive.car import dbc_dict
|
||||
from selfdrive.car.docs_definitions import CarInfo
|
||||
Ecu = car.CarParams.Ecu
|
||||
|
||||
MAX_ANGLE = 87. # make sure we never command the extremes (0xfff) which cause latching fault
|
||||
|
||||
|
||||
class CAR:
|
||||
FUSION = "FORD FUSION 2018"
|
||||
|
||||
|
||||
CAR_INFO: Dict[str, Union[CarInfo, List[CarInfo]]] = {
|
||||
CAR.FUSION: CarInfo("Ford Fusion 2018", "All")
|
||||
}
|
||||
|
||||
DBC = {
|
||||
CAR.FUSION: dbc_dict('ford_fusion_2018_pt', 'ford_fusion_2018_adas'),
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ class CarInterface(CarInterfaceBase):
|
|||
return CarInterfaceBase.get_steer_feedforward_default
|
||||
|
||||
@staticmethod
|
||||
def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None):
|
||||
def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None, disable_radar=False):
|
||||
ret = CarInterfaceBase.get_std_params(candidate, fingerprint)
|
||||
ret.carName = "gm"
|
||||
ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.gm)]
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
from enum import Enum
|
||||
from typing import Dict, List, Union
|
||||
|
||||
from cereal import car
|
||||
from selfdrive.car import dbc_dict
|
||||
from selfdrive.car.docs_definitions import CarFootnote, CarInfo, Column
|
||||
Ecu = car.CarParams.Ecu
|
||||
|
||||
class CarControllerParams():
|
||||
|
||||
class CarControllerParams:
|
||||
STEER_MAX = 300 # Safety limit, not LKA max. Trucks use 600.
|
||||
STEER_STEP = 2 # control frames per command
|
||||
STEER_DELTA_UP = 7
|
||||
|
@ -38,6 +43,7 @@ class CarControllerParams():
|
|||
|
||||
STEER_THRESHOLD = 1.0
|
||||
|
||||
|
||||
class CAR:
|
||||
HOLDEN_ASTRA = "HOLDEN ASTRA RS-V BK 2017"
|
||||
VOLT = "CHEVROLET VOLT PREMIER 2017"
|
||||
|
@ -47,6 +53,26 @@ class CAR:
|
|||
BUICK_REGAL = "BUICK REGAL ESSENCE 2018"
|
||||
ESCALADE_ESV = "CADILLAC ESCALADE ESV 2016"
|
||||
|
||||
|
||||
class Footnote(Enum):
|
||||
OBD_II = CarFootnote(
|
||||
'Requires an <a href="https://comma.ai/shop/products/comma-car-harness">OBD-II car harness</a> and ' +
|
||||
'<a href="https://github.com/commaai/openpilot/wiki/GM#hardware">community built ASCM harness</a>. ' +
|
||||
'<b><i>NOTE: disconnecting the ASCM disables Automatic Emergency Braking (AEB).</i></b>',
|
||||
Column.MODEL)
|
||||
|
||||
|
||||
CAR_INFO: Dict[str, Union[CarInfo, List[CarInfo]]] = {
|
||||
CAR.HOLDEN_ASTRA: CarInfo("Holden Astra 2017", "Adaptive Cruise"),
|
||||
CAR.VOLT: CarInfo("Chevrolet Volt 2017-18", "Adaptive Cruise", footnotes=[Footnote.OBD_II], min_enable_speed=0),
|
||||
CAR.CADILLAC_ATS: CarInfo("Cadillac ATS Premium Performance 2018", "Adaptive Cruise"),
|
||||
CAR.MALIBU: CarInfo("Chevrolet Malibu Premier 2017", "Adaptive Cruise"),
|
||||
CAR.ACADIA: CarInfo("GMC Acadia 2018", "Adaptive Cruise", video_link="https://www.youtube.com/watch?v=0ZN6DdsBUZo", footnotes=[Footnote.OBD_II]),
|
||||
CAR.BUICK_REGAL: CarInfo("Buick Regal Essence 2018", "Adaptive Cruise"),
|
||||
CAR.ESCALADE_ESV: CarInfo("Cadillac Escalade ESV 2016", "ACC + LKAS", footnotes=[Footnote.OBD_II]),
|
||||
}
|
||||
|
||||
|
||||
class CruiseButtons:
|
||||
INIT = 0
|
||||
UNPRESS = 1
|
||||
|
|
|
@ -1,18 +1,21 @@
|
|||
from collections import namedtuple
|
||||
|
||||
from cereal import car
|
||||
from common.realtime import DT_CTRL
|
||||
from selfdrive.controls.lib.drive_helpers import rate_limit
|
||||
from common.conversions import Conversions as CV
|
||||
from common.numpy_fast import clip, interp
|
||||
from common.realtime import DT_CTRL
|
||||
from opendbc.can.packer import CANPacker
|
||||
from selfdrive.car import create_gas_interceptor_command
|
||||
from selfdrive.car.honda import hondacan
|
||||
from selfdrive.car.honda.values import CruiseButtons, VISUAL_HUD, HONDA_BOSCH, HONDA_NIDEC_ALT_PCM_ACCEL, CarControllerParams
|
||||
from opendbc.can.packer import CANPacker
|
||||
from selfdrive.controls.lib.drive_helpers import rate_limit
|
||||
|
||||
VisualAlert = car.CarControl.HUDControl.VisualAlert
|
||||
LongCtrlState = car.CarControl.Actuators.LongControlState
|
||||
|
||||
|
||||
def compute_gb_honda_bosch(accel, speed):
|
||||
#TODO returns 0s, is unused
|
||||
# TODO returns 0s, is unused
|
||||
return 0.0, 0.0
|
||||
|
||||
|
||||
|
@ -33,14 +36,14 @@ def compute_gas_brake(accel, speed, fingerprint):
|
|||
return compute_gb_honda_nidec(accel, speed)
|
||||
|
||||
|
||||
#TODO not clear this does anything useful
|
||||
def actuator_hystereses(brake, braking, brake_steady, v_ego, car_fingerprint):
|
||||
# TODO not clear this does anything useful
|
||||
def actuator_hysteresis(brake, braking, brake_steady, v_ego, car_fingerprint):
|
||||
# hyst params
|
||||
brake_hyst_on = 0.02 # to activate brakes exceed this value
|
||||
brake_hyst_off = 0.005 # to deactivate brakes below this value
|
||||
brake_hyst_gap = 0.01 # don't change brake command for small oscillations within this value
|
||||
brake_hyst_on = 0.02 # to activate brakes exceed this value
|
||||
brake_hyst_off = 0.005 # to deactivate brakes below this value
|
||||
brake_hyst_gap = 0.01 # don't change brake command for small oscillations within this value
|
||||
|
||||
#*** hysteresis logic to avoid brake blinking. go above 0.1 to trigger
|
||||
# *** hysteresis logic to avoid brake blinking. go above 0.1 to trigger
|
||||
if (brake < brake_hyst_on and not braking) or brake < brake_hyst_off:
|
||||
brake = 0.
|
||||
braking = brake > 0.
|
||||
|
@ -93,164 +96,170 @@ def process_hud_alert(hud_alert):
|
|||
|
||||
HUDData = namedtuple("HUDData",
|
||||
["pcm_accel", "v_cruise", "car",
|
||||
"lanes", "fcw", "acc_alert", "steer_required"])
|
||||
"lanes", "fcw", "acc_alert", "steer_required"])
|
||||
|
||||
|
||||
class CarController():
|
||||
class CarController:
|
||||
def __init__(self, dbc_name, CP, VM):
|
||||
self.CP = CP
|
||||
self.packer = CANPacker(dbc_name)
|
||||
self.params = CarControllerParams(CP)
|
||||
self.frame = 0
|
||||
|
||||
self.braking = False
|
||||
self.brake_steady = 0.
|
||||
self.brake_last = 0.
|
||||
self.apply_brake_last = 0
|
||||
self.last_pump_ts = 0.
|
||||
self.packer = CANPacker(dbc_name)
|
||||
|
||||
self.accel = 0
|
||||
self.speed = 0
|
||||
self.gas = 0
|
||||
self.brake = 0
|
||||
|
||||
self.params = CarControllerParams(CP)
|
||||
def update(self, CC, CS):
|
||||
actuators = CC.actuators
|
||||
hud_control = CC.hudControl
|
||||
hud_v_cruise = hud_control.setSpeed * CV.MS_TO_KPH if hud_control.speedVisible else 255
|
||||
pcm_cancel_cmd = CC.cruiseControl.cancel
|
||||
|
||||
def update(self, c, CS, frame, actuators, pcm_cancel_cmd,
|
||||
hud_v_cruise, hud_show_lanes, hud_show_car, hud_alert):
|
||||
|
||||
P = self.params
|
||||
|
||||
if c.longActive:
|
||||
if CC.longActive:
|
||||
accel = actuators.accel
|
||||
gas, brake = compute_gas_brake(actuators.accel, CS.out.vEgo, CS.CP.carFingerprint)
|
||||
gas, brake = compute_gas_brake(actuators.accel, CS.out.vEgo, self.CP.carFingerprint)
|
||||
else:
|
||||
accel = 0.0
|
||||
gas, brake = 0.0, 0.0
|
||||
|
||||
# *** apply brake hysteresis ***
|
||||
pre_limit_brake, self.braking, self.brake_steady = actuator_hystereses(brake, self.braking, self.brake_steady, CS.out.vEgo, CS.CP.carFingerprint)
|
||||
pre_limit_brake, self.braking, self.brake_steady = actuator_hysteresis(brake, self.braking, self.brake_steady,
|
||||
CS.out.vEgo, self.CP.carFingerprint)
|
||||
|
||||
# *** rate limit after the enable check ***
|
||||
self.brake_last = rate_limit(pre_limit_brake, self.brake_last, -2., DT_CTRL)
|
||||
|
||||
# vehicle hud display, wait for one update from 10Hz 0x304 msg
|
||||
if hud_show_lanes:
|
||||
if hud_control.lanesVisible:
|
||||
hud_lanes = 1
|
||||
else:
|
||||
hud_lanes = 0
|
||||
|
||||
if c.enabled:
|
||||
if hud_show_car:
|
||||
if CC.enabled:
|
||||
if hud_control.leadVisible:
|
||||
hud_car = 2
|
||||
else:
|
||||
hud_car = 1
|
||||
else:
|
||||
hud_car = 0
|
||||
|
||||
fcw_display, steer_required, acc_alert = process_hud_alert(hud_alert)
|
||||
|
||||
fcw_display, steer_required, acc_alert = process_hud_alert(hud_control.visualAlert)
|
||||
|
||||
# **** process the car messages ****
|
||||
|
||||
# steer torque is converted back to CAN reference (positive when steering right)
|
||||
apply_steer = int(interp(-actuators.steer * P.STEER_MAX, P.STEER_LOOKUP_BP, P.STEER_LOOKUP_V))
|
||||
apply_steer = int(interp(-actuators.steer * self.params.STEER_MAX,
|
||||
self.params.STEER_LOOKUP_BP, self.params.STEER_LOOKUP_V))
|
||||
|
||||
# Send CAN commands.
|
||||
# Send CAN commands
|
||||
can_sends = []
|
||||
|
||||
# tester present - w/ no response (keeps radar disabled)
|
||||
if CS.CP.carFingerprint in HONDA_BOSCH and CS.CP.openpilotLongitudinalControl:
|
||||
if (frame % 10) == 0:
|
||||
if self.CP.carFingerprint in HONDA_BOSCH and self.CP.openpilotLongitudinalControl:
|
||||
if self.frame % 10 == 0:
|
||||
can_sends.append((0x18DAB0F1, 0, b"\x02\x3E\x80\x00\x00\x00\x00\x00", 1))
|
||||
|
||||
# Send steering command.
|
||||
idx = frame % 4
|
||||
can_sends.append(hondacan.create_steering_control(self.packer, apply_steer,
|
||||
c.latActive, CS.CP.carFingerprint, idx, CS.CP.openpilotLongitudinalControl))
|
||||
idx = self.frame % 4
|
||||
can_sends.append(hondacan.create_steering_control(self.packer, apply_steer, CC.latActive, self.CP.carFingerprint,
|
||||
idx, CS.CP.openpilotLongitudinalControl))
|
||||
|
||||
stopping = actuators.longControlState == LongCtrlState.stopping
|
||||
|
||||
# wind brake from air resistance decel at high speed
|
||||
wind_brake = interp(CS.out.vEgo, [0.0, 2.3, 35.0], [0.001, 0.002, 0.15])
|
||||
# all of this is only relevant for HONDA NIDEC
|
||||
max_accel = interp(CS.out.vEgo, P.NIDEC_MAX_ACCEL_BP, P.NIDEC_MAX_ACCEL_V)
|
||||
max_accel = interp(CS.out.vEgo, self.params.NIDEC_MAX_ACCEL_BP, self.params.NIDEC_MAX_ACCEL_V)
|
||||
# TODO this 1.44 is just to maintain previous behavior
|
||||
pcm_speed_BP = [-wind_brake,
|
||||
-wind_brake*(3/4),
|
||||
0.0,
|
||||
0.5]
|
||||
-wind_brake * (3 / 4),
|
||||
0.0,
|
||||
0.5]
|
||||
# The Honda ODYSSEY seems to have different PCM_ACCEL
|
||||
# msgs, is it other cars too?
|
||||
if CS.CP.enableGasInterceptor:
|
||||
if self.CP.enableGasInterceptor or not CC.longActive:
|
||||
pcm_speed = 0.0
|
||||
pcm_accel = int(0.0)
|
||||
elif CS.CP.carFingerprint in HONDA_NIDEC_ALT_PCM_ACCEL:
|
||||
elif self.CP.carFingerprint in HONDA_NIDEC_ALT_PCM_ACCEL:
|
||||
pcm_speed_V = [0.0,
|
||||
clip(CS.out.vEgo - 3.0, 0.0, 100.0),
|
||||
clip(CS.out.vEgo + 0.0, 0.0, 100.0),
|
||||
clip(CS.out.vEgo + 5.0, 0.0, 100.0)]
|
||||
pcm_speed = interp(gas-brake, pcm_speed_BP, pcm_speed_V)
|
||||
pcm_accel = int((1.0) * 0xc6)
|
||||
pcm_speed = interp(gas - brake, pcm_speed_BP, pcm_speed_V)
|
||||
pcm_accel = int(1.0 * 0xc6)
|
||||
else:
|
||||
pcm_speed_V = [0.0,
|
||||
clip(CS.out.vEgo - 2.0, 0.0, 100.0),
|
||||
clip(CS.out.vEgo + 2.0, 0.0, 100.0),
|
||||
clip(CS.out.vEgo + 5.0, 0.0, 100.0)]
|
||||
pcm_speed = interp(gas-brake, pcm_speed_BP, pcm_speed_V)
|
||||
pcm_accel = int(clip((accel/1.44)/max_accel, 0.0, 1.0) * 0xc6)
|
||||
pcm_speed = interp(gas - brake, pcm_speed_BP, pcm_speed_V)
|
||||
pcm_accel = int(clip((accel / 1.44) / max_accel, 0.0, 1.0) * 0xc6)
|
||||
|
||||
if not CS.CP.openpilotLongitudinalControl:
|
||||
if (frame % 2) == 0:
|
||||
idx = frame // 2
|
||||
can_sends.append(hondacan.create_bosch_supplemental_1(self.packer, CS.CP.carFingerprint, idx))
|
||||
if not self.CP.openpilotLongitudinalControl:
|
||||
if self.frame % 2 == 0:
|
||||
idx = self.frame // 2
|
||||
can_sends.append(hondacan.create_bosch_supplemental_1(self.packer, self.CP.carFingerprint, idx))
|
||||
# If using stock ACC, spam cancel command to kill gas when OP disengages.
|
||||
if pcm_cancel_cmd:
|
||||
can_sends.append(hondacan.spam_buttons_command(self.packer, CruiseButtons.CANCEL, idx, CS.CP.carFingerprint))
|
||||
can_sends.append(hondacan.spam_buttons_command(self.packer, CruiseButtons.CANCEL, idx, self.CP.carFingerprint))
|
||||
elif CS.out.cruiseState.standstill:
|
||||
can_sends.append(hondacan.spam_buttons_command(self.packer, CruiseButtons.RES_ACCEL, idx, CS.CP.carFingerprint))
|
||||
can_sends.append(hondacan.spam_buttons_command(self.packer, CruiseButtons.RES_ACCEL, idx, self.CP.carFingerprint))
|
||||
|
||||
else:
|
||||
# Send gas and brake commands.
|
||||
if (frame % 2) == 0:
|
||||
idx = frame // 2
|
||||
ts = frame * DT_CTRL
|
||||
if self.frame % 2 == 0:
|
||||
idx = self.frame // 2
|
||||
ts = self.frame * DT_CTRL
|
||||
|
||||
if CS.CP.carFingerprint in HONDA_BOSCH:
|
||||
self.accel = clip(accel, P.BOSCH_ACCEL_MIN, P.BOSCH_ACCEL_MAX)
|
||||
self.gas = interp(accel, P.BOSCH_GAS_LOOKUP_BP, P.BOSCH_GAS_LOOKUP_V)
|
||||
can_sends.extend(hondacan.create_acc_commands(self.packer, c.enabled, c.longActive, accel, self.gas, idx, stopping, CS.CP.carFingerprint))
|
||||
if self.CP.carFingerprint in HONDA_BOSCH:
|
||||
self.accel = clip(accel, self.params.BOSCH_ACCEL_MIN, self.params.BOSCH_ACCEL_MAX)
|
||||
self.gas = interp(accel, self.params.BOSCH_GAS_LOOKUP_BP, self.params.BOSCH_GAS_LOOKUP_V)
|
||||
can_sends.extend(hondacan.create_acc_commands(self.packer, CC.enabled, CC.longActive, accel, self.gas,
|
||||
idx, stopping, self.CP.carFingerprint))
|
||||
else:
|
||||
apply_brake = clip(self.brake_last - wind_brake, 0.0, 1.0)
|
||||
apply_brake = int(clip(apply_brake * P.NIDEC_BRAKE_MAX, 0, P.NIDEC_BRAKE_MAX - 1))
|
||||
apply_brake = int(clip(apply_brake * self.params.NIDEC_BRAKE_MAX, 0, self.params.NIDEC_BRAKE_MAX - 1))
|
||||
pump_on, self.last_pump_ts = brake_pump_hysteresis(apply_brake, self.apply_brake_last, self.last_pump_ts, ts)
|
||||
|
||||
pcm_override = True
|
||||
can_sends.append(hondacan.create_brake_command(self.packer, apply_brake, pump_on,
|
||||
pcm_override, pcm_cancel_cmd, fcw_display, idx, CS.CP.carFingerprint, CS.stock_brake))
|
||||
pcm_override, pcm_cancel_cmd, fcw_display, idx,
|
||||
self.CP.carFingerprint, CS.stock_brake))
|
||||
self.apply_brake_last = apply_brake
|
||||
self.brake = apply_brake / P.NIDEC_BRAKE_MAX
|
||||
self.brake = apply_brake / self.params.NIDEC_BRAKE_MAX
|
||||
|
||||
if CS.CP.enableGasInterceptor:
|
||||
if self.CP.enableGasInterceptor:
|
||||
# way too aggressive at low speed without this
|
||||
gas_mult = interp(CS.out.vEgo, [0., 10.], [0.4, 1.0])
|
||||
# send exactly zero if apply_gas is zero. Interceptor will send the max between read value and apply_gas.
|
||||
# This prevents unexpected pedal range rescaling
|
||||
# Sending non-zero gas when OP is not enabled will cause the PCM not to respond to throttle as expected
|
||||
# when you do enable.
|
||||
if c.longActive:
|
||||
self.gas = clip(gas_mult * (gas - brake + wind_brake*3/4), 0., 1.)
|
||||
if CC.longActive:
|
||||
self.gas = clip(gas_mult * (gas - brake + wind_brake * 3 / 4), 0., 1.)
|
||||
else:
|
||||
self.gas = 0.0
|
||||
can_sends.append(create_gas_interceptor_command(self.packer, self.gas, idx))
|
||||
|
||||
# Send dashboard UI commands.
|
||||
if (frame % 10) == 0:
|
||||
idx = (frame//10) % 4
|
||||
if self.frame % 10 == 0:
|
||||
idx = (self.frame // 10) % 4
|
||||
hud = HUDData(int(pcm_accel), int(round(hud_v_cruise)), hud_car,
|
||||
hud_lanes, fcw_display, acc_alert, steer_required)
|
||||
can_sends.extend(hondacan.create_ui_commands(self.packer, CS.CP, pcm_speed, hud, CS.is_metric, idx, CS.stock_hud))
|
||||
can_sends.extend(hondacan.create_ui_commands(self.packer, self.CP, pcm_speed, hud, CS.is_metric, idx, CS.stock_hud))
|
||||
|
||||
if (CS.CP.openpilotLongitudinalControl) and (CS.CP.carFingerprint not in HONDA_BOSCH):
|
||||
if self.CP.openpilotLongitudinalControl and self.CP.carFingerprint not in HONDA_BOSCH:
|
||||
self.speed = pcm_speed
|
||||
|
||||
if not CS.CP.enableGasInterceptor:
|
||||
if not self.CP.enableGasInterceptor:
|
||||
self.gas = pcm_accel / 0xc6
|
||||
|
||||
new_actuators = actuators.copy()
|
||||
|
@ -259,4 +268,5 @@ class CarController():
|
|||
new_actuators.gas = self.gas
|
||||
new_actuators.brake = self.brake
|
||||
|
||||
self.frame += 1
|
||||
return new_actuators, can_sends
|
||||
|
|
|
@ -3,7 +3,6 @@ from cereal import car
|
|||
from panda import Panda
|
||||
from common.conversions import Conversions as CV
|
||||
from common.numpy_fast import interp
|
||||
from common.params import Params
|
||||
from selfdrive.car.honda.values import CarControllerParams, CruiseButtons, HondaFlags, CAR, HONDA_BOSCH, HONDA_NIDEC_ALT_SCM_MESSAGES, HONDA_BOSCH_ALT_BRAKE_SIGNAL
|
||||
from selfdrive.car import STD_CARGO_KG, CivicParams, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint, get_safety_config
|
||||
from selfdrive.car.interfaces import CarInterfaceBase
|
||||
|
@ -28,7 +27,7 @@ class CarInterface(CarInterfaceBase):
|
|||
return CarControllerParams.NIDEC_ACCEL_MIN, interp(current_speed, ACCEL_MAX_BP, ACCEL_MAX_VALS)
|
||||
|
||||
@staticmethod
|
||||
def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=[]): # pylint: disable=dangerous-default-value
|
||||
def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=[], disable_radar=False): # pylint: disable=dangerous-default-value
|
||||
ret = CarInterfaceBase.get_std_params(candidate, fingerprint)
|
||||
ret.carName = "honda"
|
||||
|
||||
|
@ -38,7 +37,7 @@ class CarInterface(CarInterfaceBase):
|
|||
|
||||
# Disable the radar and let openpilot control longitudinal
|
||||
# WARNING: THIS DISABLES AEB!
|
||||
ret.openpilotLongitudinalControl = Params().get_bool("DisableRadar")
|
||||
ret.openpilotLongitudinalControl = disable_radar
|
||||
|
||||
ret.pcmCruise = not ret.openpilotLongitudinalControl
|
||||
else:
|
||||
|
@ -403,8 +402,8 @@ class CarInterface(CarInterfaceBase):
|
|||
for b in ret.buttonEvents:
|
||||
|
||||
# do enable on both accel and decel buttons
|
||||
if b.type in (ButtonType.accelCruise, ButtonType.decelCruise) and not b.pressed:
|
||||
if not self.CP.pcmCruise:
|
||||
if not self.CP.pcmCruise:
|
||||
if b.type in (ButtonType.accelCruise, ButtonType.decelCruise) and not b.pressed:
|
||||
events.add(EventName.buttonEnable)
|
||||
|
||||
# do disable on button down
|
||||
|
@ -419,17 +418,5 @@ class CarInterface(CarInterfaceBase):
|
|||
# pass in a car.CarControl
|
||||
# to be called @ 100hz
|
||||
def apply(self, c):
|
||||
hud_control = c.hudControl
|
||||
if hud_control.speedVisible:
|
||||
hud_v_cruise = hud_control.setSpeed * CV.MS_TO_KPH
|
||||
else:
|
||||
hud_v_cruise = 255
|
||||
|
||||
ret = self.CC.update(c, self.CS, self.frame,
|
||||
c.actuators, c.cruiseControl.cancel,
|
||||
hud_v_cruise, hud_control.lanesVisible,
|
||||
hud_show_car=hud_control.leadVisible,
|
||||
hud_alert=hud_control.visualAlert)
|
||||
|
||||
self.frame += 1
|
||||
ret = self.CC.update(c, self.CS)
|
||||
return ret
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
from enum import IntFlag
|
||||
from enum import Enum, IntFlag
|
||||
from typing import Dict, List, Union
|
||||
|
||||
from cereal import car
|
||||
from selfdrive.car import dbc_dict
|
||||
from selfdrive.car.docs_definitions import CarFootnote, CarInfo, Column
|
||||
from common.conversions import Conversions as CV
|
||||
|
||||
Ecu = car.CarParams.Ecu
|
||||
VisualAlert = car.CarControl.HUDControl.VisualAlert
|
||||
|
||||
|
||||
class CarControllerParams():
|
||||
class CarControllerParams:
|
||||
# Allow small margin below -3.5 m/s^2 from ISO 15622:2018 since we
|
||||
# perform the closed loop control, and might need some
|
||||
# to apply some more braking if we're on a downhill slope.
|
||||
|
@ -63,6 +65,7 @@ VISUAL_HUD = {
|
|||
VisualAlert.speedTooHigh: 8
|
||||
}
|
||||
|
||||
|
||||
class CAR:
|
||||
ACCORD = "HONDA ACCORD 2018"
|
||||
ACCORDH = "HONDA ACCORD HYBRID 2018"
|
||||
|
@ -87,6 +90,43 @@ class CAR:
|
|||
INSIGHT = "HONDA INSIGHT 2019"
|
||||
HONDA_E = "HONDA E 2020"
|
||||
|
||||
|
||||
class Footnote(Enum):
|
||||
CIVIC_DIESEL = CarFootnote(
|
||||
"2019 Honda Civic 1.6L Diesel Sedan does not have ALC below 12mph.",
|
||||
Column.FSR_STEERING)
|
||||
|
||||
|
||||
CAR_INFO: Dict[str, Union[CarInfo, List[CarInfo]]] = {
|
||||
CAR.ACCORD: [
|
||||
CarInfo("Honda Accord 2018-21", "All", video_link="https://www.youtube.com/watch?v=mrUwlj3Mi58", min_steer_speed=3. * CV.MPH_TO_MS),
|
||||
CarInfo("Honda Inspire 2018", "All", min_steer_speed=3. * CV.MPH_TO_MS),
|
||||
],
|
||||
CAR.ACCORDH: CarInfo("Honda Accord Hybrid 2018-21", "All", min_steer_speed=3. * CV.MPH_TO_MS),
|
||||
CAR.CIVIC: CarInfo("Honda Civic 2016-18", "Honda Sensing", min_steer_speed=12. * CV.MPH_TO_MS),
|
||||
CAR.CIVIC_BOSCH: [
|
||||
CarInfo("Honda Civic 2019-20", "All", video_link="https://www.youtube.com/watch?v=4Iz1Mz5LGF8", footnotes=[Footnote.CIVIC_DIESEL], min_steer_speed=2. * CV.MPH_TO_MS),
|
||||
CarInfo("Honda Civic Hatchback 2017-21", "Honda Sensing", min_steer_speed=12. * CV.MPH_TO_MS),
|
||||
],
|
||||
CAR.ACURA_ILX: CarInfo("Acura ILX 2016-19", "AcuraWatch Plus", min_steer_speed=25. * CV.MPH_TO_MS),
|
||||
CAR.CRV: CarInfo("Honda CR-V 2015-16", "Touring", min_steer_speed=12. * CV.MPH_TO_MS),
|
||||
CAR.CRV_5G: CarInfo("Honda CR-V 2017-21", "Honda Sensing", min_steer_speed=12. * CV.MPH_TO_MS),
|
||||
# CAR.CRV_EU: CarInfo("Honda CR-V EU", "Touring"), # Euro version of CRV Touring
|
||||
CAR.CRV_HYBRID: CarInfo("Honda CR-V Hybrid 2017-19", "Honda Sensing", min_steer_speed=12. * CV.MPH_TO_MS),
|
||||
CAR.FIT: CarInfo("Honda Fit 2018-19", "Honda Sensing", min_steer_speed=12. * CV.MPH_TO_MS),
|
||||
CAR.FREED: CarInfo("Honda Freed 2020", "Honda Sensing", min_steer_speed=12. * CV.MPH_TO_MS),
|
||||
CAR.HRV: CarInfo("Honda HR-V 2019-20", "Honda Sensing", min_steer_speed=12. * CV.MPH_TO_MS),
|
||||
CAR.ODYSSEY: CarInfo("Honda Odyssey 2018-20", "Honda Sensing"),
|
||||
CAR.ACURA_RDX: CarInfo("Acura RDX 2016-18", "AcuraWatch Plus", min_steer_speed=12. * CV.MPH_TO_MS),
|
||||
CAR.ACURA_RDX_3G: CarInfo("Acura RDX 2019-21", "All", min_steer_speed=3. * CV.MPH_TO_MS),
|
||||
CAR.PILOT: CarInfo("Honda Pilot 2016-21", "Honda Sensing", min_steer_speed=12. * CV.MPH_TO_MS),
|
||||
CAR.PASSPORT: CarInfo("Honda Passport 2019-21", "All", min_steer_speed=12. * CV.MPH_TO_MS),
|
||||
CAR.RIDGELINE: CarInfo("Honda Ridgeline 2017-21", "Honda Sensing", min_steer_speed=12. * CV.MPH_TO_MS),
|
||||
CAR.INSIGHT: CarInfo("Honda Insight 2019-21", "All", min_steer_speed=3. * CV.MPH_TO_MS),
|
||||
CAR.HONDA_E: CarInfo("Honda e 2020", "All", min_steer_speed=3. * CV.MPH_TO_MS),
|
||||
}
|
||||
|
||||
|
||||
FW_VERSIONS = {
|
||||
CAR.ACCORD: {
|
||||
(Ecu.programmedFuelInjection, 0x18da10f1, None): [
|
||||
|
|
|
@ -11,34 +11,35 @@ VisualAlert = car.CarControl.HUDControl.VisualAlert
|
|||
LongCtrlState = car.CarControl.Actuators.LongControlState
|
||||
|
||||
|
||||
def process_hud_alert(enabled, fingerprint, visual_alert, left_lane,
|
||||
right_lane, left_lane_depart, right_lane_depart):
|
||||
sys_warning = (visual_alert in (VisualAlert.steerRequired, VisualAlert.ldw))
|
||||
def process_hud_alert(enabled, fingerprint, hud_control):
|
||||
sys_warning = (hud_control.visualAlert in (VisualAlert.steerRequired, VisualAlert.ldw))
|
||||
|
||||
# initialize to no line visible
|
||||
sys_state = 1
|
||||
if left_lane and right_lane or sys_warning: # HUD alert only display when LKAS status is active
|
||||
if hud_control.leftLaneVisible and hud_control.rightLaneVisible or sys_warning: # HUD alert only display when LKAS status is active
|
||||
sys_state = 3 if enabled or sys_warning else 4
|
||||
elif left_lane:
|
||||
elif hud_control.leftLaneVisible:
|
||||
sys_state = 5
|
||||
elif right_lane:
|
||||
elif hud_control.rightLaneVisible:
|
||||
sys_state = 6
|
||||
|
||||
# initialize to no warnings
|
||||
left_lane_warning = 0
|
||||
right_lane_warning = 0
|
||||
if left_lane_depart:
|
||||
if hud_control.leftLaneDepart:
|
||||
left_lane_warning = 1 if fingerprint in (CAR.GENESIS_G90, CAR.GENESIS_G80) else 2
|
||||
if right_lane_depart:
|
||||
if hud_control.rightLaneDepart:
|
||||
right_lane_warning = 1 if fingerprint in (CAR.GENESIS_G90, CAR.GENESIS_G80) else 2
|
||||
|
||||
return sys_warning, sys_state, left_lane_warning, right_lane_warning
|
||||
|
||||
|
||||
class CarController():
|
||||
class CarController:
|
||||
def __init__(self, dbc_name, CP, VM):
|
||||
self.p = CarControllerParams(CP)
|
||||
self.CP = CP
|
||||
self.params = CarControllerParams(CP)
|
||||
self.packer = CANPacker(dbc_name)
|
||||
self.frame = 0
|
||||
|
||||
self.apply_steer_last = 0
|
||||
self.car_fingerprint = CP.carFingerprint
|
||||
|
@ -46,47 +47,49 @@ class CarController():
|
|||
self.last_resume_frame = 0
|
||||
self.accel = 0
|
||||
|
||||
def update(self, c, CS, frame, actuators, pcm_cancel_cmd, visual_alert, hud_speed,
|
||||
left_lane, right_lane, left_lane_depart, right_lane_depart):
|
||||
def update(self, CC, CS):
|
||||
actuators = CC.actuators
|
||||
hud_control = CC.hudControl
|
||||
pcm_cancel_cmd = CC.cruiseControl.cancel
|
||||
|
||||
# Steering Torque
|
||||
new_steer = int(round(actuators.steer * self.p.STEER_MAX))
|
||||
apply_steer = apply_std_steer_torque_limits(new_steer, self.apply_steer_last, CS.out.steeringTorque, self.p)
|
||||
new_steer = int(round(actuators.steer * self.params.STEER_MAX))
|
||||
apply_steer = apply_std_steer_torque_limits(new_steer, self.apply_steer_last, CS.out.steeringTorque, self.params)
|
||||
self.steer_rate_limited = new_steer != apply_steer
|
||||
|
||||
if not c.latActive:
|
||||
if not CC.latActive:
|
||||
apply_steer = 0
|
||||
|
||||
self.apply_steer_last = apply_steer
|
||||
|
||||
sys_warning, sys_state, left_lane_warning, right_lane_warning = \
|
||||
process_hud_alert(c.enabled, self.car_fingerprint, visual_alert,
|
||||
left_lane, right_lane, left_lane_depart, right_lane_depart)
|
||||
sys_warning, sys_state, left_lane_warning, right_lane_warning = process_hud_alert(CC.enabled, self.car_fingerprint,
|
||||
hud_control)
|
||||
|
||||
can_sends = []
|
||||
|
||||
# tester present - w/ no response (keeps radar disabled)
|
||||
if CS.CP.openpilotLongitudinalControl:
|
||||
if (frame % 100) == 0:
|
||||
if self.CP.openpilotLongitudinalControl:
|
||||
if self.frame % 100 == 0:
|
||||
can_sends.append([0x7D0, 0, b"\x02\x3E\x80\x00\x00\x00\x00\x00", 0])
|
||||
|
||||
can_sends.append(create_lkas11(self.packer, frame, self.car_fingerprint, apply_steer, c.latActive,
|
||||
CS.lkas11, sys_warning, sys_state, c.enabled,
|
||||
left_lane, right_lane,
|
||||
can_sends.append(create_lkas11(self.packer, self.frame, self.car_fingerprint, apply_steer, CC.latActive,
|
||||
CS.lkas11, sys_warning, sys_state, CC.enabled,
|
||||
hud_control.leftLaneVisible, hud_control.rightLaneVisible,
|
||||
left_lane_warning, right_lane_warning))
|
||||
|
||||
if not CS.CP.openpilotLongitudinalControl:
|
||||
if not self.CP.openpilotLongitudinalControl:
|
||||
if pcm_cancel_cmd:
|
||||
can_sends.append(create_clu11(self.packer, frame, CS.clu11, Buttons.CANCEL))
|
||||
can_sends.append(create_clu11(self.packer, self.frame, CS.clu11, Buttons.CANCEL))
|
||||
elif CS.out.cruiseState.standstill:
|
||||
# send resume at a max freq of 10Hz
|
||||
if (frame - self.last_resume_frame) * DT_CTRL > 0.1:
|
||||
if (self.frame - self.last_resume_frame) * DT_CTRL > 0.1:
|
||||
# send 25 messages at a time to increases the likelihood of resume being accepted
|
||||
can_sends.extend([create_clu11(self.packer, frame, CS.clu11, Buttons.RES_ACCEL)] * 25)
|
||||
self.last_resume_frame = frame
|
||||
can_sends.extend([create_clu11(self.packer, self.frame, CS.clu11, Buttons.RES_ACCEL)] * 25)
|
||||
self.last_resume_frame = self.frame
|
||||
|
||||
if frame % 2 == 0 and CS.CP.openpilotLongitudinalControl:
|
||||
if self.frame % 2 == 0 and self.CP.openpilotLongitudinalControl:
|
||||
lead_visible = False
|
||||
accel = actuators.accel if c.longActive else 0
|
||||
accel = actuators.accel if CC.longActive else 0
|
||||
|
||||
jerk = clip(2.0 * (accel - CS.out.aEgo), -12.7, 12.7)
|
||||
|
||||
|
@ -96,27 +99,29 @@ class CarController():
|
|||
accel = clip(accel, CarControllerParams.ACCEL_MIN, CarControllerParams.ACCEL_MAX)
|
||||
|
||||
stopping = (actuators.longControlState == LongCtrlState.stopping)
|
||||
set_speed_in_units = hud_speed * (CV.MS_TO_MPH if CS.clu11["CF_Clu_SPEED_UNIT"] == 1 else CV.MS_TO_KPH)
|
||||
can_sends.extend(create_acc_commands(self.packer, c.enabled, accel, jerk, int(frame / 2), lead_visible, set_speed_in_units, stopping))
|
||||
set_speed_in_units = hud_control.setSpeed * (CV.MS_TO_MPH if CS.clu11["CF_Clu_SPEED_UNIT"] == 1 else CV.MS_TO_KPH)
|
||||
can_sends.extend(create_acc_commands(self.packer, CC.enabled, accel, jerk, int(self.frame / 2), lead_visible,
|
||||
set_speed_in_units, stopping, CS.out.gasPressed))
|
||||
self.accel = accel
|
||||
|
||||
# 20 Hz LFA MFA message
|
||||
if frame % 5 == 0 and self.car_fingerprint in (CAR.SONATA, CAR.PALISADE, CAR.IONIQ, CAR.KIA_NIRO_EV, CAR.KIA_NIRO_HEV_2021,
|
||||
CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.KIA_CEED, CAR.KIA_SELTOS, CAR.KONA_EV,
|
||||
CAR.ELANTRA_2021, CAR.ELANTRA_HEV_2021, CAR.SONATA_HYBRID, CAR.KONA_HEV, CAR.SANTA_FE_2022,
|
||||
CAR.KIA_K5_2021, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022, CAR.GENESIS_G70_2020, CAR.SANTA_FE_PHEV_2022):
|
||||
can_sends.append(create_lfahda_mfc(self.packer, c.enabled))
|
||||
if self.frame % 5 == 0 and self.car_fingerprint in (CAR.SONATA, CAR.PALISADE, CAR.IONIQ, CAR.KIA_NIRO_EV, CAR.KIA_NIRO_HEV_2021,
|
||||
CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.KIA_CEED, CAR.KIA_SELTOS, CAR.KONA_EV,
|
||||
CAR.ELANTRA_2021, CAR.ELANTRA_HEV_2021, CAR.SONATA_HYBRID, CAR.KONA_HEV, CAR.SANTA_FE_2022,
|
||||
CAR.KIA_K5_2021, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022, CAR.GENESIS_G70_2020, CAR.SANTA_FE_PHEV_2022):
|
||||
can_sends.append(create_lfahda_mfc(self.packer, CC.enabled))
|
||||
|
||||
# 5 Hz ACC options
|
||||
if frame % 20 == 0 and CS.CP.openpilotLongitudinalControl:
|
||||
if self.frame % 20 == 0 and self.CP.openpilotLongitudinalControl:
|
||||
can_sends.extend(create_acc_opt(self.packer))
|
||||
|
||||
# 2 Hz front radar options
|
||||
if frame % 50 == 0 and CS.CP.openpilotLongitudinalControl:
|
||||
if self.frame % 50 == 0 and self.CP.openpilotLongitudinalControl:
|
||||
can_sends.append(create_frt_radar_opt(self.packer))
|
||||
|
||||
new_actuators = actuators.copy()
|
||||
new_actuators.steer = apply_steer / self.p.STEER_MAX
|
||||
new_actuators.steer = apply_steer / self.params.STEER_MAX
|
||||
new_actuators.accel = self.accel
|
||||
|
||||
self.frame += 1
|
||||
return new_actuators, can_sends
|
||||
|
|
|
@ -78,7 +78,7 @@ def create_lfahda_mfc(packer, enabled, hda_set_speed=0):
|
|||
}
|
||||
return packer.make_can_msg("LFAHDA_MFC", 0, values)
|
||||
|
||||
def create_acc_commands(packer, enabled, accel, jerk, idx, lead_visible, set_speed, stopping):
|
||||
def create_acc_commands(packer, enabled, accel, jerk, idx, lead_visible, set_speed, stopping, gas_pressed):
|
||||
commands = []
|
||||
|
||||
scc11_values = {
|
||||
|
@ -95,7 +95,7 @@ def create_acc_commands(packer, enabled, accel, jerk, idx, lead_visible, set_spe
|
|||
commands.append(packer.make_can_msg("SCC11", 0, scc11_values))
|
||||
|
||||
scc12_values = {
|
||||
"ACCMode": 1 if enabled else 0,
|
||||
"ACCMode": 2 if enabled and gas_pressed else 1 if enabled else 0,
|
||||
"StopReq": 1 if enabled and stopping else 0,
|
||||
"aReqRaw": accel if enabled else 0,
|
||||
"aReqValue": accel if enabled else 0, # stock ramps up and down respecting jerk limit until it reaches aReqRaw
|
||||
|
@ -111,7 +111,7 @@ def create_acc_commands(packer, enabled, accel, jerk, idx, lead_visible, set_spe
|
|||
"ComfortBandLower": 0.0, # stock usually is 0 but sometimes uses higher values
|
||||
"JerkUpperLimit": max(jerk, 1.0) if (enabled and not stopping) else 0, # stock usually is 1.0 but sometimes uses higher values
|
||||
"JerkLowerLimit": max(-jerk, 1.0) if enabled else 0, # stock usually is 0.5 but sometimes uses higher values
|
||||
"ACCMode": 1 if enabled else 4, # stock will always be 4 instead of 0 after first disengage
|
||||
"ACCMode": 2 if enabled and gas_pressed else 1 if enabled else 4, # stock will always be 4 instead of 0 after first disengage
|
||||
"ObjGap": 2 if lead_visible else 0, # 5: >30, m, 4: 25-30 m, 3: 20-25 m, 2: < 20 m, 0: no lead
|
||||
}
|
||||
commands.append(packer.make_can_msg("SCC14", 0, scc14_values))
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
#!/usr/bin/env python3
|
||||
from cereal import car
|
||||
from panda import Panda
|
||||
from common.params import Params
|
||||
from common.conversions import Conversions as CV
|
||||
from selfdrive.car.hyundai.values import CAR, EV_CAR, HYBRID_CAR, LEGACY_SAFETY_MODE_CAR, Buttons, CarControllerParams
|
||||
from selfdrive.car.hyundai.values import CAR, DBC, EV_CAR, HYBRID_CAR, LEGACY_SAFETY_MODE_CAR, Buttons, CarControllerParams
|
||||
from selfdrive.car.hyundai.radar_interface import RADAR_START_ADDR
|
||||
from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint, get_safety_config
|
||||
from selfdrive.car.interfaces import CarInterfaceBase
|
||||
|
@ -18,15 +17,15 @@ class CarInterface(CarInterfaceBase):
|
|||
return CarControllerParams.ACCEL_MIN, CarControllerParams.ACCEL_MAX
|
||||
|
||||
@staticmethod
|
||||
def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=[]): # pylint: disable=dangerous-default-value
|
||||
def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=[], disable_radar=False): # pylint: disable=dangerous-default-value
|
||||
ret = CarInterfaceBase.get_std_params(candidate, fingerprint)
|
||||
|
||||
ret.carName = "hyundai"
|
||||
ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.hyundai, 0)]
|
||||
ret.radarOffCan = RADAR_START_ADDR not in fingerprint[1]
|
||||
ret.radarOffCan = RADAR_START_ADDR not in fingerprint[1] or DBC[ret.carFingerprint]["radar"] is None
|
||||
|
||||
# WARNING: disabling radar also disables AEB (and we show the same warning on the instrument cluster as if you manually disabled AEB)
|
||||
ret.openpilotLongitudinalControl = Params().get_bool("DisableRadar") and (candidate not in LEGACY_SAFETY_MODE_CAR)
|
||||
ret.openpilotLongitudinalControl = disable_radar and (candidate not in LEGACY_SAFETY_MODE_CAR)
|
||||
|
||||
ret.pcmCruise = not ret.openpilotLongitudinalControl
|
||||
|
||||
|
@ -349,9 +348,5 @@ class CarInterface(CarInterfaceBase):
|
|||
return self.CS.out
|
||||
|
||||
def apply(self, c):
|
||||
hud_control = c.hudControl
|
||||
ret = self.CC.update(c, self.CS, self.frame, c.actuators, c.cruiseControl.cancel, hud_control.visualAlert,
|
||||
hud_control.setSpeed, hud_control.leftLaneVisible, hud_control.rightLaneVisible,
|
||||
hud_control.leftLaneDepart, hud_control.rightLaneDepart)
|
||||
self.frame += 1
|
||||
ret = self.CC.update(c, self.CS)
|
||||
return ret
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
from dataclasses import dataclass
|
||||
from typing import Dict, List, Union
|
||||
|
||||
from cereal import car
|
||||
from common.conversions import Conversions as CV
|
||||
from selfdrive.car import dbc_dict
|
||||
from selfdrive.car.docs_definitions import CarInfo
|
||||
Ecu = car.CarParams.Ecu
|
||||
|
||||
# Steer torque limits
|
||||
|
@ -22,6 +27,7 @@ class CarControllerParams:
|
|||
self.STEER_DRIVER_MULTIPLIER = 2
|
||||
self.STEER_DRIVER_FACTOR = 1
|
||||
|
||||
|
||||
class CAR:
|
||||
# Hyundai
|
||||
ELANTRA = "HYUNDAI ELANTRA 2017"
|
||||
|
@ -67,6 +73,60 @@ class CAR:
|
|||
GENESIS_G90 = "GENESIS G90 2017"
|
||||
|
||||
|
||||
@dataclass
|
||||
class HyundaiCarInfo(CarInfo):
|
||||
package: str = "SCC + LKAS"
|
||||
good_torque: bool = True
|
||||
|
||||
|
||||
CAR_INFO: Dict[str, Union[HyundaiCarInfo, List[HyundaiCarInfo]]] = {
|
||||
CAR.ELANTRA: HyundaiCarInfo("Hyundai Elantra 2017-19", min_enable_speed=19 * CV.MPH_TO_MS),
|
||||
CAR.ELANTRA_2021: HyundaiCarInfo("Hyundai Elantra 2021-22", video_link="https://youtu.be/_EdYQtV52-c"),
|
||||
CAR.ELANTRA_HEV_2021: HyundaiCarInfo("Hyundai Elantra Hybrid 2021", video_link="https://youtu.be/_EdYQtV52-c"),
|
||||
CAR.HYUNDAI_GENESIS: HyundaiCarInfo("Hyundai Genesis 2015-16", min_enable_speed=19 * CV.MPH_TO_MS),
|
||||
CAR.IONIQ: HyundaiCarInfo("Hyundai Ioniq Hybrid 2017-19"),
|
||||
CAR.IONIQ_HEV_2022: HyundaiCarInfo("Hyundai Ioniq Hybrid 2020-22", "SCC + LFA"),
|
||||
CAR.IONIQ_EV_LTD: HyundaiCarInfo("Hyundai Ioniq Electric 2019"),
|
||||
CAR.IONIQ_EV_2020: HyundaiCarInfo("Hyundai Ioniq Electric 2020"),
|
||||
CAR.IONIQ_PHEV: HyundaiCarInfo("Hyundai Ioniq Plug-In Hybrid 2020-21"),
|
||||
CAR.KONA: HyundaiCarInfo("Hyundai Kona 2020"),
|
||||
CAR.KONA_EV: HyundaiCarInfo("Hyundai Kona Electric 2018-19"),
|
||||
CAR.KONA_HEV: HyundaiCarInfo("Hyundai Kona Hybrid 2020", video_link="https://youtu.be/_EdYQtV52-c"),
|
||||
CAR.SANTA_FE: HyundaiCarInfo("Hyundai Santa Fe 2019-20", "All"),
|
||||
CAR.SANTA_FE_2022: HyundaiCarInfo("Hyundai Santa Fe 2021-22", "All"),
|
||||
CAR.SANTA_FE_HEV_2022: HyundaiCarInfo("Hyundai Santa Fe Hybrid 2022", "All"),
|
||||
CAR.SANTA_FE_PHEV_2022: HyundaiCarInfo("Hyundai Santa Fe Plug-In Hybrid 2022", "All"),
|
||||
CAR.SONATA: HyundaiCarInfo("Hyundai Sonata 2020-22", "All", video_link="https://www.youtube.com/watch?v=ix63r9kE3Fw"),
|
||||
CAR.SONATA_LF: HyundaiCarInfo("Hyundai Sonata 2018-19"),
|
||||
CAR.PALISADE: [
|
||||
HyundaiCarInfo("Hyundai Palisade 2020-21", "All", video_link="https://youtu.be/TAnDqjF4fDY?t=456"),
|
||||
HyundaiCarInfo("Kia Telluride 2020"),
|
||||
],
|
||||
CAR.VELOSTER: HyundaiCarInfo("Hyundai Veloster 2019-20", min_enable_speed=5. * CV.MPH_TO_MS),
|
||||
CAR.SONATA_HYBRID: HyundaiCarInfo("Hyundai Sonata Hybrid 2021-22", "All"),
|
||||
|
||||
# Kia
|
||||
CAR.KIA_FORTE: HyundaiCarInfo("Kia Forte 2018-21"),
|
||||
CAR.KIA_K5_2021: HyundaiCarInfo("Kia K5 2021-22", "SCC + LFA"),
|
||||
CAR.KIA_NIRO_EV: HyundaiCarInfo("Kia Niro Electric 2019-22", "All", video_link="https://www.youtube.com/watch?v=lT7zcG6ZpGo"),
|
||||
CAR.KIA_NIRO_HEV: HyundaiCarInfo("Kia Niro Plug-In Hybrid 2019", min_enable_speed=10. * CV.MPH_TO_MS),
|
||||
CAR.KIA_NIRO_HEV_2021: HyundaiCarInfo("Kia Niro Hybrid 2021-22"),
|
||||
CAR.KIA_OPTIMA: [
|
||||
HyundaiCarInfo("Kia Optima 2017", min_steer_speed=32. * CV.MPH_TO_MS),
|
||||
HyundaiCarInfo("Kia Optima 2019"),
|
||||
],
|
||||
CAR.KIA_SELTOS: HyundaiCarInfo("Kia Seltos 2021"),
|
||||
CAR.KIA_SORENTO: HyundaiCarInfo("Kia Sorento 2018-19", video_link="https://www.youtube.com/watch?v=Fkh3s6WHJz8"),
|
||||
CAR.KIA_STINGER: HyundaiCarInfo("Kia Stinger 2018", video_link="https://www.youtube.com/watch?v=MJ94qoofYw0"),
|
||||
CAR.KIA_CEED: HyundaiCarInfo("Kia Ceed 2019"),
|
||||
|
||||
# Genesis
|
||||
CAR.GENESIS_G70: HyundaiCarInfo("Genesis G70 2018", "All"),
|
||||
CAR.GENESIS_G70_2020: HyundaiCarInfo("Genesis G70 2020", "All"),
|
||||
CAR.GENESIS_G80: HyundaiCarInfo("Genesis G80 2018", "All"),
|
||||
CAR.GENESIS_G90: HyundaiCarInfo("Genesis G90 2018", "All"),
|
||||
}
|
||||
|
||||
class Buttons:
|
||||
NONE = 0
|
||||
RES_ACCEL = 1
|
||||
|
@ -693,10 +753,12 @@ FW_VERSIONS = {
|
|||
CAR.GENESIS_G70_2020: {
|
||||
(Ecu.eps, 0x7d4, None): [
|
||||
b'\xf1\x00IK MDPS R 1.00 1.07 57700-G9220 4I2VL107',
|
||||
b'\xf1\x00IK MDPS R 1.00 1.07 57700-G9420 4I4VL107',
|
||||
],
|
||||
(Ecu.transmission, 0x7e1, None): [
|
||||
b'\xf1\x87VCJLP18407832DN3\x88vXfvUVT\x97eFU\x87d7v\x88eVeveFU\x89\x98\x7f\xff\xb2\xb0\xf1\x81E25\x00\x00\x00',
|
||||
b'\x00\x00\x00\x00\xf1\x00bcsh8p54 E25\x00\x00\x00\x00\x00\x00\x00SIK0T33NB4\xecE\xefL',
|
||||
b'\xf1\x87VDKLT18912362DN4wfVfwefeveVUwfvw\x88vWfvUFU\x89\xa9\x8f\xff\x87w\xf1\x81E25\x00\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 E25\x00\x00\x00\x00\x00\x00\x00SIK0T33NB4\xecE\xefL',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00IK__ SCC F-CUP 1.00 1.02 96400-G9100 ',
|
||||
|
|
|
@ -50,7 +50,7 @@ class CarInterfaceBase(ABC):
|
|||
|
||||
@staticmethod
|
||||
@abstractmethod
|
||||
def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None):
|
||||
def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None, disable_radar=False):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
|
@ -75,8 +75,6 @@ class CarInterfaceBase(ABC):
|
|||
|
||||
# standard ALC params
|
||||
ret.steerControlType = car.CarParams.SteerControlType.torque
|
||||
ret.steerMaxBP = [0.]
|
||||
ret.steerMaxV = [1.]
|
||||
ret.minSteerSpeed = 0.
|
||||
ret.wheelSpeedFactor = 1.0
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ VisualAlert = car.CarControl.HUDControl.VisualAlert
|
|||
|
||||
class CarController():
|
||||
def __init__(self, dbc_name, CP, VM):
|
||||
self.CP = CP
|
||||
self.apply_steer_last = 0
|
||||
self.packer = CANPacker(dbc_name)
|
||||
self.steer_rate_limited = False
|
||||
|
@ -30,7 +31,7 @@ class CarController():
|
|||
# Mazda Stop and Go requires a RES button (or gas) press if the car stops more than 3 seconds
|
||||
# Send Resume button at 20hz if we're engaged at standstill to support full stop and go!
|
||||
# TODO: improve the resume trigger logic by looking at actual radar data
|
||||
can_sends.append(mazdacan.create_button_cmd(self.packer, CS.CP.carFingerprint, CS.crz_btns_counter, Buttons.RESUME))
|
||||
can_sends.append(mazdacan.create_button_cmd(self.packer, self.CP.carFingerprint, CS.crz_btns_counter, Buttons.RESUME))
|
||||
|
||||
if c.cruiseControl.cancel:
|
||||
# If brake is pressed, let us wait >70ms before trying to disable crz to avoid
|
||||
|
@ -41,7 +42,7 @@ class CarController():
|
|||
if frame % 10 == 0 and not (CS.out.brakePressed and self.brake_counter < 7):
|
||||
# Cancel Stock ACC if it's enabled while OP is disengaged
|
||||
# Send at a rate of 10hz until we sync with stock ACC state
|
||||
can_sends.append(mazdacan.create_button_cmd(self.packer, CS.CP.carFingerprint, CS.crz_btns_counter, Buttons.CANCEL))
|
||||
can_sends.append(mazdacan.create_button_cmd(self.packer, self.CP.carFingerprint, CS.crz_btns_counter, Buttons.CANCEL))
|
||||
else:
|
||||
self.brake_counter = 0
|
||||
|
||||
|
@ -56,7 +57,7 @@ class CarController():
|
|||
can_sends.append(mazdacan.create_alert_command(self.packer, CS.cam_laneinfo, ldw, steer_required))
|
||||
|
||||
# send steering command
|
||||
can_sends.append(mazdacan.create_steering_control(self.packer, CS.CP.carFingerprint,
|
||||
can_sends.append(mazdacan.create_steering_control(self.packer, self.CP.carFingerprint,
|
||||
frame, apply_steer, CS.cam_lkas))
|
||||
|
||||
new_actuators = c.actuators.copy()
|
||||
|
|
|
@ -72,6 +72,8 @@ class CarState(CarStateBase):
|
|||
self.lkas_allowed_speed = True
|
||||
elif speed_kph < LKAS_LIMITS.DISABLE_SPEED:
|
||||
self.lkas_allowed_speed = False
|
||||
else:
|
||||
self.lkas_allowed_speed = True
|
||||
|
||||
# TODO: the signal used for available seems to be the adaptive cruise signal, instead of the main on
|
||||
# it should be used for carState.cruiseState.nonAdaptive instead
|
||||
|
|
|
@ -15,7 +15,7 @@ class CarInterface(CarInterfaceBase):
|
|||
return float(accel) / 4.0
|
||||
|
||||
@staticmethod
|
||||
def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None):
|
||||
def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None, disable_radar=False):
|
||||
ret = CarInterfaceBase.get_std_params(candidate, fingerprint)
|
||||
|
||||
ret.carName = "mazda"
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
from typing import Dict, List, Union
|
||||
|
||||
from selfdrive.car import dbc_dict
|
||||
from selfdrive.car.docs_definitions import CarInfo
|
||||
from cereal import car
|
||||
Ecu = car.CarParams.Ecu
|
||||
|
||||
|
@ -14,6 +17,7 @@ class CarControllerParams:
|
|||
STEER_DRIVER_FACTOR = 1 # from dbc
|
||||
STEER_ERROR_MAX = 350 # max delta between torque cmd and torque motor
|
||||
|
||||
|
||||
class CAR:
|
||||
CX5 = "MAZDA CX-5"
|
||||
CX9 = "MAZDA CX-9"
|
||||
|
@ -22,6 +26,17 @@ class CAR:
|
|||
CX9_2021 = "MAZDA CX-9 2021"
|
||||
CX5_2022 = "MAZDA CX-5 2022"
|
||||
|
||||
|
||||
CAR_INFO: Dict[str, Union[CarInfo, List[CarInfo]]] = {
|
||||
CAR.CX5: CarInfo("Mazda CX-5 2017, 2019", "All"), # TODO: verify years and torque for first 4
|
||||
CAR.CX9: CarInfo("Mazda CX-9 2016-17", "All"),
|
||||
CAR.MAZDA3: CarInfo("Mazda 3 2017", "All"),
|
||||
CAR.MAZDA6: CarInfo("Mazda 6 2017", "All"),
|
||||
CAR.CX9_2021: CarInfo("Mazda CX-9 2021", "All", good_torque=True),
|
||||
CAR.CX5_2022: CarInfo("Mazda CX-5 2022", "All", good_torque=True),
|
||||
}
|
||||
|
||||
|
||||
class LKAS_LIMITS:
|
||||
STEER_THRESHOLD = 15
|
||||
DISABLE_SPEED = 45 # kph
|
||||
|
|
|
@ -33,7 +33,7 @@ class CarInterface(CarInterfaceBase):
|
|||
return accel
|
||||
|
||||
@staticmethod
|
||||
def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None):
|
||||
def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None, disable_radar=False):
|
||||
ret = CarInterfaceBase.get_std_params(candidate, fingerprint)
|
||||
ret.carName = "mock"
|
||||
ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.noOutput)]
|
||||
|
|
|
@ -1,2 +1,10 @@
|
|||
from typing import Dict, List, Union
|
||||
|
||||
from selfdrive.car.docs_definitions import CarInfo
|
||||
|
||||
|
||||
class CAR:
|
||||
MOCK = 'mock'
|
||||
|
||||
|
||||
CAR_INFO: Dict[str, Union[CarInfo, List[CarInfo]]] = {}
|
||||
|
|
|
@ -58,14 +58,14 @@ class CarController():
|
|||
self.last_angle = apply_angle
|
||||
|
||||
if self.CP.carFingerprint in (CAR.ROGUE, CAR.XTRAIL, CAR.ALTIMA) and cruise_cancel:
|
||||
can_sends.append(nissancan.create_acc_cancel_cmd(self.packer, self.car_fingerprint, CS.cruise_throttle_msg, frame))
|
||||
can_sends.append(nissancan.create_acc_cancel_cmd(self.packer, self.car_fingerprint, CS.cruise_throttle_msg, frame))
|
||||
|
||||
# TODO: Find better way to cancel!
|
||||
# For some reason spamming the cancel button is unreliable on the Leaf
|
||||
# We now cancel by making propilot think the seatbelt is unlatched,
|
||||
# this generates a beep and a warning message every time you disengage
|
||||
if self.CP.carFingerprint in (CAR.LEAF, CAR.LEAF_IC) and frame % 2 == 0:
|
||||
can_sends.append(nissancan.create_cancel_msg(self.packer, CS.cancel_msg, cruise_cancel))
|
||||
can_sends.append(nissancan.create_cancel_msg(self.packer, CS.cancel_msg, cruise_cancel))
|
||||
|
||||
can_sends.append(nissancan.create_steering_control(
|
||||
self.packer, apply_angle, frame, c.enabled, self.lkas_max_torque))
|
||||
|
|
|
@ -10,7 +10,7 @@ class CarInterface(CarInterfaceBase):
|
|||
self.cp_adas = self.CS.get_adas_can_parser(CP)
|
||||
|
||||
@staticmethod
|
||||
def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None):
|
||||
def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None, disable_radar=False):
|
||||
|
||||
ret = CarInterfaceBase.get_std_params(candidate, fingerprint)
|
||||
ret.carName = "nissan"
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
from typing import Dict, List, Union
|
||||
|
||||
from selfdrive.car import dbc_dict
|
||||
from selfdrive.car.docs_definitions import CarInfo
|
||||
from cereal import car
|
||||
Ecu = car.CarParams.Ecu
|
||||
|
||||
|
@ -10,6 +13,7 @@ class CarControllerParams:
|
|||
LKAS_MAX_TORQUE = 1 # A value of 1 is easy to overpower
|
||||
STEER_THRESHOLD = 1.0
|
||||
|
||||
|
||||
class CAR:
|
||||
XTRAIL = "NISSAN X-TRAIL 2017"
|
||||
LEAF = "NISSAN LEAF 2018"
|
||||
|
@ -20,6 +24,13 @@ class CAR:
|
|||
ALTIMA = "NISSAN ALTIMA 2020"
|
||||
|
||||
|
||||
CAR_INFO: Dict[str, Union[CarInfo, List[CarInfo]]] = {
|
||||
CAR.XTRAIL: CarInfo("Nissan X-Trail 2017", "ProPILOT"),
|
||||
CAR.LEAF: CarInfo("Nissan Leaf 2018-22", "ProPILOT"),
|
||||
CAR.ROGUE: CarInfo("Nissan Rogue 2018-20", "ProPILOT"),
|
||||
CAR.ALTIMA: CarInfo("Nissan Altima 2019-20", "ProPILOT"),
|
||||
}
|
||||
|
||||
FINGERPRINTS = {
|
||||
CAR.XTRAIL: [
|
||||
{
|
||||
|
|
|
@ -6,6 +6,7 @@ from opendbc.can.packer import CANPacker
|
|||
|
||||
class CarController():
|
||||
def __init__(self, dbc_name, CP, VM):
|
||||
self.CP = CP
|
||||
self.apply_steer_last = 0
|
||||
self.es_distance_cnt = -1
|
||||
self.es_lkas_cnt = -1
|
||||
|
@ -33,7 +34,7 @@ class CarController():
|
|||
if not c.latActive:
|
||||
apply_steer = 0
|
||||
|
||||
if CS.CP.carFingerprint in PREGLOBAL_CARS:
|
||||
if self.CP.carFingerprint in PREGLOBAL_CARS:
|
||||
can_sends.append(subarucan.create_preglobal_steering_control(self.packer, apply_steer, frame, self.p.STEER_STEP))
|
||||
else:
|
||||
can_sends.append(subarucan.create_steering_control(self.packer, apply_steer, frame, self.p.STEER_STEP))
|
||||
|
@ -43,7 +44,7 @@ class CarController():
|
|||
|
||||
# *** alerts and pcm cancel ***
|
||||
|
||||
if CS.CP.carFingerprint in PREGLOBAL_CARS:
|
||||
if self.CP.carFingerprint in PREGLOBAL_CARS:
|
||||
if self.es_distance_cnt != CS.es_distance_msg["Counter"]:
|
||||
# 1 = main, 2 = set shallow, 3 = set deep, 4 = resume shallow, 5 = resume deep
|
||||
# disengage ACC when OP is disengaged
|
||||
|
|
|
@ -7,7 +7,7 @@ from selfdrive.car.interfaces import CarInterfaceBase
|
|||
class CarInterface(CarInterfaceBase):
|
||||
|
||||
@staticmethod
|
||||
def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None):
|
||||
def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None, disable_radar=False):
|
||||
ret = CarInterfaceBase.get_std_params(candidate, fingerprint)
|
||||
|
||||
ret.carName = "subaru"
|
||||
|
|
|
@ -54,7 +54,7 @@ def create_es_lkas(packer, es_lkas_msg, enabled, visual_alert, left_line, right_
|
|||
values["LKAS_ACTIVE"] = 1 # Show LKAS lane lines
|
||||
values["LKAS_Dash_State"] = 2 # Green enabled indicator
|
||||
else:
|
||||
values["LKAS_Dash_State"] = 0 # LKAS Not enabled
|
||||
values["LKAS_Dash_State"] = 0 # LKAS Not enabled
|
||||
|
||||
values["LKAS_Left_Line_Visible"] = int(left_line)
|
||||
values["LKAS_Right_Line_Visible"] = int(right_line)
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
from typing import Dict, List, Union
|
||||
|
||||
from selfdrive.car import dbc_dict
|
||||
from selfdrive.car.docs_definitions import CarInfo
|
||||
from cereal import car
|
||||
Ecu = car.CarParams.Ecu
|
||||
|
||||
|
@ -15,6 +18,7 @@ class CarControllerParams:
|
|||
self.STEER_DRIVER_MULTIPLIER = 10 # weight driver torque heavily
|
||||
self.STEER_DRIVER_FACTOR = 1 # from dbc
|
||||
|
||||
|
||||
class CAR:
|
||||
ASCENT = "SUBARU ASCENT LIMITED 2019"
|
||||
IMPREZA = "SUBARU IMPREZA LIMITED 2019"
|
||||
|
@ -25,6 +29,21 @@ class CAR:
|
|||
OUTBACK_PREGLOBAL = "SUBARU OUTBACK 2015 - 2017"
|
||||
OUTBACK_PREGLOBAL_2018 = "SUBARU OUTBACK 2018 - 2019"
|
||||
|
||||
|
||||
CAR_INFO: Dict[str, Union[CarInfo, List[CarInfo]]] = {
|
||||
CAR.ASCENT: CarInfo("Subaru Ascent 2019", "EyeSight"),
|
||||
CAR.IMPREZA: [
|
||||
CarInfo("Subaru Impreza 2017-19", "EyeSight"),
|
||||
CarInfo("Subaru Crosstrek 2018-20", "EyeSight"),
|
||||
],
|
||||
CAR.FORESTER: CarInfo("Subaru Forester 2019-21", "EyeSight"),
|
||||
CAR.FORESTER_PREGLOBAL: CarInfo("Subaru Forester 2017-18", "EyeSight"),
|
||||
CAR.LEGACY_PREGLOBAL: CarInfo("Subaru Legacy 2015-18", "EyeSight"),
|
||||
CAR.OUTBACK_PREGLOBAL: CarInfo("Subaru Outback 2015-17", "EyeSight"),
|
||||
CAR.OUTBACK_PREGLOBAL_2018: CarInfo("Subaru Outback 2018-19", "EyeSight"),
|
||||
}
|
||||
|
||||
|
||||
FINGERPRINTS = {
|
||||
CAR.IMPREZA_2020: [{
|
||||
2: 8, 64: 8, 65: 8, 72: 8, 73: 8, 280: 8, 281: 8, 282: 8, 290: 8, 312: 8, 313: 8, 314: 8, 315: 8, 316: 8, 326: 8, 372: 8, 544: 8, 545: 8, 546: 8, 552: 8, 554: 8, 557: 8, 576: 8, 577: 8, 722: 8, 801: 8, 802: 8, 803: 8, 805: 8, 808: 8, 816: 8, 826: 8, 837: 8, 838: 8, 839: 8, 842: 8, 912: 8, 915: 8, 940: 8, 1617: 8, 1632: 8, 1650: 8, 1677: 8, 1697: 8, 1722: 8, 1743: 8, 1759: 8, 1786: 5, 1787: 5, 1788: 8, 1809: 8, 1813: 8, 1817: 8, 1821: 8, 1840: 8, 1848: 8, 1924: 8, 1932: 8, 1952: 8, 1960: 8, 1968: 8, 1976: 8, 2015: 8, 2016: 8, 2024: 8
|
||||
|
|
|
@ -44,7 +44,7 @@ class CarState(CarStateBase):
|
|||
ret.steeringTorque = -cp.vl["EPAS_sysStatus"]["EPAS_torsionBarTorque"]
|
||||
ret.steeringPressed = (self.hands_on_level > 0)
|
||||
ret.steerFaultPermanent = steer_status == "EAC_FAULT"
|
||||
ret.steerFaultTemporary = self.steer_warning != "EAC_ERROR_IDLE"
|
||||
ret.steerFaultTemporary = (self.steer_warning not in ("EAC_ERROR_IDLE", "EAC_ERROR_HANDS_ON"))
|
||||
|
||||
# Cruise state
|
||||
cruise_state = self.can_define.dv["DI_state"]["DI_cruiseState"].get(int(cp.vl["DI_state"]["DI_cruiseState"]), None)
|
||||
|
|