diff --git a/README.md b/README.md
index f8052b285..a82b98dbc 100644
--- a/README.md
+++ b/README.md
@@ -68,6 +68,7 @@ Supported Cars
| Cadillac3 | ATS 2018 | Adaptive Cruise | Yes | Yes | 0mph | 7mph | Custom7|
| Chrysler | Pacifica 2018 | Adaptive Cruise | Yes | Stock | 0mph | 9mph | FCA |
| Chrysler | Pacifica Hybrid 2017-18 | Adaptive Cruise | Yes | Stock | 0mph | 9mph | FCA |
+| Chrysler | Pacifica Hybrid 2019 | Adaptive Cruise | Yes | Stock | 0mph | 39mph | FCA |
| GMC3 | Acadia Denali 2018 | Adaptive Cruise | Yes | Yes | 0mph | 7mph | Custom7|
| Holden3 | Astra 2017 | Adaptive Cruise | Yes | Yes | 0mph | 7mph | Custom7|
| Honda | Accord 2018 | All | Yes | Stock | 0mph | 3mph | Bosch |
@@ -76,6 +77,7 @@ Supported Cars
| Honda | Civic Hatchback 2017-19 | Honda Sensing | Yes | Stock | 0mph | 12mph | Bosch |
| Honda | CR-V 2015-16 | Touring | Yes | Yes | 25mph1| 12mph | Nidec |
| Honda | CR-V 2017-18 | Honda Sensing | Yes | Stock | 0mph | 12mph | Bosch |
+| Honda | CR-V Hybrid 2019 | All | Yes | Stock | 0mph | 12mph | Bosch |
| Honda | Odyssey 2017-19 | Honda Sensing | Yes | Yes | 25mph1| 0mph | Inverted Nidec |
| Honda | Pilot 2016-18 | Honda Sensing | Yes | Yes | 25mph1| 12mph | Nidec |
| Honda | Pilot 2019 | All | Yes | Yes | 25mph1| 12mph | Inverted Nidec |
@@ -83,7 +85,8 @@ Supported Cars
| Hyundai | Santa Fe 2019 | All | Yes | Stock | 0mph | 0mph | Custom6|
| Hyundai | Elantra 2017 | SCC + LKAS | Yes | Stock | 19mph | 34mph | Custom6|
| Hyundai | Genesis 2018 | All | Yes | Stock | 19mph | 34mph | Custom6|
-| Jeep | Grand Cherokee 2017-19 | Adaptive Cruise | Yes | Stock | 0mph | 9mph | FCA |
+| Jeep | Grand Cherokee 2017-18 | Adaptive Cruise | Yes | Stock | 0mph | 9mph | FCA |
+| Jeep | Grand Cherokee 2019 | Adaptive Cruise | Yes | Stock | 0mph | 39mph | FCA |
| Kia | Optima 2019 | SCC + LKAS | Yes | Stock | 0mph | 0mph | Custom6|
| Kia | Sorento 2018 | All | Yes | Stock | 0mph | 0mph | Custom6|
| Kia | Stinger 2018 | SCC + LKAS | Yes | Stock | 0mph | 0mph | Custom6|
diff --git a/common/transformations/camera.py b/common/transformations/camera.py
index 42432a7bb..367c0879a 100644
--- a/common/transformations/camera.py
+++ b/common/transformations/camera.py
@@ -64,7 +64,7 @@ def normalize(img_pts, intrinsics=eon_intrinsics):
input_shape = img_pts.shape
img_pts = np.atleast_2d(img_pts)
img_pts = np.hstack((img_pts, np.ones((img_pts.shape[0],1))))
- img_pts_normalized = intrinsics_inv.dot(img_pts.T).T
+ img_pts_normalized = img_pts.dot(intrinsics_inv.T)
img_pts_normalized[(img_pts < 0).any(axis=1)] = np.nan
return img_pts_normalized[:,:2].reshape(input_shape)
@@ -76,7 +76,7 @@ def denormalize(img_pts, intrinsics=eon_intrinsics):
input_shape = img_pts.shape
img_pts = np.atleast_2d(img_pts)
img_pts = np.hstack((img_pts, np.ones((img_pts.shape[0],1))))
- img_pts_denormalized = intrinsics.dot(img_pts.T).T
+ img_pts_denormalized = img_pts.dot(intrinsics.T)
img_pts_denormalized[img_pts_denormalized[:,0] > W] = np.nan
img_pts_denormalized[img_pts_denormalized[:,0] < 0] = np.nan
img_pts_denormalized[img_pts_denormalized[:,1] > H] = np.nan
diff --git a/panda/board/safety/safety_chrysler.h b/panda/board/safety/safety_chrysler.h
index b1c6a743f..4af588401 100644
--- a/panda/board/safety/safety_chrysler.h
+++ b/panda/board/safety/safety_chrysler.h
@@ -5,7 +5,7 @@ const int CHRYSLER_MAX_RATE_UP = 3;
const int CHRYSLER_MAX_RATE_DOWN = 3;
const int CHRYSLER_MAX_TORQUE_ERROR = 80; // max torque cmd in excess of torque motor
-int chrysler_camera_detected = 0;
+int chrysler_camera_detected = 0; // is giraffe switch 2 high?
int chrysler_rt_torque_last = 0;
int chrysler_desired_torque_last = 0;
int chrysler_cruise_engaged_last = 0;
@@ -125,12 +125,29 @@ static int chrysler_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
return true;
}
+static void chrysler_init(int16_t param) {
+ chrysler_camera_detected = 0;
+}
+
+static int chrysler_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
+ int32_t addr = to_fwd->RIR >> 21;
+ // forward CAN 0 -> 2 so stock LKAS camera sees messages
+ if (bus_num == 0 && !chrysler_camera_detected) {
+ return 2;
+ }
+ // forward all messages from camera except LKAS_COMMAND and LKAS_HUD
+ if (bus_num == 2 && !chrysler_camera_detected && addr != 658 && addr != 678) {
+ return 0;
+ }
+ return -1; // do not forward
+}
+
const safety_hooks chrysler_hooks = {
- .init = nooutput_init,
+ .init = chrysler_init,
.rx = chrysler_rx_hook,
.tx = chrysler_tx_hook,
.tx_lin = nooutput_tx_lin_hook,
.ignition = default_ign_hook,
- .fwd = nooutput_fwd_hook,
+ .fwd = chrysler_fwd_hook,
};
diff --git a/selfdrive/car/chrysler/carcontroller.py b/selfdrive/car/chrysler/carcontroller.py
index 83c2ecc32..7db36634c 100644
--- a/selfdrive/car/chrysler/carcontroller.py
+++ b/selfdrive/car/chrysler/carcontroller.py
@@ -2,9 +2,9 @@ from cereal import car
from selfdrive.boardd.boardd import can_list_to_can_capnp
from selfdrive.car import apply_toyota_steer_torque_limits
from selfdrive.car.chrysler.chryslercan import create_lkas_hud, create_lkas_command, \
- create_wheel_buttons, create_lkas_heartbit, \
+ create_wheel_buttons, \
create_chimes
-from selfdrive.car.chrysler.values import ECU
+from selfdrive.car.chrysler.values import ECU, CAR
from selfdrive.can.packer import CANPacker
AudibleAlert = car.CarControl.HUDControl.AudibleAlert
@@ -29,6 +29,7 @@ class CarController(object):
self.car_fingerprint = car_fingerprint
self.alert_active = False
self.send_chime = False
+ self.gone_fast_yet = False
self.fake_ecus = set()
if enable_camera:
@@ -39,8 +40,8 @@ class CarController(object):
def update(self, sendcan, enabled, CS, frame, actuators,
pcm_cancel_cmd, hud_alert, audible_alert):
-
# this seems needed to avoid steering faults and to force the sync with the EPS counter
+ frame = CS.lkas_counter
if self.prev_frame == frame:
return
@@ -51,6 +52,11 @@ class CarController(object):
CS.steer_torque_motor, SteerLimitParams)
moving_fast = CS.v_ego > CS.CP.minSteerSpeed # for status message
+ if CS.v_ego > (CS.CP.minSteerSpeed - 0.5): # for command high bit
+ self.gone_fast_yet = True
+ elif self.car_fingerprint in (CAR.PACIFICA_2019_HYBRID, CAR.JEEP_CHEROKEE_2019):
+ if CS.v_ego < (CS.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
if not lkas_active:
@@ -76,18 +82,17 @@ class CarController(object):
new_msg = create_wheel_buttons(self.ccframe)
can_sends.append(new_msg)
+ # LKAS_HEARTBIT is forwarded by Panda so no need to send it here.
# frame is 100Hz (0.01s period)
- if (self.ccframe % 10 == 0): # 0.1s period
- new_msg = create_lkas_heartbit(self.car_fingerprint)
- can_sends.append(new_msg)
-
if (self.ccframe % 25 == 0): # 0.25s period
- new_msg = create_lkas_hud(self.packer, CS.gear_shifter, lkas_active, hud_alert, self.car_fingerprint,
- self.hud_count)
- can_sends.append(new_msg)
- self.hud_count += 1
+ if (CS.lkas_car_model != -1):
+ new_msg = create_lkas_hud(
+ self.packer, CS.gear_shifter, lkas_active, hud_alert,
+ self.hud_count, CS.lkas_car_model)
+ can_sends.append(new_msg)
+ self.hud_count += 1
- new_msg = create_lkas_command(self.packer, int(apply_steer), frame)
+ new_msg = create_lkas_command(self.packer, int(apply_steer), self.gone_fast_yet, frame)
can_sends.append(new_msg)
self.ccframe += 1
diff --git a/selfdrive/car/chrysler/carstate.py b/selfdrive/car/chrysler/carstate.py
index a6344027d..fd3c081f3 100644
--- a/selfdrive/car/chrysler/carstate.py
+++ b/selfdrive/car/chrysler/carstate.py
@@ -63,6 +63,18 @@ def get_can_parser(CP):
return CANParser(DBC[CP.carFingerprint]['pt'], signals, checks, 0)
+def get_camera_parser(CP):
+ signals = [
+ # sig_name, sig_address, default
+ # TODO read in all the other values
+ ("COUNTER", "LKAS_COMMAND", -1),
+ ("CAR_MODEL", "LKAS_HUD", -1),
+ ("LKAS_STATUS_OK", "LKAS_HEARTBIT", -1)
+ ]
+ checks = []
+
+ return CANParser(DBC[CP.carFingerprint]['pt'], signals, checks, 2)
+
class CarState(object):
def __init__(self, CP):
@@ -85,7 +97,7 @@ class CarState(object):
self.v_ego = 0.0
- def update(self, cp):
+ def update(self, cp, cp_cam):
# copy can_valid
self.can_valid = cp.can_valid
@@ -142,3 +154,7 @@ class CarState(object):
self.pcm_acc_status = self.main_on
self.generic_toggle = bool(cp.vl["STEERING_LEVERS"]['HIGH_BEAM_FLASH'])
+
+ self.lkas_counter = cp_cam.vl["LKAS_COMMAND"]['COUNTER']
+ self.lkas_car_model = cp_cam.vl["LKAS_HUD"]['CAR_MODEL']
+ self.lkas_status_ok = cp_cam.vl["LKAS_HEARTBIT"]['LKAS_STATUS_OK']
diff --git a/selfdrive/car/chrysler/chryslercan.py b/selfdrive/car/chrysler/chryslercan.py
index e17ee3623..53c1eb662 100644
--- a/selfdrive/car/chrysler/chryslercan.py
+++ b/selfdrive/car/chrysler/chryslercan.py
@@ -5,14 +5,6 @@ from selfdrive.car.chrysler.values import CAR
VisualAlert = car.CarControl.HUDControl.VisualAlert
AudibleAlert = car.CarControl.HUDControl.AudibleAlert
-MODEL_TO_CONSTANT = {
- CAR.PACIFICA_2017_HYBRID: 0,
- CAR.PACIFICA_2018: 0x64,
- CAR.PACIFICA_2018_HYBRID: 0xa8,
- CAR.PACIFICA_2019_HYBRID: 0x68,
- CAR.JEEP_CHEROKEE: 0xa4,
- }
-
def calc_checksum(data):
"""This function does not want the checksum byte in the input data.
@@ -53,28 +45,26 @@ def calc_checksum(data):
def make_can_msg(addr, dat):
return [addr, 0, dat, 0]
-def create_lkas_heartbit(car_fingerprint):
- # LKAS_HEARTBIT (729) Lane-keeping heartbeat.
- msg = '0000000820'.decode('hex') # 2017
- return make_can_msg(0x2d9, msg)
+def create_lkas_heartbit(packer, lkas_status_ok):
+ # LKAS_HEARTBIT 0x2d9 (729) Lane-keeping heartbeat.
+ values = {
+ "LKAS_STATUS_OK": lkas_status_ok
+ }
+ return packer.make_can_msg("LKAS_HEARTBIT", 0, values)
-def create_lkas_hud(packer, gear, lkas_active, hud_alert, car_fingerprint, hud_count):
+def create_lkas_hud(packer, gear, lkas_active, hud_alert, hud_count, lkas_car_model):
# LKAS_HUD 0x2a6 (678) Controls what lane-keeping icon is displayed.
if hud_alert == VisualAlert.steerRequired:
msg = '0000000300000000'.decode('hex')
return make_can_msg(0x2a6, msg)
- color = 0 # default values are for park or neutral
- lines = 0
+ color = 1 # default values are for park or neutral in 2017 are 0 0, but trying 1 1 for 2019
+ lines = 1
alerts = 0
- if hud_count < (3 *4): # first 3 seconds, 4Hz
- lines = 1
+ if hud_count < (1 *4): # first 3 seconds, 4Hz
alerts = 1
- elif hud_count < (6 * 4): # next 3 seconds, 4Hz
- lines = 1
- alerts = 0
# CAR.PACIFICA_2018_HYBRID and CAR.PACIFICA_2019_HYBRID
# had color = 1 and lines = 1 but trying 2017 hybrid style for now.
if gear in ('drive', 'reverse', 'low'):
@@ -87,7 +77,7 @@ def create_lkas_hud(packer, gear, lkas_active, hud_alert, car_fingerprint, hud_c
values = {
"LKAS_ICON_COLOR": color, # byte 0, last 2 bits
- "CAR_MODEL": MODEL_TO_CONSTANT[car_fingerprint], # byte 1
+ "CAR_MODEL": lkas_car_model, # byte 1
"LKAS_LANE_LINES": lines, # byte 2, last 4 bits
"LKAS_ALERTS": alerts, # byte 3, last 4 bits
}
@@ -95,11 +85,11 @@ def create_lkas_hud(packer, gear, lkas_active, hud_alert, car_fingerprint, hud_c
return packer.make_can_msg("LKAS_HUD", 0, values) # 0x2a6
-def create_lkas_command(packer, apply_steer, frame):
- # LKAS_COMMAND (658) Lane-keeping signal to turn the wheel.
+def create_lkas_command(packer, apply_steer, moving_fast, frame):
+ # LKAS_COMMAND 0x292 (658) Lane-keeping signal to turn the wheel.
values = {
"LKAS_STEERING_TORQUE": apply_steer,
- "LKAS_HIGH_TORQUE": 1,
+ "LKAS_HIGH_TORQUE": int(moving_fast),
"COUNTER": frame % 0x10,
}
diff --git a/selfdrive/car/chrysler/chryslercan_test.py b/selfdrive/car/chrysler/chryslercan_test.py
index 2edfff9f2..b4ca4a91f 100644
--- a/selfdrive/car/chrysler/chryslercan_test.py
+++ b/selfdrive/car/chrysler/chryslercan_test.py
@@ -1,5 +1,6 @@
import chryslercan
from values import CAR
+from carcontroller import CarController
from selfdrive.can.packer import CANPacker
from cereal import car
@@ -16,32 +17,52 @@ class TestChryslerCan(unittest.TestCase):
self.assertEqual(0xcc, chryslercan.calc_checksum([0x14, 0, 0, 0, 0x20]))
def test_heartbit(self):
+ packer = CANPacker('chrysler_pacifica_2017_hybrid')
self.assertEqual(
[0x2d9, 0, '0000000820'.decode('hex'), 0],
- chryslercan.create_lkas_heartbit(CAR.PACIFICA_2017_HYBRID))
+ chryslercan.create_lkas_heartbit(packer, 0x820))
def test_hud(self):
packer = CANPacker('chrysler_pacifica_2017_hybrid')
self.assertEqual(
- [0x2a6, 0, '0000010100000000'.decode('hex'), 0],
- chryslercan.create_lkas_hud(packer,
- 'park', False, False, CAR.PACIFICA_2017_HYBRID, 1))
+ [0x2a6, 0, '0100010100000000'.decode('hex'), 0],
+ chryslercan.create_lkas_hud(
+ packer,
+ 'park', False, False, 1, 0))
self.assertEqual(
- [0x2a6, 0, '0000010000000000'.decode('hex'), 0],
- chryslercan.create_lkas_hud(packer,
- 'park', False, False, CAR.PACIFICA_2017_HYBRID, 5*4))
+ [0x2a6, 0, '0100010000000000'.decode('hex'), 0],
+ chryslercan.create_lkas_hud(
+ packer,
+ 'park', False, False, 5*4, 0))
self.assertEqual(
- [0x2a6, 0, '0000000000000000'.decode('hex'), 0],
- chryslercan.create_lkas_hud(packer,
- 'park', False, False, CAR.PACIFICA_2017_HYBRID, 99999))
+ [0x2a6, 0, '0100010000000000'.decode('hex'), 0],
+ chryslercan.create_lkas_hud(
+ packer,
+ 'park', False, False, 99999, 0))
self.assertEqual(
[0x2a6, 0, '0200060000000000'.decode('hex'), 0],
- chryslercan.create_lkas_hud(packer,
- 'drive', True, False, CAR.PACIFICA_2017_HYBRID, 99999))
+ chryslercan.create_lkas_hud(
+ packer,
+ 'drive', True, False, 99999, 0))
self.assertEqual(
[0x2a6, 0, '0264060000000000'.decode('hex'), 0],
- chryslercan.create_lkas_hud(packer,
- 'drive', True, False, CAR.PACIFICA_2018, 99999))
+ chryslercan.create_lkas_hud(
+ packer,
+ 'drive', True, False, 99999, 0x64))
+
+ def test_command(self):
+ packer = CANPacker('chrysler_pacifica_2017_hybrid')
+ self.assertEqual(
+ [0x292, 0, '140000001086'.decode('hex'), 0],
+ chryslercan.create_lkas_command(
+ packer,
+ 0, True, 1))
+ self.assertEqual(
+ [0x292, 0, '040000008083'.decode('hex'), 0],
+ chryslercan.create_lkas_command(
+ packer,
+ 0, False, 8))
+
if __name__ == '__main__':
unittest.main()
diff --git a/selfdrive/car/chrysler/interface.py b/selfdrive/car/chrysler/interface.py
index ac797616b..7e96ebc2b 100755
--- a/selfdrive/car/chrysler/interface.py
+++ b/selfdrive/car/chrysler/interface.py
@@ -4,7 +4,7 @@ from cereal import car
from selfdrive.config import Conversions as CV
from selfdrive.controls.lib.drive_helpers import EventTypes as ET, create_event
from selfdrive.controls.lib.vehicle_model import VehicleModel
-from selfdrive.car.chrysler.carstate import CarState, get_can_parser
+from selfdrive.car.chrysler.carstate import CarState, get_can_parser, get_camera_parser
from selfdrive.car.chrysler.values import ECU, check_ecu_msgs, CAR
try:
@@ -27,8 +27,8 @@ class CarInterface(object):
# *** init the major players ***
self.CS = CarState(CP)
-
self.cp = get_can_parser(CP)
+ self.cp_cam = get_camera_parser(CP)
# sending if read only is False
if sendcan is not None:
@@ -79,7 +79,7 @@ class CarInterface(object):
ret.steerActuatorDelay = 0.1
ret.steerRateCost = 0.7
- if candidate == CAR.JEEP_CHEROKEE:
+ if candidate in (CAR.JEEP_CHEROKEE, CAR.JEEP_CHEROKEE_2019):
ret.wheelbase = 2.91 # in meters
ret.steerRatio = 12.7
ret.steerActuatorDelay = 0.2 # in seconds
@@ -91,6 +91,9 @@ class CarInterface(object):
ret.minSteerSpeed = 3.8 # m/s
ret.minEnableSpeed = -1. # enable is done by stock ACC, so ignore this
+ if candidate in (CAR.PACIFICA_2019_HYBRID, CAR.JEEP_CHEROKEE_2019):
+ ret.minSteerSpeed = 17.5 # m/s 17 on the way up, 13 on the way down once engaged.
+ # TODO allow 2019 cars to steer down to 13 m/s if already engaged.
centerToRear = ret.wheelbase - ret.centerToFront
# TODO: get actual value, for now starting with reasonable value for
@@ -137,10 +140,9 @@ class CarInterface(object):
def update(self, c):
# ******************* do can recv *******************
canMonoTimes = []
-
self.cp.update(int(sec_since_boot() * 1e9), False)
-
- self.CS.update(self.cp)
+ self.cp_cam.update(int(sec_since_boot() * 1e9), False)
+ self.CS.update(self.cp, self.cp_cam)
# create message
ret = car.CarState.new_message()
@@ -208,6 +210,8 @@ class CarInterface(object):
self.low_speed_alert = (ret.vEgo < self.CP.minSteerSpeed)
ret.genericToggle = self.CS.generic_toggle
+ #ret.lkasCounter = self.CS.lkas_counter
+ #ret.lkasCarModel = self.CS.lkas_car_model
# events
events = []
diff --git a/selfdrive/car/chrysler/values.py b/selfdrive/car/chrysler/values.py
index 6e3a24b8f..4636b89a3 100644
--- a/selfdrive/car/chrysler/values.py
+++ b/selfdrive/car/chrysler/values.py
@@ -6,6 +6,7 @@ class CAR:
PACIFICA_2019_HYBRID = "CHRYSLER PACIFICA HYBRID 2019"
PACIFICA_2018 = "CHRYSLER PACIFICA 2018"
JEEP_CHEROKEE = "JEEP GRAND CHEROKEE V6 2018" # Also covers Tailhawk 2017.
+ JEEP_CHEROKEE_2019 = "JEEP GRAND CHEROKEE 2019"
# Unique can messages:
# Only the hybrids have 270: 8
@@ -24,11 +25,9 @@ FINGERPRINTS = {
],
CAR.PACIFICA_2018: [
{55: 8, 257: 5, 258: 8, 264: 8, 268: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 292: 8, 294: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 368: 8, 376: 3, 384: 8, 388: 4, 416: 7, 448: 6, 456: 4, 464: 8, 469: 8, 480: 8, 500: 8, 501: 8, 512: 8, 514: 8, 520: 8, 528: 8, 532: 8, 544: 8, 557: 8, 559: 8, 560: 4, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 624: 8, 625: 8, 632: 8, 639: 8, 658: 6, 660: 8, 669: 3, 671: 8, 672: 8, 678: 8, 680: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 729: 5, 736: 8, 746: 5, 752: 2, 760: 8, 764: 8, 766: 8, 770: 8, 773: 8, 779: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 832: 8, 838: 2, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 882: 8, 897: 8, 924: 8, 926: 3, 937: 8, 947: 8, 948: 8, 969: 4, 974: 5, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1098: 8, 1100: 8},
-
],
CAR.PACIFICA_2018_HYBRID: [
- {68: 8, 257: 5, 258: 8, 264: 8, 268: 8, 270: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 291: 8, 292: 8, 294: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 368: 8, 376: 3, 384: 8, 388: 4, 448: 6, 456: 4, 464: 8, 469: 8, 480: 8, 500: 8, 501: 8, 512: 8, 514: 8, 520: 8, 528: 8, 532: 8, 544: 8, 557: 8, 559: 8, 560: 4, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 624: 8, 625: 8, 632: 8, 639: 8, 653: 8, 654: 8, 655: 8, 660: 8, 669: 3, 671: 8, 672: 8, 680: 8, 701: 8, 704: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 736: 8, 737: 8, 746: 5, 760: 8, 764: 8, 766: 8, 770: 8, 773: 8, 779: 8, 782: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 832: 8, 838: 2, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 878: 8, 882: 8, 897: 8, 908: 8, 924: 8, 926: 3, 929: 8, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 958: 8, 959: 8, 969: 4, 974: 5, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1082: 8, 1083: 8, 1098: 8, 1100: 8},
- {168: 8, 257: 5, 258: 8, 264: 8, 268: 8, 270: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 291: 8, 292: 8, 294: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 368: 8, 376: 3, 384: 8, 388: 4, 448: 6, 456: 4, 464: 8, 469: 8, 480: 8, 500: 8, 501: 8, 512: 8, 514: 8, 520: 8, 528: 8, 532: 8, 544: 8, 557: 8, 559: 8, 560: 4, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 624: 8, 625: 8, 632: 8, 639: 8, 653: 8, 654: 8, 655: 8, 660: 8, 669: 3, 671: 8, 672: 8, 680: 8, 701: 8, 704: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 736: 8, 737: 8, 746: 5, 760: 8, 764: 8, 766: 8, 770: 8, 773: 8, 779: 8, 782: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 832: 8, 838: 2, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 878: 8, 882: 8, 897: 8, 908: 8, 924: 8, 926: 3, 929: 8, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 958: 8, 959: 8, 969: 4, 974: 5, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1082: 8, 1083: 8, 1098: 8, 1100: 8},
+ {68: 8, 168: 8, 257: 5, 258: 8, 264: 8, 268: 8, 270: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 291: 8, 292: 8, 294: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 368: 8, 376: 3, 384: 8, 388: 4, 448: 6, 456: 4, 464: 8, 469: 8, 480: 8, 500: 8, 501: 8, 512: 8, 514: 8, 520: 8, 528: 8, 532: 8, 544: 8, 557: 8, 559: 8, 560: 4, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 624: 8, 625: 8, 632: 8, 639: 8, 653: 8, 654: 8, 655: 8, 660: 8, 669: 3, 671: 8, 672: 8, 680: 8, 701: 8, 704: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 736: 8, 737: 8, 746: 5, 760: 8, 764: 8, 766: 8, 770: 8, 773: 8, 779: 8, 782: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 808: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 832: 8, 838: 2, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 878: 8, 882: 8, 897: 8, 908: 8, 924: 8, 926: 3, 929: 8, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 958: 8, 959: 8, 969: 4, 974: 5, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1082: 8, 1083: 8, 1098: 8, 1100: 8},
],
CAR.PACIFICA_2019_HYBRID: [
{168: 8, 257: 5, 258: 8, 264: 8, 268: 8, 270: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 291: 8, 292: 8, 294: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 368: 8, 376: 3, 384: 8, 388: 4, 448: 6, 456: 4, 464: 8, 469: 8, 480: 8, 500: 8, 501: 8, 512: 8, 514: 8, 515: 7, 516: 7, 517: 7, 518: 7, 520: 8, 528: 8, 532: 8, 542: 8, 544: 8, 557: 8, 559: 8, 560: 8, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 624: 8, 625: 8, 632: 8, 639: 8, 653: 8, 654: 8, 655: 8, 660: 8, 669: 3, 671: 8, 672: 8, 680: 8, 701: 8, 703: 8, 704: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 736: 8, 737: 8, 746: 5, 752: 2, 754: 8, 760: 8, 764: 8, 766: 8, 770:8, 773: 8, 779: 8, 782: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 832: 8, 838: 2, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 878: 8, 882: 8, 897: 8, 906: 8, 908: 8, 924: 8, 926: 3, 929: 8, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 958: 8, 959: 8, 962: 8, 969: 4, 973: 8, 974: 5, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1082: 8, 1083: 8, 1098: 8, 1100: 8, 1538: 8},
@@ -42,6 +41,8 @@ FINGERPRINTS = {
{55: 8, 168: 8, 181: 8, 256: 4, 257: 5, 258: 8, 264: 8, 268: 8, 272: 6, 273: 6, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 292: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 352: 8, 362: 8, 368: 8, 376: 3, 384: 8, 388: 4, 416: 7, 448: 6, 456: 4, 464: 8, 500: 8, 501: 8, 512: 8, 514: 8, 520: 8, 532: 8, 544: 8, 557: 8, 559: 8, 560: 4, 564: 4, 571: 3, 579: 8, 584: 8, 608: 8, 624: 8, 625: 8, 632: 8, 639: 8, 656: 4, 658: 6, 660: 8, 671: 8, 672: 8, 676: 8, 678: 8, 680: 8, 683: 8, 684: 8, 703: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 729: 5, 736: 8, 737: 8, 738: 8, 746: 5, 752: 2, 754: 8, 760: 8, 761: 8, 764: 8, 766: 8, 773: 8, 776: 8, 779: 8, 782: 8, 783: 8, 784: 8, 785: 8, 788: 3, 792: 8, 799: 8, 800: 8, 804: 8, 806: 2, 808: 8, 810: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 831: 6, 832: 8, 838: 2, 844: 5, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 882: 8, 897: 8, 906: 8, 924: 8, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 968: 8, 969: 4, 970: 8, 973: 8, 974: 5, 976: 8, 977: 4, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1062: 8, 1098: 8, 1100: 8},
# Jeep Grand Cherokee 2017 Trailhawk
{257: 5, 258: 8, 264: 8, 268: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 292: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 352: 8, 362: 8, 368: 8, 376: 3, 384: 8, 388: 4, 416: 7, 448: 6, 456: 4, 464: 8, 500: 8, 501: 8, 512: 8, 514: 8, 520: 8, 532: 8, 544: 8, 557: 8, 559: 8, 560: 4, 564: 4, 571: 3, 584: 8, 608: 8, 618: 8, 624: 8, 625: 8, 632: 8, 639: 8, 660: 8, 671: 8, 672: 8, 680: 8, 684: 8, 703: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 736: 8, 737: 8, 746: 5, 752: 2, 760: 8, 761: 8, 764: 8, 766: 8, 773: 8, 776: 8, 779: 8, 783: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 806: 2, 808: 8, 810: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 831: 6, 832: 8, 838: 2, 844: 5, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 882: 8, 897: 8, 924: 3, 937: 8, 947: 8, 948: 8, 969: 4, 974: 5, 977: 4, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1062: 8, 1098: 8, 1100: 8},
+ ],
+ CAR.JEEP_CHEROKEE_2019: [
# Jeep Grand Cherokee 2019 from Switzerland
# 530: 8 is so far only in this Jeep.
{55: 8, 181: 8, 256: 4, 257: 5, 258: 8, 264: 8, 268: 8, 272: 6, 273: 6, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 292: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 352: 8, 362: 8, 368: 8, 376: 3, 384: 8, 388: 4, 416: 7, 448: 6, 456: 4, 464: 8, 500: 8, 501: 8, 512: 8, 514: 8, 520: 8, 530: 8, 532: 8, 544: 8, 557: 8, 559: 8, 560: 8, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 618: 8, 624: 8, 625: 8, 632: 8, 639: 8, 660: 8, 671: 8, 672: 8, 676: 8, 680: 8, 683: 8, 684: 8, 703: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 736: 8, 737: 8, 738: 8, 746: 5, 752: 2, 754: 8, 760: 8, 761: 8, 764: 8, 773: 8, 776: 8, 779: 8, 782: 8, 783: 8, 784: 8, 792: 8, 799: 8, 804: 8, 806: 2, 808: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 831: 6, 832: 8, 838: 2, 844: 5, 848: 8, 853: 8, 856: 4, 860: 6, 882: 8, 897: 8, 906: 8, 924: 8, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 968: 8, 969: 4, 970: 8, 973: 8, 974: 5, 977: 4, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1062: 8, 1098: 8, 1100: 8},
@@ -65,6 +66,9 @@ DBC = {
CAR.JEEP_CHEROKEE: dbc_dict( # Same DBC file works.
'chrysler_pacifica_2017_hybrid', # 'pt'
'chrysler_pacifica_2017_hybrid_private_fusion'), # 'radar'
+ CAR.JEEP_CHEROKEE_2019: dbc_dict( # Same DBC file works.
+ 'chrysler_pacifica_2017_hybrid', # 'pt'
+ 'chrysler_pacifica_2017_hybrid_private_fusion'), # 'radar'
}
STEER_THRESHOLD = 120
diff --git a/selfdrive/car/honda/carcontroller.py b/selfdrive/car/honda/carcontroller.py
index 08c0235fd..9325e8964 100644
--- a/selfdrive/car/honda/carcontroller.py
+++ b/selfdrive/car/honda/carcontroller.py
@@ -138,6 +138,8 @@ class CarController(object):
STEER_MAX = 0xF00
elif CS.CP.carFingerprint in (CAR.CRV, CAR.ACURA_RDX):
STEER_MAX = 0x3e8 # CR-V only uses 12-bits and requires a lower value (max value from energee)
+ elif CS.CP.carFingerprint in (CAR.ODYSSEY_CHN):
+ STEER_MAX = 0x7FFF
else:
STEER_MAX = 0x1000
diff --git a/selfdrive/car/honda/carstate.py b/selfdrive/car/honda/carstate.py
index 718e7ae61..b8164e8c5 100644
--- a/selfdrive/car/honda/carstate.py
+++ b/selfdrive/car/honda/carstate.py
@@ -60,18 +60,35 @@ def get_can_signals(CP):
("ENGINE_DATA", 100),
("WHEEL_SPEEDS", 50),
("STEERING_SENSORS", 100),
- ("SCM_FEEDBACK", 10),
- ("GEARBOX", 100),
("SEATBELT_STATUS", 10),
("CRUISE", 10),
("POWERTRAIN_DATA", 100),
("VSA_STATUS", 50),
- ("SCM_BUTTONS", 25),
]
+ if CP.carFingerprint == CAR.ODYSSEY_CHN:
+ checks += [
+ ("SCM_FEEDBACK", 25),
+ ("SCM_BUTTONS", 50),
+ ]
+ else:
+ checks += [
+ ("SCM_FEEDBACK", 10),
+ ("SCM_BUTTONS", 25),
+ ]
+
+ if CP.carFingerprint == CAR.CRV_HYBRID:
+ checks += [
+ ("GEARBOX", 50),
+ ]
+ else:
+ checks += [
+ ("GEARBOX", 100),
+ ]
+
if CP.radarOffCan:
# Civic is only bosch to use the same brake message as other hondas.
- if CP.carFingerprint not in (CAR.ACCORDH, CAR.CIVIC_BOSCH):
+ if CP.carFingerprint not in (CAR.ACCORDH, CAR.CIVIC_BOSCH, CAR.CRV_HYBRID):
signals += [("BRAKE_PRESSED", "BRAKE_MODULE", 0)]
checks += [("BRAKE_MODULE", 50)]
signals += [("CAR_GAS", "GAS_PEDAL_2", 0),
@@ -85,11 +102,17 @@ def get_can_signals(CP):
("BRAKE_ERROR_2", "STANDSTILL", 1),
("CRUISE_SPEED_PCM", "CRUISE", 0),
("CRUISE_SPEED_OFFSET", "CRUISE_PARAMS", 0)]
- checks += [("CRUISE_PARAMS", 50),
- ("STANDSTILL", 50)]
+ checks += [("STANDSTILL", 50)]
- if CP.carFingerprint in (CAR.ACCORD, CAR.ACCORD_15, CAR.ACCORDH, CAR.CIVIC_BOSCH):
+ if CP.carFingerprint == CAR.ODYSSEY_CHN:
+ checks += [("CRUISE_PARAMS", 10)]
+ else:
+ checks += [("CRUISE_PARAMS", 50)]
+
+ if CP.carFingerprint in (CAR.ACCORD, CAR.ACCORD_15, CAR.ACCORDH, CAR.CIVIC_BOSCH, CAR.CRV_HYBRID):
signals += [("DRIVERS_DOOR_OPEN", "SCM_FEEDBACK", 1)]
+ elif CP.carFingerprint == CAR.ODYSSEY_CHN:
+ signals += [("DRIVERS_DOOR_OPEN", "SCM_BUTTONS", 1)]
else:
signals += [("DOOR_OPEN_FL", "DOORS_STATUS", 1),
("DOOR_OPEN_FR", "DOORS_STATUS", 1),
@@ -114,6 +137,10 @@ def get_can_signals(CP):
elif CP.carFingerprint == CAR.PILOT:
signals += [("MAIN_ON", "SCM_BUTTONS", 0),
("CAR_GAS", "GAS_PEDAL_2", 0)]
+ elif CP.carFingerprint == CAR.ODYSSEY_CHN:
+ signals += [("MAIN_ON", "SCM_BUTTONS", 0),
+ ("EPB_STATE", "EPB_STATUS", 0)]
+ checks += [("EPB_STATUS", 50)]
# add gas interceptor reading if we are using it
if CP.enableGasInterceptor:
@@ -130,9 +157,9 @@ def get_can_parser(CP):
def get_cam_can_parser(CP):
signals = []
- # all hondas except CRV and RDX use 0xe4 for steering
+ # all hondas except CRV, RDX and 2019 Odyssey@China use 0xe4 for steering
checks = [(0xe4, 100)]
- if CP.carFingerprint in [CAR.CRV, CAR.ACURA_RDX]:
+ if CP.carFingerprint in [CAR.CRV, CAR.ACURA_RDX, CAR.ODYSSEY_CHN]:
checks = [(0x194, 100)]
cam_bus = 1 if CP.carFingerprint in HONDA_BOSCH else 2
@@ -189,9 +216,12 @@ class CarState(object):
# ******************* parse out can *******************
- if self.CP.carFingerprint in (CAR.ACCORD, CAR.ACCORD_15, CAR.ACCORDH, CAR.CIVIC_BOSCH): # TODO: find wheels moving bit in dbc
+ if self.CP.carFingerprint in (CAR.ACCORD, CAR.ACCORD_15, CAR.ACCORDH, CAR.CIVIC_BOSCH, CAR.CRV_HYBRID): # TODO: find wheels moving bit in dbc
self.standstill = cp.vl["ENGINE_DATA"]['XMISSION_SPEED'] < 0.1
self.door_all_closed = not cp.vl["SCM_FEEDBACK"]['DRIVERS_DOOR_OPEN']
+ elif self.CP.carFingerprint == CAR.ODYSSEY_CHN:
+ self.standstill = cp.vl["ENGINE_DATA"]['XMISSION_SPEED'] < 0.1
+ self.door_all_closed = not cp.vl["SCM_BUTTONS"]['DRIVERS_DOOR_OPEN']
else:
self.standstill = not cp.vl["STANDSTILL"]['WHEELS_MOVING']
self.door_all_closed = not any([cp.vl["DOORS_STATUS"]['DOOR_OPEN_FL'], cp.vl["DOORS_STATUS"]['DOOR_OPEN_FR'],
@@ -248,9 +278,12 @@ class CarState(object):
self.right_blinker_on = cp.vl["SCM_FEEDBACK"]['RIGHT_BLINKER']
self.brake_hold = cp.vl["VSA_STATUS"]['BRAKE_HOLD_ACTIVE']
- if self.CP.carFingerprint in (CAR.CIVIC, CAR.ODYSSEY, CAR.CRV_5G, CAR.ACCORD, CAR.ACCORD_15, CAR.ACCORDH, CAR.CIVIC_BOSCH):
+ if self.CP.carFingerprint in (CAR.CIVIC, CAR.ODYSSEY, CAR.CRV_5G, CAR.ACCORD, CAR.ACCORD_15, CAR.ACCORDH, CAR.CIVIC_BOSCH, CAR.CRV_HYBRID):
self.park_brake = cp.vl["EPB_STATUS"]['EPB_STATE'] != 0
self.main_on = cp.vl["SCM_FEEDBACK"]['MAIN_ON']
+ elif self.CP.carFingerprint == CAR.ODYSSEY_CHN:
+ self.park_brake = cp.vl["EPB_STATUS"]['EPB_STATE'] != 0
+ self.main_on = cp.vl["SCM_BUTTONS"]['MAIN_ON']
else:
self.park_brake = 0 # TODO
self.main_on = cp.vl["SCM_BUTTONS"]['MAIN_ON']
@@ -260,7 +293,7 @@ class CarState(object):
self.pedal_gas = cp.vl["POWERTRAIN_DATA"]['PEDAL_GAS']
# crv doesn't include cruise control
- if self.CP.carFingerprint in (CAR.CRV, CAR.ODYSSEY, CAR.ACURA_RDX, CAR.RIDGELINE, CAR.PILOT_2019):
+ if self.CP.carFingerprint in (CAR.CRV, CAR.ODYSSEY, CAR.ACURA_RDX, CAR.RIDGELINE, CAR.PILOT_2019, CAR.ODYSSEY_CHN):
self.car_gas = self.pedal_gas
else:
self.car_gas = cp.vl["GAS_PEDAL_2"]['CAR_GAS']
@@ -273,7 +306,7 @@ class CarState(object):
if self.CP.radarOffCan:
self.stopped = cp.vl["ACC_HUD"]['CRUISE_SPEED'] == 252.
self.cruise_speed_offset = calc_cruise_offset(0, self.v_ego)
- if self.CP.carFingerprint in (CAR.CIVIC_BOSCH, CAR.ACCORDH):
+ if self.CP.carFingerprint in (CAR.CIVIC_BOSCH, CAR.ACCORDH, CAR.CRV_HYBRID):
self.brake_switch = cp.vl["POWERTRAIN_DATA"]['BRAKE_SWITCH']
self.brake_pressed = cp.vl["POWERTRAIN_DATA"]['BRAKE_PRESSED'] or \
(self.brake_switch and self.brake_switch_prev and \
diff --git a/selfdrive/car/honda/hondacan.py b/selfdrive/car/honda/hondacan.py
index 435360d65..8f369feca 100644
--- a/selfdrive/car/honda/hondacan.py
+++ b/selfdrive/car/honda/hondacan.py
@@ -65,8 +65,8 @@ def create_ui_commands(packer, pcm_speed, hud, car_fingerprint, idx):
'CRUISE_SPEED': hud.v_cruise,
'ENABLE_MINI_CAR': hud.mini_car,
'HUD_LEAD': hud.car,
- 'SET_ME_X03': 0x03,
- 'SET_ME_X03_2': 0x03,
+ 'SET_ME_X03': 0x01 if car_fingerprint == CAR.ODYSSEY_CHN else 0x03,
+ 'SET_ME_X03_2': 0x02 if car_fingerprint == CAR.ODYSSEY_CHN else 0x03,
'SET_ME_X01': 0x01,
}
commands.append(packer.make_can_msg("ACC_HUD", 0, acc_hud_values, idx))
diff --git a/selfdrive/car/honda/interface.py b/selfdrive/car/honda/interface.py
index 3acd2c741..4072b0354 100755
--- a/selfdrive/car/honda/interface.py
+++ b/selfdrive/car/honda/interface.py
@@ -260,6 +260,20 @@ class CarInterface(object):
ret.longitudinalKiBP = [0., 35.]
ret.longitudinalKiV = [0.18, 0.12]
+ elif candidate == CAR.CRV_HYBRID:
+ stop_and_go = True
+ ret.safetyParam = 1 # Accord and CRV 5G use an alternate user brake msg
+ ret.mass = 1667. + std_cargo # mean of 4 models in kg
+ ret.wheelbase = 2.66
+ ret.centerToFront = ret.wheelbase * 0.41
+ ret.steerRatio = 16.0 # 12.3 is spec end-to-end
+ tire_stiffness_factor = 0.677
+ ret.steerKpV, ret.steerKiV = [[0.6], [0.18]]
+ ret.longitudinalKpBP = [0., 5., 35.]
+ ret.longitudinalKpV = [1.2, 0.8, 0.5]
+ ret.longitudinalKiBP = [0., 35.]
+ ret.longitudinalKiV = [0.18, 0.12]
+
elif candidate == CAR.ACURA_RDX:
stop_and_go = False
ret.mass = 3935 * CV.LB_TO_KG + std_cargo
@@ -286,6 +300,19 @@ class CarInterface(object):
ret.longitudinalKiBP = [0., 35.]
ret.longitudinalKiV = [0.18, 0.12]
+ elif candidate == CAR.ODYSSEY_CHN:
+ stop_and_go = False
+ ret.mass = 1849.2 + std_cargo # mean of 4 models in kg
+ ret.wheelbase = 2.90 # spec
+ ret.centerToFront = ret.wheelbase * 0.41 # from CAR.ODYSSEY
+ ret.steerRatio = 14.35 # from CAR.ODYSSEY
+ tire_stiffness_factor = 0.82 # from CAR.ODYSSEY
+ ret.steerKpV, ret.steerKiV = [[0.45], [0.135]]
+ ret.longitudinalKpBP = [0., 5., 35.]
+ ret.longitudinalKpV = [1.2, 0.8, 0.5]
+ ret.longitudinalKiBP = [0., 35.]
+ ret.longitudinalKiV = [0.18, 0.12]
+
elif candidate in (CAR.PILOT, CAR.PILOT_2019):
stop_and_go = False
ret.mass = 4303 * CV.LB_TO_KG + std_cargo
diff --git a/selfdrive/car/honda/values.py b/selfdrive/car/honda/values.py
index 56302551f..f106ccab3 100644
--- a/selfdrive/car/honda/values.py
+++ b/selfdrive/car/honda/values.py
@@ -65,7 +65,9 @@ class CAR:
ACURA_ILX = "ACURA ILX 2016 ACURAWATCH PLUS"
CRV = "HONDA CR-V 2016 TOURING"
CRV_5G = "HONDA CR-V 2017 EX"
+ CRV_HYBRID = "HONDA CR-V 2019 HYBRID"
ODYSSEY = "HONDA ODYSSEY 2018 EX-L"
+ ODYSSEY_CHN = "HONDA ODYSSEY 2019 EXCLUSIVE CHN"
ACURA_RDX = "ACURA RDX 2018 ACURAWATCH PLUS"
PILOT = "HONDA PILOT 2017 TOURING"
PILOT_2019 = "HONDA PILOT 2019 ELITE"
@@ -101,6 +103,9 @@ FINGERPRINTS = {
CAR.CRV_5G: [{
57: 3, 148: 8, 199: 4, 228: 5, 231: 5, 232: 7, 304: 8, 330: 8, 340: 8, 344: 8, 380: 8, 399: 7, 401: 8, 420: 8, 423: 2, 427: 3, 428: 8, 432: 7, 441: 5, 446: 3, 450: 8, 464: 8, 467: 2, 469: 3, 470: 2, 474: 8, 476: 7, 477: 8, 479: 8, 490: 8, 493: 5, 495: 8, 507: 1, 545: 6, 597: 8, 661: 4, 662: 4, 773: 7, 777: 8, 780: 8, 795: 8, 800: 8, 804: 8, 806: 8, 808: 8, 814: 4, 815: 8, 817: 4, 825: 4, 829: 5, 862: 8, 881: 8, 882: 4, 884: 8, 888: 8, 891: 8, 927: 8, 918: 7, 929: 8, 983: 8, 985: 3, 1024: 5, 1027: 5, 1029: 8, 1036: 8, 1039: 8, 1064: 7, 1108: 8, 1092: 1, 1115: 4, 1125: 8, 1127: 2, 1296: 8, 1302: 8, 1322: 5, 1361: 5, 1365: 5, 1424: 5, 1600: 5, 1601: 8, 1618: 5, 1633: 8, 1670: 5
}],
+ CAR.CRV_HYBRID: [{
+ 57: 3, 148: 8, 228: 5, 304: 8, 330: 8, 344: 8, 380: 8, 387: 8, 388: 8, 399: 7, 419: 8, 420: 8, 427: 3, 432: 7, 441: 5, 450: 8, 464: 8, 477: 8, 479: 8, 490: 8, 495: 8, 525: 8, 531: 8, 545: 6, 662: 4, 773: 7, 777: 8, 780: 8, 804: 8, 806: 8, 808: 8, 814: 4, 829: 5, 833: 6, 862: 8, 884: 8, 891: 8, 927: 8, 929: 8, 1302: 8, 1361: 5, 1365: 5, 1600: 5, 1601: 8
+ }],
# 2018 Odyssey w/ Added Comma Pedal Support (512L & 513L)
CAR.ODYSSEY: [{
57: 3, 148: 8, 228: 5, 229: 4, 316: 8, 342: 6, 344: 8, 380: 8, 399: 7, 411: 5, 419: 8, 420: 8, 427: 3, 432: 7, 450: 8, 463: 8, 464: 8, 476: 4, 490: 8, 506: 8, 512: 6, 513: 6, 542: 7, 545: 6, 597: 8, 662: 4, 773: 7, 777: 8, 780: 8, 795: 8, 800: 8, 804: 8, 806: 8, 808: 8, 817: 4, 819: 7, 821: 5, 825: 4, 829: 5, 837: 5, 856: 7, 862: 8, 871: 8, 881: 8, 882: 4, 884: 8, 891: 8, 892: 8, 905: 8, 923: 2, 927: 8, 929: 8, 963: 8, 965: 8, 966: 8, 967: 8, 983: 8, 985: 3, 1029: 8, 1036: 8, 1052: 8, 1064: 7, 1088: 8, 1089: 8, 1092: 1, 1108: 8, 1110: 8, 1125: 8, 1296: 8, 1302: 8, 1600: 5, 1601: 8, 1612: 5, 1613: 5, 1614: 5, 1615: 8, 1616: 5, 1619: 5, 1623: 5, 1668: 5
@@ -109,6 +114,9 @@ FINGERPRINTS = {
{
57: 3, 148: 8, 228: 5, 229: 4, 304: 8, 342: 6, 344: 8, 380: 8, 399: 7, 411: 5, 419: 8, 420: 8, 427: 3, 432: 7, 440: 8, 450: 8, 463: 8, 464: 8, 476: 4, 490: 8, 506: 8, 507: 1, 542: 7, 545: 6, 597: 8, 662: 4, 773: 7, 777: 8, 780: 8, 795: 8, 800: 8, 804: 8, 806: 8, 808: 8, 817: 4, 819: 7, 821: 5, 825: 4, 829: 5, 837: 5, 856: 7, 862: 8, 871: 8, 881: 8, 882: 4, 884: 8, 891: 8, 892: 8, 905: 8, 923: 2, 927: 8, 929: 8, 963: 8, 965: 8, 966: 8, 967: 8, 983: 8, 985: 3, 1029: 8, 1036: 8, 1052: 8, 1064: 7, 1088: 8, 1089: 8, 1092: 1, 1108: 8, 1110: 8, 1125: 8, 1296: 8, 1302: 8, 1600: 5, 1601: 8, 1612: 5, 1613: 5, 1614: 5, 1616: 5, 1619: 5, 1623: 5, 1668: 5
}],
+ CAR.ODYSSEY_CHN: [{
+ 57: 3, 145: 8, 316: 8, 342: 6, 344: 8, 380: 8, 398: 3, 399: 7, 401: 8, 404: 4, 411: 5, 420: 8, 422: 8, 423: 2, 426: 8, 432: 7, 450: 8, 464: 8, 490: 8, 506: 8, 507: 1, 597: 8, 610: 8, 611: 8, 612: 8, 617: 8, 660: 8, 661: 4, 773: 7, 780: 8, 804: 8, 808: 8, 829: 5, 862: 8, 884: 7, 892: 8, 923: 2, 929: 8, 1030: 5, 1137: 8, 1302: 8, 1348: 5, 1361: 5, 1365: 5, 1600: 5, 1601: 8, 1639: 8
+ }],
# 2017 Pilot Touring AND 2016 Pilot EX-L w/ Added Comma Pedal Support (512L & 513L)
CAR.PILOT: [{
57: 3, 145: 8, 228: 5, 229: 4, 308: 5, 316: 8, 334: 8, 339: 7, 342: 6, 344: 8, 379: 8, 380: 8, 392: 6, 399: 7, 419: 8, 420: 8, 422: 8, 425: 8, 426: 8, 427: 3, 432: 7, 463: 8, 464: 8, 476: 4, 490: 8, 506: 8, 507: 1, 512: 6, 513: 6, 538: 3, 542: 7, 545: 5, 546: 3, 597: 8, 660: 8, 773: 7, 777: 8, 780: 8, 795: 8, 800: 8, 804: 8, 808: 8, 819: 7, 821: 5, 829: 5, 837: 5, 856: 7, 871: 8, 882: 2, 884: 7, 891: 8, 892: 8, 923: 2, 929: 8, 963: 8, 965: 8, 966: 8, 967: 8, 983: 8, 985: 3, 1027: 5, 1029: 8, 1036: 8, 1039: 8, 1064: 7, 1088: 8, 1089: 8, 1108: 8, 1125: 8, 1296: 8, 1424: 5, 1600: 5, 1601: 8, 1612: 5, 1613: 5, 1616: 5, 1618: 5, 1668: 5
@@ -140,7 +148,9 @@ DBC = {
CAR.CIVIC_BOSCH: dbc_dict('honda_civic_hatchback_ex_2017_can_generated', None),
CAR.CRV: dbc_dict('honda_crv_touring_2016_can_generated', 'acura_ilx_2016_nidec'),
CAR.CRV_5G: dbc_dict('honda_crv_ex_2017_can_generated', None),
+ CAR.CRV_HYBRID: dbc_dict('honda_crv_hybrid_2019_can_generated', None),
CAR.ODYSSEY: dbc_dict('honda_odyssey_exl_2018_generated', 'acura_ilx_2016_nidec'),
+ CAR.ODYSSEY_CHN: dbc_dict('honda_odyssey_extreme_edition_2018_china_can', 'acura_ilx_2016_nidec'),
CAR.PILOT: dbc_dict('honda_pilot_touring_2017_can_generated', 'acura_ilx_2016_nidec'),
CAR.PILOT_2019: dbc_dict('honda_pilot_touring_2017_can_generated', 'acura_ilx_2016_nidec'),
CAR.RIDGELINE: dbc_dict('honda_ridgeline_black_edition_2017_can_generated', 'acura_ilx_2016_nidec'),
@@ -156,7 +166,9 @@ STEER_THRESHOLD = {
CAR.CIVIC_BOSCH: 1200,
CAR.CRV: 1200,
CAR.CRV_5G: 1200,
+ CAR.CRV_HYBRID: 1200,
CAR.ODYSSEY: 1200,
+ CAR.ODYSSEY_CHN: 1200,
CAR.PILOT: 1200,
CAR.PILOT_2019: 1200,
CAR.RIDGELINE: 1200,
@@ -172,11 +184,13 @@ SPEED_FACTOR = {
CAR.CIVIC_BOSCH: 1.,
CAR.CRV: 1.025,
CAR.CRV_5G: 1.025,
+ CAR.CRV_HYBRID: 1.025,
CAR.ODYSSEY: 1.,
+ CAR.ODYSSEY_CHN: 1.,
CAR.PILOT: 1.,
CAR.PILOT_2019: 1.,
CAR.RIDGELINE: 1.,
}
# TODO: get these from dbc file
-HONDA_BOSCH = [CAR.ACCORD, CAR.ACCORD_15, CAR.ACCORDH, CAR.CIVIC_BOSCH, CAR.CRV_5G]
+HONDA_BOSCH = [CAR.ACCORD, CAR.ACCORD_15, CAR.ACCORDH, CAR.CIVIC_BOSCH, CAR.CRV_5G, CAR.CRV_HYBRID]