brand/honda/nidec-stock-long

2026-02-20: init
This commit is contained in:
Rick Lan
2026-02-20 19:43:20 +08:00
parent 01e9d51093
commit b5c149dfed
8 changed files with 78 additions and 2 deletions

View File

@@ -162,4 +162,5 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"dp_dev_tethering", {PERSISTENT, BOOL, "0"}},
{"dp_ui_mici", {PERSISTENT, BOOL, "0"}},
{"dp_lat_offset_cm", {PERSISTENT, INT, "0"}},
{"dp_honda_nidec_stock_long", {PERSISTENT, BOOL, "0"}},
};

View File

@@ -4,6 +4,19 @@ except:
from openpilot.system.ui.lib.multilang import tr
SETTINGS = [
{
"title": "Honda / Acura",
"condition": "brand == 'honda'",
"settings": [
{
"key": "dp_honda_nidec_stock_long",
"type": "toggle_item",
"title": lambda: tr("Nidec: Use Stock Longitudinal Control"),
"description": lambda: tr("Use Honda's factory ACC for gas/brake control instead of openpilot. openpilot will only control steering. Requires reboot to take effect."),
"brands": ["honda"],
},
],
},
{
"title": "Toyota / Lexus",
"condition": "brand == 'toyota'",

View File

@@ -54,6 +54,9 @@ class CarInterface(CarInterfaceBase):
ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.hondaNidec)]
ret.openpilotLongitudinalControl = True
if dp_params & structs.DPFlags.HondaNidecStockLong:
ret.openpilotLongitudinalControl = False
ret.pcmCruise = True
if candidate == CAR.HONDA_CRV_5G:
@@ -208,6 +211,8 @@ class CarInterface(CarInterfaceBase):
ret.safetyConfigs[-1].safetyParam |= HondaSafetyFlags.RADARLESS.value
if candidate in HONDA_BOSCH_CANFD:
ret.safetyConfigs[-1].safetyParam |= HondaSafetyFlags.BOSCH_CANFD.value
if not ret.openpilotLongitudinalControl and candidate not in HONDA_BOSCH:
ret.safetyConfigs[-1].safetyParam |= HondaSafetyFlags.NIDEC_STOCK_LONG.value
# min speed to enable ACC. if car can do stop and go, then set enabling speed
# to a negative value, so it won't matter. Otherwise, add 0.5 mph margin to not

View File

@@ -56,6 +56,7 @@ class HondaSafetyFlags(IntFlag):
NIDEC_ALT = 4
RADARLESS = 8
BOSCH_CANFD = 16
NIDEC_STOCK_LONG = 32
class HondaFlags(IntFlag):

View File

@@ -22,4 +22,5 @@ CarParamsT = capnp.lib.capnp._StructModule
class DPFlags:
LatALKA = 1
ExtRadar = 2
HondaNidecStockLong = 2 ** 2
pass

View File

