mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-06-24 12:12:07 +08:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ccd5141fe8 | |||
| 50313b9374 |
@@ -22,34 +22,24 @@ https://docs.sunnypilot.ai/ is your one stop shop for everything from features t
|
||||
Detailed instructions for [how to mount the device in a car](https://comma.ai/setup).
|
||||
|
||||
## Installation
|
||||
Please refer to [Recommended Branches](#-recommended-branches) to find your preferred/supported branch. This guide will assume you want to install the latest `release-c3` branch.
|
||||
Please refer to [Recommended Branches](#-recommended-branches) to find your preferred/supported branch. This guide will assume you want to install the latest `staging-c3-new` branch.
|
||||
|
||||
### If you want to use our newest branches (our rewrite)
|
||||
> [!TIP]
|
||||
>You can see the rewrite state on our [rewrite project board](https://github.com/orgs/sunnypilot/projects/2), and to install the new branches, you can use the following links
|
||||
|
||||
* sunnypilot not installed or you installed a version before 0.8.17?
|
||||
1. [Factory reset/uninstall](https://github.com/commaai/openpilot/wiki/FAQ#how-can-i-reset-the-device) the previous software if you have another software/fork installed.
|
||||
2. After factory reset/uninstall and upon reboot, select `Custom Software` when given the option.
|
||||
3. Input the installation URL per [Recommended Branches](#-recommended-branches). Example: ```release-c3.sunnypilot.ai```.
|
||||
3. Input the installation URL per [Recommended Branches](#-recommended-branches). Example: ```https://staging-c3-new.sunnypilot.ai```.
|
||||
4. Complete the rest of the installation following the onscreen instructions.
|
||||
|
||||
* sunnypilot already installed and you installed a version after 0.8.17?
|
||||
1. On the comma three, go to `Settings` ▶️ `Software`.
|
||||
2. At the `Download` option, press `CHECK`. This will fetch the list of latest branches from sunnypilot.
|
||||
3. At the `Target Branch` option, press `SELECT` to open the Target Branch selector.
|
||||
4. Scroll to select the desired branch per Recommended Branches (see below). Example: `release-c3`
|
||||
4. Scroll to select the desired branch per Recommended Branches (see below). Example: `staging-c3-new`
|
||||
|
||||
| Branch | Installation URL |
|
||||
|:------------:|:--------------------------------:|
|
||||
| `release-c3` | https://release-c3.sunnypilot.ai |
|
||||
| `staging-c3` | https://staging-c3.sunnypilot.ai |
|
||||
| `dev-c3` | https://dev-c3.sunnypilot.ai |
|
||||
|
||||
### If you want to use our newest branches (our rewrite)
|
||||
> [!TIP]
|
||||
>You can see the rewrite state on our [rewrite project board](https://github.com/orgs/sunnypilot/projects/2), and to install the new branches, you can use the following links
|
||||
|
||||
|
||||
> [!IMPORTANT]
|
||||
> It is recommended to [re-flash AGNOS](https://flash.comma.ai/) if you intend to downgrade from the new branches.
|
||||
> You can still restore the latest sunnylink backup made on the old branches.
|
||||
|
||||
| Branch | Installation URL |
|
||||
|:----------------:|:---------------------------------------------:|
|
||||
@@ -59,8 +49,31 @@ Please refer to [Recommended Branches](#-recommended-branches) to find your pref
|
||||
| `release-c3-new` | **Not yet available**. |
|
||||
|
||||
> [!TIP]
|
||||
> You can use sunnypilot/targetbranch as an install URL. Example: 'sunnypilot/staging-c3-new'.
|
||||
|
||||
> [!NOTE]
|
||||
> Do you require further assistance with software installation? Join the [sunnypilot Discord server](https://discord.sunnypilot.com) and message us in the `#installation-help` channel.
|
||||
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Older legacy branches</summary>
|
||||
|
||||
### If you want to use our older legacy branches (*not recommended*)
|
||||
|
||||
> [**IMPORTANT**]
|
||||
> It is recommended to [re-flash AGNOS](https://flash.comma.ai/) if you intend to downgrade from the new branches.
|
||||
> You can still restore the latest sunnylink backup made on the old branches.
|
||||
|
||||
| Branch | Installation URL |
|
||||
|:------------:|:--------------------------------:|
|
||||
| `release-c3` | https://release-c3.sunnypilot.ai |
|
||||
| `staging-c3` | https://staging-c3.sunnypilot.ai |
|
||||
| `dev-c3` | https://dev-c3.sunnypilot.ai |
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
## 🎆 Pull Requests
|
||||
We welcome both pull requests and issues on GitHub. Bug fixes are encouraged.
|
||||
|
||||
|
||||
+9
-5
@@ -1,18 +1,22 @@
|
||||
Version 0.10.1 (2025-09-08)
|
||||
========================
|
||||
* Record driving feedback using LKAS button
|
||||
* Honda City 2023 support thanks to drFritz!
|
||||
|
||||
Version 0.10.0 (2025-08-05)
|
||||
========================
|
||||
* New driving model
|
||||
* New training architecture
|
||||
* Architecture outlined in CVPR paper: "Learning to Drive from a World Model"
|
||||
* Longitudinal MPC replaced by E2E planning from worldmodel in experimental mode
|
||||
* Action from lateral MPC as training objective replaced by E2E planning from worldmodel
|
||||
* Described in our CVPR paper: "Learning to Drive from a World Model"
|
||||
* Longitudinal MPC replaced by E2E planning from World Model in Experimental Mode
|
||||
* Action from lateral MPC as training objective replaced by E2E planning from World Model
|
||||
* Low-speed lead car ground-truth fixes
|
||||
|
||||
* Enable live-learned steering actuation delay
|
||||
* Record driving feedback using LKAS button when MADS is disabled
|
||||
* Opt-in audio recording for dashcam video
|
||||
* Acura MDX 2025 support thanks to vanillagorillaa and MVL!
|
||||
* Honda Accord 2023-25 support thanks to vanillagorillaa and MVL!
|
||||
* Honda CR-V 2023-25 support thanks to vanillagorillaa and MVL!
|
||||
* Honda Pilot 2023-25 support thanks to vanillagorillaa and MVL!
|
||||
|
||||
Version 0.9.9 (2025-05-23)
|
||||
========================
|
||||
|
||||
+10
-1
@@ -172,6 +172,8 @@ struct OnroadEventSP @0xda96579883444c35 {
|
||||
experimentalModeSwitched @14;
|
||||
wrongCarModeAlertOnly @15;
|
||||
pedalPressedAlertOnly @16;
|
||||
laneTurnLeft @17;
|
||||
laneTurnRight @18;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,9 +260,16 @@ struct LiveMapDataSP @0xf416ec09499d9d19 {
|
||||
roadName @5 :Text;
|
||||
}
|
||||
|
||||
struct CustomReserved9 @0xa1680744031fdb2d {
|
||||
struct ModelDataV2SP @0xa1680744031fdb2d {
|
||||
laneTurnDirection @0 :TurnDirection;
|
||||
}
|
||||
|
||||
enum TurnDirection {
|
||||
none @0;
|
||||
turnLeft @1;
|
||||
turnRight @2;
|
||||
}
|
||||
|
||||
struct CustomReserved10 @0xcb9fd56c7057593a {
|
||||
}
|
||||
|
||||
|
||||
+115
-39
@@ -1793,7 +1793,7 @@ const ::capnp::_::RawSchema s_f6e831752fcdf793 = {
|
||||
1, 11, i_f6e831752fcdf793, nullptr, nullptr, { &s_f6e831752fcdf793, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<119> b_b8007ed8a646b5e6 = {
|
||||
static const ::capnp::_::AlignedData<129> b_b8007ed8a646b5e6 = {
|
||||
{ 0, 0, 0, 0, 5, 0, 6, 0,
|
||||
230, 181, 70, 166, 216, 126, 0, 184,
|
||||
27, 0, 0, 0, 2, 0, 0, 0,
|
||||
@@ -1803,7 +1803,7 @@ static const ::capnp::_::AlignedData<119> b_b8007ed8a646b5e6 = {
|
||||
21, 0, 0, 0, 42, 1, 0, 0,
|
||||
37, 0, 0, 0, 7, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
33, 0, 0, 0, 159, 1, 0, 0,
|
||||
33, 0, 0, 0, 207, 1, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
99, 117, 115, 116, 111, 109, 46, 99,
|
||||
@@ -1812,57 +1812,63 @@ static const ::capnp::_::AlignedData<119> b_b8007ed8a646b5e6 = {
|
||||
83, 80, 46, 69, 118, 101, 110, 116,
|
||||
78, 97, 109, 101, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 0, 1, 0,
|
||||
68, 0, 0, 0, 1, 0, 2, 0,
|
||||
76, 0, 0, 0, 1, 0, 2, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
197, 0, 0, 0, 90, 0, 0, 0,
|
||||
221, 0, 0, 0, 90, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0, 0, 0,
|
||||
193, 0, 0, 0, 98, 0, 0, 0,
|
||||
217, 0, 0, 0, 98, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
2, 0, 0, 0, 0, 0, 0, 0,
|
||||
189, 0, 0, 0, 186, 0, 0, 0,
|
||||
213, 0, 0, 0, 186, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
3, 0, 0, 0, 0, 0, 0, 0,
|
||||
189, 0, 0, 0, 218, 0, 0, 0,
|
||||
213, 0, 0, 0, 218, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
4, 0, 0, 0, 0, 0, 0, 0,
|
||||
193, 0, 0, 0, 138, 0, 0, 0,
|
||||
217, 0, 0, 0, 138, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
5, 0, 0, 0, 0, 0, 0, 0,
|
||||
193, 0, 0, 0, 146, 0, 0, 0,
|
||||
217, 0, 0, 0, 146, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
6, 0, 0, 0, 0, 0, 0, 0,
|
||||
193, 0, 0, 0, 130, 0, 0, 0,
|
||||
217, 0, 0, 0, 130, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
7, 0, 0, 0, 0, 0, 0, 0,
|
||||
189, 0, 0, 0, 130, 0, 0, 0,
|
||||
213, 0, 0, 0, 130, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
8, 0, 0, 0, 0, 0, 0, 0,
|
||||
185, 0, 0, 0, 146, 0, 0, 0,
|
||||
209, 0, 0, 0, 146, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
9, 0, 0, 0, 0, 0, 0, 0,
|
||||
185, 0, 0, 0, 122, 0, 0, 0,
|
||||
209, 0, 0, 0, 122, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
10, 0, 0, 0, 0, 0, 0, 0,
|
||||
181, 0, 0, 0, 202, 0, 0, 0,
|
||||
205, 0, 0, 0, 202, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
11, 0, 0, 0, 0, 0, 0, 0,
|
||||
185, 0, 0, 0, 130, 0, 0, 0,
|
||||
209, 0, 0, 0, 130, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
12, 0, 0, 0, 0, 0, 0, 0,
|
||||
181, 0, 0, 0, 194, 0, 0, 0,
|
||||
205, 0, 0, 0, 194, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
13, 0, 0, 0, 0, 0, 0, 0,
|
||||
181, 0, 0, 0, 226, 0, 0, 0,
|
||||
205, 0, 0, 0, 226, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
14, 0, 0, 0, 0, 0, 0, 0,
|
||||
185, 0, 0, 0, 202, 0, 0, 0,
|
||||
209, 0, 0, 0, 202, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
15, 0, 0, 0, 0, 0, 0, 0,
|
||||
189, 0, 0, 0, 178, 0, 0, 0,
|
||||
213, 0, 0, 0, 178, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
16, 0, 0, 0, 0, 0, 0, 0,
|
||||
189, 0, 0, 0, 178, 0, 0, 0,
|
||||
213, 0, 0, 0, 178, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
17, 0, 0, 0, 0, 0, 0, 0,
|
||||
213, 0, 0, 0, 106, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
18, 0, 0, 0, 0, 0, 0, 0,
|
||||
209, 0, 0, 0, 114, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
108, 107, 97, 115, 69, 110, 97, 98,
|
||||
108, 101, 0, 0, 0, 0, 0, 0,
|
||||
@@ -1912,14 +1918,18 @@ static const ::capnp::_::AlignedData<119> b_b8007ed8a646b5e6 = {
|
||||
116, 79, 110, 108, 121, 0, 0, 0,
|
||||
112, 101, 100, 97, 108, 80, 114, 101,
|
||||
115, 115, 101, 100, 65, 108, 101, 114,
|
||||
116, 79, 110, 108, 121, 0, 0, 0, }
|
||||
116, 79, 110, 108, 121, 0, 0, 0,
|
||||
108, 97, 110, 101, 84, 117, 114, 110,
|
||||
76, 101, 102, 116, 0, 0, 0, 0,
|
||||
108, 97, 110, 101, 84, 117, 114, 110,
|
||||
82, 105, 103, 104, 116, 0, 0, 0, }
|
||||
};
|
||||
::capnp::word const* const bp_b8007ed8a646b5e6 = b_b8007ed8a646b5e6.words;
|
||||
#if !CAPNP_LITE
|
||||
static const uint16_t m_b8007ed8a646b5e6[] = {12, 14, 13, 1, 0, 3, 2, 16, 6, 9, 5, 4, 11, 8, 10, 7, 15};
|
||||
static const uint16_t m_b8007ed8a646b5e6[] = {12, 14, 13, 17, 18, 1, 0, 3, 2, 16, 6, 9, 5, 4, 11, 8, 10, 7, 15};
|
||||
const ::capnp::_::RawSchema s_b8007ed8a646b5e6 = {
|
||||
0xb8007ed8a646b5e6, b_b8007ed8a646b5e6.words, 119, nullptr, m_b8007ed8a646b5e6,
|
||||
0, 17, nullptr, nullptr, nullptr, { &s_b8007ed8a646b5e6, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
0xb8007ed8a646b5e6, b_b8007ed8a646b5e6.words, 129, nullptr, m_b8007ed8a646b5e6,
|
||||
0, 19, nullptr, nullptr, nullptr, { &s_b8007ed8a646b5e6, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
CAPNP_DEFINE_ENUM(EventName_b8007ed8a646b5e6, b8007ed8a646b5e6);
|
||||
@@ -3016,32 +3026,98 @@ const ::capnp::_::RawSchema s_f416ec09499d9d19 = {
|
||||
0, 6, i_f416ec09499d9d19, nullptr, nullptr, { &s_f416ec09499d9d19, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<17> b_a1680744031fdb2d = {
|
||||
static const ::capnp::_::AlignedData<35> b_a1680744031fdb2d = {
|
||||
{ 0, 0, 0, 0, 5, 0, 6, 0,
|
||||
45, 219, 31, 3, 68, 7, 104, 161,
|
||||
13, 0, 0, 0, 1, 0, 0, 0,
|
||||
13, 0, 0, 0, 1, 0, 1, 0,
|
||||
89, 10, 85, 29, 102, 186, 38, 181,
|
||||
0, 0, 7, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
21, 0, 0, 0, 234, 0, 0, 0,
|
||||
21, 0, 0, 0, 218, 0, 0, 0,
|
||||
33, 0, 0, 0, 7, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
29, 0, 0, 0, 63, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
99, 117, 115, 116, 111, 109, 46, 99,
|
||||
97, 112, 110, 112, 58, 67, 117, 115,
|
||||
116, 111, 109, 82, 101, 115, 101, 114,
|
||||
118, 101, 100, 57, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 0, 1, 0, }
|
||||
97, 112, 110, 112, 58, 77, 111, 100,
|
||||
101, 108, 68, 97, 116, 97, 86, 50,
|
||||
83, 80, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 0, 1, 0,
|
||||
4, 0, 0, 0, 3, 0, 4, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
13, 0, 0, 0, 146, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
16, 0, 0, 0, 3, 0, 1, 0,
|
||||
28, 0, 0, 0, 2, 0, 1, 0,
|
||||
108, 97, 110, 101, 84, 117, 114, 110,
|
||||
68, 105, 114, 101, 99, 116, 105, 111,
|
||||
110, 0, 0, 0, 0, 0, 0, 0,
|
||||
15, 0, 0, 0, 0, 0, 0, 0,
|
||||
150, 169, 61, 176, 185, 17, 36, 191,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
15, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, }
|
||||
};
|
||||
::capnp::word const* const bp_a1680744031fdb2d = b_a1680744031fdb2d.words;
|
||||
#if !CAPNP_LITE
|
||||
static const ::capnp::_::RawSchema* const d_a1680744031fdb2d[] = {
|
||||
&s_bf2411b9b03da996,
|
||||
};
|
||||
static const uint16_t m_a1680744031fdb2d[] = {0};
|
||||
static const uint16_t i_a1680744031fdb2d[] = {0};
|
||||
const ::capnp::_::RawSchema s_a1680744031fdb2d = {
|
||||
0xa1680744031fdb2d, b_a1680744031fdb2d.words, 17, nullptr, nullptr,
|
||||
0, 0, nullptr, nullptr, nullptr, { &s_a1680744031fdb2d, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
0xa1680744031fdb2d, b_a1680744031fdb2d.words, 35, d_a1680744031fdb2d, m_a1680744031fdb2d,
|
||||
1, 1, i_a1680744031fdb2d, nullptr, nullptr, { &s_a1680744031fdb2d, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<32> b_bf2411b9b03da996 = {
|
||||
{ 0, 0, 0, 0, 5, 0, 6, 0,
|
||||
150, 169, 61, 176, 185, 17, 36, 191,
|
||||
13, 0, 0, 0, 2, 0, 0, 0,
|
||||
89, 10, 85, 29, 102, 186, 38, 181,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
21, 0, 0, 0, 218, 0, 0, 0,
|
||||
33, 0, 0, 0, 7, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
29, 0, 0, 0, 79, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
99, 117, 115, 116, 111, 109, 46, 99,
|
||||
97, 112, 110, 112, 58, 84, 117, 114,
|
||||
110, 68, 105, 114, 101, 99, 116, 105,
|
||||
111, 110, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 0, 1, 0,
|
||||
12, 0, 0, 0, 1, 0, 2, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
29, 0, 0, 0, 42, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0, 0, 0,
|
||||
21, 0, 0, 0, 74, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
2, 0, 0, 0, 0, 0, 0, 0,
|
||||
17, 0, 0, 0, 82, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
110, 111, 110, 101, 0, 0, 0, 0,
|
||||
116, 117, 114, 110, 76, 101, 102, 116,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
116, 117, 114, 110, 82, 105, 103, 104,
|
||||
116, 0, 0, 0, 0, 0, 0, 0, }
|
||||
};
|
||||
::capnp::word const* const bp_bf2411b9b03da996 = b_bf2411b9b03da996.words;
|
||||
#if !CAPNP_LITE
|
||||
static const uint16_t m_bf2411b9b03da996[] = {0, 1, 2};
|
||||
const ::capnp::_::RawSchema s_bf2411b9b03da996 = {
|
||||
0xbf2411b9b03da996, b_bf2411b9b03da996.words, 32, nullptr, m_bf2411b9b03da996,
|
||||
0, 3, nullptr, nullptr, nullptr, { &s_bf2411b9b03da996, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
CAPNP_DEFINE_ENUM(TurnDirection_bf2411b9b03da996, bf2411b9b03da996);
|
||||
static const ::capnp::_::AlignedData<17> b_cb9fd56c7057593a = {
|
||||
{ 0, 0, 0, 0, 5, 0, 6, 0,
|
||||
58, 89, 87, 112, 108, 213, 159, 203,
|
||||
@@ -3609,15 +3685,15 @@ constexpr ::capnp::_::RawSchema const* LiveMapDataSP::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// CustomReserved9
|
||||
// ModelDataV2SP
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr uint16_t CustomReserved9::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t CustomReserved9::_capnpPrivate::pointerCount;
|
||||
constexpr uint16_t ModelDataV2SP::_capnpPrivate::dataWordSize;
|
||||
constexpr uint16_t ModelDataV2SP::_capnpPrivate::pointerCount;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#if !CAPNP_LITE
|
||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr ::capnp::Kind CustomReserved9::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* CustomReserved9::_capnpPrivate::schema;
|
||||
constexpr ::capnp::Kind ModelDataV2SP::_capnpPrivate::kind;
|
||||
constexpr ::capnp::_::RawSchema const* ModelDataV2SP::_capnpPrivate::schema;
|
||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
|
||||
@@ -90,6 +90,8 @@ enum class EventName_b8007ed8a646b5e6: uint16_t {
|
||||
EXPERIMENTAL_MODE_SWITCHED,
|
||||
WRONG_CAR_MODE_ALERT_ONLY,
|
||||
PEDAL_PRESSED_ALERT_ONLY,
|
||||
LANE_TURN_LEFT,
|
||||
LANE_TURN_RIGHT,
|
||||
};
|
||||
CAPNP_DECLARE_ENUM(EventName, b8007ed8a646b5e6);
|
||||
CAPNP_DECLARE_SCHEMA(80ae746ee2596b11);
|
||||
@@ -112,6 +114,13 @@ CAPNP_DECLARE_SCHEMA(9e62278160b7df26);
|
||||
CAPNP_DECLARE_SCHEMA(b86e6369214c01c8);
|
||||
CAPNP_DECLARE_SCHEMA(f416ec09499d9d19);
|
||||
CAPNP_DECLARE_SCHEMA(a1680744031fdb2d);
|
||||
CAPNP_DECLARE_SCHEMA(bf2411b9b03da996);
|
||||
enum class TurnDirection_bf2411b9b03da996: uint16_t {
|
||||
NONE,
|
||||
TURN_LEFT,
|
||||
TURN_RIGHT,
|
||||
};
|
||||
CAPNP_DECLARE_ENUM(TurnDirection, bf2411b9b03da996);
|
||||
CAPNP_DECLARE_SCHEMA(cb9fd56c7057593a);
|
||||
CAPNP_DECLARE_SCHEMA(c2243c65e0340384);
|
||||
CAPNP_DECLARE_SCHEMA(9ccdc8676701b412);
|
||||
@@ -531,21 +540,23 @@ struct LiveMapDataSP {
|
||||
};
|
||||
};
|
||||
|
||||
struct CustomReserved9 {
|
||||
CustomReserved9() = delete;
|
||||
struct ModelDataV2SP {
|
||||
ModelDataV2SP() = delete;
|
||||
|
||||
class Reader;
|
||||
class Builder;
|
||||
class Pipeline;
|
||||
|
||||
struct _capnpPrivate {
|
||||
CAPNP_DECLARE_STRUCT_HEADER(a1680744031fdb2d, 0, 0)
|
||||
CAPNP_DECLARE_STRUCT_HEADER(a1680744031fdb2d, 1, 0)
|
||||
#if !CAPNP_LITE
|
||||
static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }
|
||||
#endif // !CAPNP_LITE
|
||||
};
|
||||
};
|
||||
|
||||
typedef ::capnp::schemas::TurnDirection_bf2411b9b03da996 TurnDirection;
|
||||
|
||||
struct CustomReserved10 {
|
||||
CustomReserved10() = delete;
|
||||
|
||||
@@ -3249,9 +3260,9 @@ private:
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
class CustomReserved9::Reader {
|
||||
class ModelDataV2SP::Reader {
|
||||
public:
|
||||
typedef CustomReserved9 Reads;
|
||||
typedef ModelDataV2SP Reads;
|
||||
|
||||
Reader() = default;
|
||||
inline explicit Reader(::capnp::_::StructReader base): _reader(base) {}
|
||||
@@ -3266,6 +3277,8 @@ public:
|
||||
}
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
inline ::cereal::TurnDirection getLaneTurnDirection() const;
|
||||
|
||||
private:
|
||||
::capnp::_::StructReader _reader;
|
||||
template <typename, ::capnp::Kind>
|
||||
@@ -3278,9 +3291,9 @@ private:
|
||||
friend class ::capnp::Orphanage;
|
||||
};
|
||||
|
||||
class CustomReserved9::Builder {
|
||||
class ModelDataV2SP::Builder {
|
||||
public:
|
||||
typedef CustomReserved9 Builds;
|
||||
typedef ModelDataV2SP Builds;
|
||||
|
||||
Builder() = delete; // Deleted to discourage incorrect usage.
|
||||
// You can explicitly initialize to nullptr instead.
|
||||
@@ -3294,6 +3307,9 @@ public:
|
||||
inline ::kj::StringTree toString() const { return asReader().toString(); }
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
inline ::cereal::TurnDirection getLaneTurnDirection();
|
||||
inline void setLaneTurnDirection( ::cereal::TurnDirection value);
|
||||
|
||||
private:
|
||||
::capnp::_::StructBuilder _builder;
|
||||
template <typename, ::capnp::Kind>
|
||||
@@ -3304,9 +3320,9 @@ private:
|
||||
};
|
||||
|
||||
#if !CAPNP_LITE
|
||||
class CustomReserved9::Pipeline {
|
||||
class ModelDataV2SP::Pipeline {
|
||||
public:
|
||||
typedef CustomReserved9 Pipelines;
|
||||
typedef ModelDataV2SP Pipelines;
|
||||
|
||||
inline Pipeline(decltype(nullptr)): _typeless(nullptr) {}
|
||||
inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless)
|
||||
@@ -6509,6 +6525,20 @@ inline ::capnp::Orphan< ::capnp::Text> LiveMapDataSP::Builder::disownRoadName()
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
|
||||
inline ::cereal::TurnDirection ModelDataV2SP::Reader::getLaneTurnDirection() const {
|
||||
return _reader.getDataField< ::cereal::TurnDirection>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
|
||||
inline ::cereal::TurnDirection ModelDataV2SP::Builder::getLaneTurnDirection() {
|
||||
return _builder.getDataField< ::cereal::TurnDirection>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
inline void ModelDataV2SP::Builder::setLaneTurnDirection( ::cereal::TurnDirection value) {
|
||||
_builder.setDataField< ::cereal::TurnDirection>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS, value);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
CAPNP_END_HEADER
|
||||
|
||||
@@ -31283,7 +31283,7 @@ static const ::capnp::_::AlignedData<2557> b_d314cfd957229c11 = {
|
||||
96, 0, 141, 255, 0, 0, 0, 0,
|
||||
0, 0, 1, 0, 116, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
165, 21, 0, 0, 130, 0, 0, 0,
|
||||
165, 21, 0, 0, 114, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
164, 21, 0, 0, 3, 0, 1, 0,
|
||||
176, 21, 0, 0, 2, 0, 1, 0,
|
||||
@@ -32669,8 +32669,8 @@ static const ::capnp::_::AlignedData<2557> b_d314cfd957229c11 = {
|
||||
16, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
99, 117, 115, 116, 111, 109, 82, 101,
|
||||
115, 101, 114, 118, 101, 100, 57, 0,
|
||||
109, 111, 100, 101, 108, 68, 97, 116,
|
||||
97, 86, 50, 83, 80, 0, 0, 0,
|
||||
16, 0, 0, 0, 0, 0, 0, 0,
|
||||
45, 219, 31, 3, 68, 7, 104, 161,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
@@ -33122,7 +33122,7 @@ static const ::capnp::_::RawSchema* const d_d314cfd957229c11[] = {
|
||||
&s_fe346a9de48d9b50,
|
||||
&s_fe35ad896ffaeacf,
|
||||
};
|
||||
static const uint16_t m_d314cfd957229c11[] = {98, 101, 133, 30, 20, 55, 42, 149, 113, 148, 60, 63, 5, 23, 112, 127, 69, 111, 22, 114, 28, 35, 7, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 116, 124, 125, 126, 6, 132, 70, 87, 76, 71, 59, 92, 128, 85, 26, 10, 91, 21, 48, 3, 41, 40, 99, 100, 1, 65, 64, 32, 96, 19, 146, 8, 46, 25, 72, 51, 44, 37, 62, 115, 36, 61, 129, 94, 131, 16, 14, 122, 119, 120, 117, 121, 118, 49, 18, 0, 24, 109, 95, 78, 105, 9, 108, 75, 82, 104, 83, 38, 84, 27, 134, 68, 110, 54, 58, 56, 47, 53, 45, 12, 81, 80, 33, 89, 90, 31, 13, 147, 2, 86, 15, 130, 107, 17, 4, 11, 73, 103, 97, 123, 52, 66, 135, 43, 34, 39, 102, 57, 50, 106, 79, 93, 67, 74, 88, 77, 29};
|
||||
static const uint16_t m_d314cfd957229c11[] = {98, 101, 133, 30, 20, 55, 42, 149, 113, 148, 60, 63, 5, 23, 112, 127, 69, 111, 22, 114, 28, 35, 7, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 124, 125, 126, 6, 132, 70, 87, 76, 71, 59, 92, 128, 85, 26, 10, 91, 21, 48, 3, 41, 40, 99, 100, 1, 65, 64, 32, 96, 19, 146, 8, 46, 25, 72, 51, 44, 37, 62, 115, 36, 61, 129, 94, 131, 16, 14, 122, 119, 120, 117, 121, 118, 49, 18, 0, 24, 109, 95, 78, 105, 9, 116, 108, 75, 82, 104, 83, 38, 84, 27, 134, 68, 110, 54, 58, 56, 47, 53, 45, 12, 81, 80, 33, 89, 90, 31, 13, 147, 2, 86, 15, 130, 107, 17, 4, 11, 73, 103, 97, 123, 52, 66, 135, 43, 34, 39, 102, 57, 50, 106, 79, 93, 67, 74, 88, 77, 29};
|
||||
static const uint16_t i_d314cfd957229c11[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 0, 67};
|
||||
const ::capnp::_::RawSchema s_d314cfd957229c11 = {
|
||||
0xd314cfd957229c11, b_d314cfd957229c11.words, 2557, d_d314cfd957229c11, m_d314cfd957229c11,
|
||||
|
||||
+38
-38
@@ -2876,7 +2876,7 @@ struct Event {
|
||||
BACKUP_MANAGER_S_P,
|
||||
CAR_STATE_S_P,
|
||||
LIVE_MAP_DATA_S_P,
|
||||
CUSTOM_RESERVED9,
|
||||
MODEL_DATA_V2_S_P,
|
||||
LIVESTREAM_ROAD_ENCODE_IDX,
|
||||
LIVESTREAM_WIDE_ROAD_ENCODE_IDX,
|
||||
LIVESTREAM_DRIVER_ENCODE_IDX,
|
||||
@@ -21598,9 +21598,9 @@ public:
|
||||
inline bool hasLiveMapDataSP() const;
|
||||
inline ::cereal::LiveMapDataSP::Reader getLiveMapDataSP() const;
|
||||
|
||||
inline bool isCustomReserved9() const;
|
||||
inline bool hasCustomReserved9() const;
|
||||
inline ::cereal::CustomReserved9::Reader getCustomReserved9() const;
|
||||
inline bool isModelDataV2SP() const;
|
||||
inline bool hasModelDataV2SP() const;
|
||||
inline ::cereal::ModelDataV2SP::Reader getModelDataV2SP() const;
|
||||
|
||||
inline bool isLivestreamRoadEncodeIdx() const;
|
||||
inline bool hasLivestreamRoadEncodeIdx() const;
|
||||
@@ -22681,13 +22681,13 @@ public:
|
||||
inline void adoptLiveMapDataSP(::capnp::Orphan< ::cereal::LiveMapDataSP>&& value);
|
||||
inline ::capnp::Orphan< ::cereal::LiveMapDataSP> disownLiveMapDataSP();
|
||||
|
||||
inline bool isCustomReserved9();
|
||||
inline bool hasCustomReserved9();
|
||||
inline ::cereal::CustomReserved9::Builder getCustomReserved9();
|
||||
inline void setCustomReserved9( ::cereal::CustomReserved9::Reader value);
|
||||
inline ::cereal::CustomReserved9::Builder initCustomReserved9();
|
||||
inline void adoptCustomReserved9(::capnp::Orphan< ::cereal::CustomReserved9>&& value);
|
||||
inline ::capnp::Orphan< ::cereal::CustomReserved9> disownCustomReserved9();
|
||||
inline bool isModelDataV2SP();
|
||||
inline bool hasModelDataV2SP();
|
||||
inline ::cereal::ModelDataV2SP::Builder getModelDataV2SP();
|
||||
inline void setModelDataV2SP( ::cereal::ModelDataV2SP::Reader value);
|
||||
inline ::cereal::ModelDataV2SP::Builder initModelDataV2SP();
|
||||
inline void adoptModelDataV2SP(::capnp::Orphan< ::cereal::ModelDataV2SP>&& value);
|
||||
inline ::capnp::Orphan< ::cereal::ModelDataV2SP> disownModelDataV2SP();
|
||||
|
||||
inline bool isLivestreamRoadEncodeIdx();
|
||||
inline bool hasLivestreamRoadEncodeIdx();
|
||||
@@ -57664,57 +57664,57 @@ inline ::capnp::Orphan< ::cereal::LiveMapDataSP> Event::Builder::disownLiveMapDa
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
|
||||
inline bool Event::Reader::isCustomReserved9() const {
|
||||
return which() == Event::CUSTOM_RESERVED9;
|
||||
inline bool Event::Reader::isModelDataV2SP() const {
|
||||
return which() == Event::MODEL_DATA_V2_S_P;
|
||||
}
|
||||
inline bool Event::Builder::isCustomReserved9() {
|
||||
return which() == Event::CUSTOM_RESERVED9;
|
||||
inline bool Event::Builder::isModelDataV2SP() {
|
||||
return which() == Event::MODEL_DATA_V2_S_P;
|
||||
}
|
||||
inline bool Event::Reader::hasCustomReserved9() const {
|
||||
if (which() != Event::CUSTOM_RESERVED9) return false;
|
||||
inline bool Event::Reader::hasModelDataV2SP() const {
|
||||
if (which() != Event::MODEL_DATA_V2_S_P) return false;
|
||||
return !_reader.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
|
||||
}
|
||||
inline bool Event::Builder::hasCustomReserved9() {
|
||||
if (which() != Event::CUSTOM_RESERVED9) return false;
|
||||
inline bool Event::Builder::hasModelDataV2SP() {
|
||||
if (which() != Event::MODEL_DATA_V2_S_P) return false;
|
||||
return !_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
|
||||
}
|
||||
inline ::cereal::CustomReserved9::Reader Event::Reader::getCustomReserved9() const {
|
||||
KJ_IREQUIRE((which() == Event::CUSTOM_RESERVED9),
|
||||
inline ::cereal::ModelDataV2SP::Reader Event::Reader::getModelDataV2SP() const {
|
||||
KJ_IREQUIRE((which() == Event::MODEL_DATA_V2_S_P),
|
||||
"Must check which() before get()ing a union member.");
|
||||
return ::capnp::_::PointerHelpers< ::cereal::CustomReserved9>::get(_reader.getPointerField(
|
||||
return ::capnp::_::PointerHelpers< ::cereal::ModelDataV2SP>::get(_reader.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
inline ::cereal::CustomReserved9::Builder Event::Builder::getCustomReserved9() {
|
||||
KJ_IREQUIRE((which() == Event::CUSTOM_RESERVED9),
|
||||
inline ::cereal::ModelDataV2SP::Builder Event::Builder::getModelDataV2SP() {
|
||||
KJ_IREQUIRE((which() == Event::MODEL_DATA_V2_S_P),
|
||||
"Must check which() before get()ing a union member.");
|
||||
return ::capnp::_::PointerHelpers< ::cereal::CustomReserved9>::get(_builder.getPointerField(
|
||||
return ::capnp::_::PointerHelpers< ::cereal::ModelDataV2SP>::get(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
inline void Event::Builder::setCustomReserved9( ::cereal::CustomReserved9::Reader value) {
|
||||
inline void Event::Builder::setModelDataV2SP( ::cereal::ModelDataV2SP::Reader value) {
|
||||
_builder.setDataField<Event::Which>(
|
||||
::capnp::bounded<4>() * ::capnp::ELEMENTS, Event::CUSTOM_RESERVED9);
|
||||
::capnp::_::PointerHelpers< ::cereal::CustomReserved9>::set(_builder.getPointerField(
|
||||
::capnp::bounded<4>() * ::capnp::ELEMENTS, Event::MODEL_DATA_V2_S_P);
|
||||
::capnp::_::PointerHelpers< ::cereal::ModelDataV2SP>::set(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS), value);
|
||||
}
|
||||
inline ::cereal::CustomReserved9::Builder Event::Builder::initCustomReserved9() {
|
||||
inline ::cereal::ModelDataV2SP::Builder Event::Builder::initModelDataV2SP() {
|
||||
_builder.setDataField<Event::Which>(
|
||||
::capnp::bounded<4>() * ::capnp::ELEMENTS, Event::CUSTOM_RESERVED9);
|
||||
return ::capnp::_::PointerHelpers< ::cereal::CustomReserved9>::init(_builder.getPointerField(
|
||||
::capnp::bounded<4>() * ::capnp::ELEMENTS, Event::MODEL_DATA_V2_S_P);
|
||||
return ::capnp::_::PointerHelpers< ::cereal::ModelDataV2SP>::init(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
inline void Event::Builder::adoptCustomReserved9(
|
||||
::capnp::Orphan< ::cereal::CustomReserved9>&& value) {
|
||||
inline void Event::Builder::adoptModelDataV2SP(
|
||||
::capnp::Orphan< ::cereal::ModelDataV2SP>&& value) {
|
||||
_builder.setDataField<Event::Which>(
|
||||
::capnp::bounded<4>() * ::capnp::ELEMENTS, Event::CUSTOM_RESERVED9);
|
||||
::capnp::_::PointerHelpers< ::cereal::CustomReserved9>::adopt(_builder.getPointerField(
|
||||
::capnp::bounded<4>() * ::capnp::ELEMENTS, Event::MODEL_DATA_V2_S_P);
|
||||
::capnp::_::PointerHelpers< ::cereal::ModelDataV2SP>::adopt(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value));
|
||||
}
|
||||
inline ::capnp::Orphan< ::cereal::CustomReserved9> Event::Builder::disownCustomReserved9() {
|
||||
KJ_IREQUIRE((which() == Event::CUSTOM_RESERVED9),
|
||||
inline ::capnp::Orphan< ::cereal::ModelDataV2SP> Event::Builder::disownModelDataV2SP() {
|
||||
KJ_IREQUIRE((which() == Event::MODEL_DATA_V2_S_P),
|
||||
"Must check which() before get()ing a union member.");
|
||||
return ::capnp::_::PointerHelpers< ::cereal::CustomReserved9>::disown(_builder.getPointerField(
|
||||
return ::capnp::_::PointerHelpers< ::cereal::ModelDataV2SP>::disown(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -2631,7 +2631,7 @@ struct Event {
|
||||
backupManagerSP @113 :Custom.BackupManagerSP;
|
||||
carStateSP @114 :Custom.CarStateSP;
|
||||
liveMapDataSP @115 :Custom.LiveMapDataSP;
|
||||
customReserved9 @116 :Custom.CustomReserved9;
|
||||
modelDataV2SP @116 :Custom.ModelDataV2SP;
|
||||
customReserved10 @136 :Custom.CustomReserved10;
|
||||
customReserved11 @137 :Custom.CustomReserved11;
|
||||
customReserved12 @138 :Custom.CustomReserved12;
|
||||
|
||||
Binary file not shown.
@@ -79,6 +79,7 @@ static std::map<std::string, service> services = {
|
||||
{ "carControlSP", {"carControlSP", true, 100, 10}},
|
||||
{ "carStateSP", {"carStateSP", true, 100, 10}},
|
||||
{ "liveMapDataSP", {"liveMapDataSP", true, 1, 1}},
|
||||
{ "modelDataV2SP", {"modelDataV2SP", true, 20, -1}},
|
||||
{ "uiDebug", {"uiDebug", true, 0, 1}},
|
||||
{ "testJoystick", {"testJoystick", true, 0, -1}},
|
||||
{ "alertDebug", {"alertDebug", true, 20, 5}},
|
||||
|
||||
@@ -88,6 +88,7 @@ _services: dict[str, tuple] = {
|
||||
"carControlSP": (True, 100., 10),
|
||||
"carStateSP": (True, 100., 10),
|
||||
"liveMapDataSP": (True, 1., 1),
|
||||
"modelDataV2SP": (True, 20.),
|
||||
|
||||
# debug
|
||||
"uiDebug": (True, 0., 1),
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
#define DEFAULT_MODEL "Down To Ride (Default)"
|
||||
#define DEFAULT_MODEL "Steam Powered (Default)"
|
||||
|
||||
+12
-5
@@ -73,9 +73,9 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
||||
{"LastOffroadStatusPacket", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, JSON}},
|
||||
{"LastPowerDropDetected", {CLEAR_ON_MANAGER_START, STRING}},
|
||||
{"LastUpdateException", {CLEAR_ON_MANAGER_START, STRING}},
|
||||
{"LastUpdateRouteCount", {PERSISTENT, INT}},
|
||||
{"LastUpdateRouteCount", {PERSISTENT, INT, "0"}},
|
||||
{"LastUpdateTime", {PERSISTENT, TIME}},
|
||||
{"LastUpdateUptimeOnroad", {PERSISTENT, FLOAT}},
|
||||
{"LastUpdateUptimeOnroad", {PERSISTENT, FLOAT, "0.0"}},
|
||||
{"LiveDelay", {PERSISTENT | BACKUP, BYTES}},
|
||||
{"LiveParameters", {PERSISTENT, JSON}},
|
||||
{"LiveParametersV2", {PERSISTENT, BYTES}},
|
||||
@@ -146,14 +146,18 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
||||
{"CustomAccLongPressIncrement", {PERSISTENT | BACKUP, INT, "5"}},
|
||||
{"CustomAccShortPressIncrement", {PERSISTENT | BACKUP, INT, "1"}},
|
||||
{"DeviceBootMode", {PERSISTENT | BACKUP, INT, "0"}},
|
||||
{"EnableCopyparty", {PERSISTENT | BACKUP, BOOL}},
|
||||
{"EnableGithubRunner", {PERSISTENT | BACKUP, BOOL}},
|
||||
{"GithubRunnerSufficientVoltage", {CLEAR_ON_MANAGER_START , BOOL}},
|
||||
{"InteractivityTimeout", {PERSISTENT | BACKUP, INT, "0"}},
|
||||
{"IsDevelopmentBranch", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||
{"MaxTimeOffroad", {PERSISTENT | BACKUP, INT, "1800"}},
|
||||
{"ModelRunnerTypeCache", {CLEAR_ON_ONROAD_TRANSITION, INT}},
|
||||
{"OffroadMode", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||
{"Offroad_TiciSupport", {CLEAR_ON_MANAGER_START, JSON}},
|
||||
{"QuickBootToggle", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||
{"QuietMode", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||
{"RainbowMode", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||
{"ShowAdvancedControls", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||
|
||||
// MADS params
|
||||
@@ -166,6 +170,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
||||
{"ModelManager_ActiveBundle", {PERSISTENT, JSON}},
|
||||
{"ModelManager_ClearCache", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||
{"ModelManager_DownloadIndex", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, INT, "0"}},
|
||||
{"ModelManager_Favs", {PERSISTENT | BACKUP, STRING}},
|
||||
{"ModelManager_LastSyncTime", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, INT, "0"}},
|
||||
{"ModelManager_ModelsCache", {PERSISTENT | BACKUP, JSON}},
|
||||
|
||||
@@ -191,14 +196,16 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
||||
{"DynamicExperimentalControl", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||
{"BlindSpot", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||
|
||||
// model panel params
|
||||
// sunnypilot model params
|
||||
{"LagdToggle", {PERSISTENT | BACKUP, BOOL, "1"}},
|
||||
{"LagdToggleDelay", {PERSISTENT | BACKUP, FLOAT, "0.2"}},
|
||||
{"LagdValueCache", {PERSISTENT, FLOAT, "0.2"}},
|
||||
{"LaneTurnDesire", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||
{"LaneTurnValue", {PERSISTENT | BACKUP, FLOAT, "19.0"}},
|
||||
|
||||
// mapd
|
||||
{"MapAdvisorySpeedLimit", {CLEAR_ON_ONROAD_TRANSITION, FLOAT}},
|
||||
{"MapdVersion", {PERSISTENT, STRING, ""}},
|
||||
{"MapdVersion", {PERSISTENT, STRING}},
|
||||
{"MapSpeedLimit", {CLEAR_ON_ONROAD_TRANSITION, FLOAT, "0.0"}},
|
||||
{"NextMapSpeedLimit", {CLEAR_ON_ONROAD_TRANSITION, JSON}},
|
||||
{"Offroad_OSMUpdateRequired", {CLEAR_ON_MANAGER_START, JSON}},
|
||||
@@ -214,5 +221,5 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
||||
{"OsmStateName", {PERSISTENT, STRING, "All"}},
|
||||
{"OsmStateTitle", {PERSISTENT, STRING}},
|
||||
{"OsmWayTest", {PERSISTENT, STRING}},
|
||||
{"RoadName", {CLEAR_ON_ONROAD_TRANSITION, STRING, ""}},
|
||||
{"RoadName", {CLEAR_ON_ONROAD_TRANSITION, STRING}},
|
||||
};
|
||||
|
||||
Binary file not shown.
+5
-2
@@ -14,8 +14,7 @@ class PIDController:
|
||||
if isinstance(self._k_d, Number):
|
||||
self._k_d = [[0], [self._k_d]]
|
||||
|
||||
self.pos_limit = pos_limit
|
||||
self.neg_limit = neg_limit
|
||||
self.set_limits(pos_limit, neg_limit)
|
||||
|
||||
self.i_rate = 1.0 / rate
|
||||
self.speed = 0.0
|
||||
@@ -41,6 +40,10 @@ class PIDController:
|
||||
self.f = 0.0
|
||||
self.control = 0
|
||||
|
||||
def set_limits(self, pos_limit, neg_limit):
|
||||
self.pos_limit = pos_limit
|
||||
self.neg_limit = neg_limit
|
||||
|
||||
def update(self, error, error_rate=0.0, speed=0.0, feedforward=0., freeze_integrator=False):
|
||||
self.speed = speed
|
||||
self.p = float(error) * self.k_p
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import subprocess
|
||||
from contextlib import contextmanager
|
||||
from subprocess import Popen, PIPE, TimeoutExpired
|
||||
|
||||
|
||||
def run_cmd(cmd: list[str], cwd=None, env=None) -> str:
|
||||
@@ -11,3 +13,16 @@ def run_cmd_default(cmd: list[str], default: str = "", cwd=None, env=None) -> st
|
||||
except subprocess.CalledProcessError:
|
||||
return default
|
||||
|
||||
|
||||
@contextmanager
|
||||
def managed_proc(cmd: list[str], env: dict[str, str]):
|
||||
proc = Popen(cmd, env=env, stdout=PIPE, stderr=PIPE)
|
||||
try:
|
||||
yield proc
|
||||
finally:
|
||||
if proc.poll() is None:
|
||||
proc.terminate()
|
||||
try:
|
||||
proc.wait(timeout=5)
|
||||
except TimeoutExpired:
|
||||
proc.kill()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1
-1
@@ -1 +1 @@
|
||||
#define COMMA_VERSION "2025.08.13-2695"
|
||||
#define COMMA_VERSION "2025.09.08-3000"
|
||||
|
||||
@@ -857,6 +857,12 @@
|
||||
"file": "/data/openpilot/selfdrive/ui/sunnypilot/qt/widgets/expandable_row.cc",
|
||||
"output": "/data/openpilot/selfdrive/ui/sunnypilot/qt/widgets/expandable_row.o"
|
||||
},
|
||||
{
|
||||
"command": "clang++ -o selfdrive/ui/sunnypilot/qt/widgets/external_storage.o -c -std=c++1z -DQCOM2 -mcpu=cortex-a57 -DSUNNYPILOT -D_REENTRANT -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_MESSAGELOGCONTEXT -Wno-deprecated-declarations -g -fPIC -O2 -Wunused -Werror -Wshadow -Wno-unknown-warning-option -Wno-inconsistent-missing-override -Wno-c99-designator -Wno-reorder-init-list -Wno-vla-cxx-extension -DQCOM2 -mcpu=cortex-a57 -DSUNNYPILOT -Ithird_party/opencl/include -I. -Ithird_party/acados/include -Ithird_party/acados/include/blasfeo/include -Ithird_party/acados/include/hpipm/include -Ithird_party/catch2/include -Ithird_party/libyuv/include -Ithird_party/json11 -Ithird_party/linux/include -Ithird_party/snpe/include -Ithird_party -Imsgq -I/usr/include -I/usr/include/aarch64-linux-gnu/qt5 -I/usr/include/aarch64-linux-gnu/qt5/QtGui/5.12.8/QtGui -I/usr/include/aarch64-linux-gnu/qt5/QtWidgets -I/usr/include/aarch64-linux-gnu/qt5/QtGui -I/usr/include/aarch64-linux-gnu/qt5/QtCore -I/usr/include/aarch64-linux-gnu/qt5/QtNetwork -I/usr/include/aarch64-linux-gnu/qt5/QtConcurrent -I/usr/include/aarch64-linux-gnu/qt5/QtDBus -I/usr/include/aarch64-linux-gnu/qt5/QtXml -Ithird_party/qrcode selfdrive/ui/sunnypilot/qt/widgets/external_storage.cc",
|
||||
"directory": "/data/openpilot",
|
||||
"file": "/data/openpilot/selfdrive/ui/sunnypilot/qt/widgets/external_storage.cc",
|
||||
"output": "/data/openpilot/selfdrive/ui/sunnypilot/qt/widgets/external_storage.o"
|
||||
},
|
||||
{
|
||||
"command": "clang++ -o selfdrive/ui/sunnypilot/qt/widgets/prime.o -c -std=c++1z -DQCOM2 -mcpu=cortex-a57 -DSUNNYPILOT -D_REENTRANT -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_MESSAGELOGCONTEXT -Wno-deprecated-declarations -g -fPIC -O2 -Wunused -Werror -Wshadow -Wno-unknown-warning-option -Wno-inconsistent-missing-override -Wno-c99-designator -Wno-reorder-init-list -Wno-vla-cxx-extension -DQCOM2 -mcpu=cortex-a57 -DSUNNYPILOT -Ithird_party/opencl/include -I. -Ithird_party/acados/include -Ithird_party/acados/include/blasfeo/include -Ithird_party/acados/include/hpipm/include -Ithird_party/catch2/include -Ithird_party/libyuv/include -Ithird_party/json11 -Ithird_party/linux/include -Ithird_party/snpe/include -Ithird_party -Imsgq -I/usr/include -I/usr/include/aarch64-linux-gnu/qt5 -I/usr/include/aarch64-linux-gnu/qt5/QtGui/5.12.8/QtGui -I/usr/include/aarch64-linux-gnu/qt5/QtWidgets -I/usr/include/aarch64-linux-gnu/qt5/QtGui -I/usr/include/aarch64-linux-gnu/qt5/QtCore -I/usr/include/aarch64-linux-gnu/qt5/QtNetwork -I/usr/include/aarch64-linux-gnu/qt5/QtConcurrent -I/usr/include/aarch64-linux-gnu/qt5/QtDBus -I/usr/include/aarch64-linux-gnu/qt5/QtXml -Ithird_party/qrcode selfdrive/ui/sunnypilot/qt/widgets/prime.cc",
|
||||
"directory": "/data/openpilot",
|
||||
@@ -1001,6 +1007,12 @@
|
||||
"file": "/data/openpilot/selfdrive/ui/sunnypilot/qt/widgets/moc_expandable_row.cc",
|
||||
"output": "/data/openpilot/selfdrive/ui/sunnypilot/qt/widgets/moc_expandable_row.o"
|
||||
},
|
||||
{
|
||||
"command": "clang++ -o selfdrive/ui/sunnypilot/qt/widgets/moc_external_storage.o -c -std=c++1z -DQCOM2 -mcpu=cortex-a57 -DSUNNYPILOT -D_REENTRANT -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_MESSAGELOGCONTEXT -Wno-deprecated-declarations -g -fPIC -O2 -Wunused -Werror -Wshadow -Wno-unknown-warning-option -Wno-inconsistent-missing-override -Wno-c99-designator -Wno-reorder-init-list -Wno-vla-cxx-extension -DQCOM2 -mcpu=cortex-a57 -DSUNNYPILOT -Ithird_party/opencl/include -I. -Ithird_party/acados/include -Ithird_party/acados/include/blasfeo/include -Ithird_party/acados/include/hpipm/include -Ithird_party/catch2/include -Ithird_party/libyuv/include -Ithird_party/json11 -Ithird_party/linux/include -Ithird_party/snpe/include -Ithird_party -Imsgq -I/usr/include -I/usr/include/aarch64-linux-gnu/qt5 -I/usr/include/aarch64-linux-gnu/qt5/QtGui/5.12.8/QtGui -I/usr/include/aarch64-linux-gnu/qt5/QtWidgets -I/usr/include/aarch64-linux-gnu/qt5/QtGui -I/usr/include/aarch64-linux-gnu/qt5/QtCore -I/usr/include/aarch64-linux-gnu/qt5/QtNetwork -I/usr/include/aarch64-linux-gnu/qt5/QtConcurrent -I/usr/include/aarch64-linux-gnu/qt5/QtDBus -I/usr/include/aarch64-linux-gnu/qt5/QtXml -Ithird_party/qrcode selfdrive/ui/sunnypilot/qt/widgets/moc_external_storage.cc",
|
||||
"directory": "/data/openpilot",
|
||||
"file": "/data/openpilot/selfdrive/ui/sunnypilot/qt/widgets/moc_external_storage.cc",
|
||||
"output": "/data/openpilot/selfdrive/ui/sunnypilot/qt/widgets/moc_external_storage.o"
|
||||
},
|
||||
{
|
||||
"command": "clang++ -o selfdrive/ui/sunnypilot/qt/widgets/moc_prime.o -c -std=c++1z -DQCOM2 -mcpu=cortex-a57 -DSUNNYPILOT -D_REENTRANT -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_MESSAGELOGCONTEXT -Wno-deprecated-declarations -g -fPIC -O2 -Wunused -Werror -Wshadow -Wno-unknown-warning-option -Wno-inconsistent-missing-override -Wno-c99-designator -Wno-reorder-init-list -Wno-vla-cxx-extension -DQCOM2 -mcpu=cortex-a57 -DSUNNYPILOT -Ithird_party/opencl/include -I. -Ithird_party/acados/include -Ithird_party/acados/include/blasfeo/include -Ithird_party/acados/include/hpipm/include -Ithird_party/catch2/include -Ithird_party/libyuv/include -Ithird_party/json11 -Ithird_party/linux/include -Ithird_party/snpe/include -Ithird_party -Imsgq -I/usr/include -I/usr/include/aarch64-linux-gnu/qt5 -I/usr/include/aarch64-linux-gnu/qt5/QtGui/5.12.8/QtGui -I/usr/include/aarch64-linux-gnu/qt5/QtWidgets -I/usr/include/aarch64-linux-gnu/qt5/QtGui -I/usr/include/aarch64-linux-gnu/qt5/QtCore -I/usr/include/aarch64-linux-gnu/qt5/QtNetwork -I/usr/include/aarch64-linux-gnu/qt5/QtConcurrent -I/usr/include/aarch64-linux-gnu/qt5/QtDBus -I/usr/include/aarch64-linux-gnu/qt5/QtXml -Ithird_party/qrcode selfdrive/ui/sunnypilot/qt/widgets/moc_prime.cc",
|
||||
"directory": "/data/openpilot",
|
||||
|
||||
+17
-4
@@ -4,12 +4,13 @@
|
||||
|
||||
A supported vehicle is one that just works when you install a comma device. All supported cars provide a better experience than any stock system. Supported vehicles reference the US market unless otherwise specified.
|
||||
|
||||
# 321 Supported Cars
|
||||
# 334 Supported Cars
|
||||
|
||||
|Make|Model|Supported Package|ACC|No ACC accel below|No ALC below|Steering Torque|Resume from stop|<a href="##"><img width=2000></a>Hardware Needed<br> |Video|Setup Video|
|
||||
|---|---|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
|
||||
|Acura|ILX 2016-18|Technology Plus Package or AcuraWatch Plus|openpilot|26 mph|25 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Acura ILX 2016-18">Buy Here</a></sub></details>|||
|
||||
|Acura|ILX 2019|All|openpilot|26 mph|25 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Acura ILX 2019">Buy Here</a></sub></details>|||
|
||||
|Acura|MDX 2025|All except Type S|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch C connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Acura MDX 2025">Buy Here</a></sub></details>|||
|
||||
|Acura|RDX 2016-18|AcuraWatch Plus or Advance Package|openpilot|26 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Acura RDX 2016-18">Buy Here</a></sub></details>|||
|
||||
|Acura|RDX 2019-21|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|3 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Acura RDX 2019-21">Buy Here</a></sub></details>|||
|
||||
|Audi|A3 2014-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Audi A3 2014-19">Buy Here</a></sub></details>|||
|
||||
@@ -72,19 +73,25 @@ A supported vehicle is one that just works when you install a comma device. All
|
||||
|Genesis|GV80 2023[<sup>6</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai M connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Genesis GV80 2023">Buy Here</a></sub></details>|||
|
||||
|GMC|Sierra 1500 2020-21|Driver Alert Package II|openpilot available[<sup>1</sup>](#footnotes)|0 mph|6 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 GM connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=GMC Sierra 1500 2020-21">Buy Here</a></sub></details>|<a href="https://youtu.be/5HbNoBLzRwE" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
||||
|Honda|Accord 2018-22|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|3 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Accord 2018-22">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=mrUwlj3Mi58" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
||||
|Honda|Accord 2023|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch C connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Accord 2023">Buy Here</a></sub></details>|||
|
||||
|Honda|Accord 2023-25|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch C connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Accord 2023-25">Buy Here</a></sub></details>|||
|
||||
|Honda|Accord Hybrid 2018-22|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|3 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Accord Hybrid 2018-22">Buy Here</a></sub></details>|||
|
||||
|Honda|Accord Hybrid 2023-25|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch C connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Accord Hybrid 2023-25">Buy Here</a></sub></details>|||
|
||||
|Honda|City (Brazil only) 2023|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|14 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch B connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Honda City (Brazil only) 2023">Buy Here</a></sub></details>|||
|
||||
|Honda|Civic 2016-18|Honda Sensing|openpilot|0 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic 2016-18">Buy Here</a></sub></details>|<a href="https://youtu.be/-IkImTe1NYE" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
||||
|Honda|Civic 2019-21|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|2 mph[<sup>5</sup>](#footnotes)|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic 2019-21">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=4Iz1Mz5LGF8" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
||||
|Honda|Civic 2022-24|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch B connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic 2022-24">Buy Here</a></sub></details>|<a href="https://youtu.be/ytiOT5lcp6Q" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
||||
|Honda|Civic Hatchback 2017-21|Honda Sensing|openpilot available[<sup>1</sup>](#footnotes)|0 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic Hatchback 2017-21">Buy Here</a></sub></details>|||
|
||||
|Honda|Civic Hatchback 2017-18|Honda Sensing|openpilot available[<sup>1</sup>](#footnotes)|0 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic Hatchback 2017-18">Buy Here</a></sub></details>|||
|
||||
|Honda|Civic Hatchback 2019-21|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic Hatchback 2019-21">Buy Here</a></sub></details>|||
|
||||
|Honda|Civic Hatchback 2022-24|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch B connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic Hatchback 2022-24">Buy Here</a></sub></details>|<a href="https://youtu.be/ytiOT5lcp6Q" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
||||
|Honda|Civic Hatchback Hybrid 2025|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch B connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic Hatchback Hybrid 2025">Buy Here</a></sub></details>|||
|
||||
|Honda|Civic Hatchback Hybrid (Europe only) 2023|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch B connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic Hatchback Hybrid (Europe only) 2023">Buy Here</a></sub></details>|||
|
||||
|Honda|Civic Hybrid 2025|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch B connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic Hybrid 2025">Buy Here</a></sub></details>|||
|
||||
|Honda|Clarity 2018-21|Honda Sensing|openpilot|0 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector + Honda Clarity Proxy Board<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://shop.retropilot.org/product/honda-clarity-proxy-board-kit">Buy Here</a></sub></details>|||
|
||||
|Honda|CR-V 2015-16|Touring Trim|openpilot|26 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Honda CR-V 2015-16">Buy Here</a></sub></details>|||
|
||||
|Honda|CR-V 2017-22|Honda Sensing|openpilot available[<sup>1</sup>](#footnotes)|0 mph|15 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Honda CR-V 2017-22">Buy Here</a></sub></details>|||
|
||||
|Honda|CR-V 2023-25|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch C connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Honda CR-V 2023-25">Buy Here</a></sub></details>|||
|
||||
|Honda|CR-V Hybrid 2017-22|Honda Sensing|openpilot available[<sup>1</sup>](#footnotes)|0 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Honda CR-V Hybrid 2017-22">Buy Here</a></sub></details>|||
|
||||
|Honda|CR-V Hybrid 2023-25|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch C connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Honda CR-V Hybrid 2023-25">Buy Here</a></sub></details>|||
|
||||
|Honda|e 2020|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|3 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Honda e 2020">Buy Here</a></sub></details>|||
|
||||
|Honda|Fit 2018-20|Honda Sensing|openpilot|26 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Fit 2018-20">Buy Here</a></sub></details>|||
|
||||
|Honda|Freed 2020|Honda Sensing|openpilot|26 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Freed 2020">Buy Here</a></sub></details>|||
|
||||
@@ -95,6 +102,7 @@ A supported vehicle is one that just works when you install a comma device. All
|
||||
|Honda|Odyssey 2018-20|Honda Sensing|openpilot|26 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Odyssey 2018-20">Buy Here</a></sub></details>|||
|
||||
|Honda|Passport 2019-25|All|openpilot|26 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Passport 2019-25">Buy Here</a></sub></details>|||
|
||||
|Honda|Pilot 2016-22|Honda Sensing|openpilot|26 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Pilot 2016-22">Buy Here</a></sub></details>|||
|
||||
|Honda|Pilot 2023-25|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch C connector<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Pilot 2023-25">Buy Here</a></sub></details>|||
|
||||
|Honda|Ridgeline 2017-25|Honda Sensing|openpilot|26 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Ridgeline 2017-25">Buy Here</a></sub></details>|||
|
||||
|Hyundai|Azera 2022|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Azera 2022">Buy Here</a></sub></details>|||
|
||||
|Hyundai|Azera Hybrid 2019|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Azera Hybrid 2019">Buy Here</a></sub></details>|||
|
||||
@@ -105,6 +113,7 @@ A supported vehicle is one that just works when you install a comma device. All
|
||||
|Hyundai|Elantra 2021-23|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Elantra 2021-23">Buy Here</a></sub></details>|<a href="https://youtu.be/_EdYQtV52-c" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
||||
|Hyundai|Elantra GT 2017-20|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Elantra GT 2017-20">Buy Here</a></sub></details>|||
|
||||
|Hyundai|Elantra Hybrid 2021-23|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Elantra Hybrid 2021-23">Buy Here</a></sub></details>|<a href="https://youtu.be/_EdYQtV52-c" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
||||
|Hyundai|Elantra Non-SCC 2022|No Smart Cruise Control (Non-SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Elantra Non-SCC 2022">Buy Here</a></sub></details>|||
|
||||
|Hyundai|Genesis 2015-16|Smart Cruise Control (SCC)|Stock|19 mph|37 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai J connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Genesis 2015-16">Buy Here</a></sub></details>|||
|
||||
|Hyundai|i30 2017-19|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai i30 2017-19">Buy Here</a></sub></details>|||
|
||||
|Hyundai|Ioniq 5 (Southeast Asia and Europe only) 2022-24[<sup>6</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai Q connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Ioniq 5 (Southeast Asia and Europe only) 2022-24">Buy Here</a></sub></details>|||
|
||||
@@ -118,11 +127,13 @@ A supported vehicle is one that just works when you install a comma device. All
|
||||
|Hyundai|Ioniq Plug-in Hybrid 2019|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Ioniq Plug-in Hybrid 2019">Buy Here</a></sub></details>|||
|
||||
|Hyundai|Ioniq Plug-in Hybrid 2020-22|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Ioniq Plug-in Hybrid 2020-22">Buy Here</a></sub></details>|||
|
||||
|Hyundai|Kona 2020|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|6 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai B connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Kona 2020">Buy Here</a></sub></details>|||
|
||||
|Hyundai|Kona 2022|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai O connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Kona 2022">Buy Here</a></sub></details>|||
|
||||
|Hyundai|Kona 2022-23|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai O connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Kona 2022-23">Buy Here</a></sub></details>|||
|
||||
|Hyundai|Kona Electric 2018-21|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai G connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Kona Electric 2018-21">Buy Here</a></sub></details>|||
|
||||
|Hyundai|Kona Electric 2022-23|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai O connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Kona Electric 2022-23">Buy Here</a></sub></details>|||
|
||||
|Hyundai|Kona Electric (with HDA II, Korea only) 2023[<sup>6</sup>](#footnotes)|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai R connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Kona Electric (with HDA II, Korea only) 2023">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=U2fOCmcQ8hw" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
||||
|Hyundai|Kona Electric Non-SCC 2019|No Smart Cruise Control (Non-SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai G connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Kona Electric Non-SCC 2019">Buy Here</a></sub></details>|||
|
||||
|Hyundai|Kona Hybrid 2020|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai I connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Kona Hybrid 2020">Buy Here</a></sub></details>|||
|
||||
|Hyundai|Kona Non-SCC 2019|No Smart Cruise Control (Non-SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai B connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Kona Non-SCC 2019">Buy Here</a></sub></details>|||
|
||||
|Hyundai|Nexo 2021|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Nexo 2021">Buy Here</a></sub></details>|||
|
||||
|Hyundai|Palisade 2020-22|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Palisade 2020-22">Buy Here</a></sub></details>|<a href="https://youtu.be/TAnDqjF4fDY?t=456" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
||||
|Hyundai|Santa Cruz 2022-24[<sup>6</sup>](#footnotes)|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai N connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Santa Cruz 2022-24">Buy Here</a></sub></details>|||
|
||||
@@ -146,6 +157,7 @@ A supported vehicle is one that just works when you install a comma device. All
|
||||
|Kia|Carnival 2022-24[<sup>6</sup>](#footnotes)|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Carnival 2022-24">Buy Here</a></sub></details>|||
|
||||
|Kia|Carnival (China only) 2023[<sup>6</sup>](#footnotes)|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Carnival (China only) 2023">Buy Here</a></sub></details>|||
|
||||
|Kia|Ceed 2019-21|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Ceed 2019-21">Buy Here</a></sub></details>|||
|
||||
|Kia|Ceed Plug-in Hybrid Non-SCC 2022|No Smart Cruise Control (Non-SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai I connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Ceed Plug-in Hybrid Non-SCC 2022">Buy Here</a></sub></details>|||
|
||||
|Kia|EV6 (Southeast Asia only) 2022-24[<sup>6</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai P connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Kia EV6 (Southeast Asia only) 2022-24">Buy Here</a></sub></details>|||
|
||||
|Kia|EV6 (with HDA II) 2022-24[<sup>6</sup>](#footnotes)|Highway Driving Assist II|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai P connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Kia EV6 (with HDA II) 2022-24">Buy Here</a></sub></details>|||
|
||||
|Kia|EV6 (without HDA II) 2022-24[<sup>6</sup>](#footnotes)|Highway Driving Assist|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai L connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Kia EV6 (without HDA II) 2022-24">Buy Here</a></sub></details>|||
|
||||
@@ -293,6 +305,7 @@ A supported vehicle is one that just works when you install a comma device. All
|
||||
|Toyota|RAV4 Hybrid 2022|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 Hybrid 2022">Buy Here</a></sub></details>|<a href="https://youtu.be/U0nH9cnrFB0" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
||||
|Toyota|RAV4 Hybrid 2023-25|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 Hybrid 2023-25">Buy Here</a></sub></details>|<a href="https://youtu.be/4eIsEq4L4Ng" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
||||
|Toyota|Sienna 2018-20|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Sienna 2018-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=q1UPOo4Sh68" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
||||
|Toyota|Wildlander PHEV 2021|All|openpilot|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Wildlander PHEV 2021">Buy Here</a></sub></details>|||
|
||||
|Volkswagen|Arteon 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Arteon 2018-23">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
||||
|Volkswagen|Arteon eHybrid 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Arteon eHybrid 2020-23">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
||||
|Volkswagen|Arteon R 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Arteon R 2020-23">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
||||
|
||||
@@ -6,7 +6,7 @@ Development is coordinated through [Discord](https://discord.comma.ai) and GitHu
|
||||
|
||||
### Getting Started
|
||||
|
||||
* Setup your [development environment](../tools/)
|
||||
* Set up your [development environment](/tools/)
|
||||
* Join our [Discord](https://discord.comma.ai)
|
||||
* Docs are at https://docs.comma.ai and https://blog.comma.ai
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Turn the speed blue
|
||||
*A getting started guide for openpilot development*
|
||||
|
||||
In 30 minutes, we'll get an openpilot development environment setup on your computer and make some changes to openpilot's UI.
|
||||
In 30 minutes, we'll get an openpilot development environment set up on your computer and make some changes to openpilot's UI.
|
||||
|
||||
And if you have a comma 3/3X, we'll deploy the change to your device for testing.
|
||||
|
||||
## 1. Setup your development environment
|
||||
## 1. Set up your development environment
|
||||
|
||||
Run this to clone openpilot and install all the dependencies:
|
||||
```bash
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ export OPENBLAS_NUM_THREADS=1
|
||||
export VECLIB_MAXIMUM_THREADS=1
|
||||
|
||||
if [ -z "$AGNOS_VERSION" ]; then
|
||||
export AGNOS_VERSION="12.6"
|
||||
export AGNOS_VERSION="12.8"
|
||||
fi
|
||||
|
||||
export STAGING_ROOT="/data/safe_staging"
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
# On any failure, run the fallback launcher
|
||||
trap 'exec ./launch_chffrplus.sh' ERR
|
||||
C3_LAUNCH_SH="./sunnypilot/system/hardware/c3/launch_chffrplus.sh"
|
||||
|
||||
MODEL="$(tr -d '\0' < "/sys/firmware/devicetree/base/model")"
|
||||
export MODEL
|
||||
|
||||
if [ "$MODEL" = "comma tici" ]; then
|
||||
# Force a failure if the launcher doesn't exist
|
||||
[ -x "$C3_LAUNCH_SH" ] || false
|
||||
|
||||
# If it exists, run it
|
||||
exec "$C3_LAUNCH_SH"
|
||||
fi
|
||||
|
||||
exec ./launch_chffrplus.sh
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -9,7 +9,7 @@
|
||||
|Acura|Integra 2023-25|All|[Community](#community)|
|
||||
|Acura|MDX 2015-16|Advance Package|[Community](#community)|
|
||||
|Acura|MDX 2017-20|All|[Community](#community)|
|
||||
|Acura|MDX 2025|All|[Community](#community)|
|
||||
|Acura|MDX 2025|All except Type S|[Upstream](#upstream)|
|
||||
|Acura|RDX 2016-18|AcuraWatch Plus or Advance Package|[Upstream](#upstream)|
|
||||
|Acura|RDX 2019-21|All|[Upstream](#upstream)|
|
||||
|Acura|RDX 2022-25|All|[Community](#community)|
|
||||
@@ -82,9 +82,9 @@
|
||||
|GMC|Yukon 2019-20|Adaptive Cruise Control (ACC) & LKAS|[Dashcam mode](#dashcam)|
|
||||
|Honda|Accord 2016-17|Honda Sensing|[Community](#community)|
|
||||
|Honda|Accord 2018-22|All|[Upstream](#upstream)|
|
||||
|Honda|Accord 2023|All|[Upstream](#upstream)|
|
||||
|Honda|Accord 2024-25|All|[Community](#community)|
|
||||
|Honda|Accord 2023-25|All|[Upstream](#upstream)|
|
||||
|Honda|Accord Hybrid 2018-22|All|[Upstream](#upstream)|
|
||||
|Honda|Accord Hybrid 2023-25|All|[Upstream](#upstream)|
|
||||
|Honda|Civic 2016-18|Honda Sensing|[Upstream](#upstream)|
|
||||
|Honda|Civic 2019-21|All|[Upstream](#upstream)|
|
||||
|Honda|Civic 2022-24|All|[Upstream](#upstream)|
|
||||
@@ -96,9 +96,9 @@
|
||||
|Honda|Clarity 2018-21|All|[Community](#community)|
|
||||
|Honda|CR-V 2015-16|Touring Trim|[Upstream](#upstream)|
|
||||
|Honda|CR-V 2017-22|Honda Sensing|[Upstream](#upstream)|
|
||||
|Honda|CR-V 2023-25|All|[Community](#community)|
|
||||
|Honda|CR-V 2023-25|All|[Upstream](#upstream)|
|
||||
|Honda|CR-V Hybrid 2017-22|Honda Sensing|[Upstream](#upstream)|
|
||||
|Honda|CR-V Hybrid 2023-25|All|[Community](#community)|
|
||||
|Honda|CR-V Hybrid 2023-25|All|[Upstream](#upstream)|
|
||||
|Honda|e 2020|All|[Upstream](#upstream)|
|
||||
|Honda|Fit 2018-20|Honda Sensing|[Upstream](#upstream)|
|
||||
|Honda|Freed 2020|Honda Sensing|[Upstream](#upstream)|
|
||||
@@ -111,8 +111,7 @@
|
||||
|Honda|Passport 2019-25|All|[Upstream](#upstream)|
|
||||
|Honda|Passport 2026|All|[Community](#community)|
|
||||
|Honda|Pilot 2016-22|Honda Sensing|[Upstream](#upstream)|
|
||||
|Honda|Pilot 2023|All|[Dashcam mode](#dashcam)|
|
||||
|Honda|Pilot 2023-25|All|[Community](#community)|
|
||||
|Honda|Pilot 2023-25|All|[Upstream](#upstream)|
|
||||
|Honda|Prologue 2024-25|All|[Not compatible](#can-bus-security)|
|
||||
|Honda|Ridgeline 2017-25|Honda Sensing|[Upstream](#upstream)|
|
||||
|Hyundai|Azera 2022|All|[Upstream](#upstream)|
|
||||
@@ -137,7 +136,7 @@
|
||||
|Hyundai|Ioniq Plug-in Hybrid 2019|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|
||||
|Hyundai|Ioniq Plug-in Hybrid 2020-22|All|[Upstream](#upstream)|
|
||||
|Hyundai|Kona 2020|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|
||||
|Hyundai|Kona 2022|Smart Cruise Control (SCC)|[Dashcam mode](#dashcam)|
|
||||
|Hyundai|Kona 2022-23|Smart Cruise Control (SCC)|[Dashcam mode](#dashcam)|
|
||||
|Hyundai|Kona Electric 2018-21|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|
||||
|Hyundai|Kona Electric 2022-23|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|
||||
|Hyundai|Kona Electric (with HDA II, Korea only) 2023|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|
||||
@@ -241,6 +240,7 @@
|
||||
|Nissan|Leaf 2018-23|ProPILOT Assist|[Upstream](#upstream)|
|
||||
|Nissan|Rogue 2018-20|ProPILOT Assist|[Upstream](#upstream)|
|
||||
|Nissan|X-Trail 2017|ProPILOT Assist|[Upstream](#upstream)|
|
||||
|Peugeot|208 2019-25|Adaptive Cruise Control (ACC) & Lane Assist|[Dashcam mode](#dashcam)|
|
||||
|Ram|1500 2019-24|Adaptive Cruise Control (ACC)|[Upstream](#upstream)|
|
||||
|Ram|2500 2020-24|Adaptive Cruise Control (ACC)|[Dashcam mode](#dashcam)|
|
||||
|Ram|3500 2019-22|Adaptive Cruise Control (ACC)|[Dashcam mode](#dashcam)|
|
||||
@@ -339,7 +339,7 @@
|
||||
|Toyota|Sienna 2024-25|Any|[Not compatible](#can-bus-security)|
|
||||
|Toyota|Tundra 2022-25|Any|[Not compatible](#can-bus-security)|
|
||||
|Toyota|Venza 2021-25|Any|[Not compatible](#can-bus-security)|
|
||||
|Toyota|Yaris (Non-US only) 2023|All|[Community](#community)|
|
||||
|Toyota|Yaris (Non-US only) 2020, 2023|All|[Community](#community)|
|
||||
|Volkswagen|Arteon 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)|
|
||||
|Volkswagen|Arteon eHybrid 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)|
|
||||
|Volkswagen|Arteon R 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)|
|
||||
|
||||
@@ -14,6 +14,7 @@ from opendbc.car.hyundai.hyundaicanfd import hkg_can_fd_checksum
|
||||
from opendbc.car.volkswagen.mqbcan import volkswagen_mqb_meb_checksum, xor_checksum
|
||||
from opendbc.car.tesla.teslacan import tesla_checksum
|
||||
from opendbc.car.body.bodycan import body_checksum
|
||||
from opendbc.car.psa.psacan import psa_checksum
|
||||
|
||||
|
||||
class SignalType:
|
||||
@@ -29,6 +30,7 @@ class SignalType:
|
||||
HKG_CAN_FD_CHECKSUM = 9
|
||||
FCA_GIORGIO_CHECKSUM = 10
|
||||
TESLA_CHECKSUM = 11
|
||||
PSA_CHECKSUM = 12
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -196,6 +198,8 @@ def get_checksum_state(dbc_name: str) -> ChecksumState | None:
|
||||
return ChecksumState(8, 4, 7, 3, False, SignalType.BODY_CHECKSUM, body_checksum)
|
||||
elif dbc_name.startswith("tesla_model3_party"):
|
||||
return ChecksumState(8, -1, 0, -1, True, SignalType.TESLA_CHECKSUM, tesla_checksum, tesla_setup_signal)
|
||||
elif dbc_name.startswith("psa_"):
|
||||
return ChecksumState(4, 4, 7, 3, False, SignalType.PSA_CHECKSUM, psa_checksum)
|
||||
return None
|
||||
|
||||
|
||||
|
||||
@@ -142,10 +142,9 @@ class CANParser:
|
||||
|
||||
self._add_message(name_or_addr, freq)
|
||||
|
||||
self.can_valid: bool = False
|
||||
self.bus_timeout: bool = False
|
||||
self.can_invalid_cnt: int = CAN_INVALID_CNT
|
||||
self.last_nonempty_nanos: int = 0
|
||||
self._last_update_nanos: int = 0
|
||||
|
||||
def _add_message(self, name_or_addr: str | int, freq: int = None) -> None:
|
||||
if isinstance(name_or_addr, numbers.Number):
|
||||
@@ -181,17 +180,29 @@ class CANParser:
|
||||
|
||||
self.message_states[msg.address] = state
|
||||
|
||||
def update_valid(self, nanos: int) -> None:
|
||||
@property
|
||||
def bus_timeout(self) -> bool:
|
||||
ignore_alive = all(s.ignore_alive for s in self.message_states.values())
|
||||
bus_timeout_threshold = 500 * 1_000_000
|
||||
for st in self.message_states.values():
|
||||
if st.timeout_threshold > 0:
|
||||
bus_timeout_threshold = min(bus_timeout_threshold, st.timeout_threshold)
|
||||
return ((self._last_update_nanos - self.last_nonempty_nanos) > bus_timeout_threshold) and not ignore_alive
|
||||
|
||||
@property
|
||||
def can_valid(self) -> bool:
|
||||
valid = True
|
||||
counters_valid = True
|
||||
bus_timeout = self.bus_timeout
|
||||
for state in self.message_states.values():
|
||||
if state.counter_fail >= MAX_BAD_COUNTER:
|
||||
counters_valid = False
|
||||
if not state.valid(nanos, self.bus_timeout):
|
||||
if not state.valid(self._last_update_nanos, bus_timeout):
|
||||
valid = False
|
||||
|
||||
# TODO: probably only want to increment this once per update() call
|
||||
self.can_invalid_cnt = 0 if valid else min(self.can_invalid_cnt + 1, CAN_INVALID_CNT)
|
||||
self.can_valid = self.can_invalid_cnt < CAN_INVALID_CNT and counters_valid
|
||||
return self.can_invalid_cnt < CAN_INVALID_CNT and counters_valid
|
||||
|
||||
def update(self, strings, sendcan: bool = False):
|
||||
if strings and not isinstance(strings[0], list | tuple):
|
||||
@@ -228,13 +239,7 @@ class CANParser:
|
||||
if not bus_empty:
|
||||
self.last_nonempty_nanos = t
|
||||
|
||||
ignore_alive = all(s.ignore_alive for s in self.message_states.values())
|
||||
bus_timeout_threshold = 500 * 1_000_000
|
||||
for st in self.message_states.values():
|
||||
if st.timeout_threshold > 0:
|
||||
bus_timeout_threshold = min(bus_timeout_threshold, st.timeout_threshold)
|
||||
self.bus_timeout = ((t - self.last_nonempty_nanos) > bus_timeout_threshold) and not ignore_alive
|
||||
self.update_valid(t)
|
||||
self._last_update_nanos = t
|
||||
|
||||
return updated_addrs
|
||||
|
||||
|
||||
@@ -182,6 +182,7 @@ class PlatformConfigBase(Freezable):
|
||||
dbc_dict: DbcDict
|
||||
|
||||
flags: int = 0
|
||||
sp_flags: int = 0
|
||||
|
||||
platform_str: str | None = None
|
||||
|
||||
@@ -246,3 +247,7 @@ class Platforms(str, ReprEnum, metaclass=PlatformsType):
|
||||
@classmethod
|
||||
def with_flags(cls, flags: IntFlag) -> set['Platforms']:
|
||||
return {p for p in cls if p.config.flags & flags}
|
||||
|
||||
@classmethod
|
||||
def with_sp_flags(cls, sp_flags: IntFlag) -> set['Platforms']:
|
||||
return {p for p in cls if p.config.sp_flags & sp_flags}
|
||||
|
||||
@@ -152,7 +152,8 @@ def fingerprint(can_recv: CanRecvCallable, can_send: CanSendCallable, set_obd_mu
|
||||
|
||||
|
||||
def get_car(can_recv: CanRecvCallable, can_send: CanSendCallable, set_obd_multiplexing: ObdCallback, alpha_long_allowed: bool,
|
||||
is_release: bool, num_pandas: int = 1, cached_params: CarParamsT | None = None, fixed_fingerprint: str | None = None):
|
||||
is_release: bool, num_pandas: int = 1, cached_params: CarParamsT | None = None,
|
||||
fixed_fingerprint: str | None = None, init_params_list_sp: list[dict[str, str]] = None):
|
||||
candidate, fingerprints, vin, car_fw, source, exact_match = fingerprint(can_recv, can_send, set_obd_multiplexing, num_pandas, cached_params,
|
||||
fixed_fingerprint)
|
||||
|
||||
@@ -168,7 +169,7 @@ def get_car(can_recv: CanRecvCallable, can_send: CanSendCallable, set_obd_multip
|
||||
CP.fuzzyFingerprint = not exact_match
|
||||
CP_SP = CarInterface.get_params_sp(CP, candidate, fingerprints, car_fw, alpha_long_allowed, docs=False)
|
||||
|
||||
sunnypilot_interfaces(CP, CP_SP, can_recv, can_send)
|
||||
sunnypilot_interfaces(CarInterface, CP, CP_SP, init_params_list_sp, can_recv, can_send)
|
||||
|
||||
return interfaces[CP.carFingerprint](CP, CP_SP)
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ class CarController(CarControllerBase, MadsCarController, CarControllerExt):
|
||||
def __init__(self, dbc_names, CP, CP_SP):
|
||||
CarControllerBase.__init__(self, dbc_names, CP, CP_SP)
|
||||
MadsCarController.__init__(self)
|
||||
CarControllerExt.__init__(self, CP)
|
||||
CarControllerExt.__init__(self, CP, CP_SP)
|
||||
self.apply_torque_last = 0
|
||||
|
||||
self.hud_count = 0
|
||||
@@ -65,7 +65,7 @@ class CarController(CarControllerBase, MadsCarController, CarControllerExt):
|
||||
if CS.out.vEgo < (self.CP.minSteerSpeed - 0.5):
|
||||
lkas_control_bit = False
|
||||
|
||||
lkas_control_bit = CarControllerExt.get_lkas_control_bit(self, CS, lkas_control_bit, self.lkas_control_bit_prev)
|
||||
lkas_control_bit = CarControllerExt.get_lkas_control_bit(self, CS, CC, lkas_control_bit, self.lkas_control_bit_prev)
|
||||
|
||||
# EPS faults if LKAS re-enables too quickly
|
||||
lkas_control_bit = lkas_control_bit and (self.frame - self.last_lkas_falling_edge > 200)
|
||||
|
||||
@@ -5,6 +5,7 @@ from opendbc.car.chrysler.carstate import CarState
|
||||
from opendbc.car.chrysler.radar_interface import RadarInterface
|
||||
from opendbc.car.chrysler.values import CAR, RAM_HD, RAM_DT, RAM_CARS, ChryslerFlags, ChryslerSafetyFlags
|
||||
from opendbc.car.interfaces import CarInterfaceBase
|
||||
from opendbc.sunnypilot.car.chrysler.values import ChryslerFlagsSP
|
||||
|
||||
|
||||
class CarInterface(CarInterfaceBase):
|
||||
@@ -88,4 +89,8 @@ class CarInterface(CarInterfaceBase):
|
||||
if candidate == CAR.RAM_HD_5TH_GEN:
|
||||
stock_cp.dashcamOnly = False
|
||||
|
||||
if 0x4FF in fingerprint[0]:
|
||||
ret.flags |= ChryslerFlagsSP.NO_MIN_STEERING_SPEED.value
|
||||
stock_cp.minSteerSpeed = 0.
|
||||
|
||||
return ret
|
||||
|
||||
@@ -145,6 +145,10 @@ class CarHarness(EnumBase):
|
||||
rivian = BaseCarHarness("Rivian A connector", parts=[Accessory.harness_box, Accessory.comma_power, Cable.long_obdc_cable, Cable.usbc_coupler])
|
||||
tesla_a = BaseCarHarness("Tesla A connector", parts=[Accessory.harness_box, Accessory.comma_power, Cable.long_obdc_cable, Cable.usbc_coupler])
|
||||
tesla_b = BaseCarHarness("Tesla B connector", parts=[Accessory.harness_box, Accessory.comma_power, Cable.long_obdc_cable, Cable.usbc_coupler])
|
||||
psa_a = BaseCarHarness("PSA A connector", parts=[Accessory.harness_box, Cable.long_obdc_cable, Cable.usbc_coupler])
|
||||
|
||||
# custom harness
|
||||
honda_clarity = BaseCarHarness("Honda Nidec connector + Honda Clarity Proxy Board")
|
||||
|
||||
|
||||
class Device(EnumBase):
|
||||
@@ -175,6 +179,7 @@ DEFAULT_CAR_PARTS: list[EnumBase] = [Device.threex]
|
||||
@dataclass
|
||||
class CarParts:
|
||||
parts: list[EnumBase] = field(default_factory=list)
|
||||
custom_parts_url: str | None = None
|
||||
|
||||
def __call__(self):
|
||||
return copy.deepcopy(self)
|
||||
@@ -304,7 +309,10 @@ class CarDocs:
|
||||
# hardware column
|
||||
hardware_col = "None"
|
||||
if self.car_parts.parts:
|
||||
buy_link = f'<a href="https://comma.ai/shop/comma-3x?harness={self.name}">Buy Here</a>'
|
||||
if self.car_parts.custom_parts_url is not None:
|
||||
buy_link = f'<a href="{self.car_parts.custom_parts_url}">Buy Here</a>'
|
||||
else:
|
||||
buy_link = f'<a href="https://comma.ai/shop/comma-3x?harness={self.name}">Buy Here</a>'
|
||||
|
||||
tools_docs = [part for part in self.car_parts.all_parts() if isinstance(part, Tool)]
|
||||
parts_docs = [part for part in self.car_parts.all_parts() if not isinstance(part, Tool)]
|
||||
|
||||
@@ -7,10 +7,11 @@ from opendbc.car.fw_query_definitions import EcuAddrBusType
|
||||
|
||||
|
||||
def _is_tester_present_response(msg: CanData, subaddr: int = None) -> bool:
|
||||
# ISO-TP messages are always padded to 8 bytes
|
||||
# ISO-TP messages may use CAN frame optimization (not always 8 bytes)
|
||||
# tester present response is always a single frame
|
||||
dat_offset = 1 if subaddr is not None else 0
|
||||
if len(msg.dat) == 8 and 1 <= msg.dat[dat_offset] <= 7:
|
||||
min_length = 4 if subaddr is not None else 3 # bytes: frame len, (pos/neg) sid, (optional negative sid)/0x00 sub-function
|
||||
if min_length <= len(msg.dat) <= 8 and 1 <= msg.dat[dat_offset] <= 7:
|
||||
# success response
|
||||
if msg.dat[dat_offset + 1] == (uds.SERVICE_TYPE.TESTER_PRESENT + 0x40):
|
||||
return True
|
||||
|
||||
@@ -40,20 +40,15 @@ class CAR(Platforms):
|
||||
CommunityCarDocs("Acura Integra 2023-25", "All"),
|
||||
CommunityCarDocs("Acura MDX 2015-16", "Advance Package"),
|
||||
CommunityCarDocs("Acura MDX 2017-20", "All"),
|
||||
CommunityCarDocs("Acura MDX 2025", "All"),
|
||||
CommunityCarDocs("Acura RDX 2022-25", "All"),
|
||||
CommunityCarDocs("Acura RLX 2017", "Advance Package or Technology Package"),
|
||||
CommunityCarDocs("Acura TLX 2015-17", "Advance Package"),
|
||||
CommunityCarDocs("Acura TLX 2018-20", "All"),
|
||||
GMSecurityCarDocs("Acura ZDX 2024", "All"),
|
||||
CommunityCarDocs("Honda Accord 2016-17", "Honda Sensing"),
|
||||
CommunityCarDocs("Honda Accord 2024-25", "All"),
|
||||
CommunityCarDocs("Honda Clarity 2018-21", "All"),
|
||||
CommunityCarDocs("Honda CR-V 2023-25", "All"),
|
||||
CommunityCarDocs("Honda CR-V Hybrid 2023-25", "All"),
|
||||
CommunityCarDocs("Honda Odyssey 2021-25", "All"),
|
||||
CommunityCarDocs("Honda Passport 2026", "All"),
|
||||
CommunityCarDocs("Honda Pilot 2023-25", "All"),
|
||||
GMSecurityCarDocs("Honda Prologue 2024-25", "All"),
|
||||
],
|
||||
)
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
from math import fabs, exp
|
||||
import numpy as np
|
||||
|
||||
from opendbc.car import get_safety_config, structs
|
||||
from opendbc.car.common.basedir import BASEDIR
|
||||
from opendbc.car.common.conversions import Conversions as CV
|
||||
from opendbc.car.gm.carcontroller import CarController
|
||||
from opendbc.car.gm.carstate import CarState
|
||||
from opendbc.car.gm.radar_interface import RadarInterface, RADAR_HEADER_MSG, CAMERA_DATA_HEADER_MSG
|
||||
from opendbc.car.gm.values import CAR, CarControllerParams, EV_CAR, CAMERA_ACC_CAR, SDGM_CAR, ALT_ACCS, CanBus, GMSafetyFlags
|
||||
from opendbc.car.interfaces import CarInterfaceBase, TorqueFromLateralAccelCallbackType, LatControlInputs, NanoFFModel
|
||||
from opendbc.car.interfaces import CarInterfaceBase, TorqueFromLateralAccelCallbackType, LateralAccelFromTorqueCallbackType
|
||||
|
||||
from opendbc.sunnypilot.car.gm.interface_ext import CarInterfaceExt
|
||||
|
||||
TransmissionType = structs.CarParams.TransmissionType
|
||||
NetworkLocation = structs.CarParams.NetworkLocation
|
||||
@@ -20,14 +21,16 @@ NON_LINEAR_TORQUE_PARAMS = {
|
||||
CAR.CHEVROLET_SILVERADO: [3.29974374, 1.0, 0.25571356, 0.0465122]
|
||||
}
|
||||
|
||||
NEURAL_PARAMS_PATH = os.path.join(BASEDIR, 'torque_data/neural_ff_weights.json')
|
||||
|
||||
|
||||
class CarInterface(CarInterfaceBase):
|
||||
class CarInterface(CarInterfaceBase, CarInterfaceExt):
|
||||
CarState = CarState
|
||||
CarController = CarController
|
||||
RadarInterface = RadarInterface
|
||||
|
||||
def __init__(self, CP, CP_SP):
|
||||
CarInterfaceBase.__init__(self, CP, CP_SP)
|
||||
CarInterfaceExt.__init__(self, CP, CarInterfaceBase)
|
||||
|
||||
@staticmethod
|
||||
def get_pid_accel_limits(CP, current_speed, cruise_speed):
|
||||
return CarControllerParams.ACCEL_MIN, CarControllerParams.ACCEL_MAX
|
||||
@@ -45,42 +48,45 @@ class CarInterface(CarInterfaceBase):
|
||||
else:
|
||||
return CarInterfaceBase.get_steer_feedforward_default
|
||||
|
||||
def torque_from_lateral_accel_siglin(self, latcontrol_inputs: LatControlInputs, torque_params: structs.CarParams.LateralTorqueTuning,
|
||||
gravity_adjusted: bool) -> float:
|
||||
def sig(val):
|
||||
# https://timvieira.github.io/blog/post/2014/02/11/exp-normalize-trick
|
||||
if val >= 0:
|
||||
return 1 / (1 + exp(-val)) - 0.5
|
||||
else:
|
||||
z = exp(val)
|
||||
return z / (1 + z) - 0.5
|
||||
def get_lataccel_torque_siglin(self) -> float:
|
||||
|
||||
# The "lat_accel vs torque" relationship is assumed to be the sum of "sigmoid + linear" curves
|
||||
# An important thing to consider is that the slope at 0 should be > 0 (ideally >1)
|
||||
# This has big effect on the stability about 0 (noise when going straight)
|
||||
# ToDo: To generalize to other GMs, explore tanh function as the nonlinear
|
||||
non_linear_torque_params = NON_LINEAR_TORQUE_PARAMS.get(self.CP.carFingerprint)
|
||||
assert non_linear_torque_params, "The params are not defined"
|
||||
a, b, c, _ = non_linear_torque_params
|
||||
steer_torque = (sig(latcontrol_inputs.lateral_acceleration * a) * b) + (latcontrol_inputs.lateral_acceleration * c)
|
||||
return float(steer_torque)
|
||||
def torque_from_lateral_accel_siglin_func(lateral_acceleration: float) -> float:
|
||||
# The "lat_accel vs torque" relationship is assumed to be the sum of "sigmoid + linear" curves
|
||||
# An important thing to consider is that the slope at 0 should be > 0 (ideally >1)
|
||||
# This has big effect on the stability about 0 (noise when going straight)
|
||||
non_linear_torque_params = NON_LINEAR_TORQUE_PARAMS.get(self.CP.carFingerprint)
|
||||
assert non_linear_torque_params, "The params are not defined"
|
||||
a, b, c, _ = non_linear_torque_params
|
||||
sig_input = a * lateral_acceleration
|
||||
sig = np.sign(sig_input) * (1 / (1 + exp(-fabs(sig_input))) - 0.5)
|
||||
steer_torque = (sig * b) + (lateral_acceleration * c)
|
||||
return float(steer_torque)
|
||||
|
||||
def torque_from_lateral_accel_neural(self, latcontrol_inputs: LatControlInputs, torque_params: structs.CarParams.LateralTorqueTuning,
|
||||
gravity_adjusted: bool) -> float:
|
||||
inputs = list(latcontrol_inputs)
|
||||
if gravity_adjusted:
|
||||
inputs[0] += inputs[1]
|
||||
return float(self.neural_ff_model.predict(inputs))
|
||||
lataccel_values = np.arange(-5.0, 5.0, 0.01)
|
||||
torque_values = [torque_from_lateral_accel_siglin_func(x) for x in lataccel_values]
|
||||
assert min(torque_values) < -1 and max(torque_values) > 1, "The torque values should cover the range [-1, 1]"
|
||||
return torque_values, lataccel_values
|
||||
|
||||
def torque_from_lateral_accel(self) -> TorqueFromLateralAccelCallbackType:
|
||||
if self.CP.carFingerprint == CAR.CHEVROLET_BOLT_EUV:
|
||||
self.neural_ff_model = NanoFFModel(NEURAL_PARAMS_PATH, self.CP.carFingerprint)
|
||||
return self.torque_from_lateral_accel_neural
|
||||
elif self.CP.carFingerprint in NON_LINEAR_TORQUE_PARAMS:
|
||||
return self.torque_from_lateral_accel_siglin
|
||||
if self.CP.carFingerprint in NON_LINEAR_TORQUE_PARAMS:
|
||||
torque_values, lataccel_values = self.get_lataccel_torque_siglin()
|
||||
|
||||
def torque_from_lateral_accel_siglin(lateral_acceleration: float, torque_params: structs.CarParams.LateralTorqueTuning):
|
||||
return np.interp(lateral_acceleration, lataccel_values, torque_values)
|
||||
return torque_from_lateral_accel_siglin
|
||||
else:
|
||||
return self.torque_from_lateral_accel_linear
|
||||
|
||||
def lateral_accel_from_torque(self) -> LateralAccelFromTorqueCallbackType:
|
||||
if self.CP.carFingerprint in NON_LINEAR_TORQUE_PARAMS:
|
||||
torque_values, lataccel_values = self.get_lataccel_torque_siglin()
|
||||
|
||||
def lateral_accel_from_torque_siglin(torque: float, torque_params: structs.CarParams.LateralTorqueTuning):
|
||||
return np.interp(torque, torque_values, lataccel_values)
|
||||
return lateral_accel_from_torque_siglin
|
||||
else:
|
||||
return self.lateral_accel_from_torque_linear
|
||||
|
||||
@staticmethod
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
|
||||
ret.brand = "gm"
|
||||
|
||||
@@ -10,6 +10,8 @@ from opendbc.car.honda.values import CAR, DBC, STEER_THRESHOLD, HONDA_BOSCH, HON
|
||||
HondaFlags, CruiseButtons, CruiseSettings, GearShifter
|
||||
from opendbc.car.interfaces import CarStateBase
|
||||
|
||||
from opendbc.sunnypilot.car.honda.carstate_ext import CarStateExt
|
||||
|
||||
TransmissionType = structs.CarParams.TransmissionType
|
||||
ButtonType = structs.CarState.ButtonEvent.Type
|
||||
|
||||
@@ -18,9 +20,10 @@ BUTTONS_DICT = {CruiseButtons.RES_ACCEL: ButtonType.accelCruise, CruiseButtons.D
|
||||
SETTINGS_BUTTONS_DICT = {CruiseSettings.DISTANCE: ButtonType.gapAdjustCruise, CruiseSettings.LKAS: ButtonType.lkas}
|
||||
|
||||
|
||||
class CarState(CarStateBase):
|
||||
class CarState(CarStateBase, CarStateExt):
|
||||
def __init__(self, CP, CP_SP):
|
||||
super().__init__(CP, CP_SP)
|
||||
CarStateBase.__init__(self, CP, CP_SP)
|
||||
CarStateExt.__init__(self, CP, CP_SP)
|
||||
can_define = CANDefine(DBC[CP.carFingerprint][Bus.pt])
|
||||
|
||||
if CP.transmissionType != TransmissionType.manual:
|
||||
@@ -206,6 +209,8 @@ class CarState(CarStateBase):
|
||||
*create_button_events(self.cruise_setting, prev_cruise_setting, SETTINGS_BUTTONS_DICT),
|
||||
]
|
||||
|
||||
CarStateExt.update(self, ret, can_parsers)
|
||||
|
||||
return ret, ret_sp
|
||||
|
||||
def get_can_parsers(self, CP, CP_SP):
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
from opendbc.car.structs import CarParams
|
||||
from opendbc.car.honda.values import CAR
|
||||
|
||||
from opendbc.sunnypilot.car.fw_versions_ext import merge_fw_versions
|
||||
from opendbc.sunnypilot.car.honda.fingerprints_ext import FW_VERSIONS_EXT
|
||||
|
||||
Ecu = CarParams.Ecu
|
||||
|
||||
# Modified FW can be identified by the second dash being replaced by a comma
|
||||
@@ -67,7 +70,6 @@ FW_VERSIONS = {
|
||||
],
|
||||
(Ecu.eps, 0x18da30f1, None): [
|
||||
b'39990-TBX-H120\x00\x00',
|
||||
b'39990-TVA,A150\x00\x00',
|
||||
b'39990-TVA-A140\x00\x00',
|
||||
b'39990-TVA-A150\x00\x00',
|
||||
b'39990-TVA-A160\x00\x00',
|
||||
@@ -147,7 +149,6 @@ FW_VERSIONS = {
|
||||
b'57114-TEA-Q220\x00\x00',
|
||||
],
|
||||
(Ecu.eps, 0x18da30f1, None): [
|
||||
b'39990-TBA,A030\x00\x00',
|
||||
b'39990-TBA-A030\x00\x00',
|
||||
b'39990-TBG-A030\x00\x00',
|
||||
b'39990-TEA-T020\x00\x00',
|
||||
@@ -220,8 +221,6 @@ FW_VERSIONS = {
|
||||
b'39990-TEA-T330\x00\x00',
|
||||
b'39990-TEA-T820\x00\x00',
|
||||
b'39990-TEZ-T020\x00\x00',
|
||||
b'39990-TGG,A020\x00\x00',
|
||||
b'39990-TGG,A120\x00\x00',
|
||||
b'39990-TGG-A020\x00\x00',
|
||||
b'39990-TGG-A120\x00\x00',
|
||||
b'39990-TGG-J510\x00\x00',
|
||||
@@ -354,7 +353,6 @@ FW_VERSIONS = {
|
||||
b'57114-TMC-Z050\x00\x00',
|
||||
],
|
||||
(Ecu.eps, 0x18da30f1, None): [
|
||||
b'39990-TLA,A040\x00\x00',
|
||||
b'39990-TLA-A040\x00\x00',
|
||||
b'39990-TLA-A110\x00\x00',
|
||||
b'39990-TLA-A220\x00\x00',
|
||||
@@ -502,6 +500,14 @@ FW_VERSIONS = {
|
||||
b'36161-TDK-J530\x00\x00',
|
||||
],
|
||||
},
|
||||
CAR.ACURA_MDX_4G_MMR: {
|
||||
(Ecu.fwdCamera, 0x18dab5f1, None): [
|
||||
b'8S102-TYA-A020\x00\x00',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x18dab0f1, None): [
|
||||
b'8S302-TYA-A020\x00\x00',
|
||||
],
|
||||
},
|
||||
CAR.HONDA_ODYSSEY: {
|
||||
(Ecu.gateway, 0x18daeff1, None): [
|
||||
b'38897-THR-A010\x00\x00',
|
||||
@@ -804,6 +810,7 @@ FW_VERSIONS = {
|
||||
(Ecu.fwdRadar, 0x18dab0f1, None): [
|
||||
b'8S102-3M3-T050\x00\x00',
|
||||
b'8S102-3M6-P030\x00\x00',
|
||||
b'8S102-3M6-PA20\x00\x00',
|
||||
b'8S102-3W0-A060\x00\x00',
|
||||
b'8S102-3W0-AB10\x00\x00',
|
||||
b'8S102-3W0-AB20\x00\x00',
|
||||
@@ -938,21 +945,13 @@ FW_VERSIONS = {
|
||||
(Ecu.fwdCamera, 0x18dab5f1, None): [
|
||||
b'8S102-T90-A050\x00\x00',
|
||||
b'8S102-T90-A060\x00\x00',
|
||||
b'8S102-T90-A070\x00\x00',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x18dab0f1, None): [
|
||||
b'8S302-T90-A040\x00\x00',
|
||||
],
|
||||
},
|
||||
CAR.HONDA_ACCORD_11G: {
|
||||
(Ecu.eps, 0x18da30f1, None): [
|
||||
b'39991-30B-A060\x00\x00',
|
||||
],
|
||||
(Ecu.gateway, 0x18daeff1, None): [
|
||||
b'5J802-30B-AA10\x00\x00',
|
||||
],
|
||||
(Ecu.srs, 0x18da53f1, None): [
|
||||
b'77959-30B-A750\x00\x00',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x18dab0f1, None): [
|
||||
b'8S302-30A-A040\x00\x00',
|
||||
],
|
||||
@@ -960,8 +959,40 @@ FW_VERSIONS = {
|
||||
b'8S102-30A-A050\x00\x00',
|
||||
b'8S102-30A-A060\x00\x00',
|
||||
],
|
||||
},
|
||||
CAR.HONDA_CRV_6G: {
|
||||
(Ecu.fwdRadar, 0x18dab0f1, None): [
|
||||
b'8S302-3C0-Q050\x00\x00',
|
||||
b'8S302-3D4-A050\x00\x00',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x18dab5f1, None): [
|
||||
b'8S102-3C0-Q060\x00\x00',
|
||||
b'8S102-3D4-A060\x00\x00',
|
||||
b'8S102-3D4-A070\x00\x00',
|
||||
b'8S102-3D4-A080\x00\x00',
|
||||
b'8S102-3D4-A090\x00\x00',
|
||||
],
|
||||
},
|
||||
CAR.HONDA_CITY_7G: {
|
||||
(Ecu.eps, 0x18da30f1, None): [
|
||||
b'39990-T14-B030\x00\x00',
|
||||
],
|
||||
(Ecu.gateway, 0x18daeff1, None): [
|
||||
b'38897-T14-M110\x00\x00',
|
||||
],
|
||||
(Ecu.srs, 0x18da53f1, None): [
|
||||
b'77959-T00-B830\x00\x00',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x18dab0f1, None): [
|
||||
b'36161-T14-P050\x00\x00',
|
||||
],
|
||||
(Ecu.vsa, 0x18da28f1, None): [
|
||||
b'57114-30B-A030\x00\x00',
|
||||
b'57114-T14-B030\x00\x00',
|
||||
],
|
||||
(Ecu.transmission, 0x18da1ef1, None): [
|
||||
b'28101-63B-M420\x00\x00',
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
FW_VERSIONS = merge_fw_versions(FW_VERSIONS, FW_VERSIONS_EXT)
|
||||
|
||||
@@ -52,8 +52,6 @@ def create_brake_command(packer, CAN, apply_brake, pump_on, pcm_override, pcm_ca
|
||||
pcm_fault_cmd = False
|
||||
|
||||
values = {
|
||||
"COMPUTER_BRAKE": apply_brake,
|
||||
"BRAKE_PUMP_REQUEST": pump_on,
|
||||
"CRUISE_OVERRIDE": pcm_override,
|
||||
"CRUISE_FAULT_CMD": pcm_fault_cmd,
|
||||
"CRUISE_CANCEL_CMD": pcm_cancel_cmd,
|
||||
@@ -66,6 +64,14 @@ def create_brake_command(packer, CAN, apply_brake, pump_on, pcm_override, pcm_ca
|
||||
"AEB_REQ_2": 0,
|
||||
"AEB_STATUS": 0,
|
||||
}
|
||||
|
||||
if car_fingerprint == CAR.HONDA_CLARITY:
|
||||
values["COMPUTER_BRAKE_ALT"] = apply_brake
|
||||
values["BRAKE_PUMP_REQUEST_ALT"] = apply_brake > 0
|
||||
else:
|
||||
values["COMPUTER_BRAKE"] = apply_brake
|
||||
values["BRAKE_PUMP_REQUEST"] = pump_on
|
||||
|
||||
return packer.make_can_msg("BRAKE_COMMAND", CAN.pt, values)
|
||||
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ from opendbc.car.honda.carstate import CarState
|
||||
from opendbc.car.honda.radar_interface import RadarInterface
|
||||
from opendbc.car.interfaces import CarInterfaceBase
|
||||
|
||||
from opendbc.sunnypilot.car.honda.values_ext import HondaFlagsSP, HondaSafetyFlagsSP
|
||||
|
||||
TransmissionType = structs.CarParams.TransmissionType
|
||||
|
||||
|
||||
@@ -36,9 +38,6 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
CAN = CanBus(ret, fingerprint)
|
||||
|
||||
# Pilot 4G needs a rescaled lateral actuator, switch to lat accel torque control, and an updated test route
|
||||
ret.dashcamOnly = candidate in [CAR.HONDA_PILOT_4G]
|
||||
|
||||
if candidate in HONDA_BOSCH:
|
||||
cfgs = [get_safety_config(structs.CarParams.SafetyModel.hondaBosch)]
|
||||
if candidate in HONDA_BOSCH_CANFD and CAN.pt >= 4:
|
||||
@@ -97,24 +96,14 @@ class CarInterface(CarInterfaceBase):
|
||||
ret.longitudinalTuning.kiBP = [0., 5., 35.]
|
||||
ret.longitudinalTuning.kiV = [1.2, 0.8, 0.5]
|
||||
|
||||
eps_modified = False
|
||||
# Disable control if EPS mod detected
|
||||
for fw in car_fw:
|
||||
if fw.ecu == "eps" and b"," in fw.fwVersion:
|
||||
eps_modified = True
|
||||
ret.dashcamOnly = True
|
||||
|
||||
if candidate == CAR.HONDA_CIVIC:
|
||||
if eps_modified:
|
||||
# stock request input values: 0x0000, 0x00DE, 0x014D, 0x01EF, 0x0290, 0x0377, 0x0454, 0x0610, 0x06EE
|
||||
# stock request output values: 0x0000, 0x0917, 0x0DC5, 0x1017, 0x119F, 0x140B, 0x1680, 0x1680, 0x1680
|
||||
# modified request output values: 0x0000, 0x0917, 0x0DC5, 0x1017, 0x119F, 0x140B, 0x1680, 0x2880, 0x3180
|
||||
# stock filter output values: 0x009F, 0x0108, 0x0108, 0x0108, 0x0108, 0x0108, 0x0108, 0x0108, 0x0108
|
||||
# modified filter output values: 0x009F, 0x0108, 0x0108, 0x0108, 0x0108, 0x0108, 0x0108, 0x0400, 0x0480
|
||||
# note: max request allowed is 4096, but request is capped at 3840 in firmware, so modifications result in 2x max
|
||||
ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 2560, 8000], [0, 2560, 3840]]
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.3], [0.1]]
|
||||
else:
|
||||
ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 2560], [0, 2560]]
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[1.1], [0.33]]
|
||||
ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 2560], [0, 2560]]
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[1.1], [0.33]]
|
||||
|
||||
elif candidate in (CAR.HONDA_CIVIC_BOSCH, CAR.HONDA_CIVIC_BOSCH_DIESEL):
|
||||
ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end
|
||||
@@ -127,11 +116,7 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
elif candidate == CAR.HONDA_ACCORD:
|
||||
ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end
|
||||
|
||||
if eps_modified:
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.3], [0.09]]
|
||||
else:
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.6], [0.18]]
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.6], [0.18]]
|
||||
|
||||
elif candidate == CAR.HONDA_ACCORD_11G:
|
||||
ret.steerActuatorDelay = 0.22
|
||||
@@ -142,21 +127,19 @@ class CarInterface(CarInterfaceBase):
|
||||
ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 3840], [0, 3840]] # TODO: determine if there is a dead zone at the top end
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.8], [0.24]]
|
||||
|
||||
elif candidate == CAR.HONDA_CITY_7G:
|
||||
ret.steerActuatorDelay = 0.15
|
||||
ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 2560], [0, 2560]]
|
||||
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
|
||||
|
||||
elif candidate in (CAR.HONDA_CRV, CAR.HONDA_CRV_EU):
|
||||
ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 1000], [0, 1000]] # TODO: determine if there is a dead zone at the top end
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.8], [0.24]]
|
||||
ret.wheelSpeedFactor = 1.025
|
||||
|
||||
elif candidate == CAR.HONDA_CRV_5G:
|
||||
if eps_modified:
|
||||
# stock request input values: 0x0000, 0x00DB, 0x01BB, 0x0296, 0x0377, 0x0454, 0x0532, 0x0610, 0x067F
|
||||
# stock request output values: 0x0000, 0x0500, 0x0A15, 0x0E6D, 0x1100, 0x1200, 0x129A, 0x134D, 0x1400
|
||||
# modified request output values: 0x0000, 0x0500, 0x0A15, 0x0E6D, 0x1100, 0x1200, 0x1ACD, 0x239A, 0x2800
|
||||
ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 2560, 10000], [0, 2560, 3840]]
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.21], [0.07]]
|
||||
else:
|
||||
ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 3840], [0, 3840]]
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.64], [0.192]]
|
||||
ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 3840], [0, 3840]]
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.64], [0.192]]
|
||||
ret.wheelSpeedFactor = 1.025
|
||||
|
||||
elif candidate == CAR.HONDA_CRV_HYBRID:
|
||||
@@ -164,6 +147,11 @@ class CarInterface(CarInterfaceBase):
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.6], [0.18]]
|
||||
ret.wheelSpeedFactor = 1.025
|
||||
|
||||
elif candidate in (CAR.HONDA_CRV_6G):
|
||||
ret.steerActuatorDelay = 0.15
|
||||
ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 2560], [0, 2560]]
|
||||
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
|
||||
|
||||
elif candidate == CAR.HONDA_FIT:
|
||||
ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.2], [0.05]]
|
||||
@@ -192,10 +180,20 @@ class CarInterface(CarInterfaceBase):
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.28], [0.08]]
|
||||
ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end
|
||||
|
||||
elif candidate in (CAR.HONDA_PILOT, CAR.HONDA_PILOT_4G):
|
||||
elif candidate == CAR.HONDA_PILOT:
|
||||
ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.38], [0.11]]
|
||||
|
||||
elif candidate == CAR.HONDA_PILOT_4G:
|
||||
ret.steerActuatorDelay = 0.15
|
||||
ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 2560], [0, 2560]]
|
||||
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
|
||||
|
||||
elif candidate == CAR.ACURA_MDX_4G_MMR:
|
||||
ret.steerActuatorDelay = 0.15
|
||||
ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 2560], [0, 2560]]
|
||||
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
|
||||
|
||||
elif candidate == CAR.HONDA_RIDGELINE:
|
||||
ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.38], [0.11]]
|
||||
@@ -208,6 +206,10 @@ class CarInterface(CarInterfaceBase):
|
||||
ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.6], [0.18]] # TODO: can probably use some tuning
|
||||
|
||||
# TODO-SP: remove when https://github.com/commaai/opendbc/pull/2687 is merged
|
||||
elif candidate == CAR.HONDA_CLARITY:
|
||||
pass
|
||||
|
||||
else:
|
||||
raise ValueError(f"unsupported car {candidate}")
|
||||
|
||||
@@ -242,6 +244,66 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
return ret
|
||||
|
||||
@staticmethod
|
||||
def _get_params_sp(stock_cp: structs.CarParams, ret: structs.CarParamsSP, candidate, fingerprint: dict[int, dict[int, int]],
|
||||
car_fw: list[structs.CarParams.CarFw], alpha_long: bool, docs: bool) -> structs.CarParamsSP:
|
||||
for fw in car_fw:
|
||||
if fw.ecu == "eps" and b"," in fw.fwVersion:
|
||||
ret.flags |= HondaFlagsSP.EPS_MODIFIED.value
|
||||
stock_cp.dashcamOnly = False
|
||||
|
||||
if candidate == CAR.HONDA_CIVIC:
|
||||
if ret.flags & HondaFlagsSP.EPS_MODIFIED:
|
||||
# stock request input values: 0x0000, 0x00DE, 0x014D, 0x01EF, 0x0290, 0x0377, 0x0454, 0x0610, 0x06EE
|
||||
# stock request output values: 0x0000, 0x0917, 0x0DC5, 0x1017, 0x119F, 0x140B, 0x1680, 0x1680, 0x1680
|
||||
# modified request output values: 0x0000, 0x0917, 0x0DC5, 0x1017, 0x119F, 0x140B, 0x1680, 0x2880, 0x3180
|
||||
# stock filter output values: 0x009F, 0x0108, 0x0108, 0x0108, 0x0108, 0x0108, 0x0108, 0x0108, 0x0108
|
||||
# modified filter output values: 0x009F, 0x0108, 0x0108, 0x0108, 0x0108, 0x0108, 0x0108, 0x0400, 0x0480
|
||||
# note: max request allowed is 4096, but request is capped at 3840 in firmware, so modifications result in 2x max
|
||||
stock_cp.lateralParams.torqueBP, stock_cp.lateralParams.torqueV = [[0, 2560, 8000], [0, 2560, 3840]]
|
||||
stock_cp.lateralTuning.pid.kpV, stock_cp.lateralTuning.pid.kiV = [[0.3], [0.1]]
|
||||
|
||||
elif candidate in (CAR.HONDA_CIVIC_BOSCH, CAR.HONDA_CIVIC_BOSCH_DIESEL):
|
||||
if ret.flags & HondaFlagsSP.EPS_MODIFIED:
|
||||
stock_cp.lateralParams.torqueBP, stock_cp.lateralParams.torqueV = [[0, 2564, 8000], [0, 2564, 3840]]
|
||||
stock_cp.lateralTuning.pid.kpV, stock_cp.lateralTuning.pid.kiV = [[0.3], [0.09]] # 2.5x Modded EPS
|
||||
|
||||
elif candidate == CAR.HONDA_CIVIC_2022:
|
||||
if ret.flags & HondaFlagsSP.EPS_MODIFIED:
|
||||
stock_cp.lateralParams.torqueBP, stock_cp.lateralParams.torqueV = [[0, 2564, 8000], [0, 2564, 3840]]
|
||||
stock_cp.lateralTuning.pid.kpV, stock_cp.lateralTuning.pid.kiV = [[0.3], [0.09]] # 2.5x Modded EPS
|
||||
|
||||
elif candidate == CAR.HONDA_ACCORD:
|
||||
if ret.flags & HondaFlagsSP.EPS_MODIFIED:
|
||||
stock_cp.lateralTuning.pid.kpV, stock_cp.lateralTuning.pid.kiV = [[0.3], [0.09]]
|
||||
|
||||
elif candidate == CAR.HONDA_CRV_5G:
|
||||
if ret.flags & HondaFlagsSP.EPS_MODIFIED:
|
||||
# stock request input values: 0x0000, 0x00DB, 0x01BB, 0x0296, 0x0377, 0x0454, 0x0532, 0x0610, 0x067F
|
||||
# stock request output values: 0x0000, 0x0500, 0x0A15, 0x0E6D, 0x1100, 0x1200, 0x129A, 0x134D, 0x1400
|
||||
# modified request output values: 0x0000, 0x0500, 0x0A15, 0x0E6D, 0x1100, 0x1200, 0x1ACD, 0x239A, 0x2800
|
||||
stock_cp.lateralParams.torqueBP, stock_cp.lateralParams.torqueV = [[0, 2560, 10000], [0, 2560, 3840]]
|
||||
stock_cp.lateralTuning.pid.kpV, stock_cp.lateralTuning.pid.kiV = [[0.21], [0.07]]
|
||||
|
||||
elif candidate == CAR.HONDA_CLARITY:
|
||||
ret.safetyParam |= HondaSafetyFlagsSP.CLARITY
|
||||
stock_cp.autoResumeSng = True
|
||||
stock_cp.minEnableSpeed = -1
|
||||
if ret.flags & HondaFlagsSP.EPS_MODIFIED:
|
||||
for fw in car_fw:
|
||||
if fw.ecu == "eps" and b"-" not in fw.fwVersion and b"," in fw.fwVersion:
|
||||
stock_cp.lateralTuning.pid.kf = 0.00004
|
||||
stock_cp.lateralParams.torqueBP, stock_cp.lateralParams.torqueV = [[0, 5760, 15360], [0, 2560, 3840]]
|
||||
stock_cp.lateralTuning.pid.kpV, stock_cp.lateralTuning.pid.kiV = [[0.1575], [0.05175]]
|
||||
elif fw.ecu == "eps" and b"-" in fw.fwVersion and b"," in fw.fwVersion:
|
||||
stock_cp.lateralParams.torqueBP, stock_cp.lateralParams.torqueV = [[0, 5760, 10240], [0, 2560, 3840]]
|
||||
stock_cp.lateralTuning.pid.kpV, stock_cp.lateralTuning.pid.kiV = [[0.3], [0.1]]
|
||||
else:
|
||||
stock_cp.lateralParams.torqueBP, stock_cp.lateralParams.torqueV = [[0, 2560], [0, 2560]]
|
||||
stock_cp.lateralTuning.pid.kpV, stock_cp.lateralTuning.pid.kiV = [[0.8], [0.24]]
|
||||
|
||||
return ret
|
||||
|
||||
@staticmethod
|
||||
def init(CP, CP_SP, can_recv, can_send, communication_control=None):
|
||||
if CP.carFingerprint in (HONDA_BOSCH - HONDA_BOSCH_RADARLESS) and CP.openpilotLongitudinalControl:
|
||||
|
||||
@@ -2,7 +2,7 @@ import re
|
||||
|
||||
from opendbc.car.honda.fingerprints import FW_VERSIONS
|
||||
|
||||
HONDA_FW_VERSION_RE = br"[A-Z0-9]{5}-[A-Z0-9]{3}(-|,)[A-Z0-9]{4}(\x00){2}$"
|
||||
HONDA_FW_VERSION_RE = br"[A-Z0-9]{5}(-|,)[A-Z0-9]{3}(-|,)[A-Z0-9]{4}(\x00){2}$"
|
||||
|
||||
|
||||
class TestHondaFingerprint:
|
||||
|
||||
@@ -6,6 +6,8 @@ from opendbc.car.common.conversions import Conversions as CV
|
||||
from opendbc.car.docs_definitions import CarFootnote, CarHarness, CarDocs, CarParts, Column, Device
|
||||
from opendbc.car.fw_query_definitions import FwQueryConfig, Request, StdQueries, p16
|
||||
|
||||
from opendbc.sunnypilot.car.honda.values_ext import HondaFlagsSP
|
||||
|
||||
Ecu = structs.CarParams.Ecu
|
||||
VisualAlert = structs.CarControl.HUDControl.VisualAlert
|
||||
GearShifter = structs.CarState.GearShifter
|
||||
@@ -124,6 +126,10 @@ class HondaCarDocs(CarDocs):
|
||||
else:
|
||||
self.car_parts = CarParts.common([harness])
|
||||
|
||||
if CP.carFingerprint in (CAR.HONDA_CLARITY,):
|
||||
self.car_parts = CarParts.common([CarHarness.honda_clarity])
|
||||
self.car_parts.custom_parts_url = "https://shop.retropilot.org/product/honda-clarity-proxy-board-kit"
|
||||
|
||||
|
||||
class Footnote(Enum):
|
||||
CIVIC_DIESEL = CarFootnote(
|
||||
@@ -169,14 +175,18 @@ class CAR(Platforms):
|
||||
{Bus.pt: 'honda_accord_2018_can_generated'},
|
||||
)
|
||||
HONDA_ACCORD_11G = HondaBoschCANFDPlatformConfig(
|
||||
[HondaCarDocs("Honda Accord 2023", "All")],
|
||||
[
|
||||
HondaCarDocs("Honda Accord 2023-25", "All"),
|
||||
HondaCarDocs("Honda Accord Hybrid 2023-25", "All"),
|
||||
],
|
||||
CarSpecs(mass=3477 * CV.LB_TO_KG, wheelbase=2.83, steerRatio=16.0, centerToFrontRatio=0.39),
|
||||
)
|
||||
HONDA_CIVIC_BOSCH = HondaBoschPlatformConfig(
|
||||
[
|
||||
HondaCarDocs("Honda Civic 2019-21", "All", video="https://www.youtube.com/watch?v=4Iz1Mz5LGF8",
|
||||
footnotes=[Footnote.CIVIC_DIESEL], min_steer_speed=2. * CV.MPH_TO_MS),
|
||||
HondaCarDocs("Honda Civic Hatchback 2017-21", min_steer_speed=12. * CV.MPH_TO_MS),
|
||||
HondaCarDocs("Honda Civic Hatchback 2017-18", min_steer_speed=12. * CV.MPH_TO_MS),
|
||||
HondaCarDocs("Honda Civic Hatchback 2019-21", "All", min_steer_speed=12. * CV.MPH_TO_MS),
|
||||
],
|
||||
CarSpecs(mass=1326, wheelbase=2.7, steerRatio=15.38, centerToFrontRatio=0.4), # steerRatio: 10.93 is end-to-end spec
|
||||
{Bus.pt: 'honda_civic_hatchback_ex_2017_can_generated'},
|
||||
@@ -206,6 +216,13 @@ class CAR(Platforms):
|
||||
{Bus.pt: 'honda_crv_ex_2017_can_generated', Bus.body: 'honda_crv_ex_2017_body_generated'},
|
||||
flags=HondaFlags.BOSCH_ALT_BRAKE,
|
||||
)
|
||||
HONDA_CRV_6G = HondaBoschCANFDPlatformConfig(
|
||||
[
|
||||
HondaCarDocs("Honda CR-V 2023-25", "All"),
|
||||
HondaCarDocs("Honda CR-V Hybrid 2023-25", "All"),
|
||||
],
|
||||
CarSpecs(mass=1703, wheelbase=2.7, steerRatio=16.2, centerToFrontRatio=0.42),
|
||||
)
|
||||
HONDA_CRV_HYBRID = HondaBoschPlatformConfig(
|
||||
[HondaCarDocs("Honda CR-V Hybrid 2017-22", min_steer_speed=12. * CV.MPH_TO_MS)],
|
||||
# mass: mean of 4 models in kg, steerRatio: 12.3 is spec end-to-end
|
||||
@@ -218,6 +235,12 @@ class CAR(Platforms):
|
||||
{Bus.pt: 'honda_civic_ex_2022_can_generated'},
|
||||
flags=HondaFlags.BOSCH_RADARLESS,
|
||||
)
|
||||
HONDA_CITY_7G = HondaBoschPlatformConfig(
|
||||
[HondaCarDocs("Honda City (Brazil only) 2023", "All")],
|
||||
CarSpecs(mass=3125 * CV.LB_TO_KG, wheelbase=2.6, steerRatio=19.0, centerToFrontRatio=0.41, minSteerSpeed=23. * CV.KPH_TO_MS),
|
||||
{Bus.pt: 'honda_civic_ex_2022_can_generated'},
|
||||
flags=HondaFlags.BOSCH_RADARLESS,
|
||||
)
|
||||
ACURA_RDX_3G = HondaBoschPlatformConfig(
|
||||
[HondaCarDocs("Acura RDX 2019-21", "All", min_steer_speed=3. * CV.MPH_TO_MS)],
|
||||
CarSpecs(mass=4068 * CV.LB_TO_KG, wheelbase=2.75, steerRatio=11.95, centerToFrontRatio=0.41, tireStiffnessFactor=0.677), # as spec
|
||||
@@ -235,9 +258,13 @@ class CAR(Platforms):
|
||||
{Bus.pt: 'acura_rdx_2020_can_generated'},
|
||||
)
|
||||
HONDA_PILOT_4G = HondaBoschCANFDPlatformConfig(
|
||||
[HondaCarDocs("Honda Pilot 2023", "All")],
|
||||
CarSpecs(mass=4278 * CV.LB_TO_KG, wheelbase=2.86, centerToFrontRatio=0.428, steerRatio=16.0, tireStiffnessFactor=0.444), # as spec
|
||||
flags=HondaFlags.BOSCH_ALT_BRAKE,
|
||||
[HondaCarDocs("Honda Pilot 2023-25", "All")],
|
||||
CarSpecs(mass=4660 * CV.LB_TO_KG, wheelbase=2.89, centerToFrontRatio=0.442, steerRatio=17.5),
|
||||
)
|
||||
# mid-model refresh
|
||||
ACURA_MDX_4G_MMR = HondaBoschCANFDPlatformConfig(
|
||||
[HondaCarDocs("Acura MDX 2025", "All except Type S")],
|
||||
CarSpecs(mass=4544 * CV.LB_TO_KG, wheelbase=2.89, centerToFrontRatio=0.428, steerRatio=16.2),
|
||||
)
|
||||
|
||||
# Nidec Cars
|
||||
@@ -314,6 +341,15 @@ class CAR(Platforms):
|
||||
flags=HondaFlags.HAS_ALL_DOOR_STATES
|
||||
)
|
||||
|
||||
# port extensions
|
||||
HONDA_CLARITY = HondaNidecPlatformConfig(
|
||||
[HondaCarDocs("Honda Clarity 2018-21", min_steer_speed=12. * CV.MPH_TO_MS)],
|
||||
CarSpecs(mass=1834, wheelbase=2.75, centerToFrontRatio=0.4, steerRatio=16.5),
|
||||
radar_dbc_dict('honda_clarity_hybrid_2018_can_generated'),
|
||||
flags=HondaFlags.HAS_ALL_DOOR_STATES,
|
||||
sp_flags=HondaFlagsSP.CLARITY,
|
||||
)
|
||||
|
||||
|
||||
HONDA_NIDEC_ALT_PCM_ACCEL = CAR.with_flags(HondaFlags.NIDEC_ALT_PCM_ACCEL)
|
||||
HONDA_NIDEC_ALT_SCM_MESSAGES = CAR.with_flags(HondaFlags.NIDEC_ALT_SCM_MESSAGES)
|
||||
@@ -330,6 +366,10 @@ STEER_THRESHOLD = {
|
||||
CAR.ACURA_RDX: 400,
|
||||
CAR.HONDA_CRV_EU: 400,
|
||||
CAR.HONDA_ACCORD_11G: 600,
|
||||
CAR.HONDA_PILOT_4G: 600,
|
||||
CAR.ACURA_MDX_4G_MMR: 600,
|
||||
CAR.HONDA_CRV_6G: 600,
|
||||
CAR.HONDA_CITY_7G: 600,
|
||||
}
|
||||
|
||||
|
||||
@@ -374,9 +414,9 @@ FW_QUERY_CONFIG = FwQueryConfig(
|
||||
# Note that we still attempt to match with them when they are present
|
||||
# This is or'd with (ALL_ECUS - ESSENTIAL_ECUS) from fw_versions.py
|
||||
non_essential_ecus={
|
||||
Ecu.eps: [CAR.ACURA_RDX_3G, CAR.HONDA_ACCORD, CAR.HONDA_CIVIC_2022, CAR.HONDA_E, CAR.HONDA_HRV_3G, *HONDA_BOSCH_CANFD],
|
||||
Ecu.eps: [CAR.ACURA_RDX_3G, CAR.HONDA_ACCORD, CAR.HONDA_CIVIC_2022, CAR.HONDA_E, CAR.HONDA_HRV_3G, CAR.HONDA_CITY_7G, *HONDA_BOSCH_CANFD],
|
||||
Ecu.vsa: [CAR.ACURA_RDX_3G, CAR.HONDA_ACCORD, CAR.HONDA_CIVIC, CAR.HONDA_CIVIC_BOSCH, CAR.HONDA_CIVIC_2022, CAR.HONDA_CRV_5G, CAR.HONDA_CRV_HYBRID,
|
||||
CAR.HONDA_E, CAR.HONDA_HRV_3G, CAR.HONDA_INSIGHT, *HONDA_BOSCH_CANFD],
|
||||
CAR.HONDA_E, CAR.HONDA_HRV_3G, CAR.HONDA_INSIGHT, CAR.HONDA_CITY_7G, *HONDA_BOSCH_CANFD],
|
||||
},
|
||||
extra_ecus=[
|
||||
(Ecu.combinationMeter, 0x18da60f1, None),
|
||||
|
||||
@@ -10,6 +10,7 @@ from opendbc.car.interfaces import CarControllerBase
|
||||
|
||||
from opendbc.sunnypilot.car.hyundai.escc import EsccCarController
|
||||
from opendbc.sunnypilot.car.hyundai.longitudinal.controller import LongitudinalController
|
||||
from opendbc.sunnypilot.car.hyundai.lead_data_ext import LeadDataCarController
|
||||
from opendbc.sunnypilot.car.hyundai.mads import MadsCarController
|
||||
|
||||
VisualAlert = structs.CarControl.HUDControl.VisualAlert
|
||||
@@ -46,11 +47,12 @@ def process_hud_alert(enabled, fingerprint, hud_control):
|
||||
return sys_warning, sys_state, left_lane_warning, right_lane_warning
|
||||
|
||||
|
||||
class CarController(CarControllerBase, EsccCarController, LongitudinalController, MadsCarController):
|
||||
class CarController(CarControllerBase, EsccCarController, LeadDataCarController, LongitudinalController, MadsCarController):
|
||||
def __init__(self, dbc_names, CP, CP_SP):
|
||||
CarControllerBase.__init__(self, dbc_names, CP, CP_SP)
|
||||
EsccCarController.__init__(self, CP, CP_SP)
|
||||
MadsCarController.__init__(self)
|
||||
LeadDataCarController.__init__(self, CP)
|
||||
LongitudinalController.__init__(self, CP, CP_SP)
|
||||
self.CAN = CanBus(CP)
|
||||
self.params = CarControllerParams(CP)
|
||||
@@ -64,6 +66,7 @@ class CarController(CarControllerBase, EsccCarController, LongitudinalController
|
||||
|
||||
def update(self, CC, CC_SP, CS, now_nanos):
|
||||
EsccCarController.update(self, CS)
|
||||
LeadDataCarController.update(self, CC_SP)
|
||||
MadsCarController.update(self, self.CP, CC, CC_SP, self.frame)
|
||||
if self.frame % 2 == 0:
|
||||
LongitudinalController.update(self, CC, CS)
|
||||
@@ -157,7 +160,7 @@ class CarController(CarControllerBase, EsccCarController, LongitudinalController
|
||||
jerk = 3.0 if actuators.longControlState == LongCtrlState.pid else 1.0
|
||||
use_fca = self.CP.flags & HyundaiFlags.USE_FCA.value
|
||||
can_sends.extend(hyundaican.create_acc_commands(self.packer, CC.enabled, accel, jerk, int(self.frame / 2),
|
||||
hud_control, set_speed_in_units, stopping,
|
||||
self.lead_data, hud_control, set_speed_in_units, stopping,
|
||||
CC.cruiseControl.override, use_fca, self.CP,
|
||||
CS.main_cruise_enabled, self.tuning, self.ESCC))
|
||||
|
||||
@@ -204,7 +207,7 @@ class CarController(CarControllerBase, EsccCarController, LongitudinalController
|
||||
can_sends.extend(hyundaicanfd.create_fca_warning_light(self.packer, self.CAN, self.frame))
|
||||
if self.frame % 2 == 0:
|
||||
can_sends.append(hyundaicanfd.create_acc_control(self.packer, self.CAN, CC.enabled, self.accel_last, accel, stopping, CC.cruiseControl.override,
|
||||
set_speed_in_units, hud_control, CS.main_cruise_enabled, self.tuning))
|
||||
set_speed_in_units, hud_control, self.lead_data, CS.main_cruise_enabled, self.tuning))
|
||||
self.accel_last = accel
|
||||
else:
|
||||
# button presses
|
||||
|
||||
@@ -12,6 +12,7 @@ from opendbc.car.interfaces import CarStateBase
|
||||
from opendbc.sunnypilot.car.hyundai.carstate_ext import CarStateExt
|
||||
from opendbc.sunnypilot.car.hyundai.escc import EsccCarStateBase
|
||||
from opendbc.sunnypilot.car.hyundai.mads import MadsCarState
|
||||
from opendbc.sunnypilot.car.hyundai.values import HyundaiFlagsSP
|
||||
|
||||
ButtonType = structs.CarState.ButtonEvent.Type
|
||||
|
||||
@@ -30,7 +31,7 @@ class CarState(CarStateBase, EsccCarStateBase, MadsCarState, CarStateExt):
|
||||
CarStateBase.__init__(self, CP, CP_SP)
|
||||
EsccCarStateBase.__init__(self)
|
||||
MadsCarState.__init__(self, CP, CP_SP)
|
||||
CarStateExt.__init__(self)
|
||||
CarStateExt.__init__(self, CP, CP_SP)
|
||||
can_define = CANDefine(DBC[CP.carFingerprint][Bus.pt])
|
||||
|
||||
self.cruise_buttons: deque = deque([Buttons.NONE] * PREV_BUTTON_SAMPLES, maxlen=PREV_BUTTON_SAMPLES)
|
||||
@@ -131,7 +132,7 @@ class CarState(CarStateBase, EsccCarStateBase, MadsCarState, CarStateExt):
|
||||
ret.cruiseState.enabled = cp.vl["TCS13"]["ACC_REQ"] == 1
|
||||
ret.cruiseState.standstill = False
|
||||
ret.cruiseState.nonAdaptive = False
|
||||
else:
|
||||
elif not self.CP_SP.flags & HyundaiFlagsSP.NON_SCC:
|
||||
ret.cruiseState.available = cp_cruise.vl["SCC11"]["MainMode_ACC"] == 1
|
||||
ret.cruiseState.enabled = cp_cruise.vl["SCC12"]["ACCMode"] != 0
|
||||
ret.cruiseState.standstill = cp_cruise.vl["SCC11"]["SCCInfoDisplay"] == 4.
|
||||
@@ -172,7 +173,7 @@ class CarState(CarStateBase, EsccCarStateBase, MadsCarState, CarStateExt):
|
||||
|
||||
ret.gearShifter = self.parse_gear_shifter(self.shifter_values.get(gear))
|
||||
|
||||
if not self.CP.openpilotLongitudinalControl or self.CP.flags & HyundaiFlags.CAMERA_SCC:
|
||||
if (not self.CP.openpilotLongitudinalControl or self.CP.flags & HyundaiFlags.CAMERA_SCC) and not self.CP_SP.flags & HyundaiFlagsSP.NON_SCC:
|
||||
aeb_src = "FCA11" if self.CP.flags & HyundaiFlags.USE_FCA.value else "SCC12"
|
||||
aeb_sig = "FCA_CmdAct" if self.CP.flags & HyundaiFlags.USE_FCA.value else "AEB_CmdAct"
|
||||
aeb_warning = cp_cruise.vl[aeb_src]["CF_VSM_Warn"] != 0
|
||||
@@ -204,7 +205,7 @@ class CarState(CarStateBase, EsccCarStateBase, MadsCarState, CarStateExt):
|
||||
if self.CP.openpilotLongitudinalControl:
|
||||
ret.cruiseState.available = self.get_main_cruise(ret)
|
||||
|
||||
CarStateExt.update(self, ret, can_parsers)
|
||||
CarStateExt.update(self, ret, can_parsers, speed_conv)
|
||||
|
||||
ret.blockPcmEnable = not self.recent_button_interaction()
|
||||
|
||||
@@ -321,7 +322,8 @@ class CarState(CarStateBase, EsccCarStateBase, MadsCarState, CarStateExt):
|
||||
if not (CP.flags & HyundaiFlags.CANFD_ALT_BUTTONS):
|
||||
# TODO: this can be removed once we add dynamic support to vl_all
|
||||
msgs += [
|
||||
("CRUISE_BUTTONS", 50)
|
||||
# this message is 50Hz but the ECU frequently stops transmitting for ~0.5s
|
||||
("CRUISE_BUTTONS", 1)
|
||||
]
|
||||
return {
|
||||
Bus.pt: CANParser(DBC[CP.carFingerprint][Bus.pt], msgs, CanBus(CP).ECAN),
|
||||
|
||||
@@ -731,6 +731,7 @@ FW_VERSIONS = {
|
||||
b'\xf1\x00DE MDPS C 1.00 1.04 56310Q4100\x00 4DEEC104',
|
||||
b'\xf1\x00DE MDPS C 1.00 1.05 56310Q4000\x00 4DEEC105',
|
||||
b'\xf1\x00DE MDPS C 1.00 1.05 56310Q4100\x00 4DEEC105',
|
||||
b'\xf1\x00DE MDPS C 1.00 1.05 56310Q4200\x00 4DEEC105',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00DEE MFC AT EUR LHD 1.00 1.00 99211-Q4000 191211',
|
||||
@@ -986,6 +987,7 @@ FW_VERSIONS = {
|
||||
},
|
||||
CAR.KIA_SORENTO: {
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00UMP LKAS AT AUS RHD 1.00 1.00 96400-C6550 S30',
|
||||
b'\xf1\x00UMP LKAS AT KOR LHD 1.00 1.00 95740-C5550 S30',
|
||||
b'\xf1\x00UMP LKAS AT USA LHD 1.00 1.00 95740-C6550 d00',
|
||||
b'\xf1\x00UMP LKAS AT USA LHD 1.01 1.01 95740-C6550 d01',
|
||||
@@ -1249,16 +1251,19 @@ FW_VERSIONS = {
|
||||
},
|
||||
CAR.HYUNDAI_KONA_2022: {
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00OSP LKA AT CND LHD 1.00 1.04 99211-J9200 904',
|
||||
b'\xf1\x00OSP LKA AT USA LHD 1.00 1.04 99211-J9200 904',
|
||||
],
|
||||
(Ecu.eps, 0x7d4, None): [
|
||||
b'\xf1\x00OSP MDPS C 1.00 1.04 56310/J9290 4OPCC104',
|
||||
b'\xf1\x00OSP MDPS C 1.00 1.04 56310/J9291 4OPCC104',
|
||||
b'\xf1\x00OSP MDPS C 1.00 1.04 56310J9291\x00 4OPCC104',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00YB__ FCA ----- 1.00 1.01 99110-J9000 \x00\x00\x00',
|
||||
],
|
||||
(Ecu.transmission, 0x7e1, None): [
|
||||
b'\xf1\x00HT6WA280BLHT6VA650A1COS4N20NS1\x00\x00\x00\x00\x00\x00\x15\xf5\x87~',
|
||||
b'\xf1\x00T01960BL T01E60A1 DOS2T16X4XE60NS4N\x90\xe6\xcb',
|
||||
b'\xf1\x00T01G00BL T01I00A1 DOS2T16X2XI00NS0\x8c`\xff\xe7',
|
||||
b'\xf1\x00T01G00BL T01I00A1 DOS2T16X4XI00NS0\x99L\xeeq',
|
||||
|
||||
@@ -2,6 +2,7 @@ import crcmod
|
||||
from opendbc.car.hyundai.values import CAR, HyundaiFlags
|
||||
|
||||
from opendbc.sunnypilot.car.hyundai.escc import EnhancedSmartCruiseControl
|
||||
from opendbc.sunnypilot.car.hyundai.lead_data_ext import CanLeadData
|
||||
|
||||
hyundai_checksum = crcmod.mkCrcFun(0x11D, initCrc=0xFD, rev=False, xorOut=0xdf)
|
||||
|
||||
@@ -42,7 +43,9 @@ def create_lkas11(packer, frame, CP, apply_torque, steer_req,
|
||||
CAR.HYUNDAI_ELANTRA_HEV_2021, CAR.HYUNDAI_SONATA_HYBRID, CAR.HYUNDAI_KONA_EV, CAR.HYUNDAI_KONA_HEV, CAR.HYUNDAI_KONA_EV_2022,
|
||||
CAR.HYUNDAI_SANTA_FE_2022, CAR.KIA_K5_2021, CAR.HYUNDAI_IONIQ_HEV_2022, CAR.HYUNDAI_SANTA_FE_HEV_2022,
|
||||
CAR.HYUNDAI_SANTA_FE_PHEV_2022, CAR.KIA_STINGER_2022, CAR.KIA_K5_HEV_2020, CAR.KIA_CEED,
|
||||
CAR.HYUNDAI_AZERA_6TH_GEN, CAR.HYUNDAI_AZERA_HEV_6TH_GEN, CAR.HYUNDAI_CUSTIN_1ST_GEN, CAR.HYUNDAI_KONA_2022):
|
||||
CAR.HYUNDAI_AZERA_6TH_GEN, CAR.HYUNDAI_AZERA_HEV_6TH_GEN, CAR.HYUNDAI_CUSTIN_1ST_GEN, CAR.HYUNDAI_KONA_2022,
|
||||
CAR.KIA_CEED_PHEV_2022_NON_SCC, CAR.HYUNDAI_KONA_EV_NON_SCC, CAR.HYUNDAI_ELANTRA_2022_NON_SCC,
|
||||
CAR.GENESIS_G70_2021_NON_SCC, CAR.KIA_SELTOS_2023_NON_SCC, CAR.HYUNDAI_BAYON_1ST_GEN_NON_SCC):
|
||||
values["CF_Lkas_LdwsActivemode"] = int(left_lane) + (int(right_lane) << 1)
|
||||
values["CF_Lkas_LdwsOpt_USM"] = 2
|
||||
|
||||
@@ -61,7 +64,7 @@ def create_lkas11(packer, frame, CP, apply_torque, steer_req,
|
||||
values["CF_Lkas_SysWarning"] = 4 if sys_warning else 0
|
||||
|
||||
# Likely cars lacking the ability to show individual lane lines in the dash
|
||||
elif CP.carFingerprint in (CAR.KIA_OPTIMA_G4, CAR.KIA_OPTIMA_G4_FL):
|
||||
elif CP.carFingerprint in (CAR.KIA_OPTIMA_G4, CAR.KIA_OPTIMA_G4_FL, CAR.HYUNDAI_KONA_NON_SCC):
|
||||
# SysWarning 4 = keep hands on wheel + beep
|
||||
values["CF_Lkas_SysWarning"] = 4 if sys_warning else 0
|
||||
|
||||
@@ -128,7 +131,8 @@ def create_lfahda_mfc(packer, enabled, lfa_icon):
|
||||
return packer.make_can_msg("LFAHDA_MFC", 0, values)
|
||||
|
||||
|
||||
def create_acc_commands(packer, enabled, accel, upper_jerk, idx, hud_control, set_speed, stopping, long_override, use_fca, CP,
|
||||
def create_acc_commands(packer, enabled, accel, upper_jerk, idx, lead_data: CanLeadData,
|
||||
hud_control, set_speed, stopping, long_override, use_fca, CP,
|
||||
main_cruise_enabled, tuning, ESCC: EnhancedSmartCruiseControl = None):
|
||||
commands = []
|
||||
|
||||
@@ -138,11 +142,11 @@ def create_acc_commands(packer, enabled, accel, upper_jerk, idx, hud_control, se
|
||||
"TauGapSet": hud_control.leadDistanceBars,
|
||||
"VSetDis": set_speed if enabled else 0,
|
||||
"AliveCounterACC": idx % 0x10,
|
||||
"ObjValid": 1, # close lead makes controls tighter
|
||||
"ACC_ObjStatus": 1, # close lead makes controls tighter
|
||||
"ObjValid": int(lead_data.lead_visible), # close lead makes controls tighter
|
||||
"ACC_ObjStatus": int(lead_data.lead_visible), # close lead makes controls tighter
|
||||
"ACC_ObjLatPos": 0,
|
||||
"ACC_ObjRelSpd": 0,
|
||||
"ACC_ObjDist": 1, # close lead makes controls tighter
|
||||
"ACC_ObjRelSpd": lead_data.lead_rel_speed,
|
||||
"ACC_ObjDist": int(lead_data.lead_distance), # close lead makes controls tighter
|
||||
}
|
||||
|
||||
def get_scc12_values():
|
||||
@@ -178,7 +182,8 @@ def create_acc_commands(packer, enabled, accel, upper_jerk, idx, hud_control, se
|
||||
"JerkUpperLimit": tuning.jerk_upper, # stock usually is 1.0 but sometimes uses higher values
|
||||
"JerkLowerLimit": tuning.jerk_lower, # stock usually is 0.5 but sometimes uses higher values
|
||||
"ACCMode": 2 if enabled and long_override else 1 if enabled else 4, # stock will always be 4 instead of 0 after first disengage
|
||||
"ObjGap": 2 if hud_control.leadVisible else 0, # 5: >30, m, 4: 25-30 m, 3: 20-25 m, 2: < 20 m, 0: no lead
|
||||
"ObjGap": lead_data.object_gap, # 5: >30, m, 4: 25-30 m, 3: 20-25 m, 2: < 20 m, 0: no lead
|
||||
"ObjDistStat": lead_data.object_rel_gap,
|
||||
}
|
||||
|
||||
def get_fca11_values():
|
||||
|
||||
@@ -3,6 +3,7 @@ import numpy as np
|
||||
from opendbc.car import CanBusBase
|
||||
from opendbc.car.crc import CRC16_XMODEM
|
||||
from opendbc.car.hyundai.values import HyundaiFlags
|
||||
from opendbc.sunnypilot.car.hyundai.lead_data_ext import CanFdLeadData
|
||||
|
||||
|
||||
class CanBus(CanBusBase):
|
||||
@@ -131,7 +132,7 @@ def create_lfahda_cluster(packer, CAN, enabled, lfa_icon):
|
||||
|
||||
|
||||
def create_acc_control(packer, CAN, enabled, accel_last, accel, stopping, gas_override, set_speed, hud_control,
|
||||
main_cruise_enabled, tuning):
|
||||
lead_data: CanFdLeadData, main_cruise_enabled, tuning):
|
||||
jerk = 5
|
||||
jn = jerk / 50
|
||||
if not enabled or gas_override:
|
||||
@@ -150,9 +151,10 @@ def create_acc_control(packer, CAN, enabled, accel_last, accel, stopping, gas_ov
|
||||
"JerkLowerLimit": tuning.jerk_lower,
|
||||
"JerkUpperLimit": tuning.jerk_upper,
|
||||
|
||||
"ACC_ObjDist": 1,
|
||||
"ObjValid": 0,
|
||||
"OBJ_STATUS": 2,
|
||||
"ACC_ObjDist": int(lead_data.lead_distance),
|
||||
"ACC_ObjRelSpd": lead_data.lead_rel_speed,
|
||||
"ObjValid": int(not lead_data.lead_visible),
|
||||
"SCC_ObjSta": 0 if not (enabled and lead_data.lead_visible) else (1 if gas_override else 2),
|
||||
"SET_ME_2": 0x4,
|
||||
"SET_ME_3": 0x3,
|
||||
"SET_ME_TMP_64": 0x64,
|
||||
|
||||
@@ -179,6 +179,22 @@ class CarInterface(CarInterfaceBase):
|
||||
if stock_cp.flags & HyundaiFlags.ALT_LIMITS_2:
|
||||
stock_cp.dashcamOnly = False
|
||||
|
||||
if ret.flags & HyundaiFlagsSP.NON_SCC:
|
||||
stock_cp.alphaLongitudinalAvailable = False
|
||||
stock_cp.openpilotLongitudinalControl = False
|
||||
stock_cp.pcmCruise = True
|
||||
ret.safetyParam |= HyundaiSafetyFlagsSP.NON_SCC
|
||||
|
||||
# untested non-SCC platforms, need user validations
|
||||
if stock_cp.carFingerprint in (CAR.HYUNDAI_BAYON_1ST_GEN_NON_SCC, CAR.KIA_FORTE_2019_NON_SCC, CAR.KIA_FORTE_2021_NON_SCC,
|
||||
CAR.KIA_SELTOS_2023_NON_SCC, CAR.GENESIS_G70_2021_NON_SCC):
|
||||
stock_cp.dashcamOnly = True
|
||||
|
||||
# Detect smartMDPS, which bypasses EPS low-speed lockout, allowing sunnypilot to send steering commands down to 0
|
||||
if 0x2AA in fingerprint[0]:
|
||||
stock_cp.minSteerSpeed = 0.0
|
||||
stock_cp.flags &= ~HyundaiFlags.MIN_STEER_32_MPH.value
|
||||
|
||||
return ret
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -11,7 +11,8 @@ from opendbc.car.hyundai.radar_interface import RADAR_START_ADDR
|
||||
from opendbc.car.hyundai.values import CAMERA_SCC_CAR, CANFD_CAR, CAN_GEARS, CAR, CHECKSUM, DATE_FW_ECUS, \
|
||||
HYBRID_CAR, EV_CAR, FW_QUERY_CONFIG, LEGACY_SAFETY_MODE_CAR, CANFD_FUZZY_WHITELIST, \
|
||||
UNSUPPORTED_LONGITUDINAL_CAR, PLATFORM_CODE_ECUS, HYUNDAI_VERSION_REQUEST_LONG, \
|
||||
HyundaiFlags, get_platform_codes, HyundaiSafetyFlags
|
||||
HyundaiFlags, get_platform_codes, HyundaiSafetyFlags, \
|
||||
NON_SCC_CAR
|
||||
from opendbc.car.hyundai.fingerprints import FW_VERSIONS
|
||||
|
||||
Ecu = CarParams.Ecu
|
||||
@@ -157,6 +158,8 @@ class TestHyundaiFingerprint:
|
||||
continue
|
||||
if platform_code_ecu == Ecu.eps and car_model in no_eps_platforms:
|
||||
continue
|
||||
if car_model in NON_SCC_CAR:
|
||||
continue
|
||||
assert platform_code_ecu in [e[0] for e in ecus]
|
||||
|
||||
def test_fw_format(self, subtests):
|
||||
@@ -171,6 +174,9 @@ class TestHyundaiFingerprint:
|
||||
if ecu[0] not in PLATFORM_CODE_ECUS:
|
||||
continue
|
||||
|
||||
if car_model in NON_SCC_CAR:
|
||||
continue
|
||||
|
||||
codes = set()
|
||||
for fw in fws:
|
||||
result = get_platform_codes([fw])
|
||||
@@ -237,6 +243,9 @@ class TestHyundaiFingerprint:
|
||||
car_fw.append(CarParams.CarFw(ecu=ecu_name, fwVersion=fw, address=addr,
|
||||
subAddress=0 if sub_addr is None else sub_addr))
|
||||
|
||||
if platform in NON_SCC_CAR:
|
||||
continue
|
||||
|
||||
CP = CarParams(carFw=car_fw)
|
||||
matches = FW_QUERY_CONFIG.match_fw_to_car_fuzzy(build_fw_dict(CP.carFw), CP.carVin, FW_VERSIONS)
|
||||
if len(matches) == 1:
|
||||
|
||||
@@ -8,6 +8,8 @@ from opendbc.car.structs import CarParams
|
||||
from opendbc.car.docs_definitions import CarFootnote, CarHarness, CarDocs, CarParts, Column, Device
|
||||
from opendbc.car.fw_query_definitions import FwQueryConfig, Request, p16
|
||||
|
||||
from opendbc.sunnypilot.car.hyundai.values import HyundaiFlagsSP
|
||||
|
||||
Ecu = CarParams.Ecu
|
||||
|
||||
|
||||
@@ -251,7 +253,7 @@ class CAR(Platforms):
|
||||
flags=HyundaiFlags.CLUSTER_GEARS | HyundaiFlags.ALT_LIMITS,
|
||||
)
|
||||
HYUNDAI_KONA_2022 = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Kona 2022", car_parts=CarParts.common([CarHarness.hyundai_o]))],
|
||||
[HyundaiCarDocs("Hyundai Kona 2022-23", car_parts=CarParts.common([CarHarness.hyundai_o]))],
|
||||
CarSpecs(mass=1491, wheelbase=2.6, steerRatio=13.42, tireStiffnessFactor=0.385),
|
||||
flags=HyundaiFlags.CAMERA_SCC | HyundaiFlags.ALT_LIMITS_2,
|
||||
)
|
||||
@@ -597,6 +599,60 @@ class CAR(Platforms):
|
||||
flags=HyundaiFlags.RADAR_SCC,
|
||||
)
|
||||
|
||||
# port extensions
|
||||
HYUNDAI_BAYON_1ST_GEN_NON_SCC = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Bayon Non-SCC 2021", "No Smart Cruise Control (Non-SCC)", car_parts=CarParts.common([CarHarness.hyundai_n]))],
|
||||
CarSpecs(mass=1150, wheelbase=2.58, steerRatio=13.27 * 1.15),
|
||||
flags=HyundaiFlags.CHECKSUM_CRC8,
|
||||
sp_flags=HyundaiFlagsSP.NON_SCC,
|
||||
)
|
||||
HYUNDAI_ELANTRA_2022_NON_SCC = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Elantra Non-SCC 2022", "No Smart Cruise Control (Non-SCC)", car_parts=CarParts.common([CarHarness.hyundai_k]))],
|
||||
HYUNDAI_ELANTRA_2021.specs,
|
||||
flags=HyundaiFlags.CHECKSUM_CRC8,
|
||||
sp_flags=HyundaiFlagsSP.NON_SCC,
|
||||
)
|
||||
HYUNDAI_KONA_NON_SCC = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Kona Non-SCC 2019", "No Smart Cruise Control (Non-SCC)", car_parts=CarParts.common([CarHarness.hyundai_b]))],
|
||||
HYUNDAI_KONA.specs,
|
||||
flags=HyundaiFlags.ALT_LIMITS,
|
||||
sp_flags=HyundaiFlagsSP.NON_SCC,
|
||||
)
|
||||
HYUNDAI_KONA_EV_NON_SCC = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Kona Electric Non-SCC 2019", "No Smart Cruise Control (Non-SCC)", car_parts=CarParts.common([CarHarness.hyundai_g]))],
|
||||
HYUNDAI_KONA_EV.specs,
|
||||
flags=HyundaiFlags.EV | HyundaiFlags.ALT_LIMITS,
|
||||
sp_flags=HyundaiFlagsSP.NON_SCC,
|
||||
)
|
||||
KIA_CEED_PHEV_2022_NON_SCC = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Kia Ceed Plug-in Hybrid Non-SCC 2022", "No Smart Cruise Control (Non-SCC)", car_parts=CarParts.common([CarHarness.hyundai_i]))],
|
||||
CarSpecs(mass=1650, wheelbase=2.65, steerRatio=13.75, tireStiffnessFactor=0.5),
|
||||
flags=HyundaiFlags.HYBRID,
|
||||
sp_flags=HyundaiFlagsSP.NON_SCC,
|
||||
)
|
||||
KIA_FORTE_2019_NON_SCC = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Kia Forte Non-SCC 2019", "No Smart Cruise Control (Non-SCC)", car_parts=CarParts.common([CarHarness.hyundai_g]))],
|
||||
KIA_FORTE.specs,
|
||||
sp_flags=HyundaiFlagsSP.NON_SCC | HyundaiFlagsSP.NON_SCC_NO_FCA,
|
||||
)
|
||||
KIA_FORTE_2021_NON_SCC = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Kia Forte Non-SCC 2021", "No Smart Cruise Control (Non-SCC)", car_parts=CarParts.common([CarHarness.hyundai_g]))],
|
||||
KIA_FORTE.specs,
|
||||
sp_flags=HyundaiFlagsSP.NON_SCC,
|
||||
)
|
||||
KIA_SELTOS_2023_NON_SCC = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Kia Seltos Non-SCC 2023-24", "No Smart Cruise Control (Non-SCC)", car_parts=CarParts.common([CarHarness.hyundai_l]))],
|
||||
KIA_SELTOS.specs,
|
||||
flags=HyundaiFlags.CHECKSUM_CRC8,
|
||||
sp_flags=HyundaiFlagsSP.NON_SCC,
|
||||
)
|
||||
GENESIS_G70_2021_NON_SCC = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Genesis G70 Non-SCC 2021", "No Smart Cruise Control (Non-SCC)", car_parts=CarParts.common([CarHarness.hyundai_f]))],
|
||||
GENESIS_G70_2020.specs,
|
||||
flags=HyundaiFlags.CHECKSUM_CRC8,
|
||||
sp_flags=HyundaiFlagsSP.NON_SCC | HyundaiFlagsSP.NON_SCC_RADAR_FCA,
|
||||
)
|
||||
|
||||
|
||||
class Buttons:
|
||||
NONE = 0
|
||||
@@ -803,4 +859,7 @@ LEGACY_SAFETY_MODE_CAR = CAR.with_flags(HyundaiFlags.LEGACY)
|
||||
# HyundaiFlags.CANFD_RADAR_SCC | HyundaiFlags.CANFD_NO_RADAR_DISABLE | )
|
||||
UNSUPPORTED_LONGITUDINAL_CAR = CAR.with_flags(HyundaiFlags.LEGACY) | CAR.with_flags(HyundaiFlags.UNSUPPORTED_LONGITUDINAL)
|
||||
|
||||
# port extensions
|
||||
NON_SCC_CAR = CAR.with_sp_flags(HyundaiFlagsSP.NON_SCC)
|
||||
|
||||
DBC = CAR.create_dbc_map()
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import json
|
||||
import os
|
||||
import numpy as np
|
||||
import time
|
||||
import tomllib
|
||||
from abc import abstractmethod, ABC
|
||||
from enum import StrEnum
|
||||
from typing import Any, NamedTuple
|
||||
from typing import Any
|
||||
from collections.abc import Callable
|
||||
from functools import cache
|
||||
|
||||
@@ -19,6 +18,8 @@ from opendbc.car.values import PLATFORMS
|
||||
from opendbc.can import CANParser
|
||||
from opendbc.car.carlog import carlog
|
||||
|
||||
from opendbc.sunnypilot.car.interfaces import CarInterfaceBaseSP
|
||||
|
||||
GearShifter = structs.CarState.GearShifter
|
||||
ButtonType = structs.CarState.ButtonEvent.Type
|
||||
|
||||
@@ -43,15 +44,8 @@ GEAR_SHIFTER_MAP: dict[str, structs.CarState.GearShifter] = {
|
||||
'B': GearShifter.brake, 'BRAKE': GearShifter.brake,
|
||||
}
|
||||
|
||||
|
||||
class LatControlInputs(NamedTuple):
|
||||
lateral_acceleration: float
|
||||
roll_compensation: float
|
||||
vego: float
|
||||
aego: float
|
||||
|
||||
|
||||
TorqueFromLateralAccelCallbackType = Callable[[LatControlInputs, structs.CarParams.LateralTorqueTuning, bool], float]
|
||||
TorqueFromLateralAccelCallbackType = Callable[[float, structs.CarParams.LateralTorqueTuning, bool], float]
|
||||
LateralAccelFromTorqueCallbackType = Callable[[float, structs.CarParams.LateralTorqueTuning, bool], float]
|
||||
|
||||
|
||||
@cache
|
||||
@@ -101,7 +95,7 @@ class RadarInterfaceBase(ABC):
|
||||
return None
|
||||
|
||||
|
||||
class CarInterfaceBase(ABC):
|
||||
class CarInterfaceBase(ABC, CarInterfaceBaseSP):
|
||||
CarState: 'CarStateBase'
|
||||
CarController: 'CarControllerBase'
|
||||
RadarInterface: 'RadarInterfaceBase' = RadarInterfaceBase
|
||||
@@ -171,6 +165,9 @@ class CarInterfaceBase(ABC):
|
||||
docs: bool) -> structs.CarParamsSP:
|
||||
car_params_sp = structs.CarParamsSP()
|
||||
|
||||
platform = PLATFORMS[candidate]
|
||||
car_params_sp.flags |= int(platform.config.sp_flags)
|
||||
|
||||
return cls._get_params_sp(car_params, car_params_sp, candidate, fingerprint, car_fw, alpha_long, docs)
|
||||
|
||||
@staticmethod
|
||||
@@ -211,14 +208,19 @@ class CarInterfaceBase(ABC):
|
||||
def get_steer_feedforward_function(self):
|
||||
return self.get_steer_feedforward_default
|
||||
|
||||
def torque_from_lateral_accel_linear(self, latcontrol_inputs: LatControlInputs, torque_params: structs.CarParams.LateralTorqueTuning,
|
||||
gravity_adjusted: bool) -> float:
|
||||
def torque_from_lateral_accel_linear(self, lateral_acceleration: float, torque_params: structs.CarParams.LateralTorqueTuning) -> float:
|
||||
# The default is a linear relationship between torque and lateral acceleration (accounting for road roll and steering friction)
|
||||
return latcontrol_inputs.lateral_acceleration / float(torque_params.latAccelFactor)
|
||||
return lateral_acceleration / float(torque_params.latAccelFactor)
|
||||
|
||||
def torque_from_lateral_accel(self) -> TorqueFromLateralAccelCallbackType:
|
||||
return self.torque_from_lateral_accel_linear
|
||||
|
||||
def lateral_accel_from_torque_linear(self, torque: float, torque_params: structs.CarParams.LateralTorqueTuning) -> float:
|
||||
return torque * float(torque_params.latAccelFactor)
|
||||
|
||||
def lateral_accel_from_torque(self) -> LateralAccelFromTorqueCallbackType:
|
||||
return self.lateral_accel_from_torque_linear
|
||||
|
||||
# returns a set of default params to avoid repetition in car specific params
|
||||
@staticmethod
|
||||
def get_std_params(candidate: str) -> structs.CarParams:
|
||||
@@ -258,8 +260,8 @@ class CarInterfaceBase(ABC):
|
||||
params = get_torque_params()[candidate]
|
||||
|
||||
tune.init('torque')
|
||||
tune.torque.kp = 1.0
|
||||
tune.torque.kf = 1.0
|
||||
tune.torque.kp = 1.0
|
||||
tune.torque.ki = 0.3
|
||||
tune.torque.friction = params['FRICTION']
|
||||
tune.torque.latAccelFactor = params['LAT_ACCEL_FACTOR']
|
||||
@@ -442,35 +444,3 @@ def get_interface_attr(attr: str, combine_brands: bool = False, ignore_none: boo
|
||||
pass
|
||||
|
||||
return result
|
||||
|
||||
|
||||
class NanoFFModel:
|
||||
def __init__(self, weights_loc: str, platform: str):
|
||||
self.weights_loc = weights_loc
|
||||
self.platform = platform
|
||||
self.load_weights(platform)
|
||||
|
||||
def load_weights(self, platform: str):
|
||||
with open(self.weights_loc) as fob:
|
||||
self.weights = {k: np.array(v) for k, v in json.load(fob)[platform].items()}
|
||||
|
||||
def relu(self, x: np.ndarray):
|
||||
return np.maximum(0.0, x)
|
||||
|
||||
def forward(self, x: np.ndarray):
|
||||
assert x.ndim == 1
|
||||
x = (x - self.weights['input_norm_mat'][:, 0]) / (self.weights['input_norm_mat'][:, 1] - self.weights['input_norm_mat'][:, 0])
|
||||
x = self.relu(np.dot(x, self.weights['w_1']) + self.weights['b_1'])
|
||||
x = self.relu(np.dot(x, self.weights['w_2']) + self.weights['b_2'])
|
||||
x = self.relu(np.dot(x, self.weights['w_3']) + self.weights['b_3'])
|
||||
x = np.dot(x, self.weights['w_4']) + self.weights['b_4']
|
||||
return x
|
||||
|
||||
def predict(self, x: list[float], do_sample: bool = False):
|
||||
x = self.forward(np.array(x))
|
||||
if do_sample:
|
||||
pred = np.random.laplace(x[0], np.exp(x[1]) / self.weights['temperature'])
|
||||
else:
|
||||
pred = x[0]
|
||||
pred = pred * (self.weights['output_norm_mat'][1] - self.weights['output_norm_mat'][0]) + self.weights['output_norm_mat'][0]
|
||||
return pred
|
||||
|
||||
@@ -160,9 +160,10 @@ def apply_center_deadzone(error, deadzone):
|
||||
|
||||
def get_friction(lateral_accel_error: float, lateral_accel_deadzone: float, friction_threshold: float,
|
||||
torque_params: structs.CarParams.LateralTorqueTuning) -> float:
|
||||
# TODO torque params' friction should be in lataxel space, not torque space
|
||||
friction_interp = np.interp(
|
||||
apply_center_deadzone(lateral_accel_error, lateral_accel_deadzone),
|
||||
[-friction_threshold, friction_threshold],
|
||||
[-torque_params.friction, torque_params.friction]
|
||||
[-torque_params.friction * torque_params.latAccelFactor, torque_params.friction * torque_params.latAccelFactor]
|
||||
)
|
||||
return float(friction_interp)
|
||||
|
||||
@@ -59,6 +59,7 @@ FW_VERSIONS = {
|
||||
b'476605SD2E',
|
||||
b'476605SH1D',
|
||||
b'476605SH7D',
|
||||
b'476605SH7E',
|
||||
b'476605SK2A',
|
||||
],
|
||||
(Ecu.eps, 0x742, None): [
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
from opendbc.can.packer import CANPacker
|
||||
from opendbc.car import Bus
|
||||
from opendbc.car.lateral import apply_std_steer_angle_limits
|
||||
from opendbc.car.interfaces import CarControllerBase
|
||||
from opendbc.car.psa.psacan import create_lka_steering
|
||||
from opendbc.car.psa.values import CarControllerParams
|
||||
|
||||
|
||||
class CarController(CarControllerBase):
|
||||
def __init__(self, dbc_names, CP, CP_SP):
|
||||
super().__init__(dbc_names, CP, CP_SP)
|
||||
self.packer = CANPacker(dbc_names[Bus.main])
|
||||
self.apply_angle_last = 0
|
||||
self.status = 2
|
||||
|
||||
def update(self, CC, CC_SP, CS, now_nanos):
|
||||
can_sends = []
|
||||
actuators = CC.actuators
|
||||
|
||||
# lateral control
|
||||
if self.frame % 5 == 0:
|
||||
apply_angle = apply_std_steer_angle_limits(actuators.steeringAngleDeg, self.apply_angle_last, CS.out.vEgoRaw,
|
||||
CS.out.steeringAngleDeg, CC.latActive, CarControllerParams.ANGLE_LIMITS)
|
||||
|
||||
# EPS disengages on steering override, activation sequence 2->3->4 to re-engage
|
||||
# STATUS - 0: UNAVAILABLE, 1: UNSELECTED, 2: READY, 3: AUTHORIZED, 4: ACTIVE
|
||||
if not CC.latActive:
|
||||
self.status = 2
|
||||
elif not CS.eps_active and not CS.out.steeringPressed:
|
||||
self.status = 2 if self.status == 4 else self.status + 1
|
||||
else:
|
||||
self.status = 4
|
||||
|
||||
can_sends.append(create_lka_steering(self.packer, CC.latActive, apply_angle, self.status))
|
||||
|
||||
self.apply_angle_last = apply_angle
|
||||
|
||||
new_actuators = actuators.as_builder()
|
||||
new_actuators.steeringAngleDeg = self.apply_angle_last
|
||||
self.frame += 1
|
||||
return new_actuators, can_sends
|
||||
@@ -0,0 +1,74 @@
|
||||
from opendbc.car import structs, Bus
|
||||
from opendbc.can.parser import CANParser
|
||||
from opendbc.car.common.conversions import Conversions as CV
|
||||
from opendbc.car.psa.values import DBC, CarControllerParams
|
||||
from opendbc.car.interfaces import CarStateBase
|
||||
|
||||
GearShifter = structs.CarState.GearShifter
|
||||
TransmissionType = structs.CarParams.TransmissionType
|
||||
|
||||
|
||||
class CarState(CarStateBase):
|
||||
def update(self, can_parsers) -> structs.CarState:
|
||||
cp = can_parsers[Bus.main]
|
||||
cp_adas = can_parsers[Bus.adas]
|
||||
cp_cam = can_parsers[Bus.cam]
|
||||
ret = structs.CarState()
|
||||
ret_sp = structs.CarStateSP()
|
||||
|
||||
# car speed
|
||||
self.parse_wheel_speeds(ret,
|
||||
cp.vl['Dyn4_FRE']['P263_VehV_VPsvValWhlFrtL'],
|
||||
cp.vl['Dyn4_FRE']['P264_VehV_VPsvValWhlFrtR'],
|
||||
cp.vl['Dyn4_FRE']['P265_VehV_VPsvValWhlBckL'],
|
||||
cp.vl['Dyn4_FRE']['P266_VehV_VPsvValWhlBckR'],
|
||||
)
|
||||
ret.yawRate = cp_adas.vl['HS2_DYN_UCF_MDD_32D']['VITESSE_LACET_BRUTE'] * CV.DEG_TO_RAD
|
||||
ret.standstill = bool(cp_adas.vl['HS2_DYN_UCF_MDD_32D']['VEHICLE_STANDSTILL'])
|
||||
|
||||
# gas
|
||||
ret.gasPressed = cp.vl['Dyn_CMM']['P002_Com_rAPP'] > 0
|
||||
|
||||
# brake
|
||||
ret.brakePressed = bool(cp_cam.vl['Dat_BSI']['P013_MainBrake'])
|
||||
ret.parkingBrake = cp.vl['Dyn_EasyMove']['P337_Com_stPrkBrk'] == 1 # 0: disengaged, 1: engaged, 3: brake actuator moving
|
||||
|
||||
# steering wheel
|
||||
ret.steeringAngleDeg = cp.vl['STEERING_ALT']['ANGLE'] # EPS
|
||||
ret.steeringRateDeg = cp.vl['STEERING_ALT']['RATE'] * (2 * cp.vl['STEERING_ALT']['RATE_SIGN'] - 1) # convert [0,1] to [-1,1] EPS: rot. speed * rot. sign
|
||||
ret.steeringTorque = cp.vl['STEERING']['DRIVER_TORQUE']
|
||||
ret.steeringTorqueEps = cp.vl['IS_DAT_DIRA']['EPS_TORQUE']
|
||||
ret.steeringPressed = self.update_steering_pressed(abs(ret.steeringTorque) > CarControllerParams.STEER_DRIVER_ALLOWANCE, 5)
|
||||
self.eps_active = cp.vl['IS_DAT_DIRA']['EPS_STATE_LKA'] == 3 # 0: Unauthorized, 1: Authorized, 2: Available, 3: Active, 4: Defect
|
||||
|
||||
# cruise
|
||||
ret.cruiseState.speed = cp_adas.vl['HS2_DAT_MDD_CMD_452']['SPEED_SETPOINT'] * CV.KPH_TO_MS # set to 255 when ACC is off, -2 kph offset from dash speed
|
||||
ret.cruiseState.enabled = cp_adas.vl['HS2_DAT_MDD_CMD_452']['RVV_ACC_ACTIVATION_REQ'] == 1
|
||||
ret.cruiseState.available = cp_adas.vl['HS2_DYN1_MDD_ETAT_2B6']['ACC_STATUS'] > 2
|
||||
ret.cruiseState.nonAdaptive = cp_adas.vl['HS2_DAT_MDD_CMD_452']['LONGITUDINAL_REGULATION_TYPE'] != 3 # 0: None, 1: CC, 2: Limiter, 3: ACC
|
||||
ret.cruiseState.standstill = bool(cp_adas.vl['HS2_DYN_UCF_MDD_32D']['VEHICLE_STANDSTILL'])
|
||||
ret.accFaulted = cp_adas.vl['HS2_DYN_UCF_MDD_32D']['ACC_ETAT_DECEL_OR_ESP_STATUS'] == 3 # 0: Inhibited, 1: Waiting, 2: Active, 3: Fault
|
||||
|
||||
# gear
|
||||
if bool(cp_cam.vl['Dat_BSI']['P103_Com_bRevGear']):
|
||||
ret.gearShifter = GearShifter.reverse
|
||||
else:
|
||||
ret.gearShifter = GearShifter.drive
|
||||
|
||||
# blinkers
|
||||
blinker = cp_cam.vl['HS2_DAT7_BSI_612']['CDE_CLG_ET_HDC']
|
||||
ret.leftBlinker = blinker == 1
|
||||
ret.rightBlinker = blinker == 2
|
||||
|
||||
# lock info
|
||||
ret.doorOpen = any((cp_cam.vl['Dat_BSI']['DRIVER_DOOR'], cp_cam.vl['Dat_BSI']['PASSENGER_DOOR']))
|
||||
ret.seatbeltUnlatched = cp_cam.vl['RESTRAINTS']['DRIVER_SEATBELT'] != 2
|
||||
return ret, ret_sp
|
||||
|
||||
@staticmethod
|
||||
def get_can_parsers(CP, CP_SP):
|
||||
return {
|
||||
Bus.main: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 0),
|
||||
Bus.adas: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 1),
|
||||
Bus.cam: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 2),
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
""" AUTO-FORMATTED USING opendbc/car/debug/format_fingerprints.py, EDIT STRUCTURE THERE."""
|
||||
from opendbc.car.structs import CarParams
|
||||
from opendbc.car.psa.values import CAR
|
||||
|
||||
Ecu = CarParams.Ecu
|
||||
|
||||
FW_VERSIONS = {
|
||||
CAR.PSA_PEUGEOT_208: {
|
||||
(Ecu.fwdRadar, 0x6b6, None): [
|
||||
b'212053276',
|
||||
],
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
from opendbc.car import structs, get_safety_config
|
||||
from opendbc.car.interfaces import CarInterfaceBase
|
||||
from opendbc.car.psa.carcontroller import CarController
|
||||
from opendbc.car.psa.carstate import CarState
|
||||
|
||||
TransmissionType = structs.CarParams.TransmissionType
|
||||
|
||||
|
||||
class CarInterface(CarInterfaceBase):
|
||||
CarState = CarState
|
||||
CarController = CarController
|
||||
|
||||
@staticmethod
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
|
||||
ret.brand = 'psa'
|
||||
|
||||
ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.psa)]
|
||||
|
||||
ret.dashcamOnly = True
|
||||
|
||||
ret.steerActuatorDelay = 0.3
|
||||
ret.steerLimitTimer = 0.1
|
||||
ret.steerAtStandstill = True
|
||||
|
||||
ret.steerControlType = structs.CarParams.SteerControlType.angle
|
||||
ret.radarUnavailable = True
|
||||
|
||||
ret.alphaLongitudinalAvailable = False
|
||||
|
||||
return ret
|
||||
@@ -0,0 +1,18 @@
|
||||
def psa_checksum(address: int, sig, d: bytearray) -> int:
|
||||
chk_ini = {0x452: 0x4, 0x38D: 0x7, 0x42D: 0xC}.get(address, 0xB)
|
||||
byte = sig.start_bit // 8
|
||||
d[byte] &= 0x0F if sig.start_bit % 8 >= 4 else 0xF0
|
||||
checksum = sum((b >> 4) + (b & 0xF) for b in d)
|
||||
return (chk_ini - checksum) & 0xF
|
||||
|
||||
|
||||
def create_lka_steering(packer, lat_active: bool, apply_angle: float, status: int):
|
||||
values = {
|
||||
'DRIVE': 1,
|
||||
'STATUS': status,
|
||||
'LXA_ACTIVATION': 1,
|
||||
'TORQUE_FACTOR': lat_active * 100,
|
||||
'SET_ANGLE': apply_angle,
|
||||
}
|
||||
|
||||
return packer.make_can_msg('LANE_KEEP_ASSIST', 0, values)
|
||||
@@ -0,0 +1,54 @@
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
from opendbc.car.structs import CarParams
|
||||
from opendbc.car import Bus, CarSpecs, DbcDict, PlatformConfig, Platforms
|
||||
from opendbc.car.lateral import AngleSteeringLimits
|
||||
from opendbc.car.docs_definitions import CarDocs, CarHarness, CarParts
|
||||
from opendbc.car.fw_query_definitions import FwQueryConfig, Request, StdQueries
|
||||
|
||||
Ecu = CarParams.Ecu
|
||||
|
||||
|
||||
class CarControllerParams:
|
||||
STEER_STEP = 1
|
||||
|
||||
ANGLE_LIMITS: AngleSteeringLimits = AngleSteeringLimits(
|
||||
390, # deg
|
||||
([0., 5., 25.], [2.5, 1.5, .2]),
|
||||
([0., 5., 25.], [5., 2., .3]),
|
||||
)
|
||||
STEER_DRIVER_ALLOWANCE = 5 # Driver intervention threshold, 0.5 Nm
|
||||
|
||||
|
||||
@dataclass
|
||||
class PSACarDocs(CarDocs):
|
||||
package: str = "Adaptive Cruise Control (ACC) & Lane Assist"
|
||||
car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.psa_a]))
|
||||
|
||||
|
||||
@dataclass
|
||||
class PSAPlatformConfig(PlatformConfig):
|
||||
dbc_dict: DbcDict = field(default_factory=lambda: {
|
||||
Bus.pt: 'psa_aee2010_r3',
|
||||
})
|
||||
|
||||
|
||||
class CAR(Platforms):
|
||||
PSA_PEUGEOT_208 = PSAPlatformConfig(
|
||||
[PSACarDocs("Peugeot 208 2019-25")],
|
||||
CarSpecs(mass=1530, wheelbase=2.54, steerRatio=17.6),
|
||||
)
|
||||
|
||||
|
||||
# Placeholder, FW Query will be added in separate PR
|
||||
FW_QUERY_CONFIG = FwQueryConfig(
|
||||
requests=[
|
||||
Request(
|
||||
[StdQueries.TESTER_PRESENT_REQUEST, StdQueries.UDS_VERSION_REQUEST],
|
||||
[StdQueries.TESTER_PRESENT_RESPONSE, StdQueries.UDS_VERSION_RESPONSE],
|
||||
bus=0,
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
DBC = CAR.create_dbc_map()
|
||||
@@ -6,8 +6,6 @@ from opendbc.car.interfaces import CarControllerBase
|
||||
from opendbc.car.tesla.teslacan import TeslaCAN
|
||||
from opendbc.car.tesla.values import CarControllerParams
|
||||
from opendbc.car.vehicle_model import VehicleModel
|
||||
|
||||
from opendbc.sunnypilot.car.tesla.virtual_torque_blending import TorqueBlendingCarController
|
||||
from opendbc.sunnypilot.car.tesla.mads import MadsCarController
|
||||
|
||||
|
||||
@@ -18,11 +16,10 @@ def get_safety_CP():
|
||||
return CarInterface.get_non_essential_params("TESLA_MODEL_Y")
|
||||
|
||||
|
||||
class CarController(CarControllerBase, MadsCarController, TorqueBlendingCarController):
|
||||
class CarController(CarControllerBase, MadsCarController):
|
||||
def __init__(self, dbc_names, CP, CP_SP):
|
||||
CarControllerBase.__init__(self, dbc_names, CP, CP_SP)
|
||||
MadsCarController.__init__(self)
|
||||
TorqueBlendingCarController.__init__(self)
|
||||
self.apply_angle_last = 0
|
||||
self.packer = CANPacker(dbc_names[Bus.party])
|
||||
self.tesla_can = TeslaCAN(self.packer)
|
||||
@@ -41,11 +38,8 @@ class CarController(CarControllerBase, MadsCarController, TorqueBlendingCarContr
|
||||
lat_active = CC.latActive and CS.hands_on_level < 3
|
||||
|
||||
if self.frame % 2 == 0:
|
||||
# Virtual torque blending
|
||||
lat_active, apply_angle = self.update_torque_blending(CS, CC, lat_active, actuators.steeringAngleDeg)
|
||||
|
||||
# Angular rate limit based on speed
|
||||
self.apply_angle_last = apply_steer_angle_limits_vm(apply_angle, self.apply_angle_last, CS.out.vEgoRaw, CS.out.steeringAngleDeg,
|
||||
self.apply_angle_last = apply_steer_angle_limits_vm(actuators.steeringAngleDeg, self.apply_angle_last, CS.out.vEgoRaw, CS.out.steeringAngleDeg,
|
||||
lat_active, CarControllerParams, self.VM)
|
||||
|
||||
can_sends.append(self.tesla_can.create_steering_control(self.apply_angle_last, lat_active, self.mads.control_type))
|
||||
|
||||
@@ -5,15 +5,12 @@ from opendbc.car.common.conversions import Conversions as CV
|
||||
from opendbc.car.interfaces import CarStateBase
|
||||
from opendbc.car.tesla.values import DBC, CANBUS, GEAR_MAP, STEER_THRESHOLD, CAR
|
||||
|
||||
from opendbc.sunnypilot.car.tesla.virtual_torque_blending import TorqueBlendingCarState
|
||||
|
||||
ButtonType = structs.CarState.ButtonEvent.Type
|
||||
|
||||
|
||||
class CarState(CarStateBase, TorqueBlendingCarState):
|
||||
class CarState(CarStateBase):
|
||||
def __init__(self, CP, CP_SP):
|
||||
CarStateBase.__init__(self, CP, CP_SP)
|
||||
TorqueBlendingCarState.__init__(self)
|
||||
super().__init__(CP, CP_SP)
|
||||
self.can_define = CANDefine(DBC[CP.carFingerprint][Bus.party])
|
||||
self.shifter_values = self.can_define.dv["DI_systemStatus"]["DI_gear"]
|
||||
|
||||
@@ -121,8 +118,6 @@ class CarState(CarStateBase, TorqueBlendingCarState):
|
||||
# Messages needed by carcontroller
|
||||
self.das_control = copy.copy(cp_ap_party.vl["DAS_control"])
|
||||
|
||||
TorqueBlendingCarState.update_torque_blending(self, ret, eac_status, eac_error_code)
|
||||
|
||||
return ret, ret_sp
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -14,6 +14,7 @@ FW_VERSIONS = {
|
||||
b'TeMYG4_DCS_Update_0.0.0 (9),E4014.26.0',
|
||||
b'TeMYG4_Legacy3Y_0.0.0 (2),E4015.02.0',
|
||||
b'TeMYG4_Legacy3Y_0.0.0 (5),E4015.03.2',
|
||||
b'TeMYG4_Legacy3Y_0.0.0 (5),E4L015.03.2',
|
||||
b'TeMYG4_Main_0.0.0 (59),E4H014.29.0',
|
||||
b'TeMYG4_Main_0.0.0 (65),E4H015.01.0',
|
||||
b'TeMYG4_Main_0.0.0 (67),E4H015.02.1',
|
||||
|
||||
@@ -3,7 +3,6 @@ from opendbc.car.interfaces import CarInterfaceBase
|
||||
from opendbc.car.tesla.carcontroller import CarController
|
||||
from opendbc.car.tesla.carstate import CarState
|
||||
from opendbc.car.tesla.values import TeslaSafetyFlags, CAR
|
||||
from opendbc.sunnypilot.car.tesla.values import TeslaFlagsSP, TeslaSafetyFlagsSP
|
||||
|
||||
|
||||
class CarInterface(CarInterfaceBase):
|
||||
@@ -42,9 +41,4 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
stock_cp.enableBsm = True
|
||||
|
||||
ret.flags |= TeslaFlagsSP.VIRTUAL_TORQUE_BLENDING.value
|
||||
|
||||
if ret.flags & TeslaFlagsSP.VIRTUAL_TORQUE_BLENDING:
|
||||
ret.safetyParam |= TeslaSafetyFlagsSP.VIRTUAL_TORQUE_BLENDING
|
||||
|
||||
return ret
|
||||
|
||||
@@ -15,6 +15,7 @@ from opendbc.car.toyota.values import CAR as TOYOTA
|
||||
from opendbc.car.values import Platform
|
||||
from opendbc.car.volkswagen.values import CAR as VOLKSWAGEN
|
||||
from opendbc.car.body.values import CAR as COMMA
|
||||
from opendbc.car.psa.values import CAR as PSA
|
||||
|
||||
# FIXME: add routes for these cars
|
||||
non_tested_cars = [
|
||||
@@ -25,6 +26,19 @@ non_tested_cars = [
|
||||
HYUNDAI.GENESIS_G90,
|
||||
VOLKSWAGEN.VOLKSWAGEN_CRAFTER_MK2, # need a route from an ACC-equipped Crafter
|
||||
SUBARU.SUBARU_FORESTER_HYBRID,
|
||||
|
||||
# port extensions
|
||||
HYUNDAI.KIA_CEED_PHEV_2022_NON_SCC,
|
||||
HYUNDAI.HYUNDAI_KONA_EV_NON_SCC,
|
||||
HYUNDAI.HYUNDAI_BAYON_1ST_GEN_NON_SCC,
|
||||
HYUNDAI.HYUNDAI_ELANTRA_2022_NON_SCC,
|
||||
HYUNDAI.HYUNDAI_KONA_NON_SCC,
|
||||
HYUNDAI.KIA_FORTE_2019_NON_SCC,
|
||||
HYUNDAI.KIA_FORTE_2021_NON_SCC,
|
||||
HYUNDAI.KIA_SELTOS_2023_NON_SCC,
|
||||
HYUNDAI.GENESIS_G70_2021_NON_SCC,
|
||||
HONDA.HONDA_CLARITY,
|
||||
TOYOTA.TOYOTA_WILDLANDER,
|
||||
]
|
||||
|
||||
|
||||
@@ -110,6 +124,9 @@ routes = [
|
||||
CarTestRoute("b1c832ad56b6bc9d/00000010--debfcf5867", HONDA.HONDA_CIVIC_2022), # 2025 Civic Hatch Hybrid with new eCVT transmission
|
||||
CarTestRoute("f9c43864cf057d05/2024-01-15--23-01-20", HONDA.HONDA_PILOT_4G), # TODO: Replace with a newer route
|
||||
CarTestRoute("f39cf149898833ff/0000002b--54f3fae045", HONDA.HONDA_ACCORD_11G),
|
||||
CarTestRoute("ad9840558640c31d/0000001a--d6cd4871c2", HONDA.ACURA_MDX_4G_MMR), # 2025 MDX
|
||||
CarTestRoute("63568e3e2f56c8ad/0000000a--a254e90429", HONDA.HONDA_CRV_6G),
|
||||
CarTestRoute("56b2cf1dacdcd033/00000048--3267801001", HONDA.HONDA_CITY_7G), # Brazilian model
|
||||
|
||||
CarTestRoute("87d7f06ade479c2e/2023-09-11--23-30-11", HYUNDAI.HYUNDAI_AZERA_6TH_GEN),
|
||||
CarTestRoute("66189dd8ec7b50e6/2023-09-20--07-02-12", HYUNDAI.HYUNDAI_AZERA_HEV_6TH_GEN),
|
||||
@@ -182,7 +199,7 @@ routes = [
|
||||
CarTestRoute("db04d2c63990e3ba/2023-02-08--16-52-39", HYUNDAI.KIA_NIRO_HEV_2ND_GEN),
|
||||
CarTestRoute("50a2212c41f65c7b/2021-05-24--16-22-06", HYUNDAI.KIA_FORTE),
|
||||
CarTestRoute("192283cdbb7a58c2/2022-10-15--01-43-18", HYUNDAI.KIA_SPORTAGE_5TH_GEN),
|
||||
CarTestRoute("09559f1fcaed4704/2023-11-16--02-24-57", HYUNDAI.KIA_SPORTAGE_5TH_GEN), # openpilot longitudinal
|
||||
CarTestRoute("09559f1fcaed4704/2023-11-16--02-24-57", HYUNDAI.KIA_SPORTAGE_5TH_GEN, segment=0), # openpilot longitudinal
|
||||
CarTestRoute("b3537035ffe6a7d6/2022-10-17--15-23-49", HYUNDAI.KIA_SPORTAGE_5TH_GEN), # hybrid
|
||||
CarTestRoute("c5ac319aa9583f83/2021-06-01--18-18-31", HYUNDAI.HYUNDAI_ELANTRA),
|
||||
CarTestRoute("734ef96182ddf940/2022-10-02--16-41-44", HYUNDAI.HYUNDAI_ELANTRA_GT_I30),
|
||||
@@ -312,6 +329,8 @@ routes = [
|
||||
CarTestRoute("f6d5b1a9d7a1c92e/2021-07-08--06-56-59", MAZDA.MAZDA_CX9_2021),
|
||||
CarTestRoute("a4af1602d8e668ac/2022-02-03--12-17-07", MAZDA.MAZDA_CX5_2022),
|
||||
|
||||
CarTestRoute("6a7075a4fdd765ee/0000004e--1f612006dd", PSA.PSA_PEUGEOT_208),
|
||||
|
||||
CarTestRoute("bc095dc92e101734/000000db--ee9fe46e57", RIVIAN.RIVIAN_R1_GEN1),
|
||||
|
||||
CarTestRoute("7dc058789994da80/00000112--adb970f6a8", TESLA.TESLA_MODEL_3),
|
||||
|
||||
@@ -260,7 +260,7 @@ class TestFwFingerprintTiming:
|
||||
print(f'get_vin {name} case, query time={self.total_time / self.N} seconds')
|
||||
|
||||
def test_fw_query_timing(self, subtests, mocker):
|
||||
total_ref_time = {1: 7.3, 2: 7.9}
|
||||
total_ref_time = {1: 7.4, 2: 8.0}
|
||||
brand_ref_times = {
|
||||
1: {
|
||||
'gm': 1.0,
|
||||
@@ -276,6 +276,7 @@ class TestFwFingerprintTiming:
|
||||
'toyota': 0.7,
|
||||
'volkswagen': 0.65,
|
||||
'rivian': 0.3,
|
||||
'psa': 0.1,
|
||||
},
|
||||
2: {
|
||||
'ford': 1.6,
|
||||
|
||||
@@ -28,6 +28,7 @@ class TestLateralLimits:
|
||||
def setup_class(cls):
|
||||
CarInterface = interfaces[cls.car_model]
|
||||
CP = CarInterface.get_non_essential_params(cls.car_model)
|
||||
_ = CarInterface.get_non_essential_params_sp(CP, cls.car_model)
|
||||
|
||||
if cls.car_model == 'MOCK':
|
||||
pytest.skip('Mock car')
|
||||
|
||||
@@ -7,6 +7,9 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
|
||||
"NISSAN_LEAF" = [nan, 1.5, nan]
|
||||
"NISSAN_ROGUE" = [nan, 1.5, nan]
|
||||
|
||||
# PSA angle based controllers
|
||||
"PSA_PEUGEOT_208" = [nan, 2.0, nan]
|
||||
|
||||
# New subarus angle based controllers
|
||||
"SUBARU_FORESTER_2022" = [nan, 3.0, nan]
|
||||
"SUBARU_OUTBACK_2023" = [nan, 3.0, nan]
|
||||
@@ -80,6 +83,10 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
|
||||
"RIVIAN_R1_GEN1" = [2.8, 2.5, 0.07]
|
||||
"HYUNDAI_NEXO_1ST_GEN" = [2.5, 2.5, 0.1]
|
||||
"HONDA_ACCORD_11G" = [1.35, 1.35, 0.17]
|
||||
"HONDA_PILOT_4G" = [1.25, 1.25, 0.21]
|
||||
"ACURA_MDX_4G_MMR" = [1.25, 1.25, 0.15]
|
||||
"HONDA_CRV_6G" = [1.3, 1.3, 0.2]
|
||||
"HONDA_CITY_7G" = [1.2, 1.2, 0.23]
|
||||
|
||||
# Dashcam or fallback configured as ideal car
|
||||
"MOCK" = [10.0, 10, 0.0]
|
||||
@@ -87,4 +94,3 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
|
||||
# Manually checked
|
||||
"HONDA_CIVIC_2022" = [2.5, 1.2, 0.15]
|
||||
"HONDA_HRV_3G" = [2.5, 1.2, 0.2]
|
||||
"HONDA_PILOT_4G" = [1.0, 1.0, 0.2]
|
||||
|
||||
@@ -85,3 +85,16 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
|
||||
"SUBARU_FORESTER_PREGLOBAL" = "SUBARU_IMPREZA"
|
||||
"SUBARU_LEGACY_PREGLOBAL" = "SUBARU_IMPREZA"
|
||||
"SUBARU_ASCENT" = "SUBARU_FORESTER"
|
||||
|
||||
# port extensions
|
||||
"KIA_CEED_PHEV_2022_NON_SCC" = "HYUNDAI_SONATA"
|
||||
"HYUNDAI_KONA_EV_NON_SCC" = "HYUNDAI_KONA_EV"
|
||||
"KIA_FORTE_2019_NON_SCC" = "HYUNDAI_SONATA"
|
||||
"KIA_FORTE_2021_NON_SCC" = "HYUNDAI_SONATA"
|
||||
"KIA_SELTOS_2023_NON_SCC" = "HYUNDAI_SONATA"
|
||||
"HYUNDAI_KONA_NON_SCC" = "HYUNDAI_KONA_EV"
|
||||
"HYUNDAI_ELANTRA_2022_NON_SCC" = "HYUNDAI_ELANTRA_2021"
|
||||
"GENESIS_G70_2021_NON_SCC" = "HYUNDAI_SONATA"
|
||||
"HYUNDAI_BAYON_1ST_GEN_NON_SCC" = "HYUNDAI_SONATA"
|
||||
"HONDA_CLARITY" = "HONDA_CIVIC"
|
||||
"TOYOTA_WILDLANDER" = "TOYOTA_RAV4_TSS2"
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
from opendbc.car.structs import CarParams
|
||||
from opendbc.car.toyota.values import CAR
|
||||
|
||||
from opendbc.sunnypilot.car.fw_versions_ext import merge_fw_versions
|
||||
from opendbc.sunnypilot.car.toyota.fingerprints_ext import FW_VERSIONS_EXT
|
||||
|
||||
Ecu = CarParams.Ecu
|
||||
|
||||
FW_VERSIONS = {
|
||||
@@ -500,6 +503,7 @@ FW_VERSIONS = {
|
||||
b'\x02896630ZZ0000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00',
|
||||
b'\x028966312K6000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00',
|
||||
b'\x028966312L0000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00',
|
||||
b'\x028966312L0100\x00\x00\x00\x008966A4703000\x00\x00\x00\x00',
|
||||
b'\x028966312Q3000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00',
|
||||
b'\x028966312Q3100\x00\x00\x00\x008966A4703000\x00\x00\x00\x00',
|
||||
b'\x028966312Q4000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00',
|
||||
@@ -1187,6 +1191,7 @@ FW_VERSIONS = {
|
||||
b'\x01F15264283200\x00\x00\x00\x00',
|
||||
b'\x01F15264286100\x00\x00\x00\x00',
|
||||
b'\x01F15264286200\x00\x00\x00\x00',
|
||||
b'\x01F152642870\x00\x00\x00\x00\x00\x00',
|
||||
],
|
||||
(Ecu.eps, 0x7a1, None): [
|
||||
b'\x028965B0R01500\x00\x00\x00\x008965B0R02500\x00\x00\x00\x00',
|
||||
@@ -1837,18 +1842,25 @@ FW_VERSIONS = {
|
||||
CAR.TOYOTA_YARIS: {
|
||||
(Ecu.engine, 0x700, None): [
|
||||
b'\x0189663K015300\x00\x00\x00\x00',
|
||||
b'\x0189663K023000\x00\x00\x00\x00',
|
||||
],
|
||||
(Ecu.eps, 0x7a1, None): [
|
||||
b'\x018965BK002100\x00\x00\x00\x00',
|
||||
b'\x018965BK003200\x00\x00\x00\x00',
|
||||
],
|
||||
(Ecu.abs, 0x7b0, None): [
|
||||
b'\x01F1526K005600\x00\x00\x00\x00',
|
||||
b'\x01F1526K007500\x00\x00\x00\x00',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x750, 0xf): [
|
||||
b'\x018821F0D04100\x00\x00\x00\x00',
|
||||
b'\x018821F0D05300\x00\x00\x00\x00',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x750, 0x6d): [
|
||||
b'\x028646F0W04100\x00\x00\x00\x008646G0W04100\x00\x00\x00\x00',
|
||||
b'\x028646F5205200\x00\x00\x00\x008646G5202200\x00\x00\x00\x00',
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
FW_VERSIONS = merge_fw_versions(FW_VERSIONS, FW_VERSIONS_EXT)
|
||||
|
||||
@@ -157,6 +157,14 @@ class CarInterface(CarInterfaceBase):
|
||||
if candidate in UNSUPPORTED_DSU_CAR:
|
||||
ret.safetyParam |= ToyotaSafetyFlagsSP.UNSUPPORTED_DSU
|
||||
|
||||
if candidate in (CAR.TOYOTA_WILDLANDER, ):
|
||||
stock_cp.lateralTuning.init('pid')
|
||||
stock_cp.lateralTuning.pid.kiBP = [0.0]
|
||||
stock_cp.lateralTuning.pid.kpBP = [0.0]
|
||||
stock_cp.lateralTuning.pid.kpV = [0.6]
|
||||
stock_cp.lateralTuning.pid.kiV = [0.1]
|
||||
stock_cp.lateralTuning.pid.kf = 0.00007818594
|
||||
|
||||
return ret
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -290,7 +290,7 @@ class CAR(Platforms):
|
||||
CarSpecs(mass=4372. * CV.LB_TO_KG, wheelbase=2.68, steerRatio=16.88, tireStiffnessFactor=0.5533),
|
||||
)
|
||||
TOYOTA_YARIS = ToyotaSecOCPlatformConfig(
|
||||
[ToyotaCommunityCarDocs("Toyota Yaris (Non-US only) 2023", min_enable_speed=MIN_ACC_SPEED)],
|
||||
[ToyotaCommunityCarDocs("Toyota Yaris (Non-US only) 2020, 2023", min_enable_speed=MIN_ACC_SPEED)],
|
||||
CarSpecs(mass=1170, wheelbase=2.55, steerRatio=14.80, tireStiffnessFactor=0.5533),
|
||||
flags=ToyotaFlags.RADAR_ACC,
|
||||
)
|
||||
@@ -396,6 +396,12 @@ class CAR(Platforms):
|
||||
flags=ToyotaFlags.UNSUPPORTED_DSU,
|
||||
)
|
||||
|
||||
# port extensions
|
||||
TOYOTA_WILDLANDER = ToyotaSecOCPlatformConfig(
|
||||
[ToyotaCarDocs("Toyota Wildlander PHEV 2021", min_enable_speed=MIN_ACC_SPEED)],
|
||||
CarSpecs(mass=4155. * CV.LB_TO_KG, wheelbase=2.69, steerRatio=16.88, tireStiffnessFactor=0.5533),
|
||||
)
|
||||
|
||||
|
||||
# (addr, cars, bus, 1/freq*100, vl)
|
||||
STATIC_DSU_MSGS = [
|
||||
|
||||
@@ -8,13 +8,14 @@ from opendbc.car.hyundai.values import CAR as HYUNDAI
|
||||
from opendbc.car.mazda.values import CAR as MAZDA
|
||||
from opendbc.car.mock.values import CAR as MOCK
|
||||
from opendbc.car.nissan.values import CAR as NISSAN
|
||||
from opendbc.car.psa.values import CAR as PSA
|
||||
from opendbc.car.rivian.values import CAR as RIVIAN
|
||||
from opendbc.car.subaru.values import CAR as SUBARU
|
||||
from opendbc.car.tesla.values import CAR as TESLA
|
||||
from opendbc.car.toyota.values import CAR as TOYOTA
|
||||
from opendbc.car.volkswagen.values import CAR as VOLKSWAGEN
|
||||
|
||||
Platform = BODY | CHRYSLER | FORD | GM | HONDA | HYUNDAI | MAZDA | MOCK | NISSAN | RIVIAN | SUBARU | TESLA | TOYOTA | VOLKSWAGEN
|
||||
Platform = BODY | CHRYSLER | FORD | GM | HONDA | HYUNDAI | MAZDA | MOCK | NISSAN | PSA | RIVIAN | SUBARU | TESLA | TOYOTA | VOLKSWAGEN
|
||||
BRANDS = get_args(Platform)
|
||||
|
||||
PLATFORMS: dict[str, Platform] = {str(platform): platform for brand in BRANDS for platform in brand}
|
||||
|
||||
@@ -441,6 +441,7 @@ FW_VERSIONS = {
|
||||
(Ecu.engine, 0x7e0, None): [
|
||||
b'\xf1\x8703N906026E \xf1\x892114',
|
||||
b'\xf1\x8704E906023AH\xf1\x893379',
|
||||
b'\xf1\x8704E906023BF\xf1\x893842',
|
||||
b'\xf1\x8704E906023BM\xf1\x894522',
|
||||
b'\xf1\x8704L906026DP\xf1\x891538',
|
||||
b'\xf1\x8704L906026ET\xf1\x891990',
|
||||
@@ -465,6 +466,7 @@ FW_VERSIONS = {
|
||||
b'\xf1\x870D9300041A \xf1\x894801',
|
||||
b'\xf1\x870D9300042H \xf1\x894901',
|
||||
b'\xf1\x870DD300045T \xf1\x891601',
|
||||
b'\xf1\x870DD300046B \xf1\x891601',
|
||||
b'\xf1\x870DD300046H \xf1\x891601',
|
||||
b'\xf1\x870DL300011H \xf1\x895201',
|
||||
b'\xf1\x870GC300042H \xf1\x891404',
|
||||
|
||||
@@ -327,7 +327,7 @@ BO_ 416 SCC_CONTROL: 32 ADRV
|
||||
SG_ VSetDis : 103|8@0+ (1,0) [0|255] "km/h or mph" XXX
|
||||
SG_ NEW_SIGNAL_6 : 104|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_ME_2 : 105|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ NEW_SIGNAL_3 : 109|2@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SCC_ObjSta : 108|3@1+ (1,0) [0|7] "" CLU,CGW
|
||||
SG_ ZEROS_10 : 111|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ ZEROS_6 : 119|16@0+ (1,0) [0|65535] "" XXX
|
||||
SG_ aReqValue : 128|11@1+ (0.01,-10.23) [-10.23|10.24] "m/s^2" XXX
|
||||
@@ -384,8 +384,8 @@ BO_ 437 FR_CMR_03_50ms: 32 FR_CMR
|
||||
SG_ Info_RtLnDptSta : 99|2@1+ (1,0) [0|3] "" RR_C_RDR,CGW
|
||||
SG_ Info_RtLnPosVal : 101|14@1- (0.0039625,0) [-32.4608|32.4568375] "m" RR_C_RDR,CGW
|
||||
SG_ Info_RtLnHdingAnglVal : 115|10@1- (0.000976563,0) [-0.500000256|0.499023693] "rad" RR_C_RDR,CGW
|
||||
SG_ Info_RtLnCvtrVal : 128|16@1- (1,0) [0|65535] "" CGW
|
||||
SG_ Info_RtLnCrvtrDrvtvVal : 144|16@1- (1,0) [0|65535] "" CGW
|
||||
SG_ Info_RtLnCvtrVal : 128|16@1- (1e-06,0) [-0.032768|0.032767] "1/m" CGW
|
||||
SG_ Info_RtLnCrvtrDrvtvVal : 144|16@1- (4e-09,0) [-0.000131072|0.000131068] "1/m2" CGW
|
||||
SG_ ID_CIPV : 192|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ Relative_Velocity : 200|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ Longitudinal_Distance : 212|12@1+ (0.05,0) [0|204.75] "m" XXX
|
||||
@@ -727,6 +727,7 @@ CM_ SG_ 437 Info_RtLnHdingAnglVal "This signal outputs the heading angle of righ
|
||||
CM_ SG_ 437 Info_RtLnCvtrVal "This signal outputs the curvature of right line.";
|
||||
CM_ SG_ 437 ID_CIPV "Valid Object = 1 to 255 - ID detected by front camera can vary depending on vehicle environment. - Additional logic would be required to apply this signal for ISG.";
|
||||
CM_ SG_ 437 Relative_Velocity "+ : Preceding, - : Oncoming - Velocity detected by front camera can vary depending on vehicle environment. - Additional logic would be required to apply this signal for ISG. - Confirmaiton by Autonomous Driving Engineering Team is required to use ID_C";
|
||||
CM_ SG_ 416 SCC_ObjSta "state of in-path object and information of controllable state.";
|
||||
CM_ SG_ 480 NEW_SIGNAL_5 "todo: figure out why always set to 1";
|
||||
CM_ BO_ 506 "Sent by the camera containing speed limit information. ISLW stands for Intelligent Speed Limit Warning, and ISLA is Intelligent Speed Limit Assist. it also contains road sign information.";
|
||||
CM_ SG_ 506 FR_CMR_Crc2Val "The data area for CRC calculation is based on the data length (DLC) of the message DB.The CRC shall be calculated over the entire data block (excluding the CRC bytes) including the user data, alive counter and Data ID - CRC Polynomial (0x1021) , In";
|
||||
@@ -904,6 +905,7 @@ VAL_ 354 FAULT_ESS 0 "HIDDEN" 1 "CHECK_EMERGENCY_STOPPING_FUNCTION" 2 "EMERGENCY
|
||||
VAL_ 362 BLINKER_CONTROL 1 "hazards" 2 "hazards button backlight" 3 "left blinkers" 4 "right blinkers";
|
||||
VAL_ 373 ACCEnable 0 "SCC ready" 1 "SCC temp fault" 2 "SCC permanent fault" 3 "SCC permanent fault, communication issue";
|
||||
VAL_ 416 ACCMode 0 "off" 1 "enabled" 2 "driver_override" 3 "off_maybe_fault" 4 "cancelled";
|
||||
VAL_ 416 SCC_ObjSta 0 "No in-path object detected" 1 "In-path object detected (uncontrollable)" 2 "In-path object detected (controllable:longitudinal)" 3 "Reserved" 4 "Reserved" 5 "Reserved" 6 "Reserved" 7 "Reserved";
|
||||
VAL_ 426 CRUISE_BUTTONS 0 "none" 1 "res_accel" 2 "set_decel" 3 "gap_distance" 4 "pause_resume";
|
||||
VAL_ 437 Info_LftLnQualSta 0 "Very Low Quality" 1 "Low Quality" 2 "High Quality" 3 "Very High Quality" 4 "Reserved" 5 "Reserved" 6 "Reserved" 7 "Error indicator";
|
||||
VAL_ 437 Info_LftLnDptSta 0 "No Left Line Departure" 1 "Left Line Departure" 2 "Reserved" 3 "Error Indicator";
|
||||
|
||||
@@ -564,7 +564,7 @@ BO_ 416 SCC_CONTROL: 32 ADRV
|
||||
SG_ VSetDis : 103|8@0+ (1,0) [0|255] "km/h or mph" XXX
|
||||
SG_ NEW_SIGNAL_6 : 104|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_ME_2 : 105|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ NEW_SIGNAL_3 : 109|2@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SCC_ObjSta : 108|3@1+ (1,0) [0|7] "" CLU,CGW
|
||||
SG_ ZEROS_10 : 111|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ ZEROS_6 : 119|16@0+ (1,0) [0|65535] "" XXX
|
||||
SG_ aReqValue : 128|11@1+ (0.01,-10.23) [-10.23|10.24] "m/s^2" XXX
|
||||
@@ -621,8 +621,8 @@ BO_ 437 FR_CMR_03_50ms: 32 FR_CMR
|
||||
SG_ Info_RtLnDptSta : 99|2@1+ (1,0) [0|3] "" RR_C_RDR,CGW
|
||||
SG_ Info_RtLnPosVal : 101|14@1- (0.0039625,0) [-32.4608|32.4568375] "m" RR_C_RDR,CGW
|
||||
SG_ Info_RtLnHdingAnglVal : 115|10@1- (0.000976563,0) [-0.500000256|0.499023693] "rad" RR_C_RDR,CGW
|
||||
SG_ Info_RtLnCvtrVal : 128|16@1- (1,0) [0|65535] "" CGW
|
||||
SG_ Info_RtLnCrvtrDrvtvVal : 144|16@1- (1,0) [0|65535] "" CGW
|
||||
SG_ Info_RtLnCvtrVal : 128|16@1- (1e-06,0) [-0.032768|0.032767] "1/m" CGW
|
||||
SG_ Info_RtLnCrvtrDrvtvVal : 144|16@1- (4e-09,0) [-0.000131072|0.000131068] "1/m2" CGW
|
||||
SG_ ID_CIPV : 192|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ Relative_Velocity : 200|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ Longitudinal_Distance : 212|12@1+ (0.05,0) [0|204.75] "m" XXX
|
||||
@@ -964,6 +964,7 @@ CM_ SG_ 437 Info_RtLnHdingAnglVal "This signal outputs the heading angle of righ
|
||||
CM_ SG_ 437 Info_RtLnCvtrVal "This signal outputs the curvature of right line.";
|
||||
CM_ SG_ 437 ID_CIPV "Valid Object = 1 to 255 - ID detected by front camera can vary depending on vehicle environment. - Additional logic would be required to apply this signal for ISG.";
|
||||
CM_ SG_ 437 Relative_Velocity "+ : Preceding, - : Oncoming - Velocity detected by front camera can vary depending on vehicle environment. - Additional logic would be required to apply this signal for ISG. - Confirmaiton by Autonomous Driving Engineering Team is required to use ID_C";
|
||||
CM_ SG_ 416 SCC_ObjSta "state of in-path object and information of controllable state.";
|
||||
CM_ SG_ 480 NEW_SIGNAL_5 "todo: figure out why always set to 1";
|
||||
CM_ BO_ 506 "Sent by the camera containing speed limit information. ISLW stands for Intelligent Speed Limit Warning, and ISLA is Intelligent Speed Limit Assist. it also contains road sign information.";
|
||||
CM_ SG_ 506 FR_CMR_Crc2Val "The data area for CRC calculation is based on the data length (DLC) of the message DB.The CRC shall be calculated over the entire data block (excluding the CRC bytes) including the user data, alive counter and Data ID - CRC Polynomial (0x1021) , In";
|
||||
@@ -1141,6 +1142,7 @@ VAL_ 354 FAULT_ESS 0 "HIDDEN" 1 "CHECK_EMERGENCY_STOPPING_FUNCTION" 2 "EMERGENCY
|
||||
VAL_ 362 BLINKER_CONTROL 1 "hazards" 2 "hazards button backlight" 3 "left blinkers" 4 "right blinkers";
|
||||
VAL_ 373 ACCEnable 0 "SCC ready" 1 "SCC temp fault" 2 "SCC permanent fault" 3 "SCC permanent fault, communication issue";
|
||||
VAL_ 416 ACCMode 0 "off" 1 "enabled" 2 "driver_override" 3 "off_maybe_fault" 4 "cancelled";
|
||||
VAL_ 416 SCC_ObjSta 0 "No in-path object detected" 1 "In-path object detected (uncontrollable)" 2 "In-path object detected (controllable:longitudinal)" 3 "Reserved" 4 "Reserved" 5 "Reserved" 6 "Reserved" 7 "Reserved";
|
||||
VAL_ 426 CRUISE_BUTTONS 0 "none" 1 "res_accel" 2 "set_decel" 3 "gap_distance" 4 "pause_resume";
|
||||
VAL_ 437 Info_LftLnQualSta 0 "Very Low Quality" 1 "Low Quality" 2 "High Quality" 3 "Very High Quality" 4 "Reserved" 5 "Reserved" 6 "Reserved" 7 "Error indicator";
|
||||
VAL_ 437 Info_LftLnDptSta 0 "No Left Line Departure" 1 "Left Line Departure" 2 "Reserved" 3 "Error Indicator";
|
||||
|
||||
@@ -1480,6 +1480,7 @@ BO_ 905 SCC14: 8 SCC
|
||||
SG_ JerkLowerLimit : 19|7@1+ (0.1,0) [0|12.7] "m/s^3" ESC
|
||||
SG_ ACCMode : 32|3@1+ (1,0) [0|7] "" CLU,HUD,LDWS_LKAS,ESC
|
||||
SG_ ObjGap : 56|8@1+ (1,0) [0|255] "" CLU,HUD,ESC
|
||||
SG_ ObjDistStat : 42|2@1+ (1,0) [0|3] "" XXX
|
||||
|
||||
BO_ 1157 LFAHDA_MFC: 4 XXX
|
||||
SG_ HDA_USM : 0|2@1+ (1,0) [0|3] "" XXX
|
||||
@@ -1500,6 +1501,7 @@ BO_ 913 BCM_PO_11: 8 Vector__XXX
|
||||
|
||||
BO_ 1426 LABEL11: 8 XXX
|
||||
SG_ CC_React : 34|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ CC_ACT : 35|1@1+ (1,0) [0|1] "" XXX
|
||||
|
||||
BO_ 910 WHL_SPD12_FS: 5 iBAU
|
||||
SG_ CRC : 0|8@1+ (1,0) [0|0] "" Vector__XXX
|
||||
@@ -1536,6 +1538,10 @@ BO_ 881 E_EMS11: 8 XXX
|
||||
BO_ 1355 EV_PC6: 8 CGW
|
||||
SG_ CF_Vcu_SbwWarnMsg : 16|3@1+ (1,0) [0|7] "" Vector__XXX
|
||||
|
||||
BO_ 1429 E_CRUISE_CONTROL: 8 XXX
|
||||
SG_ CRUISE_LAMP_M : 50|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ CRUISE_LAMP_S : 51|1@0+ (1,0) [0|1] "" XXX
|
||||
|
||||
BO_ 1430 EV_PC2: 8 CGW
|
||||
SG_ CR_Ldc_ActVol_LS_V : 32|8@1+ (0.1,0) [0|0] "V" Vector__XXX
|
||||
|
||||
@@ -1680,6 +1686,7 @@ VAL_ 871 CF_Lvr_IsgState 0 "enabled" 1 "activated" 2 "unknown" 3 "disabled";
|
||||
VAL_ 871 CF_Lvr_Gear 12 "T" 5 "D" 8 "S" 6 "N" 7 "R" 0 "P";
|
||||
VAL_ 882 Elect_Gear_Shifter 4 "S" 5 "D" 8 "S" 6 "N" 7 "R" 0 "P";
|
||||
VAL_ 905 ACCMode 0 "off" 1 "enabled" 2 "driver_override" 3 "off_maybe_fault" 4 "cancelled";
|
||||
VAL_ 905 ObjDistStat 0 "no_object" 1 "receding" 2 "approaching";
|
||||
VAL_ 909 CF_VSM_Warn 2 "FCW" 3 "AEB";
|
||||
VAL_ 916 ACCEnable 0 "SCC ready" 1 "SCC temp fault" 2 "SCC permanent fault" 3 "SCC permanent fault, communication issue";
|
||||
VAL_ 1056 SCCInfoDisplay 0 "No Message" 2 "Cruise Control" 3 "Lost Lead" 4 "Standstill";
|
||||
|
||||
@@ -162,8 +162,8 @@ BO_ 773 STEERING_ALT: 7 XXX
|
||||
SG_ ANGLE : 7|16@0- (0.1,0) [-3276.8|3276.7] "degrees" XXX
|
||||
SG_ RATE : 23|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ RATE_SIGN : 31|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ COUNTER : 35|4@0+ (1,0) [0|255] "" XXX
|
||||
SG_ CHECKSUM : 39|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 0_COUNTER : 35|4@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 0_CHECKSUM : 39|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ RATE_ALT : 47|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 781 Dyn4_FRE: 8 CDS___Fahrdynamikregelung
|
||||
@@ -833,6 +833,7 @@ CM_ SG_ 758 CHECKSUM_TRANSM_DYN_ACC2 "CHK_INI = 0x7";
|
||||
CM_ SG_ 758 PROCESS_COUNTER_4B_ACC2 "This counter increments from 0 to 15 at each activation of the calculation process.";
|
||||
CM_ SG_ 773 ANGLE "-565 to 560, seems like estimate and not init";
|
||||
CM_ SG_ 773 RATE_SIGN "1=moving clockwise, 0=moving anticlockwise";
|
||||
CM_ SG_ 773 0_CHECKSUM "TODO: find checksum";
|
||||
CM_ BO_ 840 "ID 348: Engine Dynamic Frame 2 (Period time 20 ms)";
|
||||
CM_ SG_ 840 P165_FlFCD_stWtLvlSensDebVal "P165: Water in fuel indication (1 = water in fuel detected / 0 = no water in fuel)";
|
||||
CM_ SG_ 840 P152_Gearbx_stGear "P152: Gear detected by ratio vehicule speed to engine speed";
|
||||
|
||||
@@ -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_clarity = false;
|
||||
typedef enum {HONDA_NIDEC, HONDA_BOSCH} HondaHw;
|
||||
static HondaHw honda_hw = HONDA_NIDEC;
|
||||
|
||||
@@ -157,6 +158,10 @@ static void honda_rx_hook(const CANPacket_t *msg) {
|
||||
bool honda_stock_aeb = GET_BIT(msg, 29U);
|
||||
int honda_stock_brake = (msg->data[0] << 2) | (msg->data[1] >> 6);
|
||||
|
||||
if (honda_clarity) {
|
||||
honda_stock_brake = (msg->data[6] << 2) | (msg->data[7] >> 6);
|
||||
}
|
||||
|
||||
// Forward AEB when stock braking is higher than openpilot braking
|
||||
// only stop forwarding when AEB event is over
|
||||
if (!honda_stock_aeb) {
|
||||
@@ -208,6 +213,11 @@ static bool honda_tx_hook(const CANPacket_t *msg) {
|
||||
// BRAKE: safety check (nidec)
|
||||
if ((msg->addr == 0x1FAU) && (msg->bus == bus_pt)) {
|
||||
honda_brake = (msg->data[0] << 2) + ((msg->data[1] >> 6) & 0x3U);
|
||||
|
||||
if (honda_clarity) {
|
||||
honda_brake = (msg->data[6] << 2) + ((msg->data[7] >> 6) & 0x3U);
|
||||
}
|
||||
|
||||
if (longitudinal_brake_checks(honda_brake, HONDA_NIDEC_LONG_LIMITS)) {
|
||||
tx = false;
|
||||
}
|
||||
@@ -289,6 +299,8 @@ static safety_config honda_nidec_init(uint16_t param) {
|
||||
|
||||
const uint16_t HONDA_PARAM_NIDEC_ALT = 4;
|
||||
|
||||
const uint16_t HONDA_PARAM_SP_CLARITY = 1;
|
||||
|
||||
honda_hw = HONDA_NIDEC;
|
||||
honda_brake = 0;
|
||||
honda_brake_switch_prev = false;
|
||||
@@ -302,6 +314,8 @@ static safety_config honda_nidec_init(uint16_t param) {
|
||||
|
||||
bool enable_nidec_alt = GET_FLAG(param, HONDA_PARAM_NIDEC_ALT);
|
||||
|
||||
honda_clarity = GET_FLAG(current_safety_param_sp, HONDA_PARAM_SP_CLARITY);
|
||||
|
||||
if (enable_nidec_alt) {
|
||||
// For Nidecs with main on signal on an alternate msg (missing 0x326)
|
||||
static RxCheck honda_nidec_alt_rx_checks[] = {
|
||||
|
||||
@@ -58,6 +58,12 @@ const LongitudinalLimits HYUNDAI_LONG_LIMITS = {
|
||||
#define HYUNDAI_LDA_BUTTON_ADDR_CHECK \
|
||||
{.msg = {{0x391, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
|
||||
#define HYUNDAI_NON_SCC_HEV_ADDR_CHECK \
|
||||
{.msg = {{0x595U, 0, 8, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
|
||||
|
||||
#define HYUNDAI_NON_SCC_EV_ADDR_CHECK \
|
||||
{.msg = {{0x592U, 0, 8, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
|
||||
|
||||
static const CanMsg HYUNDAI_TX_MSGS[] = {
|
||||
HYUNDAI_COMMON_TX_MSGS(0)
|
||||
};
|
||||
@@ -191,6 +197,24 @@ static void hyundai_rx_hook(const CANPacket_t *msg) {
|
||||
if (msg->addr == 0x394U) {
|
||||
brake_pressed = ((msg->data[5] >> 5U) & 0x3U) == 0x2U;
|
||||
}
|
||||
|
||||
if (msg->addr == 0x592U) {
|
||||
acc_main_on = GET_BIT(msg, 34U);
|
||||
bool cruise_engaged = GET_BIT(msg, 35U);
|
||||
hyundai_common_cruise_state_check(cruise_engaged);
|
||||
}
|
||||
|
||||
if (msg->addr == 0x595U) {
|
||||
acc_main_on = GET_BIT(msg, 50U);
|
||||
bool cruise_engaged = GET_BIT(msg, 51U);
|
||||
hyundai_common_cruise_state_check(cruise_engaged);
|
||||
}
|
||||
|
||||
if ((msg->addr == 0x260U) && hyundai_non_scc && !hyundai_ev_gas_signal && !hyundai_hybrid_gas_signal) {
|
||||
acc_main_on = GET_BIT(msg, 25U);
|
||||
bool cruise_engaged = GET_BIT(msg, 26U);
|
||||
hyundai_common_cruise_state_check(cruise_engaged);
|
||||
}
|
||||
}
|
||||
|
||||
hyundai_common_reset_acc_main_on_mismatches();
|
||||
@@ -380,6 +404,37 @@ static safety_config hyundai_init(uint16_t param) {
|
||||
HYUNDAI_LDA_BUTTON_ADDR_CHECK
|
||||
};
|
||||
|
||||
static RxCheck hyundai_non_scc_addr_checks[] = {
|
||||
HYUNDAI_COMMON_RX_CHECKS(false)
|
||||
};
|
||||
|
||||
static RxCheck hyundai_non_scc_lda_button_addr_checks[] = {
|
||||
HYUNDAI_COMMON_RX_CHECKS(false)
|
||||
HYUNDAI_LDA_BUTTON_ADDR_CHECK
|
||||
};
|
||||
|
||||
static RxCheck hyundai_hev_non_scc_addr_checks[] = {
|
||||
HYUNDAI_COMMON_RX_CHECKS(false)
|
||||
HYUNDAI_NON_SCC_HEV_ADDR_CHECK
|
||||
};
|
||||
|
||||
static RxCheck hyundai_hev_non_scc_lda_button_addr_checks[] = {
|
||||
HYUNDAI_COMMON_RX_CHECKS(false)
|
||||
HYUNDAI_NON_SCC_HEV_ADDR_CHECK
|
||||
HYUNDAI_LDA_BUTTON_ADDR_CHECK
|
||||
};
|
||||
|
||||
static RxCheck hyundai_ev_non_scc_addr_checks[] = {
|
||||
HYUNDAI_COMMON_RX_CHECKS(false)
|
||||
HYUNDAI_NON_SCC_EV_ADDR_CHECK
|
||||
};
|
||||
|
||||
static RxCheck hyundai_ev_non_scc_lda_button_addr_checks[] = {
|
||||
HYUNDAI_COMMON_RX_CHECKS(false)
|
||||
HYUNDAI_NON_SCC_EV_ADDR_CHECK
|
||||
HYUNDAI_LDA_BUTTON_ADDR_CHECK
|
||||
};
|
||||
|
||||
SET_TX_MSGS(HYUNDAI_TX_MSGS, ret);
|
||||
if (hyundai_fcev_gas_signal) {
|
||||
if (hyundai_has_lda_button) {
|
||||
@@ -387,6 +442,26 @@ static safety_config hyundai_init(uint16_t param) {
|
||||
} else {
|
||||
SET_RX_CHECKS(hyundai_fcev_rx_checks, ret);
|
||||
}
|
||||
} else if (hyundai_non_scc) {
|
||||
if (hyundai_ev_gas_signal) {
|
||||
if (hyundai_has_lda_button) {
|
||||
SET_RX_CHECKS(hyundai_ev_non_scc_lda_button_addr_checks, ret);
|
||||
} else {
|
||||
SET_RX_CHECKS(hyundai_ev_non_scc_addr_checks, ret);
|
||||
}
|
||||
} else if (hyundai_hybrid_gas_signal) {
|
||||
if (hyundai_has_lda_button) {
|
||||
SET_RX_CHECKS(hyundai_hev_non_scc_lda_button_addr_checks, ret);
|
||||
} else {
|
||||
SET_RX_CHECKS(hyundai_hev_non_scc_addr_checks, ret);
|
||||
}
|
||||
} else {
|
||||
if (hyundai_has_lda_button) {
|
||||
SET_RX_CHECKS(hyundai_non_scc_lda_button_addr_checks, ret);
|
||||
} else {
|
||||
SET_RX_CHECKS(hyundai_non_scc_addr_checks, ret);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (hyundai_has_lda_button) {
|
||||
SET_RX_CHECKS(hyundai_lda_button_rx_checks, ret);
|
||||
|
||||
@@ -21,6 +21,7 @@ enum {
|
||||
HYUNDAI_PARAM_SP_ESCC = 1,
|
||||
HYUNDAI_PARAM_SP_LONGITUDINAL_MAIN_CRUISE_TOGGLEABLE = 2,
|
||||
HYUNDAI_PARAM_SP_HAS_LDA_BUTTON = 4,
|
||||
HYUNDAI_PARAM_SP_NON_SCC = 8,
|
||||
};
|
||||
|
||||
// common state
|
||||
@@ -58,6 +59,9 @@ bool hyundai_longitudinal_main_cruise_toggleable = false;
|
||||
extern bool hyundai_has_lda_button;
|
||||
bool hyundai_has_lda_button = false;
|
||||
|
||||
extern bool hyundai_non_scc;
|
||||
bool hyundai_non_scc = false;
|
||||
|
||||
static uint8_t hyundai_last_button_interaction; // button messages since the user pressed an enable button
|
||||
|
||||
static bool main_button_prev;
|
||||
@@ -85,6 +89,7 @@ void hyundai_common_init(uint16_t param) {
|
||||
hyundai_escc = GET_FLAG(current_safety_param_sp, HYUNDAI_PARAM_SP_ESCC);
|
||||
hyundai_longitudinal_main_cruise_toggleable = GET_FLAG(current_safety_param_sp, HYUNDAI_PARAM_SP_LONGITUDINAL_MAIN_CRUISE_TOGGLEABLE);
|
||||
hyundai_has_lda_button = GET_FLAG(current_safety_param_sp, HYUNDAI_PARAM_SP_HAS_LDA_BUTTON);
|
||||
hyundai_non_scc = GET_FLAG(current_safety_param_sp, HYUNDAI_PARAM_SP_NON_SCC);
|
||||
|
||||
hyundai_last_button_interaction = HYUNDAI_PREV_BUTTON_SAMPLES;
|
||||
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
#pragma once
|
||||
|
||||
#include "opendbc/safety/safety_declarations.h"
|
||||
|
||||
#define PSA_STEERING 757U // RX from XXX, driver torque
|
||||
#define PSA_STEERING_ALT 773U // RX from EPS, steering angle
|
||||
#define PSA_DYN_CMM 520U // RX from CMM, gas pedal
|
||||
#define PSA_HS2_DYN_ABR_38D 909U // RX from UC_FREIN, speed
|
||||
#define PSA_HS2_DAT_MDD_CMD_452 1106U // RX from BSI, cruise state
|
||||
#define PSA_DAT_BSI 1042U // RX from BSI, brake
|
||||
#define PSA_LANE_KEEP_ASSIST 1010U // TX from OP, EPS
|
||||
|
||||
// CAN bus
|
||||
#define PSA_MAIN_BUS 0U
|
||||
#define PSA_ADAS_BUS 1U
|
||||
#define PSA_CAM_BUS 2U
|
||||
|
||||
static uint8_t psa_get_counter(const CANPacket_t *msg) {
|
||||
uint8_t cnt = 0;
|
||||
if (msg->addr == PSA_HS2_DAT_MDD_CMD_452) {
|
||||
cnt = (msg->data[3] >> 4) & 0xFU;
|
||||
} else if (msg->addr == PSA_HS2_DYN_ABR_38D) {
|
||||
cnt = (msg->data[5] >> 4) & 0xFU;
|
||||
} else {
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static uint32_t psa_get_checksum(const CANPacket_t *msg) {
|
||||
uint8_t chksum = 0;
|
||||
if (msg->addr == PSA_HS2_DAT_MDD_CMD_452) {
|
||||
chksum = msg->data[5] & 0xFU;
|
||||
} else if (msg->addr == PSA_HS2_DYN_ABR_38D) {
|
||||
chksum = msg->data[5] & 0xFU;
|
||||
} else {
|
||||
}
|
||||
return chksum;
|
||||
}
|
||||
|
||||
static uint8_t _psa_compute_checksum(const CANPacket_t *msg, uint8_t chk_ini, int chk_pos) {
|
||||
int len = GET_LEN(msg);
|
||||
|
||||
uint8_t sum = 0;
|
||||
for (int i = 0; i < len; i++) {
|
||||
uint8_t b = msg->data[i];
|
||||
|
||||
if (i == chk_pos) {
|
||||
// set checksum in low nibble to 0
|
||||
b &= 0xF0U;
|
||||
}
|
||||
sum += (b >> 4) + (b & 0xFU);
|
||||
}
|
||||
return (chk_ini - sum) & 0xFU;
|
||||
}
|
||||
|
||||
static uint32_t psa_compute_checksum(const CANPacket_t *msg) {
|
||||
uint8_t chk = 0;
|
||||
if (msg->addr == PSA_HS2_DAT_MDD_CMD_452) {
|
||||
chk = _psa_compute_checksum(msg, 0x4, 5);
|
||||
} else if (msg->addr == PSA_HS2_DYN_ABR_38D) {
|
||||
chk = _psa_compute_checksum(msg, 0x7, 5);
|
||||
} else {
|
||||
}
|
||||
return chk;
|
||||
}
|
||||
|
||||
static void psa_rx_hook(const CANPacket_t *msg) {
|
||||
if (msg->bus == PSA_MAIN_BUS) {
|
||||
if (msg->addr == PSA_DYN_CMM) {
|
||||
gas_pressed = msg->data[3] > 0U; // P002_Com_rAPP
|
||||
}
|
||||
if (msg->addr == PSA_STEERING_ALT) {
|
||||
int angle_meas_new = to_signed((msg->data[0] << 8) | msg->data[1], 16); // ANGLE
|
||||
update_sample(&angle_meas, angle_meas_new);
|
||||
}
|
||||
if (msg->addr == PSA_HS2_DYN_ABR_38D) {
|
||||
int speed = (msg->data[0] << 8) | msg->data[1];
|
||||
vehicle_moving = speed > 0;
|
||||
UPDATE_VEHICLE_SPEED(speed * 0.01 * KPH_TO_MS); // VITESSE_VEHICULE_ROUES
|
||||
}
|
||||
}
|
||||
|
||||
if (msg->bus == PSA_ADAS_BUS) {
|
||||
if (msg->addr == PSA_HS2_DAT_MDD_CMD_452) {
|
||||
pcm_cruise_check((msg->data[2U] >> 7U) & 1U); // RVV_ACC_ACTIVATION_REQ
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (msg->bus == PSA_CAM_BUS) {
|
||||
if (msg->addr == PSA_DAT_BSI) {
|
||||
brake_pressed = (msg->data[0U] >> 5U) & 1U; // P013_MainBrake
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool psa_tx_hook(const CANPacket_t *msg) {
|
||||
bool tx = true;
|
||||
static const AngleSteeringLimits PSA_STEERING_LIMITS = {
|
||||
.max_angle = 3900,
|
||||
.angle_deg_to_can = 10,
|
||||
.angle_rate_up_lookup = {
|
||||
{0., 5., 25.},
|
||||
{2.5, 1.5, .2},
|
||||
},
|
||||
.angle_rate_down_lookup = {
|
||||
{0., 5., 25.},
|
||||
{5., 2., .3},
|
||||
},
|
||||
};
|
||||
|
||||
// Safety check for LKA
|
||||
if (msg->addr == PSA_LANE_KEEP_ASSIST) {
|
||||
// SET_ANGLE
|
||||
int desired_angle = to_signed((msg->data[6] << 6) | ((msg->data[7] & 0xFCU) >> 2), 14);
|
||||
// TORQUE_FACTOR
|
||||
bool lka_active = ((msg->data[5] & 0xFEU) >> 1) == 100U;
|
||||
|
||||
if (steer_angle_cmd_checks(desired_angle, lka_active, PSA_STEERING_LIMITS)) {
|
||||
tx = false;
|
||||
}
|
||||
}
|
||||
return tx;
|
||||
}
|
||||
|
||||
static safety_config psa_init(uint16_t param) {
|
||||
UNUSED(param);
|
||||
static const CanMsg PSA_TX_MSGS[] = {
|
||||
{PSA_LANE_KEEP_ASSIST, PSA_MAIN_BUS, 8, .check_relay = true}, // EPS steering
|
||||
};
|
||||
|
||||
static RxCheck psa_rx_checks[] = {
|
||||
{.msg = {{PSA_HS2_DAT_MDD_CMD_452, PSA_ADAS_BUS, 6, 20U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // cruise state
|
||||
{.msg = {{PSA_HS2_DYN_ABR_38D, PSA_MAIN_BUS, 8, 25U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // speed
|
||||
{.msg = {{PSA_STEERING_ALT, PSA_MAIN_BUS, 7, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // steering angle
|
||||
{.msg = {{PSA_STEERING, PSA_MAIN_BUS, 7, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // driver torque
|
||||
{.msg = {{PSA_DYN_CMM, PSA_MAIN_BUS, 8, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // gas pedal
|
||||
{.msg = {{PSA_DAT_BSI, PSA_CAM_BUS, 8, 20U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // brake
|
||||
};
|
||||
|
||||
return BUILD_SAFETY_CFG(psa_rx_checks, PSA_TX_MSGS);
|
||||
}
|
||||
|
||||
const safety_hooks psa_hooks = {
|
||||
.init = psa_init,
|
||||
.rx = psa_rx_hook,
|
||||
.tx = psa_tx_hook,
|
||||
.get_counter = psa_get_counter,
|
||||
.get_checksum = psa_get_checksum,
|
||||
.compute_checksum = psa_compute_checksum,
|
||||
};
|
||||
@@ -2,12 +2,6 @@
|
||||
|
||||
#include "opendbc/safety/safety_declarations.h"
|
||||
|
||||
enum {
|
||||
TESLA_PARAM_SP_VIRTUAL_TORQUE_BLENDING = 1,
|
||||
};
|
||||
|
||||
static bool tesla_virtual_torque_blending;
|
||||
|
||||
static bool tesla_longitudinal = false;
|
||||
static bool tesla_stock_aeb = false;
|
||||
|
||||
@@ -111,8 +105,7 @@ static void tesla_rx_hook(const CANPacket_t *msg) {
|
||||
const int eac_error_code = msg->data[2] >> 4; // EPAS3S_eacErrorCode
|
||||
|
||||
// Disengage on normal user override, or if high angle rate fault from user overriding extremely quickly
|
||||
const bool hands_on_level_check = (!tesla_virtual_torque_blending && (hands_on_level >= 3));
|
||||
steering_disengage = hands_on_level_check || ((eac_status == 0) && (eac_error_code == 9));
|
||||
steering_disengage = (hands_on_level >= 3) || ((eac_status == 0) && (eac_error_code == 9));
|
||||
}
|
||||
|
||||
// Vehicle speed (DI_speed)
|
||||
@@ -340,8 +333,6 @@ static safety_config tesla_init(uint16_t param) {
|
||||
tesla_longitudinal = GET_FLAG(param, TESLA_FLAG_LONGITUDINAL_CONTROL);
|
||||
#endif
|
||||
|
||||
tesla_virtual_torque_blending = GET_FLAG(current_safety_param_sp, TESLA_PARAM_SP_VIRTUAL_TORQUE_BLENDING);
|
||||
|
||||
tesla_stock_aeb = false;
|
||||
tesla_stock_lkas = false;
|
||||
tesla_stock_lkas_prev = false;
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "opendbc/safety/modes/volkswagen_pq.h"
|
||||
#include "opendbc/safety/modes/elm327.h"
|
||||
#include "opendbc/safety/modes/body.h"
|
||||
#include "opendbc/safety/modes/psa.h"
|
||||
|
||||
// CAN-FD only safety modes
|
||||
#ifdef CANFD
|
||||
@@ -415,6 +416,7 @@ int set_safety_hooks(uint16_t mode, uint16_t param) {
|
||||
{SAFETY_HYUNDAI_CANFD, &hyundai_canfd_hooks},
|
||||
#endif
|
||||
#ifdef ALLOW_DEBUG
|
||||
{SAFETY_PSA, &psa_hooks},
|
||||
{SAFETY_SUBARU_PREGLOBAL, &subaru_preglobal_hooks},
|
||||
{SAFETY_VOLKSWAGEN_PQ, &volkswagen_pq_hooks},
|
||||
{SAFETY_ALLOUTPUT, &alloutput_hooks},
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#define SAFETY_FAW 26U
|
||||
#define SAFETY_BODY 27U
|
||||
#define SAFETY_HYUNDAI_CANFD 28U
|
||||
#define SAFETY_PSA 31U
|
||||
#define SAFETY_RIVIAN 33U
|
||||
#define SAFETY_VOLKSWAGEN_MEB 34U
|
||||
|
||||
@@ -341,3 +342,4 @@ extern const safety_hooks toyota_hooks;
|
||||
extern const safety_hooks volkswagen_mqb_hooks;
|
||||
extern const safety_hooks volkswagen_pq_hooks;
|
||||
extern const safety_hooks rivian_hooks;
|
||||
extern const safety_hooks psa_hooks;
|
||||
|
||||
@@ -266,7 +266,6 @@ class TorqueSteeringSafetyTestBase(PandaSafetyTestBase, abc.ABC):
|
||||
max_torque = self._get_max_torque(speed)
|
||||
for enabled in [0, 1]:
|
||||
for t in range(int(-max_torque * 1.5), int(max_torque * 1.5)):
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_controls_allowed(enabled)
|
||||
self._set_prev_torque(t)
|
||||
if abs(t) > max_torque or (not enabled and abs(t) > 0):
|
||||
@@ -543,7 +542,6 @@ class MotorTorqueSteeringSafetyTest(TorqueSteeringSafetyTestBase, abc.ABC):
|
||||
max_torque = self._get_max_torque(speed)
|
||||
for controls_allowed in [True, False]:
|
||||
for torque in np.arange(-max_torque - 1000, max_torque + 1000, self.MAX_RATE_UP):
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_controls_allowed(controls_allowed)
|
||||
self.safety.set_rt_torque_last(torque)
|
||||
self.safety.set_torque_meas(torque, torque)
|
||||
@@ -767,7 +765,6 @@ class AngleSteeringSafetyTest(VehicleSpeedSafetyTest):
|
||||
self._reset_angle_measurement(angle_meas)
|
||||
|
||||
for angle_cmd in np.arange(-90, 91, 10):
|
||||
self._mads_states_cleanup()
|
||||
self._set_prev_desired_angle(angle_cmd)
|
||||
|
||||
# controls_allowed is checked if actuation bit is 1, else the angle must be close to meas (inactive)
|
||||
|
||||
@@ -155,7 +155,6 @@ class HyundaiLongitudinalBase(common.LongitudinalAccelSafetyTest):
|
||||
self.safety.set_safety_hooks(default_safety_mode, default_safety_param)
|
||||
|
||||
# Test initial state
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_mads_params(enable_mads, False, False)
|
||||
|
||||
self.assertFalse(self.safety.get_acc_main_on())
|
||||
@@ -173,7 +172,6 @@ class HyundaiLongitudinalBase(common.LongitudinalAccelSafetyTest):
|
||||
for _ in range(10):
|
||||
self._rx(self._main_cruise_button_msg(1))
|
||||
self.assertFalse(self.safety.get_controls_allowed_lat())
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_current_safety_param_sp(default_safety_param_sp)
|
||||
|
||||
def test_acc_main_sync_mismatches_reset(self):
|
||||
@@ -188,7 +186,6 @@ class HyundaiLongitudinalBase(common.LongitudinalAccelSafetyTest):
|
||||
self.safety.set_current_safety_param_sp(default_safety_param_sp | main_cruise_toggleable_flag)
|
||||
self.safety.set_safety_hooks(default_safety_mode, default_safety_param)
|
||||
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_mads_params(enable_mads, False, False)
|
||||
|
||||
# Initial state
|
||||
@@ -208,7 +205,6 @@ class HyundaiLongitudinalBase(common.LongitudinalAccelSafetyTest):
|
||||
self._tx(self._tx_acc_state_msg(False)) # acc_main_on_tx = False
|
||||
self.assertFalse(self.safety.get_acc_main_on())
|
||||
self.assertEqual(0, self.safety.get_acc_main_on_mismatches())
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_current_safety_param_sp(default_safety_param_sp)
|
||||
|
||||
def test_acc_main_sync_mismatch_counter(self):
|
||||
@@ -223,7 +219,6 @@ class HyundaiLongitudinalBase(common.LongitudinalAccelSafetyTest):
|
||||
self.safety.set_current_safety_param_sp(default_safety_param_sp | main_cruise_toggleable_flag)
|
||||
self.safety.set_safety_hooks(default_safety_mode, default_safety_param)
|
||||
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_mads_params(enable_mads, False, False)
|
||||
self.safety.set_controls_allowed_lat(True)
|
||||
|
||||
@@ -251,7 +246,6 @@ class HyundaiLongitudinalBase(common.LongitudinalAccelSafetyTest):
|
||||
# Counter should reset after disengagement
|
||||
self._tx(self._tx_acc_state_msg(False))
|
||||
self.assertEqual(0, self.safety.get_acc_main_on_mismatches())
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_current_safety_param_sp(default_safety_param_sp)
|
||||
|
||||
def test_acc_main_sync_mismatch_recovery(self):
|
||||
@@ -266,7 +260,6 @@ class HyundaiLongitudinalBase(common.LongitudinalAccelSafetyTest):
|
||||
self.safety.set_current_safety_param_sp(default_safety_param_sp | main_cruise_toggleable_flag)
|
||||
self.safety.set_safety_hooks(default_safety_mode, default_safety_param)
|
||||
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_mads_params(enable_mads, False, False)
|
||||
|
||||
# Create initial mismatch
|
||||
@@ -278,7 +271,6 @@ class HyundaiLongitudinalBase(common.LongitudinalAccelSafetyTest):
|
||||
# Sync states
|
||||
self._tx(self._tx_acc_state_msg(True)) # Match acc_main_on_tx to acc_main_on
|
||||
self.assertEqual(0, self.safety.get_acc_main_on_mismatches())
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_current_safety_param_sp(default_safety_param_sp)
|
||||
|
||||
def test_tester_present_allowed(self, ecu_disable: bool = True):
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from parameterized import parameterized
|
||||
import abc
|
||||
import unittest
|
||||
|
||||
@@ -15,7 +16,7 @@ class MadsSafetyTestBase(unittest.TestCase):
|
||||
def _acc_state_msg(self, enabled):
|
||||
raise NotImplementedError
|
||||
|
||||
def _mads_states_cleanup(self):
|
||||
def teardown_method(self, method):
|
||||
self.safety.set_mads_button_press(-1)
|
||||
self.safety.set_controls_allowed_lat(False)
|
||||
self.safety.set_controls_requested_lat(False)
|
||||
@@ -29,7 +30,6 @@ class MadsSafetyTestBase(unittest.TestCase):
|
||||
# If boolean is True, the heartbeat is engaged and should remain engaged, otherwise it should disengage.
|
||||
with self.subTest(heartbeat_engaged=boolean, should_remain_engaged=boolean):
|
||||
# Setup initial conditions
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_mads_params(True, False, False) # Enable MADS
|
||||
self.safety.set_controls_allowed_lat(True)
|
||||
self.assertTrue(self.safety.get_controls_allowed_lat())
|
||||
@@ -53,257 +53,200 @@ class MadsSafetyTestBase(unittest.TestCase):
|
||||
except NotImplementedError as err:
|
||||
raise unittest.SkipTest("Skipping test because MADS button is not supported") from err
|
||||
|
||||
try:
|
||||
for enable_mads in (True, False):
|
||||
with self.subTest("enable_mads", mads_enabled=enable_mads):
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_mads_params(enable_mads, False, False)
|
||||
self.assertEqual(enable_mads, self.safety.get_enable_mads())
|
||||
for enable_mads in (True, False):
|
||||
with self.subTest("enable_mads", mads_enabled=enable_mads):
|
||||
self.safety.set_mads_params(enable_mads, False, False)
|
||||
self.assertEqual(enable_mads, self.safety.get_enable_mads())
|
||||
|
||||
self._rx(self._lkas_button_msg(True))
|
||||
self._rx(self._speed_msg(0))
|
||||
self._rx(self._lkas_button_msg(False))
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertEqual(enable_mads, self.safety.get_controls_allowed_lat())
|
||||
finally:
|
||||
self._mads_states_cleanup()
|
||||
self._rx(self._lkas_button_msg(True))
|
||||
self._rx(self._lkas_button_msg(False))
|
||||
self.assertEqual(enable_mads, self.safety.get_controls_allowed_lat())
|
||||
|
||||
def test_enable_control_allowed_with_manual_acc_main_on_state(self):
|
||||
try:
|
||||
self._acc_state_msg(False)
|
||||
except NotImplementedError as err:
|
||||
self._mads_states_cleanup()
|
||||
raise unittest.SkipTest("Skipping test because _acc_state_msg is not implemented for this car") from err
|
||||
|
||||
try:
|
||||
for enable_mads in (True, False):
|
||||
with self.subTest("enable_mads", mads_enabled=enable_mads):
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_mads_params(enable_mads, False, False)
|
||||
self._rx(self._acc_state_msg(True))
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertEqual(enable_mads, self.safety.get_controls_allowed_lat())
|
||||
finally:
|
||||
self._mads_states_cleanup()
|
||||
for enable_mads in (True, False):
|
||||
with self.subTest("enable_mads", mads_enabled=enable_mads):
|
||||
self.safety.set_mads_params(enable_mads, False, False)
|
||||
self._rx(self._acc_state_msg(True))
|
||||
self.assertEqual(enable_mads, self.safety.get_controls_allowed_lat())
|
||||
|
||||
def test_enable_control_allowed_with_manual_mads_button_state(self):
|
||||
try:
|
||||
for enable_mads in (True, False):
|
||||
with self.subTest("enable_mads", mads_enabled=enable_mads):
|
||||
for mads_button_press in (-1, 0, 1):
|
||||
with self.subTest("mads_button_press", button_state=mads_button_press):
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_mads_params(enable_mads, False, False)
|
||||
for enable_mads in (True, False):
|
||||
with self.subTest("enable_mads", mads_enabled=enable_mads):
|
||||
for mads_button_press in (-1, 0, 1):
|
||||
with self.subTest("mads_button_press", button_state=mads_button_press):
|
||||
self.safety.set_mads_params(enable_mads, False, False)
|
||||
|
||||
self.safety.set_mads_button_press(mads_button_press)
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertEqual(enable_mads and mads_button_press == 1, self.safety.get_controls_allowed_lat())
|
||||
finally:
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_mads_button_press(mads_button_press)
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertEqual(enable_mads and mads_button_press == 1, self.safety.get_controls_allowed_lat())
|
||||
|
||||
def test_enable_control_allowed_from_acc_main_on(self):
|
||||
"""Test that lateral controls are allowed when ACC main is enabled and disabled when ACC main is disabled"""
|
||||
try:
|
||||
for enable_mads in (True, False):
|
||||
with self.subTest("enable_mads", mads_enabled=enable_mads):
|
||||
for acc_main_on in (True, False):
|
||||
with self.subTest("initial_acc_main", initial_acc_main=acc_main_on):
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_mads_params(enable_mads, False, False)
|
||||
for enable_mads in (True, False):
|
||||
with self.subTest("enable_mads", mads_enabled=enable_mads):
|
||||
for acc_main_on in (True, False):
|
||||
with self.subTest("initial_acc_main", initial_acc_main=acc_main_on):
|
||||
self.safety.set_mads_params(enable_mads, False, False)
|
||||
|
||||
# Set initial state
|
||||
self.safety.set_acc_main_on(acc_main_on)
|
||||
self._rx(self._speed_msg(0))
|
||||
expected_lat = enable_mads and acc_main_on
|
||||
self.assertEqual(expected_lat, self.safety.get_controls_allowed_lat(),
|
||||
f"Expected lat: [{expected_lat}] when acc_main_on goes to [{acc_main_on}]")
|
||||
# Set initial state
|
||||
self.safety.set_acc_main_on(acc_main_on)
|
||||
self._rx(self._speed_msg(0))
|
||||
expected_lat = enable_mads and acc_main_on
|
||||
self.assertEqual(expected_lat, self.safety.get_controls_allowed_lat(),
|
||||
f"Expected lat: [{expected_lat}] when acc_main_on goes to [{acc_main_on}]")
|
||||
|
||||
# Test transition to opposite state
|
||||
self.safety.set_acc_main_on(not acc_main_on)
|
||||
self._rx(self._speed_msg(0))
|
||||
expected_lat = enable_mads and not acc_main_on
|
||||
self.assertEqual(expected_lat, self.safety.get_controls_allowed_lat(),
|
||||
f"Expected lat: [{expected_lat}] when acc_main_on goes from [{acc_main_on}] to [{not acc_main_on}]")
|
||||
# Test transition to opposite state
|
||||
self.safety.set_acc_main_on(not acc_main_on)
|
||||
self._rx(self._speed_msg(0))
|
||||
expected_lat = enable_mads and not acc_main_on
|
||||
self.assertEqual(expected_lat, self.safety.get_controls_allowed_lat(),
|
||||
f"Expected lat: [{expected_lat}] when acc_main_on goes from [{acc_main_on}] to [{not acc_main_on}]")
|
||||
|
||||
# Test transition back to initial state
|
||||
self.safety.set_acc_main_on(acc_main_on)
|
||||
self._rx(self._speed_msg(0))
|
||||
expected_lat = enable_mads and acc_main_on
|
||||
self.assertEqual(expected_lat, self.safety.get_controls_allowed_lat(),
|
||||
f"Expected lat: [{expected_lat}] when acc_main_on goes from [{not acc_main_on}] to [{acc_main_on}]")
|
||||
finally:
|
||||
self._mads_states_cleanup()
|
||||
# Test transition back to initial state
|
||||
self.safety.set_acc_main_on(acc_main_on)
|
||||
self._rx(self._speed_msg(0))
|
||||
expected_lat = enable_mads and acc_main_on
|
||||
self.assertEqual(expected_lat, self.safety.get_controls_allowed_lat(),
|
||||
f"Expected lat: [{expected_lat}] when acc_main_on goes from [{not acc_main_on}] to [{acc_main_on}]")
|
||||
|
||||
def test_mads_with_acc_main_on(self):
|
||||
try:
|
||||
for enable_mads in (True, False):
|
||||
with self.subTest("enable_mads", mads_enabled=enable_mads):
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_mads_params(enable_mads, False, False)
|
||||
for enable_mads in (True, False):
|
||||
with self.subTest("enable_mads", mads_enabled=enable_mads):
|
||||
self.safety.set_mads_params(enable_mads, False, False)
|
||||
|
||||
self.safety.set_acc_main_on(True)
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertEqual(enable_mads, self.safety.get_controls_allowed_lat())
|
||||
self.safety.set_acc_main_on(True)
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertEqual(enable_mads, self.safety.get_controls_allowed_lat())
|
||||
|
||||
self.safety.set_acc_main_on(False)
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertFalse(self.safety.get_controls_allowed_lat())
|
||||
finally:
|
||||
self._mads_states_cleanup()
|
||||
|
||||
def test_pause_lateral_on_brake_setup(self):
|
||||
try:
|
||||
for enable_mads in (True, False):
|
||||
with self.subTest("enable_mads", enable_mads=enable_mads):
|
||||
for pause_lateral_on_brake in (True, False):
|
||||
with self.subTest("pause_lateral_on_brake", pause_lateral_on_brake=pause_lateral_on_brake):
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_mads_params(enable_mads, False, pause_lateral_on_brake)
|
||||
self.assertEqual(enable_mads and pause_lateral_on_brake, self.safety.get_pause_lateral_on_brake())
|
||||
finally:
|
||||
self._mads_states_cleanup()
|
||||
|
||||
def test_pause_lateral_on_brake(self):
|
||||
try:
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_mads_params(True, False, True)
|
||||
|
||||
self._rx(self._user_brake_msg(False))
|
||||
self.safety.set_controls_requested_lat(True)
|
||||
self.safety.set_controls_allowed_lat(True)
|
||||
|
||||
self._rx(self._user_brake_msg(True))
|
||||
# Test we pause lateral
|
||||
self.assertFalse(self.safety.get_controls_allowed_lat())
|
||||
# Make sure we can re-gain lateral actuation
|
||||
self._rx(self._user_brake_msg(False))
|
||||
self.assertTrue(self.safety.get_controls_allowed_lat())
|
||||
finally:
|
||||
self._mads_states_cleanup()
|
||||
|
||||
def test_no_pause_lateral_on_brake(self):
|
||||
try:
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_mads_params(True, False, False)
|
||||
|
||||
self._rx(self._user_brake_msg(False))
|
||||
self.safety.set_controls_requested_lat(True)
|
||||
self.safety.set_controls_allowed_lat(True)
|
||||
|
||||
self._rx(self._user_brake_msg(True))
|
||||
self.assertTrue(self.safety.get_controls_allowed_lat())
|
||||
finally:
|
||||
self._mads_states_cleanup()
|
||||
|
||||
def test_engage_with_brake_pressed(self):
|
||||
try:
|
||||
self._lkas_button_msg(False)
|
||||
except NotImplementedError as err:
|
||||
raise unittest.SkipTest("Skipping test because MADS button is not supported") from err
|
||||
|
||||
try:
|
||||
for enable_mads in (True, False):
|
||||
with self.subTest("enable_mads", enable_mads=enable_mads):
|
||||
for pause_lateral_on_brake in (True, False):
|
||||
with self.subTest("pause_lateral_on_brake", pause_lateral_on_brake=pause_lateral_on_brake):
|
||||
with self.subTest("mads_button"):
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_mads_params(enable_mads, False, pause_lateral_on_brake)
|
||||
|
||||
# Brake press rising edge
|
||||
self._rx(self._user_brake_msg(True))
|
||||
self._rx(self._lkas_button_msg(True))
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertEqual(enable_mads and not pause_lateral_on_brake, self.safety.get_controls_allowed_lat())
|
||||
|
||||
# Continuous braking after the first frame of brake press rising edge
|
||||
self.assertEqual(enable_mads and not pause_lateral_on_brake, self.safety.get_controls_allowed_lat())
|
||||
for _ in range(400):
|
||||
self._rx(self._user_brake_msg(True))
|
||||
self.assertEqual(enable_mads and not pause_lateral_on_brake, self.safety.get_controls_allowed_lat())
|
||||
|
||||
with self.subTest("acc_main_on"):
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_mads_params(enable_mads, False, pause_lateral_on_brake)
|
||||
|
||||
# Brake press rising edge
|
||||
self._rx(self._user_brake_msg(True))
|
||||
self.safety.set_acc_main_on(True)
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertEqual(enable_mads and not pause_lateral_on_brake, self.safety.get_controls_allowed_lat())
|
||||
|
||||
# Continuous braking after the first frame of brake press rising edge
|
||||
self.assertEqual(enable_mads and not pause_lateral_on_brake, self.safety.get_controls_allowed_lat())
|
||||
for _ in range(400):
|
||||
self._rx(self._user_brake_msg(True))
|
||||
self.assertEqual(enable_mads and not pause_lateral_on_brake, self.safety.get_controls_allowed_lat())
|
||||
finally:
|
||||
self._mads_states_cleanup()
|
||||
|
||||
def test_pause_lateral_on_brake_with_pressed_and_released(self):
|
||||
try:
|
||||
for enable_mads in (True, False):
|
||||
with self.subTest("enable_mads", enable_mads=enable_mads):
|
||||
for pause_lateral_on_brake in (True, False):
|
||||
with self.subTest("pause_lateral_on_brake", pause_lateral_on_brake=pause_lateral_on_brake):
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_mads_params(enable_mads, False, pause_lateral_on_brake)
|
||||
|
||||
# Set controls_allowed_lat rising edge
|
||||
self.safety.set_controls_requested_lat(True)
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertEqual(enable_mads, self.safety.get_controls_allowed_lat())
|
||||
|
||||
# User brake press, validate controls_allowed_lat is false
|
||||
self._rx(self._user_brake_msg(True))
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertEqual(enable_mads and not pause_lateral_on_brake, self.safety.get_controls_allowed_lat())
|
||||
|
||||
# User brake release, validate controls_allowed_lat is true
|
||||
self._rx(self._user_brake_msg(False))
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertEqual(enable_mads, self.safety.get_controls_allowed_lat())
|
||||
finally:
|
||||
self._mads_states_cleanup()
|
||||
|
||||
def test_pause_lateral_on_brake_persistent_control_allowed_off(self):
|
||||
try:
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_mads_params(True, False, True)
|
||||
|
||||
self.safety.set_controls_requested_lat(True)
|
||||
|
||||
# Vehicle moving, validate controls_allowed_lat is true
|
||||
for _ in range(10):
|
||||
self._rx(self._speed_msg(10))
|
||||
self.assertTrue(self.safety.get_controls_allowed_lat())
|
||||
|
||||
# User braked, vehicle slowed down in 10 frames, then stopped for 10 frames
|
||||
# Validate controls_allowed_lat is false
|
||||
self._rx(self._user_brake_msg(True))
|
||||
for _ in range(10):
|
||||
self._rx(self._speed_msg(5))
|
||||
self.assertFalse(self.safety.get_controls_allowed_lat())
|
||||
for _ in range(10):
|
||||
self.safety.set_acc_main_on(False)
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertFalse(self.safety.get_controls_allowed_lat())
|
||||
finally:
|
||||
self._mads_states_cleanup()
|
||||
|
||||
def test_pause_lateral_on_brake_setup(self):
|
||||
for enable_mads in (True, False):
|
||||
with self.subTest("enable_mads", enable_mads=enable_mads):
|
||||
for pause_lateral_on_brake in (True, False):
|
||||
with self.subTest("pause_lateral_on_brake", pause_lateral_on_brake=pause_lateral_on_brake):
|
||||
self.safety.set_mads_params(enable_mads, False, pause_lateral_on_brake)
|
||||
self.assertEqual(enable_mads and pause_lateral_on_brake, self.safety.get_pause_lateral_on_brake())
|
||||
|
||||
def test_pause_lateral_on_brake(self):
|
||||
self.safety.set_mads_params(True, False, True)
|
||||
|
||||
self._rx(self._user_brake_msg(False))
|
||||
self.safety.set_controls_requested_lat(True)
|
||||
self.safety.set_controls_allowed_lat(True)
|
||||
|
||||
self._rx(self._user_brake_msg(True))
|
||||
# Test we pause lateral
|
||||
self.assertFalse(self.safety.get_controls_allowed_lat())
|
||||
# Make sure we can re-gain lateral actuation
|
||||
self._rx(self._user_brake_msg(False))
|
||||
self.assertTrue(self.safety.get_controls_allowed_lat())
|
||||
|
||||
def test_no_pause_lateral_on_brake(self):
|
||||
self.safety.set_mads_params(True, False, False)
|
||||
|
||||
self._rx(self._user_brake_msg(False))
|
||||
self.safety.set_controls_requested_lat(True)
|
||||
self.safety.set_controls_allowed_lat(True)
|
||||
|
||||
self._rx(self._user_brake_msg(True))
|
||||
self.assertTrue(self.safety.get_controls_allowed_lat())
|
||||
|
||||
@parameterized.expand(["mads_button", "acc_main_on"])
|
||||
def test_engage_with_brake_pressed(self, engage_method):
|
||||
if engage_method == "mads_button":
|
||||
try:
|
||||
self._lkas_button_msg(False)
|
||||
except NotImplementedError as err:
|
||||
raise unittest.SkipTest("Skipping test because MADS button is not supported") from err
|
||||
elif engage_method == "acc_main_on":
|
||||
try:
|
||||
self._acc_state_msg(False)
|
||||
except NotImplementedError as err:
|
||||
raise unittest.SkipTest("Skipping test because ACC main is not supported") from err
|
||||
|
||||
for enable_mads in (True, False):
|
||||
with self.subTest("enable_mads", enable_mads=enable_mads):
|
||||
for pause_lateral_on_brake in (True, False):
|
||||
with self.subTest("pause_lateral_on_brake", pause_lateral_on_brake=pause_lateral_on_brake):
|
||||
with self.subTest(engage_method):
|
||||
self.safety.set_mads_params(enable_mads, False, pause_lateral_on_brake)
|
||||
|
||||
# Brake press rising edge
|
||||
self._rx(self._user_brake_msg(True))
|
||||
|
||||
if engage_method == "mads_button":
|
||||
self._rx(self._lkas_button_msg(True))
|
||||
elif engage_method == "acc_main_on":
|
||||
self.safety.set_acc_main_on(True)
|
||||
self.assertTrue(self.safety.get_acc_main_on())
|
||||
else:
|
||||
raise ValueError(f"Invalid engage_method: {engage_method}")
|
||||
self._rx(self._speed_msg(0))
|
||||
|
||||
self.assertEqual(enable_mads and not pause_lateral_on_brake, self.safety.get_controls_allowed_lat())
|
||||
|
||||
# Continuous braking after the first frame of brake press rising edge
|
||||
for _ in range(400):
|
||||
self.assertEqual(enable_mads and not pause_lateral_on_brake, self.safety.get_controls_allowed_lat())
|
||||
|
||||
def test_pause_lateral_on_brake_with_pressed_and_released(self):
|
||||
for enable_mads in (True, False):
|
||||
with self.subTest("enable_mads", enable_mads=enable_mads):
|
||||
for pause_lateral_on_brake in (True, False):
|
||||
with self.subTest("pause_lateral_on_brake", pause_lateral_on_brake=pause_lateral_on_brake):
|
||||
self.safety.set_mads_params(enable_mads, False, pause_lateral_on_brake)
|
||||
|
||||
# Set controls_allowed_lat rising edge
|
||||
self.safety.set_controls_requested_lat(True)
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertEqual(enable_mads, self.safety.get_controls_allowed_lat())
|
||||
|
||||
# User brake press, validate controls_allowed_lat is false
|
||||
self._rx(self._user_brake_msg(True))
|
||||
self.assertEqual(enable_mads and not pause_lateral_on_brake, self.safety.get_controls_allowed_lat())
|
||||
|
||||
# User brake release, validate controls_allowed_lat is true
|
||||
self._rx(self._user_brake_msg(False))
|
||||
self.assertEqual(enable_mads, self.safety.get_controls_allowed_lat())
|
||||
|
||||
def test_pause_lateral_on_brake_persistent_control_allowed_off(self):
|
||||
self.safety.set_mads_params(True, False, True)
|
||||
|
||||
self.safety.set_controls_requested_lat(True)
|
||||
|
||||
# Vehicle moving, validate controls_allowed_lat is true
|
||||
for _ in range(10):
|
||||
self._rx(self._speed_msg(10))
|
||||
self.assertTrue(self.safety.get_controls_allowed_lat())
|
||||
|
||||
# User braked, vehicle slowed down in 10 frames, then stopped for 10 frames
|
||||
# Validate controls_allowed_lat is false
|
||||
self._rx(self._user_brake_msg(True))
|
||||
for _ in range(10):
|
||||
self._rx(self._speed_msg(5))
|
||||
self.assertFalse(self.safety.get_controls_allowed_lat())
|
||||
for _ in range(10):
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertFalse(self.safety.get_controls_allowed_lat())
|
||||
|
||||
def test_enable_lateral_control_with_controls_allowed_rising_edge(self):
|
||||
try:
|
||||
for enable_mads in (True, False):
|
||||
with self.subTest("enable_mads", enable_mads=enable_mads):
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_mads_params(enable_mads, False, False)
|
||||
for enable_mads in (True, False):
|
||||
with self.subTest("enable_mads", enable_mads=enable_mads):
|
||||
self.safety.set_mads_params(enable_mads, False, False)
|
||||
|
||||
self.safety.set_controls_allowed(False)
|
||||
self._rx(self._speed_msg(0))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
finally:
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_controls_allowed(False)
|
||||
self._rx(self._speed_msg(0))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
|
||||
def test_enable_control_allowed_with_mads_button_and_disable_with_main_cruise(self):
|
||||
"""Tests main cruise and MADS button state transitions.
|
||||
@@ -324,27 +267,19 @@ class MadsSafetyTestBase(unittest.TestCase):
|
||||
except NotImplementedError as err:
|
||||
raise unittest.SkipTest("Skipping test because _acc_state_msg is not implemented for this car") from err
|
||||
|
||||
try:
|
||||
for enable_mads in (True, False):
|
||||
with self.subTest("enable_mads", enable_mads=enable_mads):
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_mads_params(enable_mads, False, False)
|
||||
for enable_mads in (True, False):
|
||||
with self.subTest("enable_mads", enable_mads=enable_mads):
|
||||
self.safety.set_mads_params(enable_mads, False, False)
|
||||
|
||||
self._rx(self._lkas_button_msg(True))
|
||||
self._rx(self._speed_msg(0))
|
||||
self._rx(self._lkas_button_msg(False))
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertEqual(enable_mads, self.safety.get_controls_allowed_lat())
|
||||
self._rx(self._lkas_button_msg(True))
|
||||
self._rx(self._lkas_button_msg(False))
|
||||
self.assertEqual(enable_mads, self.safety.get_controls_allowed_lat())
|
||||
|
||||
self._rx(self._acc_state_msg(True))
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertEqual(enable_mads, self.safety.get_controls_allowed_lat())
|
||||
self._rx(self._acc_state_msg(True))
|
||||
self.assertEqual(enable_mads, self.safety.get_controls_allowed_lat())
|
||||
|
||||
self._rx(self._acc_state_msg(False))
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertFalse(self.safety.get_controls_allowed_lat())
|
||||
finally:
|
||||
self._mads_states_cleanup()
|
||||
self._rx(self._acc_state_msg(False))
|
||||
self.assertFalse(self.safety.get_controls_allowed_lat())
|
||||
|
||||
def test_brake_disengage_with_control_request(self):
|
||||
"""Tests behavior when controls are requested while brake is engaged
|
||||
@@ -356,30 +291,24 @@ class MadsSafetyTestBase(unittest.TestCase):
|
||||
4. Release brake
|
||||
5. Verify controls become allowed
|
||||
"""
|
||||
try:
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_mads_params(True, False, True) # enable MADS with pause lateral on brake
|
||||
self.safety.set_mads_params(True, False, True) # enable MADS with pause lateral on brake
|
||||
|
||||
# Initial state
|
||||
self.safety.set_controls_allowed_lat(True)
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertTrue(self.safety.get_controls_allowed_lat())
|
||||
# Initial state
|
||||
self.safety.set_controls_allowed_lat(True)
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertTrue(self.safety.get_controls_allowed_lat())
|
||||
|
||||
# Brake press disengages lateral
|
||||
self._rx(self._user_brake_msg(True))
|
||||
self.assertFalse(self.safety.get_controls_allowed_lat())
|
||||
# Brake press disengages lateral
|
||||
self._rx(self._user_brake_msg(True))
|
||||
self.assertFalse(self.safety.get_controls_allowed_lat())
|
||||
|
||||
# Request controls while braking
|
||||
self.safety.set_controls_requested_lat(True)
|
||||
self.assertFalse(self.safety.get_controls_allowed_lat())
|
||||
# Request controls while braking
|
||||
self.safety.set_controls_requested_lat(True)
|
||||
self.assertFalse(self.safety.get_controls_allowed_lat())
|
||||
|
||||
# Release brake - should enable since controls were requested
|
||||
self._rx(self._user_brake_msg(False))
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertTrue(self.safety.get_controls_allowed_lat())
|
||||
|
||||
finally:
|
||||
self._mads_states_cleanup()
|
||||
# Release brake - should enable since controls were requested
|
||||
self._rx(self._user_brake_msg(False))
|
||||
self.assertTrue(self.safety.get_controls_allowed_lat())
|
||||
|
||||
def test_brake_disengage_with_acc_main_off(self):
|
||||
"""Tests behavior when ACC main is turned off while brake is engaged
|
||||
@@ -391,66 +320,49 @@ class MadsSafetyTestBase(unittest.TestCase):
|
||||
4. Release brake
|
||||
5. Verify controls remain disengaged
|
||||
"""
|
||||
try:
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_mads_params(True, False, True) # enable MADS with pause lateral on brake
|
||||
self.safety.set_mads_params(True, False, True) # enable MADS with pause lateral on brake
|
||||
|
||||
# Initial state - enable with ACC main
|
||||
self.safety.set_acc_main_on(True)
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertTrue(self.safety.get_controls_allowed_lat())
|
||||
# Initial state - enable with ACC main
|
||||
self.safety.set_acc_main_on(True)
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertTrue(self.safety.get_controls_allowed_lat())
|
||||
|
||||
# Brake press disengages lateral
|
||||
self._rx(self._user_brake_msg(True))
|
||||
self.assertFalse(self.safety.get_controls_allowed_lat())
|
||||
# Brake press disengages lateral
|
||||
self._rx(self._user_brake_msg(True))
|
||||
self.assertFalse(self.safety.get_controls_allowed_lat())
|
||||
|
||||
# Turn ACC main off while braking
|
||||
self.safety.set_acc_main_on(False)
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertFalse(self.safety.get_controls_allowed_lat())
|
||||
# Turn ACC main off while braking
|
||||
self.safety.set_acc_main_on(False)
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertFalse(self.safety.get_controls_allowed_lat())
|
||||
|
||||
# Release brake - should remain disabled since ACC main is off
|
||||
self._rx(self._user_brake_msg(False))
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertFalse(self.safety.get_controls_allowed_lat())
|
||||
|
||||
finally:
|
||||
self._mads_states_cleanup()
|
||||
# Release brake - should remain disabled since ACC main is off
|
||||
self._rx(self._user_brake_msg(False))
|
||||
self.assertFalse(self.safety.get_controls_allowed_lat())
|
||||
|
||||
def test_steering_disengage_with_control_request(self):
|
||||
try:
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_mads_params(True, False, False)
|
||||
self.safety.set_mads_params(True, False, False)
|
||||
|
||||
self.safety.set_controls_allowed_lat(True)
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertTrue(self.safety.get_controls_allowed_lat())
|
||||
|
||||
self.safety.set_steering_disengage(True)
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertFalse(self.safety.get_controls_allowed_lat())
|
||||
|
||||
def test_disengage_on_brake(self):
|
||||
for disengage_on_brake in (True, False):
|
||||
self.safety.set_mads_params(True, disengage_on_brake, False)
|
||||
|
||||
self.safety.set_controls_allowed_lat(True)
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertTrue(self.safety.get_controls_allowed_lat())
|
||||
|
||||
self.safety.set_steering_disengage(True)
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertFalse(self.safety.get_controls_allowed_lat())
|
||||
self._rx(self._user_brake_msg(True))
|
||||
self.assertEqual(not disengage_on_brake, self.safety.get_controls_allowed_lat())
|
||||
|
||||
finally:
|
||||
self._mads_states_cleanup()
|
||||
|
||||
def test_disengage_on_brake(self):
|
||||
try:
|
||||
for disengage_on_brake in (True, False):
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_mads_params(True, disengage_on_brake, False)
|
||||
|
||||
self.safety.set_controls_allowed_lat(True)
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertTrue(self.safety.get_controls_allowed_lat())
|
||||
|
||||
self._rx(self._user_brake_msg(True))
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertEqual(not disengage_on_brake, self.safety.get_controls_allowed_lat())
|
||||
|
||||
self._rx(self._user_brake_msg(False))
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertEqual(not disengage_on_brake, self.safety.get_controls_allowed_lat())
|
||||
finally:
|
||||
self._mads_states_cleanup()
|
||||
self._rx(self._user_brake_msg(False))
|
||||
self.assertEqual(not disengage_on_brake, self.safety.get_controls_allowed_lat())
|
||||
|
||||
# TODO-SP: controls_allowed and controls_allowed_lat check for steering safety tests
|
||||
|
||||
@@ -4,6 +4,7 @@ set -e
|
||||
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
|
||||
cd $DIR
|
||||
|
||||
source $DIR/../../../setup.sh
|
||||
$DIR/install_mull.sh
|
||||
|
||||
GIT_REF="${GIT_REF:-origin/master}"
|
||||
@@ -11,6 +12,6 @@ GIT_ROOT=$(git rev-parse --show-toplevel)
|
||||
MULL_OPS="mutators: [cxx_increment, cxx_decrement, cxx_comparison, cxx_boundary, cxx_bitwise_assignment, cxx_bitwise, cxx_arithmetic_assignment, cxx_arithmetic, cxx_remove_negation]"
|
||||
echo -e "$MULL_OPS" > $GIT_ROOT/mull.yml
|
||||
scons --mutation -j$(nproc) -D
|
||||
echo -e "timeout: 100000\ngitDiffRef: $GIT_REF\ngitProjectRoot: $GIT_ROOT" >> $GIT_ROOT/mull.yml
|
||||
echo -e "timeout: 1000000\ngitDiffRef: $GIT_REF\ngitProjectRoot: $GIT_ROOT" >> $GIT_ROOT/mull.yml
|
||||
|
||||
mull-runner-17 --ld-search-path /lib/x86_64-linux-gnu/ ./libsafety/libsafety.so -test-program=pytest -- -n8 --ignore-glob=misra/*
|
||||
|
||||
@@ -66,8 +66,8 @@ def replay_drive(msgs, safety_mode, param, alternative_experience, param_sp):
|
||||
|
||||
if msg.which() == 'sendcan':
|
||||
for canmsg in msg.sendcan:
|
||||
msg = package_can_msg(canmsg)
|
||||
sent = safety.safety_tx_hook(msg)
|
||||
_msg = package_can_msg(canmsg)
|
||||
sent = safety.safety_tx_hook(_msg)
|
||||
|
||||
# mismatched
|
||||
if safety.get_controls_allowed() and not safety.get_controls_allowed_lat():
|
||||
@@ -112,8 +112,8 @@ def replay_drive(msgs, safety_mode, param, alternative_experience, param_sp):
|
||||
# ignore msgs we sent
|
||||
for canmsg in filter(lambda m: m.src < 128, msg.can):
|
||||
safety.safety_fwd_hook(canmsg.src, canmsg.address)
|
||||
msg = package_can_msg(canmsg)
|
||||
recv = safety.safety_rx_hook(msg)
|
||||
_msg = package_can_msg(canmsg)
|
||||
recv = safety.safety_rx_hook(_msg)
|
||||
if not recv:
|
||||
rx_invalid += 1
|
||||
invalid_addrs.add(canmsg.address)
|
||||
|
||||
@@ -273,7 +273,6 @@ class TestFordSafetyBase(common.PandaCarSafetyTest):
|
||||
for path_angle in path_angles:
|
||||
for curvature_rate in curvature_rates:
|
||||
for curvature in curvatures:
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_controls_allowed(controls_allowed)
|
||||
self._set_prev_desired_angle(curvature)
|
||||
self._reset_curvature_measurement(curvature, speed)
|
||||
@@ -380,17 +379,13 @@ class TestFordSafetyBase(common.PandaCarSafetyTest):
|
||||
self.assertEqual(enabled, self._tx(self._acc_button_msg(Buttons.CANCEL, bus)))
|
||||
|
||||
def test_enable_control_allowed_from_acc_main_on(self):
|
||||
try:
|
||||
for enable_mads in (True, False):
|
||||
with self.subTest("enable_mads", mads_enabled=enable_mads):
|
||||
for main_button_msg_valid in (True, False):
|
||||
with self.subTest("main_button_msg_valid", state_valid=main_button_msg_valid):
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_mads_params(enable_mads, False, False)
|
||||
self._rx(self._pcm_status_msg(main_button_msg_valid))
|
||||
self.assertEqual(enable_mads and main_button_msg_valid, self.safety.get_controls_allowed_lat())
|
||||
finally:
|
||||
self._mads_states_cleanup()
|
||||
for enable_mads in (True, False):
|
||||
with self.subTest("enable_mads", mads_enabled=enable_mads):
|
||||
for main_button_msg_valid in (True, False):
|
||||
with self.subTest("main_button_msg_valid", state_valid=main_button_msg_valid):
|
||||
self.safety.set_mads_params(enable_mads, False, False)
|
||||
self._rx(self._pcm_status_msg(main_button_msg_valid))
|
||||
self.assertEqual(enable_mads and main_button_msg_valid, self.safety.get_controls_allowed_lat())
|
||||
|
||||
|
||||
class TestFordCANFDStockSafety(TestFordSafetyBase):
|
||||
|
||||
@@ -8,6 +8,8 @@ import opendbc.safety.tests.common as common
|
||||
from opendbc.car.structs import CarParams
|
||||
from opendbc.safety.tests.common import CANPackerPanda, MAX_WRONG_COUNTERS
|
||||
|
||||
from opendbc.sunnypilot.car.honda.values_ext import HondaSafetyFlagsSP
|
||||
|
||||
HONDA_N_COMMON_TX_MSGS = [[0xE4, 0], [0x194, 0], [0x1FA, 0], [0x30C, 0], [0x33D, 0]]
|
||||
|
||||
|
||||
@@ -233,7 +235,6 @@ class HondaBase(common.PandaCarSafetyTest):
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_steer_safety_check(self):
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_controls_allowed(0)
|
||||
self.assertTrue(self._tx(self._send_steer_msg(0x0000)))
|
||||
self.assertFalse(self._tx(self._send_steer_msg(0x1000)))
|
||||
@@ -245,41 +246,36 @@ class HondaBase(common.PandaCarSafetyTest):
|
||||
|
||||
def test_enable_control_allowed_with_mads_button(self):
|
||||
"""Tests MADS button state transitions and internal button press state."""
|
||||
try:
|
||||
for enable_mads in (True, False):
|
||||
with self.subTest("enable_mads", mads_enabled=enable_mads):
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_mads_params(enable_mads, False, False)
|
||||
for enable_mads in (True, False):
|
||||
with self.subTest("enable_mads", mads_enabled=enable_mads):
|
||||
self.safety.set_mads_params(enable_mads, False, False)
|
||||
|
||||
# Verify initial state
|
||||
self._rx(self._lkas_button_msg(False, 0))
|
||||
self.assertEqual(0, self.safety.get_mads_button_press()) # NOT_PRESSED
|
||||
self.assertFalse(self.safety.get_controls_allowed_lat())
|
||||
# Verify initial state
|
||||
self._rx(self._lkas_button_msg(False, 0))
|
||||
self.assertEqual(0, self.safety.get_mads_button_press()) # NOT_PRESSED
|
||||
self.assertFalse(self.safety.get_controls_allowed_lat())
|
||||
|
||||
# Verify press sets correct internal state
|
||||
self._rx(self._lkas_button_msg(False, 1))
|
||||
self.assertEqual(1, self.safety.get_mads_button_press()) # PRESSED
|
||||
# Verify press sets correct internal state
|
||||
self._rx(self._lkas_button_msg(False, 1))
|
||||
self.assertEqual(1, self.safety.get_mads_button_press()) # PRESSED
|
||||
self.assertEqual(enable_mads, self.safety.get_controls_allowed_lat())
|
||||
|
||||
# Verify release sets correct internal state
|
||||
self._rx(self._lkas_button_msg(False, 0))
|
||||
self.assertEqual(0, self.safety.get_mads_button_press()) # NOT_PRESSED
|
||||
self.assertEqual(enable_mads, self.safety.get_controls_allowed_lat())
|
||||
|
||||
# Test invalid values - should not change button press state
|
||||
for invalid_setting in (2, 3):
|
||||
self._rx(self._lkas_button_msg(False, invalid_setting))
|
||||
self.assertEqual(0, self.safety.get_mads_button_press()) # Should remain NOT_PRESSED
|
||||
self.assertEqual(enable_mads, self.safety.get_controls_allowed_lat())
|
||||
|
||||
# Verify release sets correct internal state
|
||||
self._rx(self._lkas_button_msg(False, 0))
|
||||
self.assertEqual(0, self.safety.get_mads_button_press()) # NOT_PRESSED
|
||||
self.assertEqual(enable_mads, self.safety.get_controls_allowed_lat())
|
||||
|
||||
# Test invalid values - should not change button press state
|
||||
for invalid_setting in (2, 3):
|
||||
self._rx(self._lkas_button_msg(False, invalid_setting))
|
||||
self.assertEqual(0, self.safety.get_mads_button_press()) # Should remain NOT_PRESSED
|
||||
self.assertEqual(enable_mads, self.safety.get_controls_allowed_lat())
|
||||
|
||||
# Verify we can still transition after invalid values
|
||||
self._rx(self._lkas_button_msg(False, 1))
|
||||
self.assertEqual(1, self.safety.get_mads_button_press())
|
||||
self._rx(self._lkas_button_msg(False, 0))
|
||||
self.assertEqual(0, self.safety.get_mads_button_press())
|
||||
|
||||
finally:
|
||||
self._mads_states_cleanup()
|
||||
# Verify we can still transition after invalid values
|
||||
self._rx(self._lkas_button_msg(False, 1))
|
||||
self.assertEqual(1, self.safety.get_mads_button_press())
|
||||
self._rx(self._lkas_button_msg(False, 0))
|
||||
self.assertEqual(0, self.safety.get_mads_button_press())
|
||||
|
||||
|
||||
# ********************* Honda Nidec **********************
|
||||
@@ -296,6 +292,8 @@ class TestHondaNidecSafetyBase(HondaBase):
|
||||
|
||||
MAX_GAS = 198
|
||||
|
||||
BRAKE_SIG = "COMPUTER_BRAKE"
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerPanda("honda_civic_touring_2016_can_generated")
|
||||
self.safety = libsafety_py.libsafety
|
||||
@@ -303,7 +301,7 @@ class TestHondaNidecSafetyBase(HondaBase):
|
||||
self.safety.init_tests()
|
||||
|
||||
def _send_brake_msg(self, brake, aeb_req=0, bus=0):
|
||||
values = {"COMPUTER_BRAKE": brake, "AEB_REQ_1": aeb_req}
|
||||
values = {self.BRAKE_SIG: brake, "AEB_REQ_1": aeb_req}
|
||||
return self.packer.make_can_msg_panda("BRAKE_COMMAND", bus, values)
|
||||
|
||||
def _rx_brake_msg(self, brake, aeb_req=0):
|
||||
@@ -642,5 +640,17 @@ class TestHondaBoschCANFDAltBrakeSafety(HondaPcmEnableBase, TestHondaBoschCANFDS
|
||||
self.safety.init_tests()
|
||||
|
||||
|
||||
class TestHondaNidecClaritySafety(TestHondaNidecPcmSafety):
|
||||
|
||||
BRAKE_SIG = "COMPUTER_BRAKE_ALT"
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerPanda("honda_clarity_hybrid_2018_can_generated")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_current_safety_param_sp(HondaSafetyFlagsSP.CLARITY)
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.hondaNidec, 0)
|
||||
self.safety.init_tests()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -18,6 +18,21 @@ LDA_BUTTON = [
|
||||
{"SAFETY_PARAM_SP": HyundaiSafetyFlagsSP.HAS_LDA_BUTTON},
|
||||
]
|
||||
|
||||
# All combinations of non-SCC HEV/PHEV/EV cars
|
||||
_ALL_NON_SCC_HEV_EV_COMBOS = [
|
||||
# Hybrid
|
||||
{"PCM_STATUS_MSG": ("E_CRUISE_CONTROL", "CRUISE_LAMP_S"),
|
||||
"ACC_STATE_MSG": ("E_CRUISE_CONTROL", "CRUISE_LAMP_M"),
|
||||
"GAS_MSG": ("E_EMS11", "CR_Vcu_AccPedDep_Pos"),
|
||||
"SAFETY_PARAM": HyundaiSafetyFlags.HYBRID_GAS},
|
||||
# EV
|
||||
{"PCM_STATUS_MSG": ("LABEL11", "CC_ACT"),
|
||||
"ACC_STATE_MSG": ("LABEL11", "CC_React"),
|
||||
"GAS_MSG": ("E_EMS11", "Accel_Pedal_Pos"),
|
||||
"SAFETY_PARAM": HyundaiSafetyFlags.EV_GAS},
|
||||
]
|
||||
ALL_NON_SCC_HEV_EV_COMBOS = [{**p, **lda} for lda in LDA_BUTTON for p in _ALL_NON_SCC_HEV_EV_COMBOS]
|
||||
|
||||
|
||||
# 4 bit checkusm used in some hyundai messages
|
||||
# lives outside the can packer because we never send this msg
|
||||
@@ -178,7 +193,6 @@ class TestHyundaiSafety(HyundaiButtonBase, common.PandaCarSafetyTest, common.Dri
|
||||
self.safety.set_current_safety_param_sp(has_lda_button)
|
||||
self.safety.set_safety_hooks(default_safety_mode, default_safety_param)
|
||||
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_mads_params(enable_mads, False, False)
|
||||
self.assertEqual(enable_mads, self.safety.get_enable_mads())
|
||||
|
||||
@@ -188,7 +202,6 @@ class TestHyundaiSafety(HyundaiButtonBase, common.PandaCarSafetyTest, common.Dri
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertEqual(enable_mads and has_lda_button_param, self.safety.get_controls_allowed_lat())
|
||||
finally:
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_current_safety_param_sp(default_safety_param_sp)
|
||||
|
||||
|
||||
@@ -465,5 +478,90 @@ class TestHyundaiLongitudinalESCCSafety(HyundaiLongitudinalBase, TestHyundaiSafe
|
||||
pass
|
||||
|
||||
|
||||
@parameterized_class(LDA_BUTTON)
|
||||
class TestHyundaiNonSCCSafety(TestHyundaiSafety):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
if cls.__name__ == "TestHyundaiNonSCCSafety":
|
||||
cls.safety = None
|
||||
raise unittest.SkipTest
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerPanda("hyundai_kia_generic")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_current_safety_param_sp(HyundaiSafetyFlagsSP.NON_SCC | self.SAFETY_PARAM_SP)
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, 0)
|
||||
self.safety.init_tests()
|
||||
|
||||
def _pcm_status_msg(self, enable):
|
||||
values = {"CRUISE_LAMP_S": enable, "AliveCounter": self.cnt_gas % 4}
|
||||
self.__class__.cnt_gas += 1
|
||||
return self.packer.make_can_msg_panda("EMS16", 0, values, fix_checksum=checksum)
|
||||
|
||||
def _acc_state_msg(self, enable):
|
||||
values = {"CRUISE_LAMP_M": enable, "AliveCounter": self.cnt_gas % 4}
|
||||
self.__class__.cnt_gas += 1
|
||||
return self.packer.make_can_msg_panda("EMS16", 0, values, fix_checksum=checksum)
|
||||
|
||||
def _user_gas_msg(self, gas: float, controls_allowed: bool = True):
|
||||
values = {"CF_Ems_AclAct": gas, "CRUISE_LAMP_M": 1, "CRUISE_LAMP_S": controls_allowed, "AliveCounter": self.cnt_gas % 4}
|
||||
self.__class__.cnt_gas += 1
|
||||
return self.packer.make_can_msg_panda("EMS16", 0, values, fix_checksum=checksum)
|
||||
|
||||
def test_allow_engage_with_gas_pressed(self):
|
||||
self._rx(self._user_gas_msg(1, self.safety.get_controls_allowed()))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self._rx(self._user_gas_msg(1, self.safety.get_controls_allowed()))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self._rx(self._user_gas_msg(1, self.safety.get_controls_allowed()))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
|
||||
def test_no_disengage_on_gas(self):
|
||||
self._rx(self._user_gas_msg(0, self.safety.get_controls_allowed()))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self._rx(self._user_gas_msg(self.GAS_PRESSED_THRESHOLD + 1, self.safety.get_controls_allowed()))
|
||||
# Test we allow lateral, but not longitudinal
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.assertFalse(self.safety.get_longitudinal_allowed())
|
||||
# Make sure we can re-gain longitudinal actuation
|
||||
self._rx(self._user_gas_msg(0, self.safety.get_controls_allowed()))
|
||||
self.assertTrue(self.safety.get_longitudinal_allowed())
|
||||
|
||||
|
||||
@parameterized_class(ALL_NON_SCC_HEV_EV_COMBOS)
|
||||
class TestHyundaiNonSCCSafety_HEV_EV(TestHyundaiSafety):
|
||||
|
||||
PCM_STATUS_MSG = ("", "")
|
||||
ACC_STATE_MSG = ("", "")
|
||||
GAS_MSG = ("", "")
|
||||
SAFETY_PARAM = 0
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
if cls.__name__ == "TestHyundaiNonSCCSafety_HEV_EV":
|
||||
cls.safety = None
|
||||
raise unittest.SkipTest
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerPanda("hyundai_kia_generic")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_current_safety_param_sp(HyundaiSafetyFlagsSP.NON_SCC | self.SAFETY_PARAM_SP)
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, self.SAFETY_PARAM)
|
||||
self.safety.init_tests()
|
||||
|
||||
def _pcm_status_msg(self, enable):
|
||||
values = {self.PCM_STATUS_MSG[1]: enable}
|
||||
return self.packer.make_can_msg_panda(self.PCM_STATUS_MSG[0], 0, values)
|
||||
|
||||
def _acc_state_msg(self, enable):
|
||||
values = {self.ACC_STATE_MSG[1]: enable}
|
||||
return self.packer.make_can_msg_panda(self.ACC_STATE_MSG[0], 0, values)
|
||||
|
||||
def _user_gas_msg(self, gas):
|
||||
values = {self.GAS_MSG[1]: gas}
|
||||
return self.packer.make_can_msg_panda(self.GAS_MSG[0], 0, values, fix_checksum=checksum)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env python3
|
||||
import unittest
|
||||
|
||||
from opendbc.car.structs import CarParams
|
||||
from opendbc.safety.tests.libsafety import libsafety_py
|
||||
import opendbc.safety.tests.common as common
|
||||
from opendbc.safety.tests.common import CANPackerPanda
|
||||
|
||||
LANE_KEEP_ASSIST = 0x3F2
|
||||
|
||||
|
||||
class TestPsaSafetyBase(common.PandaCarSafetyTest, common.AngleSteeringSafetyTest):
|
||||
RELAY_MALFUNCTION_ADDRS = {0: (LANE_KEEP_ASSIST,)}
|
||||
FWD_BLACKLISTED_ADDRS = {2: [LANE_KEEP_ASSIST]}
|
||||
TX_MSGS = [[1010, 0]]
|
||||
|
||||
MAIN_BUS = 0
|
||||
ADAS_BUS = 1
|
||||
CAM_BUS = 2
|
||||
|
||||
STEER_ANGLE_MAX = 390
|
||||
DEG_TO_CAN = 10
|
||||
|
||||
ANGLE_RATE_BP = [0., 5., 25.]
|
||||
ANGLE_RATE_UP = [2.5, 1.5, .2]
|
||||
ANGLE_RATE_DOWN = [5., 2., .3]
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerPanda("psa_aee2010_r3")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.psa, 0)
|
||||
self.safety.init_tests()
|
||||
|
||||
def _angle_cmd_msg(self, angle: float, enabled: bool):
|
||||
values = {"SET_ANGLE": angle, "TORQUE_FACTOR": 100 if enabled else 0}
|
||||
return self.packer.make_can_msg_panda("LANE_KEEP_ASSIST", self.MAIN_BUS, values)
|
||||
|
||||
def _angle_meas_msg(self, angle: float):
|
||||
values = {"ANGLE": angle}
|
||||
return self.packer.make_can_msg_panda("STEERING_ALT", self.MAIN_BUS, values)
|
||||
|
||||
def _pcm_status_msg(self, enable):
|
||||
values = {"RVV_ACC_ACTIVATION_REQ": enable}
|
||||
return self.packer.make_can_msg_panda("HS2_DAT_MDD_CMD_452", self.ADAS_BUS, values)
|
||||
|
||||
def _speed_msg(self, speed):
|
||||
values = {"VITESSE_VEHICULE_ROUES": speed * 3.6}
|
||||
return self.packer.make_can_msg_panda("HS2_DYN_ABR_38D", self.MAIN_BUS, values)
|
||||
|
||||
def _user_brake_msg(self, brake):
|
||||
values = {"P013_MainBrake": brake}
|
||||
return self.packer.make_can_msg_panda("Dat_BSI", self.CAM_BUS, values)
|
||||
|
||||
def _user_gas_msg(self, gas):
|
||||
values = {"P002_Com_rAPP": int(gas * 100)}
|
||||
return self.packer.make_can_msg_panda("Dyn_CMM", self.MAIN_BUS, values)
|
||||
|
||||
def test_rx_hook(self):
|
||||
# speed
|
||||
for _ in range(10):
|
||||
self.assertTrue(self._rx(self._speed_msg(0)))
|
||||
msg = self._speed_msg(0)
|
||||
# invalidate checksum
|
||||
msg[0].data[5] = 0x00
|
||||
self.assertFalse(self._rx(msg))
|
||||
|
||||
# cruise
|
||||
for _ in range(10):
|
||||
self.assertTrue(self._rx(self._pcm_status_msg(0)))
|
||||
msg = self._pcm_status_msg(0)
|
||||
# invalidate checksum
|
||||
msg[0].data[5] = 0x00
|
||||
self.assertFalse(self._rx(msg))
|
||||
msg = self._pcm_status_msg(0)
|
||||
# write to unused payload byte
|
||||
msg[0].data[6] = 0xAB
|
||||
self.assertTrue(self._rx(msg))
|
||||
|
||||
|
||||
class TestPsaStockSafety(TestPsaSafetyBase):
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerPanda("psa_aee2010_r3")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.psa, 0)
|
||||
self.safety.init_tests()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -120,13 +120,11 @@ class TestSubaruSafetyBase(common.PandaCarSafetyTest):
|
||||
with self.subTest("enable_mads", mads_enabled=enable_mads):
|
||||
for mads_button_press in range(4):
|
||||
with self.subTest("mads_button_press", button_state=mads_button_press):
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_mads_params(enable_mads, False, False)
|
||||
|
||||
self._rx(self._lkas_button_msg(False, mads_button_press))
|
||||
self.assertEqual(enable_mads and mads_button_press in range(1, 4),
|
||||
self.safety.get_controls_allowed_lat())
|
||||
self._mads_states_cleanup()
|
||||
|
||||
|
||||
class TestSubaruStockLongitudinalSafetyBase(TestSubaruSafetyBase):
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
import random
|
||||
from parameterized import parameterized_class
|
||||
import unittest
|
||||
import numpy as np
|
||||
|
||||
@@ -13,19 +12,12 @@ from opendbc.can import CANDefine
|
||||
from opendbc.safety.tests.libsafety import libsafety_py
|
||||
import opendbc.safety.tests.common as common
|
||||
from opendbc.safety.tests.common import CANPackerPanda, MAX_SPEED_DELTA, MAX_WRONG_COUNTERS, away_round, round_speed
|
||||
from opendbc.sunnypilot.car.tesla.values import TeslaSafetyFlagsSP
|
||||
|
||||
MSG_DAS_steeringControl = 0x488
|
||||
MSG_APS_eacMonitor = 0x27d
|
||||
MSG_DAS_Control = 0x2b9
|
||||
|
||||
|
||||
VIRTUAL_TORQUE_BLENDING_SAFETY_PARAM_SP = [
|
||||
{"SAFETY_PARAM_SP": TeslaSafetyFlagsSP.DEFAULT},
|
||||
{"SAFETY_PARAM_SP": TeslaSafetyFlagsSP.VIRTUAL_TORQUE_BLENDING},
|
||||
]
|
||||
|
||||
|
||||
def round_angle(apply_angle, can_offset=0):
|
||||
apply_angle_can = (apply_angle + 1638.35) / 0.1 + can_offset
|
||||
# 0.49999_ == 0.5
|
||||
@@ -64,8 +56,6 @@ class TestTeslaSafetyBase(common.PandaCarSafetyTest, common.AngleSteeringSafetyT
|
||||
|
||||
packer: CANPackerPanda
|
||||
|
||||
SAFETY_PARAM_SP: int = 0
|
||||
|
||||
def _get_steer_cmd_angle_max(self, speed):
|
||||
return get_max_angle_vm(max(speed, 1), self.VM, CarControllerParams)
|
||||
|
||||
@@ -215,24 +205,18 @@ class TestTeslaSafetyBase(common.PandaCarSafetyTest, common.AngleSteeringSafetyT
|
||||
for hands_on_level in range(4):
|
||||
for eac_status in range(8):
|
||||
for eac_error_code in range(16):
|
||||
for virtual_torque_blending_enabled in (True, False):
|
||||
self.safety.set_controls_allowed(True)
|
||||
self.safety.set_controls_allowed(True)
|
||||
|
||||
virtual_torque_blending = TeslaSafetyFlagsSP.VIRTUAL_TORQUE_BLENDING if virtual_torque_blending_enabled else 0
|
||||
hands_on_level_check = False if virtual_torque_blending_enabled else (hands_on_level >= 3)
|
||||
hands_on_level = 0 if virtual_torque_blending_enabled else hands_on_level
|
||||
self.safety.set_current_safety_param_sp(virtual_torque_blending)
|
||||
should_disengage = hands_on_level >= 3 or (eac_status == 0 and eac_error_code == 9)
|
||||
self.assertTrue(self._rx(self._angle_meas_msg(0, hands_on_level=hands_on_level, eac_status=eac_status,
|
||||
eac_error_code=eac_error_code)))
|
||||
self.assertNotEqual(should_disengage, self.safety.get_controls_allowed())
|
||||
self.assertEqual(should_disengage, self.safety.get_steering_disengage_prev())
|
||||
|
||||
should_disengage = hands_on_level_check or (eac_status == 0 and eac_error_code == 9)
|
||||
self.assertTrue(self._rx(self._angle_meas_msg(0, hands_on_level=hands_on_level, eac_status=eac_status,
|
||||
eac_error_code=eac_error_code)))
|
||||
self.assertNotEqual(should_disengage, self.safety.get_controls_allowed())
|
||||
self.assertEqual(should_disengage, self.safety.get_steering_disengage_prev())
|
||||
|
||||
# Should not recover
|
||||
self.assertTrue(self._rx(self._angle_meas_msg(0, hands_on_level=0, eac_status=1, eac_error_code=0)))
|
||||
self.assertNotEqual(should_disengage, self.safety.get_controls_allowed())
|
||||
self.assertFalse(self.safety.get_steering_disengage_prev())
|
||||
# Should not recover
|
||||
self.assertTrue(self._rx(self._angle_meas_msg(0, hands_on_level=0, eac_status=1, eac_error_code=0)))
|
||||
self.assertNotEqual(should_disengage, self.safety.get_controls_allowed())
|
||||
self.assertFalse(self.safety.get_steering_disengage_prev())
|
||||
|
||||
def test_autopark_summon_while_enabled(self):
|
||||
# We should not respect Autopark that activates while controls are allowed
|
||||
@@ -289,7 +273,6 @@ class TestTeslaSafetyBase(common.PandaCarSafetyTest, common.AngleSteeringSafetyT
|
||||
lkas_msg_cam = self._angle_cmd_msg(0, state=self.steer_control_types['LANE_KEEP_ASSIST'], bus=2)
|
||||
|
||||
for enable_mads in (True, False):
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_mads_params(enable_mads, True, False)
|
||||
# stock system sends no LKAS -> no forwarding, and OP is allowed to TX
|
||||
self.assertEqual(1, self._rx(no_lkas_msg_cam))
|
||||
@@ -373,7 +356,6 @@ class TestTeslaSafetyBase(common.PandaCarSafetyTest, common.AngleSteeringSafetyT
|
||||
self.assertTrue(self._tx(self._angle_cmd_msg(0, True)))
|
||||
|
||||
|
||||
@parameterized_class(VIRTUAL_TORQUE_BLENDING_SAFETY_PARAM_SP)
|
||||
class TestTeslaStockSafety(TestTeslaSafetyBase):
|
||||
|
||||
LONGITUDINAL = False
|
||||
@@ -381,7 +363,6 @@ class TestTeslaStockSafety(TestTeslaSafetyBase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_current_safety_param_sp(self.SAFETY_PARAM_SP)
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.tesla, 0)
|
||||
self.safety.init_tests()
|
||||
|
||||
@@ -416,7 +397,6 @@ class TestTeslaStockSafety(TestTeslaSafetyBase):
|
||||
self.assertFalse(self._tx(no_aeb_msg))
|
||||
|
||||
|
||||
@parameterized_class(VIRTUAL_TORQUE_BLENDING_SAFETY_PARAM_SP)
|
||||
class TestTeslaLongitudinalSafety(TestTeslaSafetyBase):
|
||||
RELAY_MALFUNCTION_ADDRS = {0: (MSG_DAS_steeringControl, MSG_APS_eacMonitor, MSG_DAS_Control)}
|
||||
FWD_BLACKLISTED_ADDRS = {2: [MSG_DAS_steeringControl, MSG_APS_eacMonitor, MSG_DAS_Control]}
|
||||
@@ -424,7 +404,6 @@ class TestTeslaLongitudinalSafety(TestTeslaSafetyBase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_current_safety_param_sp(self.SAFETY_PARAM_SP)
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.tesla, TeslaSafetyFlags.LONG_CONTROL)
|
||||
self.safety.init_tests()
|
||||
|
||||
|
||||
@@ -112,7 +112,6 @@ class TestToyotaSafetyBase(common.PandaCarSafetyTest, common.LongitudinalAccelSa
|
||||
[0, 1], [0, 1],
|
||||
[0, 50, 100],
|
||||
np.linspace(-20, 20, 5)):
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_controls_allowed(engaged)
|
||||
|
||||
should_tx = not req and not req2 and angle == 0 and torque_wind_down == 0
|
||||
@@ -211,7 +210,6 @@ class TestToyotaSafetyAngle(TestToyotaSafetyBase, common.AngleSteeringSafetyTest
|
||||
"""
|
||||
for controls_allowed in (True, False):
|
||||
for angle in np.arange(-90, 90, 1):
|
||||
self._mads_states_cleanup()
|
||||
self.safety.set_controls_allowed(controls_allowed)
|
||||
self._reset_angle_measurement(angle)
|
||||
self._set_prev_desired_angle(angle)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user