diff --git a/README.md b/README.md
index 7d29096bd5..66b659686f 100644
--- a/README.md
+++ b/README.md
@@ -158,6 +158,7 @@ Community Maintained Cars and Features
| Nissan | Rogue 20192 | Propilot | Stock | 0mph | 0mph |
| Nissan | X-Trail 20172 | Propilot | Stock | 0mph | 0mph |
| Subaru | Crosstrek 2018-19 | EyeSight | Stock | 0mph | 0mph |
+| Subaru | Forester 2019 | EyeSight | Stock | 0mph | 0mph |
| Subaru | Impreza 2017-20 | EyeSight | Stock | 0mph | 0mph |
| Volkswagen| Golf 2015-19 | Driver Assistance | Stock | 0mph | 0mph |
diff --git a/selfdrive/car/subaru/carstate.py b/selfdrive/car/subaru/carstate.py
index 41bc129ebb..a1dc3b5cc2 100644
--- a/selfdrive/car/subaru/carstate.py
+++ b/selfdrive/car/subaru/carstate.py
@@ -51,8 +51,8 @@ class CarState(CarStateBase):
ret.cruiseState.enabled = cp.vl["CruiseControl"]['Cruise_Activated'] != 0
ret.cruiseState.available = cp.vl["CruiseControl"]['Cruise_On'] != 0
ret.cruiseState.speed = cp_cam.vl["ES_DashStatus"]['Cruise_Set_Speed'] * CV.KPH_TO_MS
- # 1 = imperial, 6 = metric
- if cp.vl["Dash_State"]['Units'] == 1:
+ # EDM Impreza: 1 = mph, UDM Forester: 7 = mph
+ if cp.vl["Dash_State"]['Units'] in [1, 7]:
ret.cruiseState.speed *= CV.MPH_TO_KPH
ret.seatbeltUnlatched = cp.vl["Dashlights"]['SEATBELT_FL'] == 1
diff --git a/selfdrive/car/subaru/interface.py b/selfdrive/car/subaru/interface.py
index a0cfdd0102..3bc13c76e1 100644
--- a/selfdrive/car/subaru/interface.py
+++ b/selfdrive/car/subaru/interface.py
@@ -28,7 +28,7 @@ class CarInterface(CarInterfaceBase):
ret.steerRateCost = 0.7
ret.steerLimitTimer = 0.4
- if candidate in [CAR.IMPREZA]:
+ if candidate == CAR.IMPREZA:
ret.mass = 1568. + STD_CARGO_KG
ret.wheelbase = 2.67
ret.centerToFront = ret.wheelbase * 0.5
@@ -38,6 +38,16 @@ class CarInterface(CarInterfaceBase):
ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0., 20.], [0., 20.]]
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.2, 0.3], [0.02, 0.03]]
+ if candidate == CAR.FORESTER:
+ ret.mass = 1568. + STD_CARGO_KG
+ ret.wheelbase = 2.67
+ ret.centerToFront = ret.wheelbase * 0.5
+ ret.steerRatio = 17 # learned, 14 stock
+ ret.steerActuatorDelay = 0.1
+ ret.lateralTuning.pid.kf = 0.000038
+ ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0., 14., 23.], [0., 14., 23.]]
+ ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.01, 0.065, 0.2], [0.001, 0.015, 0.025]]
+
# TODO: get actual value, for now starting with reasonable value for
# civic and scaling by mass and wheelbase
ret.rotationalInertia = scale_rot_inertia(ret.mass, ret.wheelbase)
diff --git a/selfdrive/car/subaru/values.py b/selfdrive/car/subaru/values.py
index 8d50b36ab4..791edcf6db 100644
--- a/selfdrive/car/subaru/values.py
+++ b/selfdrive/car/subaru/values.py
@@ -6,6 +6,7 @@ Ecu = car.CarParams.Ecu
class CAR:
IMPREZA = "SUBARU IMPREZA LIMITED 2019"
+ FORESTER = "SUBARU FORESTER 2019"
FINGERPRINTS = {
CAR.IMPREZA: [{
@@ -15,10 +16,19 @@ FINGERPRINTS = {
{
2: 8, 64: 8, 65: 8, 72: 8, 73: 8, 256: 8, 280: 8, 281: 8, 290: 8, 312: 8, 313: 8, 314: 8, 315: 8, 316: 8, 326: 8, 372: 8, 544: 8, 545: 8, 546: 8, 554: 8, 557: 8, 576: 8, 577: 8, 722: 8, 801: 8, 802: 8, 805: 8, 808: 8, 811: 8, 826: 8, 837: 8, 838: 8, 839: 8, 842: 8, 912: 8, 915: 8, 940: 8, 1614: 8, 1617: 8, 1632: 8, 1650: 8, 1657: 8, 1658: 8, 1677: 8, 1697: 8, 1759: 8, 1786: 5, 1787: 5, 1788: 8
}],
+ CAR.FORESTER: [{
+ # Forester Sport 2019
+ 2: 8, 64: 8, 65: 8, 72: 8, 73: 8, 280: 8, 281: 8, 282: 8, 312: 8, 313: 8, 314: 8, 315: 8, 316: 8, 326: 8, 372: 8, 552: 8, 557: 8, 576: 8, 577: 8, 722: 8, 808: 8, 811: 8, 816: 8, 826: 8, 837: 8, 838: 8, 839: 8, 842: 8, 912: 8, 915: 8, 940: 8, 1614: 8, 1617: 8, 1632: 8, 1650: 8, 1651: 8, 1657: 8, 1658: 8, 1677: 8, 1697: 8, 1698: 8, 1722: 8, 1743: 8, 1759: 8, 1787: 5, 1788: 8, 1809: 8, 1813: 8, 1817: 8, 1821: 8, 1840: 8, 1848: 8, 1924: 8, 1932: 8, 1952: 8, 1960: 8
+ },
+ # Forester 2019
+ {
+ 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, 554: 8, 557: 8, 576: 8, 577: 8, 722: 8, 801: 8, 802: 8, 803: 8, 805: 8, 808: 8, 811: 8, 826: 8, 837: 8, 838: 8, 839: 8, 842: 8, 912: 8, 915: 8, 940: 8, 1614: 8, 1617: 8, 1632: 8, 1650: 8, 1651: 8, 1657: 8, 1658: 8, 1677: 8, 1722: 8, 1759: 8, 1787: 5, 1788: 8
+ }],
}
STEER_THRESHOLD = {
CAR.IMPREZA: 80,
+ CAR.FORESTER: 80,
}
ECU_FINGERPRINT = {
@@ -27,4 +37,5 @@ ECU_FINGERPRINT = {
DBC = {
CAR.IMPREZA: dbc_dict('subaru_global_2017', None),
+ CAR.FORESTER: dbc_dict('subaru_global_2017', None),
}
diff --git a/selfdrive/test/test_car_models.py b/selfdrive/test/test_car_models.py
index 0a6cc6af4d..7c6e7b3303 100755
--- a/selfdrive/test/test_car_models.py
+++ b/selfdrive/test/test_car_models.py
@@ -356,6 +356,10 @@ routes = {
'carFingerprint': VOLKSWAGEN.GOLF,
'enableCamera': True,
},
+ "c321c6b697c5a5ff|2020-06-23--11-04-33": {
+ 'carFingerprint': SUBARU.FORESTER,
+ 'enableCamera': True,
+ },
"791340bc01ed993d|2019-03-10--16-28-08": {
'carFingerprint': SUBARU.IMPREZA,
'enableCamera': True,