@@ -32,6 +32,7 @@ static bool honda_fwd_brake = false;
static bool honda_bosch_long = false;
static bool honda_bosch_radarless = false;
static bool honda_bosch_canfd = false;
static bool honda_nidec_stock_long = false;
typedef enum {HONDA_NIDEC, HONDA_BOSCH} HondaHw;
static HondaHw honda_hw = HONDA_NIDEC;
@@ -279,6 +280,10 @@ static bool honda_tx_hook(const CANPacket_t *msg) {
static safety_config honda_nidec_init(uint16_t param) {
alka_allowed = true; // dp - ALKA enabled for Honda Nidec
// Steering-only (stock long)
static CanMsg HONDA_N_STOCK_LONG_TX_MSGS[] = {{0xE4, 0, 5, .check_relay = true}, {0x194, 0, 4, .check_relay = true},
{0x33D, 0, 5, .check_relay = true}};
// 0x1FA is dynamically forwarded based on stock AEB
// 0xE4 is steering on all cars except CRV and RDX, 0x194 for CRV and RDX,
// 0x1FA is brake control, 0x30C is acc hud, 0x33D is lkas hud
@@ -286,6 +291,7 @@ static safety_config honda_nidec_init(uint16_t param) {
{0x30C, 0, 8, .check_relay = true}, {0x33D, 0, 5, .check_relay = true}};
const uint16_t HONDA_PARAM_NIDEC_ALT = 4;
const uint16_t HONDA_PARAM_NIDEC_STOCK_LONG = 32;
honda_hw = HONDA_NIDEC;
honda_brake = 0;
@@ -295,6 +301,7 @@ static safety_config honda_nidec_init(uint16_t param) {
honda_bosch_long = false;
honda_bosch_radarless = false;
honda_bosch_canfd = false;
honda_nidec_stock_long = GET_FLAG(param, HONDA_PARAM_NIDEC_STOCK_LONG);
safety_config ret;
@@ -318,7 +325,11 @@ static safety_config honda_nidec_init(uint16_t param) {
SET_RX_CHECKS(honda_nidec_common_rx_checks, ret);
}
SET_TX_MSGS(HONDA_N_TX_MSGS, ret);
if (honda_nidec_stock_long) {
SET_TX_MSGS(HONDA_N_STOCK_LONG_TX_MSGS, ret);
} else {
SET_TX_MSGS(HONDA_N_TX_MSGS, ret);
}
return ret;
}
@@ -418,7 +429,7 @@ static bool honda_nidec_fwd_hook(int bus_num, int addr) {
if (bus_num == 2) {
// forwarded if stock AEB is active
bool is_brake_msg = addr == 0x1FA;
block_msg = is_brake_msg && !honda_fwd_brake;
block_msg = is_brake_msg && !honda_fwd_brake && !honda_nidec_stock_long;
}
return block_msg;

View File

@@ -338,6 +338,47 @@ class TestHondaNidecPcmSafety(HondaPcmEnableBase, TestHondaNidecSafetyBase):
pass
class TestHondaNidecStockLongSafety(HondaPcmEnableBase, TestHondaNidecSafetyBase):
"""
Covers Honda Nidec with stock longitudinal control
"""
TX_MSGS = [[0xE4, 0], [0x194, 0], [0x33D, 0]]
FWD_BLACKLISTED_ADDRS = {2: [0xE4, 0x194, 0x33D]}
RELAY_MALFUNCTION_ADDRS = {0: (0xE4, 0x194, 0x33D)}
def setUp(self):
self.packer = CANPackerSafety("honda_civic_touring_2016_can_generated")
self.safety = libsafety_py.libsafety
self.safety.set_safety_hooks(CarParams.SafetyModel.hondaNidec, HondaSafetyFlags.NIDEC_STOCK_LONG)
self.safety.init_tests()
# Nidec doesn't disengage on falling edge of cruise
def test_disable_control_allowed_from_cruise(self):
pass
# No-op longitudinal tests (stock handles it)
def test_brake_safety_check(self):
pass
def test_acc_hud_safety_check(self):
pass
def test_fwd_hook(self):
pass
def test_honda_fwd_brake_latching(self):
pass
def _send_brake_msg(self, brake, aeb_req=0, bus=0):
pass
def _rx_brake_msg(self, brake, aeb_req=0):
pass
def _send_acc_hud_msg(self, pcm_gas, pcm_speed):
pass
class TestHondaNidecPcmAltSafety(TestHondaNidecPcmSafety):
"""
Covers the Honda Nidec safety mode with alt SCM messages

View File

@@ -105,6 +105,9 @@ class Car:
if self.params.get_bool("dp_lat_alka"):
dp_params |= structs.DPFlags.LatALKA
if self.params.get_bool("dp_honda_nidec_stock_long"):
dp_params |= structs.DPFlags.HondaNidecStockLong
dp_fingerprint = str(self.params.get("dp_dev_model_selected") or "")
self.CI = get_car(*self.can_callbacks, obd_callback(self.params), alpha_long_allowed, is_release, num_pandas, dp_params, cached_params, dp_fingerprint=dp_fingerprint)
self.RI = interfaces[self.CI.CP.carFingerprint].RadarInterface(self.CI.CP)