mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-09-30 19:33:45 +08:00
openpilot v0.8.12 release
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
<p>FCC ID: 2AOHHTURBOXSOMD845</p>
|
||||
|
||||
<h5>Quectel/EG25-G</h5>
|
||||
<p>FCC ID: XMR201903EG25GM</p>
|
||||
<p>FCC ID: XMR201903EG25G</p>
|
||||
<p>
|
||||
This device complies with Part 15 of the FCC Rules.
|
||||
Operation is subject to the following two conditions:
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -30,7 +30,7 @@ from selfdrive.hardware import HARDWARE, PC
|
||||
from selfdrive.loggerd.config import ROOT
|
||||
from selfdrive.loggerd.xattr_cache import getxattr, setxattr
|
||||
from selfdrive.swaglog import cloudlog, SWAGLOG_DIR
|
||||
from selfdrive.version import version, get_version, get_git_remote, get_git_branch, get_git_commit
|
||||
from selfdrive.version import get_version, get_origin, get_short_branch, get_commit
|
||||
|
||||
ATHENA_HOST = os.getenv('ATHENA_HOST', 'wss://athena.comma.ai')
|
||||
HANDLER_THREADS = int(os.getenv('HANDLER_THREADS', "4"))
|
||||
@@ -176,17 +176,19 @@ def getMessage(service=None, timeout=1000):
|
||||
def getVersion():
|
||||
return {
|
||||
"version": get_version(),
|
||||
"remote": get_git_remote(),
|
||||
"branch": get_git_branch(),
|
||||
"commit": get_git_commit(),
|
||||
"remote": get_origin(),
|
||||
"branch": get_short_branch(),
|
||||
"commit": get_commit(),
|
||||
}
|
||||
|
||||
|
||||
@dispatcher.add_method
|
||||
def setNavDestination(latitude=0, longitude=0):
|
||||
def setNavDestination(latitude=0, longitude=0, place_name=None, place_details=None):
|
||||
destination = {
|
||||
"latitude": latitude,
|
||||
"longitude": longitude,
|
||||
"place_name": place_name,
|
||||
"place_details": place_details,
|
||||
}
|
||||
Params().put("NavDestination", json.dumps(destination))
|
||||
|
||||
@@ -551,7 +553,7 @@ def main():
|
||||
except socket.timeout:
|
||||
try:
|
||||
r = requests.get("http://api.commadotai.com/v1/me", allow_redirects=False,
|
||||
headers={"User-Agent": f"openpilot-{version}"}, timeout=15.0)
|
||||
headers={"User-Agent": f"openpilot-{get_version()}"}, timeout=15.0)
|
||||
if r.status_code == 302 and r.headers['Location'].startswith("http://u.web2go.com"):
|
||||
params.put_bool("PrimeRedirected", True)
|
||||
except Exception:
|
||||
|
||||
@@ -6,7 +6,7 @@ from multiprocessing import Process
|
||||
from common.params import Params
|
||||
from selfdrive.manager.process import launcher
|
||||
from selfdrive.swaglog import cloudlog
|
||||
from selfdrive.version import version, dirty
|
||||
from selfdrive.version import get_version, get_dirty
|
||||
|
||||
ATHENA_MGR_PID_PARAM = "AthenadPid"
|
||||
|
||||
@@ -14,7 +14,7 @@ ATHENA_MGR_PID_PARAM = "AthenadPid"
|
||||
def main():
|
||||
params = Params()
|
||||
dongle_id = params.get("DongleId").decode('utf-8')
|
||||
cloudlog.bind_global(dongle_id=dongle_id, version=version, dirty=dirty)
|
||||
cloudlog.bind_global(dongle_id=dongle_id, version=get_version(), dirty=get_dirty())
|
||||
|
||||
try:
|
||||
while 1:
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
#/!/usr/bin/env python3
|
||||
import time
|
||||
import json
|
||||
import jwt
|
||||
from pathlib import Path
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from common.api import api_get
|
||||
from common.params import Params
|
||||
from common.spinner import Spinner
|
||||
from common.file_helpers import mkdirs_exists_ok
|
||||
from common.basedir import PERSIST
|
||||
from selfdrive.controls.lib.alertmanager import set_offroad_alert
|
||||
from selfdrive.hardware import HARDWARE
|
||||
@@ -27,19 +26,11 @@ def register(show_spinner=False) -> str:
|
||||
dongle_id = params.get("DongleId", encoding='utf8')
|
||||
needs_registration = None in (IMEI, HardwareSerial, dongle_id)
|
||||
|
||||
# create a key for auth
|
||||
# your private key is kept on your device persist partition and never sent to our servers
|
||||
# do not erase your persist partition
|
||||
if not os.path.isfile(PERSIST+"/comma/id_rsa.pub"):
|
||||
needs_registration = True
|
||||
cloudlog.warning("generating your personal RSA key")
|
||||
mkdirs_exists_ok(PERSIST+"/comma")
|
||||
assert os.system("openssl genrsa -out "+PERSIST+"/comma/id_rsa.tmp 2048") == 0
|
||||
assert os.system("openssl rsa -in "+PERSIST+"/comma/id_rsa.tmp -pubout -out "+PERSIST+"/comma/id_rsa.tmp.pub") == 0
|
||||
os.rename(PERSIST+"/comma/id_rsa.tmp", PERSIST+"/comma/id_rsa")
|
||||
os.rename(PERSIST+"/comma/id_rsa.tmp.pub", PERSIST+"/comma/id_rsa.pub")
|
||||
|
||||
if needs_registration:
|
||||
pubkey = Path(PERSIST+"/comma/id_rsa.pub")
|
||||
if not pubkey.is_file():
|
||||
dongle_id = UNREGISTERED_DONGLE_ID
|
||||
cloudlog.warning(f"missing public key: {pubkey}")
|
||||
elif needs_registration:
|
||||
if show_spinner:
|
||||
spinner = Spinner()
|
||||
spinner.update("registering device")
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
boardd
|
||||
boardd_api_impl.cpp
|
||||
tests/test_boardd_usbprotocol
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
Import('env', 'envCython', 'common', 'cereal', 'messaging')
|
||||
|
||||
env.Program('boardd', ['boardd.cc', 'panda.cc', 'pigeon.cc'], LIBS=['usb-1.0', common, cereal, messaging, 'pthread', 'zmq', 'capnp', 'kj'])
|
||||
libs = ['usb-1.0', common, cereal, messaging, 'pthread', 'zmq', 'capnp', 'kj']
|
||||
env.Program('boardd', ['boardd.cc', 'panda.cc', 'pigeon.cc'], LIBS=libs)
|
||||
env.Library('libcan_list_to_can_capnp', ['can_list_to_can_capnp.cc'])
|
||||
|
||||
envCython.Program('boardd_api_impl.so', 'boardd_api_impl.pyx', LIBS=["can_list_to_can_capnp", 'capnp', 'kj'] + envCython["LIBS"])
|
||||
if GetOption('test'):
|
||||
env.Program('tests/test_boardd_usbprotocol', ['tests/test_boardd_usbprotocol.cc', 'panda.cc'], LIBS=libs)
|
||||
|
||||
+62
-74
@@ -62,7 +62,7 @@ std::atomic<bool> pigeon_active(false);
|
||||
|
||||
ExitHandler do_exit;
|
||||
|
||||
std::string get_time_str(const struct tm &time) {
|
||||
static std::string get_time_str(const struct tm &time) {
|
||||
char s[30] = {'\0'};
|
||||
std::strftime(s, std::size(s), "%Y-%m-%d %H:%M:%S", &time);
|
||||
return s;
|
||||
@@ -70,11 +70,43 @@ std::string get_time_str(const struct tm &time) {
|
||||
|
||||
bool check_all_connected(const std::vector<Panda *> &pandas) {
|
||||
for (const auto& panda : pandas) {
|
||||
if (!panda->connected) return false;
|
||||
if (!panda->connected) {
|
||||
do_exit = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
enum class SyncTimeDir { TO_PANDA, FROM_PANDA };
|
||||
|
||||
void sync_time(Panda *panda, SyncTimeDir dir) {
|
||||
if (!panda->has_rtc) return;
|
||||
|
||||
setenv("TZ", "UTC", 1);
|
||||
struct tm sys_time = util::get_time();
|
||||
struct tm rtc_time = panda->get_rtc();
|
||||
|
||||
if (dir == SyncTimeDir::TO_PANDA) {
|
||||
if (util::time_valid(sys_time)) {
|
||||
// Write time to RTC if it looks reasonable
|
||||
double seconds = difftime(mktime(&rtc_time), mktime(&sys_time));
|
||||
if (std::abs(seconds) > 1.1) {
|
||||
panda->set_rtc(sys_time);
|
||||
LOGW("Updating panda RTC. dt = %.2f System: %s RTC: %s",
|
||||
seconds, get_time_str(sys_time).c_str(), get_time_str(rtc_time).c_str());
|
||||
}
|
||||
}
|
||||
} else if (dir == SyncTimeDir::FROM_PANDA) {
|
||||
if (!util::time_valid(sys_time) && util::time_valid(rtc_time)) {
|
||||
const struct timeval tv = {mktime(&rtc_time), 0};
|
||||
settimeofday(&tv, 0);
|
||||
LOGE("System time wrong, setting from RTC. System: %s RTC: %s",
|
||||
get_time_str(sys_time).c_str(), get_time_str(rtc_time).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool safety_setter_thread(std::vector<Panda *> pandas) {
|
||||
LOGD("Starting safety setter thread");
|
||||
|
||||
@@ -168,40 +200,22 @@ Panda *usb_connect(std::string serial="", uint32_t index=0) {
|
||||
std::call_once(connected_once, &Panda::set_usb_power_mode, panda, cereal::PeripheralState::UsbPowerMode::CDP);
|
||||
#endif
|
||||
|
||||
if (panda->has_rtc) {
|
||||
setenv("TZ","UTC",1);
|
||||
struct tm sys_time = util::get_time();
|
||||
struct tm rtc_time = panda->get_rtc();
|
||||
|
||||
if (!util::time_valid(sys_time) && util::time_valid(rtc_time)) {
|
||||
LOGE("System time wrong, setting from RTC. System: %s RTC: %s",
|
||||
get_time_str(sys_time).c_str(), get_time_str(rtc_time).c_str());
|
||||
const struct timeval tv = {mktime(&rtc_time), 0};
|
||||
settimeofday(&tv, 0);
|
||||
}
|
||||
}
|
||||
|
||||
sync_time(panda.get(), SyncTimeDir::FROM_PANDA);
|
||||
return panda.release();
|
||||
}
|
||||
|
||||
void can_send_thread(std::vector<Panda *> pandas, bool fake_send) {
|
||||
LOGD("start send thread");
|
||||
util::set_thread_name("boardd_can_send");
|
||||
|
||||
AlignedBuffer aligned_buf;
|
||||
Context * context = Context::create();
|
||||
SubSocket * subscriber = SubSocket::create(context, "sendcan");
|
||||
std::unique_ptr<Context> context(Context::create());
|
||||
std::unique_ptr<SubSocket> subscriber(SubSocket::create(context.get(), "sendcan"));
|
||||
assert(subscriber != NULL);
|
||||
subscriber->setTimeout(100);
|
||||
|
||||
// run as fast as messages come in
|
||||
while (!do_exit) {
|
||||
if (!check_all_connected(pandas)) {
|
||||
do_exit = true;
|
||||
break;
|
||||
}
|
||||
|
||||
Message * msg = subscriber->receive();
|
||||
|
||||
while (!do_exit && check_all_connected(pandas)) {
|
||||
std::unique_ptr<Message> msg(subscriber->receive());
|
||||
if (!msg) {
|
||||
if (errno == EINTR) {
|
||||
do_exit = true;
|
||||
@@ -209,27 +223,20 @@ void can_send_thread(std::vector<Panda *> pandas, bool fake_send) {
|
||||
continue;
|
||||
}
|
||||
|
||||
capnp::FlatArrayMessageReader cmsg(aligned_buf.align(msg));
|
||||
capnp::FlatArrayMessageReader cmsg(aligned_buf.align(msg.get()));
|
||||
cereal::Event::Reader event = cmsg.getRoot<cereal::Event>();
|
||||
|
||||
//Dont send if older than 1 second
|
||||
if (nanos_since_boot() - event.getLogMonoTime() < 1e9) {
|
||||
if (!fake_send) {
|
||||
for (const auto& panda : pandas) {
|
||||
panda->can_send(event.getSendcan());
|
||||
}
|
||||
if ((nanos_since_boot() - event.getLogMonoTime() < 1e9) && !fake_send) {
|
||||
for (const auto& panda : pandas) {
|
||||
panda->can_send(event.getSendcan());
|
||||
}
|
||||
}
|
||||
|
||||
delete msg;
|
||||
}
|
||||
|
||||
delete subscriber;
|
||||
delete context;
|
||||
}
|
||||
|
||||
void can_recv_thread(std::vector<Panda *> pandas) {
|
||||
LOGD("start recv thread");
|
||||
util::set_thread_name("boardd_can_recv");
|
||||
|
||||
// can = 8006
|
||||
PubMaster pm({"can"});
|
||||
@@ -239,12 +246,7 @@ void can_recv_thread(std::vector<Panda *> pandas) {
|
||||
uint64_t next_frame_time = nanos_since_boot() + dt;
|
||||
std::vector<can_frame> raw_can_data;
|
||||
|
||||
while (!do_exit) {
|
||||
if (!check_all_connected(pandas)){
|
||||
do_exit = true;
|
||||
break;
|
||||
}
|
||||
|
||||
while (!do_exit && check_all_connected(pandas)) {
|
||||
bool comms_healthy = true;
|
||||
raw_can_data.clear();
|
||||
for (const auto& panda : pandas) {
|
||||
@@ -315,7 +317,7 @@ bool send_panda_states(PubMaster *pm, const std::vector<Panda *> &pandas, bool s
|
||||
|
||||
for (uint32_t i=0; i<pandas.size(); i++) {
|
||||
auto panda = pandas[i];
|
||||
auto pandaState = pandaStates[i];
|
||||
const auto &pandaState = pandaStates[i];
|
||||
|
||||
// Make sure CAN buses are live: safety_setter_thread does not work if Panda CAN are silent and there is only one other CAN node
|
||||
if (pandaState.safety_model == (uint8_t)(cereal::CarParams::SafetyModel::SILENT)) {
|
||||
@@ -334,7 +336,6 @@ bool send_panda_states(PubMaster *pm, const std::vector<Panda *> &pandas, bool s
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO: do we still need this?
|
||||
if (!panda->comms_healthy) {
|
||||
evt.setValid(false);
|
||||
}
|
||||
@@ -407,6 +408,8 @@ void send_peripheral_state(PubMaster *pm, Panda *panda) {
|
||||
}
|
||||
|
||||
void panda_state_thread(PubMaster *pm, std::vector<Panda *> pandas, bool spoofing_started) {
|
||||
util::set_thread_name("boardd_panda_state");
|
||||
|
||||
Params params;
|
||||
Panda *peripheral_panda = pandas[0];
|
||||
bool ignition_last = false;
|
||||
@@ -415,15 +418,12 @@ void panda_state_thread(PubMaster *pm, std::vector<Panda *> pandas, bool spoofin
|
||||
LOGD("start panda state thread");
|
||||
|
||||
// run at 2hz
|
||||
while (!do_exit) {
|
||||
if(!check_all_connected(pandas)) {
|
||||
do_exit = true;
|
||||
break;
|
||||
}
|
||||
|
||||
while (!do_exit && check_all_connected(pandas)) {
|
||||
// send out peripheralState
|
||||
send_peripheral_state(pm, peripheral_panda);
|
||||
ignition = send_panda_states(pm, pandas, spoofing_started);
|
||||
|
||||
// TODO: make this check fast, currently takes 16ms
|
||||
// check if we have new pandas and are offroad
|
||||
if (!ignition && (pandas.size() != Panda::list().size())) {
|
||||
LOGW("Reconnecting to changed amount of pandas!");
|
||||
@@ -431,7 +431,7 @@ void panda_state_thread(PubMaster *pm, std::vector<Panda *> pandas, bool spoofin
|
||||
break;
|
||||
}
|
||||
|
||||
// clear VIN, CarParams, and set new safety on car start
|
||||
// clear ignition-based params and set new safety on car start
|
||||
if (ignition && !ignition_last) {
|
||||
params.clearAll(CLEAR_ON_IGNITION_ON);
|
||||
if (!safety_future.valid() || safety_future.wait_for(0ms) == std::future_status::ready) {
|
||||
@@ -454,7 +454,8 @@ void panda_state_thread(PubMaster *pm, std::vector<Panda *> pandas, bool spoofin
|
||||
|
||||
|
||||
void peripheral_control_thread(Panda *panda) {
|
||||
LOGD("start peripheral control thread");
|
||||
util::set_thread_name("boardd_peripheral_control");
|
||||
|
||||
SubMaster sm({"deviceState", "driverCameraState"});
|
||||
|
||||
uint64_t last_front_frame_t = 0;
|
||||
@@ -525,21 +526,8 @@ void peripheral_control_thread(Panda *panda) {
|
||||
}
|
||||
|
||||
// Write to rtc once per minute when no ignition present
|
||||
if ((panda->has_rtc) && !ignition && (cnt % 120 == 1)) {
|
||||
// Write time to RTC if it looks reasonable
|
||||
setenv("TZ","UTC",1);
|
||||
struct tm sys_time = util::get_time();
|
||||
|
||||
if (util::time_valid(sys_time)) {
|
||||
struct tm rtc_time = panda->get_rtc();
|
||||
double seconds = difftime(mktime(&rtc_time), mktime(&sys_time));
|
||||
|
||||
if (std::abs(seconds) > 1.1) {
|
||||
panda->set_rtc(sys_time);
|
||||
LOGW("Updating panda RTC. dt = %.2f System: %s RTC: %s",
|
||||
seconds, get_time_str(sys_time).c_str(), get_time_str(rtc_time).c_str());
|
||||
}
|
||||
}
|
||||
if (!ignition && (cnt % 120 == 1)) {
|
||||
sync_time(panda, SyncTimeDir::TO_PANDA);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -552,10 +540,12 @@ static void pigeon_publish_raw(PubMaster &pm, const std::string &dat) {
|
||||
}
|
||||
|
||||
void pigeon_thread(Panda *panda) {
|
||||
util::set_thread_name("boardd_pigeon");
|
||||
|
||||
PubMaster pm({"ubloxRaw"});
|
||||
bool ignition_last = false;
|
||||
|
||||
Pigeon *pigeon = Hardware::TICI() ? Pigeon::connect("/dev/ttyHS0") : Pigeon::connect(panda);
|
||||
std::unique_ptr<Pigeon> pigeon(Hardware::TICI() ? Pigeon::connect("/dev/ttyHS0") : Pigeon::connect(panda));
|
||||
|
||||
std::unordered_map<char, uint64_t> last_recv_time;
|
||||
std::unordered_map<char, int64_t> cls_max_dt = {
|
||||
@@ -623,8 +613,6 @@ void pigeon_thread(Panda *panda) {
|
||||
// 10ms - 100 Hz
|
||||
util::sleep_for(10);
|
||||
}
|
||||
|
||||
delete pigeon;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
@@ -632,9 +620,9 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
if (!Hardware::PC()) {
|
||||
int err;
|
||||
err = set_realtime_priority(54);
|
||||
err = util::set_realtime_priority(54);
|
||||
assert(err == 0);
|
||||
err = set_core_affinity({Hardware::TICI() ? 4 : 3});
|
||||
err = util::set_core_affinity({Hardware::TICI() ? 4 : 3});
|
||||
assert(err == 0);
|
||||
}
|
||||
|
||||
|
||||
+78
-94
@@ -352,7 +352,7 @@ void Panda::set_data_speed_kbps(uint16_t bus, uint16_t speed) {
|
||||
usb_write(0xf9, bus, (speed * 10));
|
||||
}
|
||||
|
||||
uint8_t Panda::len_to_dlc(uint8_t len) {
|
||||
static uint8_t len_to_dlc(uint8_t len) {
|
||||
if (len <= 8) {
|
||||
return len;
|
||||
}
|
||||
@@ -363,114 +363,98 @@ uint8_t Panda::len_to_dlc(uint8_t len) {
|
||||
}
|
||||
}
|
||||
|
||||
static void write_packet(uint8_t *dest, int *write_pos, const uint8_t *src, size_t size) {
|
||||
for (int i = 0, &pos = *write_pos; i < size; ++i, ++pos) {
|
||||
// Insert counter every 64 bytes (first byte of 64 bytes USB packet)
|
||||
if (pos % USBPACKET_MAX_SIZE == 0) {
|
||||
dest[pos] = pos / USBPACKET_MAX_SIZE;
|
||||
pos++;
|
||||
}
|
||||
dest[pos] = src[i];
|
||||
}
|
||||
}
|
||||
|
||||
void Panda::pack_can_buffer(const capnp::List<cereal::CanData>::Reader &can_data_list,
|
||||
std::function<void(uint8_t *, size_t)> write_func) {
|
||||
int32_t pos = 0;
|
||||
uint8_t send_buf[2 * USB_TX_SOFT_LIMIT];
|
||||
|
||||
for (auto cmsg : can_data_list) {
|
||||
// check if the message is intended for this panda
|
||||
uint8_t bus = cmsg.getSrc();
|
||||
if (bus < bus_offset || bus >= (bus_offset + PANDA_BUS_CNT)) {
|
||||
continue;
|
||||
}
|
||||
auto can_data = cmsg.getDat();
|
||||
uint8_t data_len_code = len_to_dlc(can_data.size());
|
||||
assert(can_data.size() <= ((hw_type == cereal::PandaState::PandaType::RED_PANDA) ? 64 : 8));
|
||||
assert(can_data.size() == dlc_to_len[data_len_code]);
|
||||
|
||||
can_header header;
|
||||
header.addr = cmsg.getAddress();
|
||||
header.extended = (cmsg.getAddress() >= 0x800) ? 1 : 0;
|
||||
header.data_len_code = data_len_code;
|
||||
header.bus = bus - bus_offset;
|
||||
|
||||
write_packet(send_buf, &pos, (uint8_t *)&header, sizeof(can_header));
|
||||
write_packet(send_buf, &pos, (uint8_t *)can_data.begin(), can_data.size());
|
||||
if (pos >= USB_TX_SOFT_LIMIT) {
|
||||
write_func(send_buf, pos);
|
||||
pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// send remaining packets
|
||||
if (pos > 0) write_func(send_buf, pos);
|
||||
}
|
||||
|
||||
void Panda::can_send(capnp::List<cereal::CanData>::Reader can_data_list) {
|
||||
if (send.size() < (can_data_list.size() * CANPACKET_MAX_SIZE)) {
|
||||
send.resize(can_data_list.size() * CANPACKET_MAX_SIZE);
|
||||
}
|
||||
|
||||
int msg_count = 0;
|
||||
while (msg_count < can_data_list.size()) {
|
||||
uint32_t pos = 0;
|
||||
while (pos < USB_TX_SOFT_LIMIT) {
|
||||
if (msg_count == can_data_list.size()) { break; }
|
||||
auto cmsg = can_data_list[msg_count];
|
||||
|
||||
// check if the message is intended for this panda
|
||||
uint8_t bus = cmsg.getSrc();
|
||||
if (bus < bus_offset || bus >= (bus_offset + PANDA_BUS_CNT)) {
|
||||
msg_count++;
|
||||
continue;
|
||||
}
|
||||
auto can_data = cmsg.getDat();
|
||||
uint8_t data_len_code = len_to_dlc(can_data.size());
|
||||
assert(can_data.size() <= (hw_type == cereal::PandaState::PandaType::RED_PANDA) ? 64 : 8);
|
||||
assert(can_data.size() == dlc_to_len[data_len_code]);
|
||||
|
||||
can_header header;
|
||||
header.addr = cmsg.getAddress();
|
||||
header.extended = (cmsg.getAddress() >= 0x800) ? 1 : 0;
|
||||
header.data_len_code = data_len_code;
|
||||
header.bus = bus - bus_offset;
|
||||
memcpy(&send[pos], &header, CANPACKET_HEAD_SIZE);
|
||||
memcpy(&send[pos+CANPACKET_HEAD_SIZE], can_data.begin(), can_data.size());
|
||||
|
||||
pos += CANPACKET_HEAD_SIZE + dlc_to_len[data_len_code];
|
||||
msg_count++;
|
||||
}
|
||||
|
||||
if (pos > 0) { // Helps not to spam with ZLP
|
||||
// Counter needs to be inserted every 64 bytes (first byte of 64 bytes USB packet)
|
||||
uint8_t counter = 0;
|
||||
uint8_t to_write[USB_TX_SOFT_LIMIT+128];
|
||||
int ptr = 0;
|
||||
for (int i = 0; i < pos; i += 63) {
|
||||
to_write[ptr] = counter;
|
||||
int copy_size = ((pos - i) < 63) ? (pos - i) : 63;
|
||||
memcpy(&to_write[ptr+1], &(send.data()[i]) , copy_size);
|
||||
ptr += copy_size + 1;
|
||||
counter++;
|
||||
}
|
||||
usb_bulk_write(3, to_write, ptr, 5);
|
||||
}
|
||||
}
|
||||
pack_can_buffer(can_data_list, [=](uint8_t* data, size_t size) {
|
||||
usb_bulk_write(3, data, size, 5);
|
||||
});
|
||||
}
|
||||
|
||||
bool Panda::can_receive(std::vector<can_frame>& out_vec) {
|
||||
uint8_t data[RECV_SIZE];
|
||||
int recv = usb_bulk_read(0x81, (uint8_t*)data, RECV_SIZE);
|
||||
|
||||
// Not sure if this can happen
|
||||
if (recv < 0) recv = 0;
|
||||
|
||||
if (recv == RECV_SIZE) {
|
||||
LOGW("Receive buffer full");
|
||||
}
|
||||
|
||||
if (!comms_healthy) {
|
||||
return false;
|
||||
}
|
||||
if (recv == RECV_SIZE) {
|
||||
LOGW("Panda receive buffer full");
|
||||
}
|
||||
|
||||
static uint8_t tail[CANPACKET_MAX_SIZE];
|
||||
uint8_t tail_size = 0;
|
||||
uint8_t counter = 0;
|
||||
for (int i = 0; i < recv; i += USBPACKET_MAX_SIZE) {
|
||||
// Check for counter every 64 bytes (length of USB packet)
|
||||
if (counter != data[i]) {
|
||||
return (recv <= 0) ? true : unpack_can_buffer(data, recv, out_vec);
|
||||
}
|
||||
|
||||
bool Panda::unpack_can_buffer(uint8_t *data, int size, std::vector<can_frame> &out_vec) {
|
||||
recv_buf.clear();
|
||||
for (int i = 0; i < size; i += USBPACKET_MAX_SIZE) {
|
||||
if (data[i] != i / USBPACKET_MAX_SIZE) {
|
||||
LOGE("CAN: MALFORMED USB RECV PACKET");
|
||||
break;
|
||||
comms_healthy = false;
|
||||
return false;
|
||||
}
|
||||
counter++;
|
||||
uint8_t chunk_len = ((recv - i) > USBPACKET_MAX_SIZE) ? 63 : (recv - i - 1); // as 1 is always reserved for counter
|
||||
uint8_t chunk[USBPACKET_MAX_SIZE + CANPACKET_MAX_SIZE];
|
||||
memcpy(chunk, tail, tail_size);
|
||||
memcpy(&chunk[tail_size], &data[i+1], chunk_len);
|
||||
chunk_len += tail_size;
|
||||
tail_size = 0;
|
||||
uint8_t pos = 0;
|
||||
while (pos < chunk_len) {
|
||||
uint8_t data_len = dlc_to_len[(chunk[pos] >> 4)];
|
||||
uint8_t pckt_len = CANPACKET_HEAD_SIZE + data_len;
|
||||
if (pckt_len <= (chunk_len - pos)) {
|
||||
can_header header;
|
||||
memcpy(&header, &chunk[pos], CANPACKET_HEAD_SIZE);
|
||||
int chunk_len = std::min(USBPACKET_MAX_SIZE, (size - i));
|
||||
recv_buf.insert(recv_buf.end(), &data[i + 1], &data[i + chunk_len]);
|
||||
}
|
||||
|
||||
can_frame &canData = out_vec.emplace_back();
|
||||
canData.busTime = 0;
|
||||
canData.address = header.addr;
|
||||
canData.src = header.bus + bus_offset;
|
||||
int pos = 0;
|
||||
while (pos < recv_buf.size()) {
|
||||
can_header header;
|
||||
memcpy(&header, &recv_buf[pos], CANPACKET_HEAD_SIZE);
|
||||
|
||||
if (header.rejected) { canData.src += CANPACKET_REJECTED; }
|
||||
if (header.returned) { canData.src += CANPACKET_RETURNED; }
|
||||
canData.dat.assign((char*)&chunk[pos+CANPACKET_HEAD_SIZE], data_len);
|
||||
can_frame &canData = out_vec.emplace_back();
|
||||
canData.busTime = 0;
|
||||
canData.address = header.addr;
|
||||
canData.src = header.bus + bus_offset;
|
||||
if (header.rejected) { canData.src += CANPACKET_REJECTED; }
|
||||
if (header.returned) { canData.src += CANPACKET_RETURNED; }
|
||||
|
||||
pos += pckt_len;
|
||||
} else {
|
||||
// Keep partial CAN packet until next USB packet
|
||||
tail_size = (chunk_len - pos);
|
||||
memcpy(tail, &chunk[pos], tail_size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
const uint8_t data_len = dlc_to_len[header.data_len_code];
|
||||
canData.dat.assign((char *)&recv_buf[pos + CANPACKET_HEAD_SIZE], data_len);
|
||||
|
||||
pos += CANPACKET_HEAD_SIZE + data_len;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <ctime>
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
@@ -17,7 +18,7 @@
|
||||
#define PANDA_BUS_CNT 4
|
||||
#define RECV_SIZE (0x4000U)
|
||||
#define USB_TX_SOFT_LIMIT (0x100U)
|
||||
#define USBPACKET_MAX_SIZE (0x40U)
|
||||
#define USBPACKET_MAX_SIZE (0x40)
|
||||
#define CANPACKET_HEAD_SIZE 5U
|
||||
#define CANPACKET_MAX_SIZE 72U
|
||||
#define CANPACKET_REJECTED (0xC0U)
|
||||
@@ -68,7 +69,7 @@ class Panda {
|
||||
libusb_context *ctx = NULL;
|
||||
libusb_device_handle *dev_handle = NULL;
|
||||
std::mutex usb_lock;
|
||||
std::vector<uint8_t> send;
|
||||
std::vector<uint8_t> recv_buf;
|
||||
void handle_usb_issue(int err, const char func[]);
|
||||
void cleanup();
|
||||
|
||||
@@ -110,7 +111,13 @@ class Panda {
|
||||
void send_heartbeat();
|
||||
void set_can_speed_kbps(uint16_t bus, uint16_t speed);
|
||||
void set_data_speed_kbps(uint16_t bus, uint16_t speed);
|
||||
uint8_t len_to_dlc(uint8_t len);
|
||||
void can_send(capnp::List<cereal::CanData>::Reader can_data_list);
|
||||
bool can_receive(std::vector<can_frame>& out_vec);
|
||||
|
||||
protected:
|
||||
// for unit tests
|
||||
Panda(uint32_t bus_offset) : bus_offset(bus_offset) {}
|
||||
void pack_can_buffer(const capnp::List<cereal::CanData>::Reader &can_data_list,
|
||||
std::function<void(uint8_t *, size_t)> write_func);
|
||||
bool unpack_can_buffer(uint8_t *data, int size, std::vector<can_frame> &out_vec);
|
||||
};
|
||||
|
||||
@@ -24,8 +24,8 @@ extern ExitHandler do_exit;
|
||||
|
||||
const std::string ack = "\xb5\x62\x05\x01\x02\x00";
|
||||
const std::string nack = "\xb5\x62\x05\x00\x02\x00";
|
||||
const std::string sos_ack = "\xb5\x62\x09\x14\x08\x00\x02\x00\x00\x00\x01\x00\x00\x00";
|
||||
const std::string sos_nack = "\xb5\x62\x09\x14\x08\x00\x02\x00\x00\x00\x00\x00\x00\x00";
|
||||
const std::string sos_save_ack = "\xb5\x62\x09\x14\x08\x00\x02\x00\x00\x00\x01\x00\x00\x00";
|
||||
const std::string sos_save_nack = "\xb5\x62\x09\x14\x08\x00\x02\x00\x00\x00\x00\x00\x00\x00";
|
||||
|
||||
Pigeon * Pigeon::connect(Panda * p) {
|
||||
PandaPigeon * pigeon = new PandaPigeon();
|
||||
@@ -72,6 +72,25 @@ bool Pigeon::send_with_ack(const std::string &cmd) {
|
||||
return wait_for_ack();
|
||||
}
|
||||
|
||||
sos_restore_response Pigeon::wait_for_backup_restore_status(int timeout_ms) {
|
||||
std::string s;
|
||||
const double start_t = millis_since_boot();
|
||||
while (!do_exit) {
|
||||
s += receive();
|
||||
|
||||
size_t position = s.find("\xb5\x62\x09\x14\x08\x00\x03");
|
||||
if (position != std::string::npos && s.size() >= (position + 11)) {
|
||||
return static_cast<sos_restore_response>(s[position + 10]);
|
||||
} else if (s.size() > 0x1000 || ((millis_since_boot() - start_t) > timeout_ms)) {
|
||||
LOGE("No backup restore response from ublox");
|
||||
return error;
|
||||
}
|
||||
|
||||
util::sleep_for(1); // Allow other threads to be scheduled
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
void Pigeon::init() {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if (do_exit) return;
|
||||
@@ -118,6 +137,22 @@ void Pigeon::init() {
|
||||
if (!send_with_ack("\xB5\x62\x06\x01\x03\x00\x0A\x09\x01\x1E\x70"s)) continue;
|
||||
if (!send_with_ack("\xB5\x62\x06\x01\x03\x00\x0A\x0B\x01\x20\x74"s)) continue;
|
||||
|
||||
// check the backup restore status
|
||||
send("\xB5\x62\x09\x14\x00\x00\x1D\x60"s);
|
||||
sos_restore_response restore_status = wait_for_backup_restore_status();
|
||||
switch(restore_status) {
|
||||
case restored:
|
||||
LOGW("almanac backup restored");
|
||||
// clear the backup
|
||||
send_with_ack("\xB5\x62\x06\x01\x03\x00\x0A\x0B\x01\x20\x74"s);
|
||||
break;
|
||||
case no_backup:
|
||||
LOGW("no almanac backup found");
|
||||
break;
|
||||
default:
|
||||
LOGE("failed to restore almanac backup, status: %d", restore_status);
|
||||
}
|
||||
|
||||
auto time = util::get_time();
|
||||
if (util::time_valid(time)) {
|
||||
LOGW("Sending current time to ublox");
|
||||
@@ -139,7 +174,7 @@ void Pigeon::stop() {
|
||||
// Store almanac in flash
|
||||
send("\xB5\x62\x09\x14\x04\x00\x00\x00\x00\x00\x21\xEC"s);
|
||||
|
||||
if (wait_for_ack(sos_ack, sos_nack)) {
|
||||
if (wait_for_ack(sos_save_ack, sos_save_nack)) {
|
||||
LOGW("Done storing almanac");
|
||||
} else {
|
||||
LOGE("Error storing almanac");
|
||||
|
||||
@@ -7,6 +7,14 @@
|
||||
|
||||
#include "selfdrive/boardd/panda.h"
|
||||
|
||||
enum sos_restore_response : int {
|
||||
unknown = 0,
|
||||
failed = 1,
|
||||
restored = 2,
|
||||
no_backup = 3,
|
||||
error = -1
|
||||
};
|
||||
|
||||
class Pigeon {
|
||||
public:
|
||||
static Pigeon* connect(Panda * p);
|
||||
@@ -18,6 +26,7 @@ class Pigeon {
|
||||
bool wait_for_ack();
|
||||
bool wait_for_ack(const std::string &ack, const std::string &nack, int timeout_ms = 1000);
|
||||
bool send_with_ack(const std::string &cmd);
|
||||
sos_restore_response wait_for_backup_restore_status(int timeout_ms = 1000);
|
||||
virtual void set_baud(int baud) = 0;
|
||||
virtual void send(const std::string &s) = 0;
|
||||
virtual std::string receive() = 0;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Import('env', 'arch', 'cereal', 'messaging', 'common', 'gpucommon', 'visionipc', 'USE_WEBCAM', 'USE_FRAME_STREAM')
|
||||
Import('env', 'arch', 'cereal', 'messaging', 'common', 'gpucommon', 'visionipc', 'USE_WEBCAM')
|
||||
|
||||
libs = ['m', 'pthread', common, 'jpeg', 'OpenCL', 'yuv', cereal, messaging, 'zmq', 'capnp', 'kj', visionipc, gpucommon]
|
||||
|
||||
@@ -18,15 +18,12 @@ else:
|
||||
env.Append(CFLAGS = '-DWEBCAM')
|
||||
env.Append(CPPPATH = ['/usr/include/opencv4', '/usr/local/include/opencv4'])
|
||||
else:
|
||||
if USE_FRAME_STREAM:
|
||||
cameras = ['cameras/camera_frame_stream.cc']
|
||||
else:
|
||||
libs += ['avutil', 'avcodec', 'avformat', 'swscale', 'bz2', 'ssl', 'curl', 'crypto']
|
||||
# TODO: import replay_lib from root SConstruct
|
||||
cameras = ['cameras/camera_replay.cc',
|
||||
env.Object('camera-util', '#/selfdrive/ui/replay/util.cc'),
|
||||
env.Object('camera-framereader', '#/selfdrive/ui/replay/framereader.cc'),
|
||||
env.Object('camera-filereader', '#/selfdrive/ui/replay/filereader.cc')]
|
||||
libs += ['avutil', 'avcodec', 'avformat', 'bz2', 'ssl', 'curl', 'crypto']
|
||||
# TODO: import replay_lib from root SConstruct
|
||||
cameras = ['cameras/camera_replay.cc',
|
||||
env.Object('camera-util', '#/selfdrive/ui/replay/util.cc'),
|
||||
env.Object('camera-framereader', '#/selfdrive/ui/replay/framereader.cc'),
|
||||
env.Object('camera-filereader', '#/selfdrive/ui/replay/filereader.cc')]
|
||||
|
||||
if arch == "Darwin":
|
||||
del libs[libs.index('OpenCL')]
|
||||
|
||||
@@ -28,8 +28,6 @@
|
||||
#include "selfdrive/camerad/cameras/camera_replay.h"
|
||||
#endif
|
||||
|
||||
const int YUV_COUNT = 100;
|
||||
|
||||
class Debayer {
|
||||
public:
|
||||
Debayer(cl_device_id device_id, cl_context context, const CameraBuf *b, const CameraState *s) {
|
||||
@@ -109,7 +107,7 @@ void CameraBuf::init(cl_device_id device_id, cl_context context, CameraState *s,
|
||||
vipc_server->create_buffers(rgb_type, UI_BUF_COUNT, true, rgb_width, rgb_height);
|
||||
rgb_stride = vipc_server->get_buffer(rgb_type)->stride;
|
||||
|
||||
vipc_server->create_buffers(yuv_type, YUV_COUNT, false, rgb_width, rgb_height);
|
||||
vipc_server->create_buffers(yuv_type, YUV_BUFFER_COUNT, false, rgb_width, rgb_height);
|
||||
|
||||
if (ci->bayer) {
|
||||
debayer = new Debayer(device_id, context, this, s);
|
||||
@@ -353,7 +351,7 @@ void *processing_thread(MultiCameraState *cameras, CameraState *cs, process_thre
|
||||
} else {
|
||||
thread_name = "WideRoadCamera";
|
||||
}
|
||||
set_thread_name(thread_name);
|
||||
util::set_thread_name(thread_name);
|
||||
|
||||
uint32_t cnt = 0;
|
||||
while (!do_exit) {
|
||||
@@ -410,11 +408,11 @@ static void driver_cam_auto_exposure(CameraState *c, SubMaster &sm) {
|
||||
camera_autoexposure(c, set_exposure_target(b, rect.x1, rect.x2, rect.x_skip, rect.y1, rect.y2, rect.y_skip));
|
||||
}
|
||||
|
||||
void common_process_driver_camera(SubMaster *sm, PubMaster *pm, CameraState *c, int cnt) {
|
||||
void common_process_driver_camera(MultiCameraState *s, CameraState *c, int cnt) {
|
||||
int j = Hardware::TICI() ? 1 : 3;
|
||||
if (cnt % j == 0) {
|
||||
sm->update(0);
|
||||
driver_cam_auto_exposure(c, *sm);
|
||||
s->sm->update(0);
|
||||
driver_cam_auto_exposure(c, *(s->sm));
|
||||
}
|
||||
MessageBuilder msg;
|
||||
auto framed = msg.initEvent().initDriverCameraState();
|
||||
@@ -423,5 +421,5 @@ void common_process_driver_camera(SubMaster *sm, PubMaster *pm, CameraState *c,
|
||||
if (env_send_driver) {
|
||||
framed.setImage(get_frame_image(&c->buf));
|
||||
}
|
||||
pm->send("driverCameraState", msg);
|
||||
s->pm->send("driverCameraState", msg);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "selfdrive/common/queue.h"
|
||||
#include "selfdrive/common/swaglog.h"
|
||||
#include "selfdrive/common/visionimg.h"
|
||||
#include "selfdrive/hardware/hw.h"
|
||||
|
||||
#define CAMERA_ID_IMX298 0
|
||||
#define CAMERA_ID_IMX179 1
|
||||
@@ -26,7 +27,8 @@
|
||||
#define CAMERA_ID_AR0231 8
|
||||
#define CAMERA_ID_MAX 9
|
||||
|
||||
#define UI_BUF_COUNT 4
|
||||
const int UI_BUF_COUNT = 4;
|
||||
const int YUV_BUFFER_COUNT = Hardware::EON() ? 100 : 40;
|
||||
|
||||
enum CameraType {
|
||||
RoadCam = 0,
|
||||
@@ -49,23 +51,6 @@ typedef struct CameraInfo {
|
||||
bool hdr;
|
||||
} CameraInfo;
|
||||
|
||||
typedef struct LogCameraInfo {
|
||||
CameraType type;
|
||||
const char* filename;
|
||||
const char* frame_packet_name;
|
||||
const char* encode_idx_name;
|
||||
VisionStreamType stream_type;
|
||||
int frame_width, frame_height;
|
||||
int fps;
|
||||
int bitrate;
|
||||
bool is_h265;
|
||||
bool downscale;
|
||||
bool has_qcamera;
|
||||
bool trigger_rotate;
|
||||
bool enable;
|
||||
bool record;
|
||||
} LogCameraInfo;
|
||||
|
||||
typedef struct FrameMetadata {
|
||||
uint32_t frame_id;
|
||||
unsigned int frame_length;
|
||||
@@ -138,7 +123,7 @@ void fill_frame_data(cereal::FrameData::Builder &framed, const FrameMetadata &fr
|
||||
kj::Array<uint8_t> get_frame_image(const CameraBuf *b);
|
||||
float set_exposure_target(const CameraBuf *b, int x_start, int x_end, int x_skip, int y_start, int y_end, int y_skip);
|
||||
std::thread start_process_thread(MultiCameraState *cameras, CameraState *cs, process_thread_cb callback);
|
||||
void common_process_driver_camera(SubMaster *sm, PubMaster *pm, CameraState *c, int cnt);
|
||||
void common_process_driver_camera(MultiCameraState *s, CameraState *c, int cnt);
|
||||
|
||||
void cameras_init(VisionIpcServer *v, MultiCameraState *s, cl_device_id device_id, cl_context ctx);
|
||||
void cameras_open(MultiCameraState *s);
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
#include "selfdrive/camerad/cameras/camera_frame_stream.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <cassert>
|
||||
|
||||
#include <capnp/dynamic.h>
|
||||
|
||||
#include "cereal/messaging/messaging.h"
|
||||
#include "selfdrive/common/util.h"
|
||||
|
||||
#define FRAME_WIDTH 1164
|
||||
#define FRAME_HEIGHT 874
|
||||
|
||||
extern ExitHandler do_exit;
|
||||
|
||||
namespace {
|
||||
|
||||
// TODO: make this more generic
|
||||
CameraInfo cameras_supported[CAMERA_ID_MAX] = {
|
||||
[CAMERA_ID_IMX298] = {
|
||||
.frame_width = FRAME_WIDTH,
|
||||
.frame_height = FRAME_HEIGHT,
|
||||
.frame_stride = FRAME_WIDTH*3,
|
||||
.bayer = false,
|
||||
.bayer_flip = false,
|
||||
},
|
||||
[CAMERA_ID_OV8865] = {
|
||||
.frame_width = 1632,
|
||||
.frame_height = 1224,
|
||||
.frame_stride = 2040, // seems right
|
||||
.bayer = false,
|
||||
.bayer_flip = 3,
|
||||
.hdr = false
|
||||
},
|
||||
};
|
||||
|
||||
void camera_init(VisionIpcServer * v, CameraState *s, int camera_id, unsigned int fps, cl_device_id device_id, cl_context ctx, VisionStreamType rgb_type, VisionStreamType yuv_type) {
|
||||
assert(camera_id < std::size(cameras_supported));
|
||||
s->ci = cameras_supported[camera_id];
|
||||
assert(s->ci.frame_width != 0);
|
||||
|
||||
s->camera_num = camera_id;
|
||||
s->fps = fps;
|
||||
s->buf.init(device_id, ctx, s, v, FRAME_BUF_COUNT, rgb_type, yuv_type);
|
||||
}
|
||||
|
||||
void run_frame_stream(CameraState &camera, const char* frame_pkt) {
|
||||
SubMaster sm({frame_pkt});
|
||||
|
||||
size_t buf_idx = 0;
|
||||
while (!do_exit) {
|
||||
sm.update(1000);
|
||||
if(sm.updated(frame_pkt)) {
|
||||
auto msg = static_cast<capnp::DynamicStruct::Reader>(sm[frame_pkt]);
|
||||
auto frame = msg.get(frame_pkt).as<capnp::DynamicStruct>();
|
||||
camera.buf.camera_bufs_metadata[buf_idx] = {
|
||||
.frame_id = frame.get("frameId").as<uint32_t>(),
|
||||
.timestamp_eof = frame.get("timestampEof").as<uint64_t>(),
|
||||
.timestamp_sof = frame.get("timestampSof").as<uint64_t>(),
|
||||
};
|
||||
|
||||
cl_command_queue q = camera.buf.camera_bufs[buf_idx].copy_q;
|
||||
cl_mem yuv_cl = camera.buf.camera_bufs[buf_idx].buf_cl;
|
||||
|
||||
auto image = frame.get("image").as<capnp::Data>();
|
||||
clEnqueueWriteBuffer(q, yuv_cl, CL_TRUE, 0, image.size(), image.begin(), 0, NULL, NULL);
|
||||
camera.buf.queue(buf_idx);
|
||||
buf_idx = (buf_idx + 1) % FRAME_BUF_COUNT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void cameras_init(VisionIpcServer *v, MultiCameraState *s, cl_device_id device_id, cl_context ctx) {
|
||||
camera_init(v, &s->road_cam, CAMERA_ID_IMX298, 20, device_id, ctx,
|
||||
VISION_STREAM_RGB_BACK, VISION_STREAM_YUV_BACK);
|
||||
camera_init(v, &s->driver_cam, CAMERA_ID_OV8865, 10, device_id, ctx,
|
||||
VISION_STREAM_RGB_FRONT, VISION_STREAM_YUV_FRONT);
|
||||
}
|
||||
|
||||
void cameras_open(MultiCameraState *s) {}
|
||||
void cameras_close(MultiCameraState *s) {}
|
||||
void camera_autoexposure(CameraState *s, float grey_frac) {}
|
||||
void process_road_camera(MultiCameraState *s, CameraState *c, int cnt) {}
|
||||
|
||||
void cameras_run(MultiCameraState *s) {
|
||||
std::thread t = start_process_thread(s, &s->road_cam, process_road_camera);
|
||||
set_thread_name("frame_streaming");
|
||||
run_frame_stream(s->road_cam, "roadCameraState");
|
||||
t.join();
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#define CL_USE_DEPRECATED_OPENCL_1_2_APIS
|
||||
#ifdef __APPLE__
|
||||
#include <OpenCL/cl.h>
|
||||
#else
|
||||
#include <CL/cl.h>
|
||||
#endif
|
||||
|
||||
#include "camera_common.h"
|
||||
|
||||
#define FRAME_BUF_COUNT 16
|
||||
|
||||
typedef struct CameraState {
|
||||
int camera_num;
|
||||
CameraInfo ci;
|
||||
|
||||
int fps;
|
||||
float digital_gain;
|
||||
|
||||
CameraBuf buf;
|
||||
} CameraState;
|
||||
|
||||
typedef struct MultiCameraState {
|
||||
CameraState road_cam;
|
||||
CameraState driver_cam;
|
||||
|
||||
SubMaster *sm;
|
||||
PubMaster *pm;
|
||||
} MultiCameraState;
|
||||
@@ -211,12 +211,12 @@ void cameras_init(VisionIpcServer *v, MultiCameraState *s, cl_device_id device_i
|
||||
/*fps*/ 20,
|
||||
#endif
|
||||
device_id, ctx,
|
||||
VISION_STREAM_RGB_BACK, VISION_STREAM_YUV_BACK);
|
||||
VISION_STREAM_RGB_BACK, VISION_STREAM_ROAD);
|
||||
|
||||
camera_init(v, &s->driver_cam, CAMERA_ID_OV8865, 1,
|
||||
/*pixel_clock=*/72000000, /*line_length_pclk=*/1602,
|
||||
/*max_gain=*/510, 10, device_id, ctx,
|
||||
VISION_STREAM_RGB_FRONT, VISION_STREAM_YUV_FRONT);
|
||||
VISION_STREAM_RGB_FRONT, VISION_STREAM_DRIVER);
|
||||
|
||||
s->sm = new SubMaster({"driverState"});
|
||||
s->pm = new PubMaster({"roadCameraState", "driverCameraState", "thumbnail"});
|
||||
@@ -227,7 +227,7 @@ void cameras_init(VisionIpcServer *v, MultiCameraState *s, cl_device_id device_i
|
||||
s->stats_bufs[i].allocate(0xb80);
|
||||
}
|
||||
std::fill_n(s->lapres, std::size(s->lapres), 16160);
|
||||
s->lap_conv = new LapConv(device_id, ctx, s->road_cam.buf.rgb_width, s->road_cam.buf.rgb_height, 3);
|
||||
s->lap_conv = new LapConv(device_id, ctx, s->road_cam.buf.rgb_width, s->road_cam.buf.rgb_height, s->road_cam.buf.rgb_stride, 3);
|
||||
}
|
||||
|
||||
static void set_exposure(CameraState *s, float exposure_frac, float gain_frac) {
|
||||
@@ -1045,7 +1045,7 @@ static void ops_thread(MultiCameraState *s) {
|
||||
CameraExpInfo road_cam_op;
|
||||
CameraExpInfo driver_cam_op;
|
||||
|
||||
set_thread_name("camera_settings");
|
||||
util::set_thread_name("camera_settings");
|
||||
SubMaster sm({"sensorEvents"});
|
||||
while(!do_exit) {
|
||||
road_cam_op = road_cam_exp.load();
|
||||
@@ -1086,10 +1086,6 @@ static void setup_self_recover(CameraState *c, const uint16_t *lapres, size_t la
|
||||
c->self_recover.store(self_recover);
|
||||
}
|
||||
|
||||
void process_driver_camera(MultiCameraState *s, CameraState *c, int cnt) {
|
||||
common_process_driver_camera(s->sm, s->pm, c, cnt);
|
||||
}
|
||||
|
||||
// called by processing_thread
|
||||
void process_road_camera(MultiCameraState *s, CameraState *c, int cnt) {
|
||||
const CameraBuf *b = &c->buf;
|
||||
@@ -1121,7 +1117,7 @@ void cameras_run(MultiCameraState *s) {
|
||||
std::vector<std::thread> threads;
|
||||
threads.push_back(std::thread(ops_thread, s));
|
||||
threads.push_back(start_process_thread(s, &s->road_cam, process_road_camera));
|
||||
threads.push_back(start_process_thread(s, &s->driver_cam, process_driver_camera));
|
||||
threads.push_back(start_process_thread(s, &s->driver_cam, common_process_driver_camera));
|
||||
|
||||
CameraState* cameras[2] = {&s->road_cam, &s->driver_cam};
|
||||
|
||||
|
||||
@@ -709,13 +709,13 @@ static void camera_open(CameraState *s) {
|
||||
|
||||
void cameras_init(VisionIpcServer *v, MultiCameraState *s, cl_device_id device_id, cl_context ctx) {
|
||||
camera_init(s, v, &s->road_cam, CAMERA_ID_AR0231, 1, 20, device_id, ctx,
|
||||
VISION_STREAM_RGB_BACK, VISION_STREAM_YUV_BACK); // swap left/right
|
||||
VISION_STREAM_RGB_BACK, VISION_STREAM_ROAD); // swap left/right
|
||||
printf("road camera initted \n");
|
||||
camera_init(s, v, &s->wide_road_cam, CAMERA_ID_AR0231, 0, 20, device_id, ctx,
|
||||
VISION_STREAM_RGB_WIDE, VISION_STREAM_YUV_WIDE);
|
||||
VISION_STREAM_RGB_WIDE, VISION_STREAM_WIDE_ROAD);
|
||||
printf("wide road camera initted \n");
|
||||
camera_init(s, v, &s->driver_cam, CAMERA_ID_AR0231, 2, 20, device_id, ctx,
|
||||
VISION_STREAM_RGB_FRONT, VISION_STREAM_YUV_FRONT);
|
||||
VISION_STREAM_RGB_FRONT, VISION_STREAM_DRIVER);
|
||||
printf("driver camera initted \n");
|
||||
|
||||
s->sm = new SubMaster({"driverState"});
|
||||
@@ -987,11 +987,6 @@ void camera_autoexposure(CameraState *s, float grey_frac) {
|
||||
set_camera_exposure(s, grey_frac);
|
||||
}
|
||||
|
||||
|
||||
void process_driver_camera(MultiCameraState *s, CameraState *c, int cnt) {
|
||||
common_process_driver_camera(s->sm, s->pm, c, cnt);
|
||||
}
|
||||
|
||||
// called by processing_thread
|
||||
void process_road_camera(MultiCameraState *s, CameraState *c, int cnt) {
|
||||
const CameraBuf *b = &c->buf;
|
||||
@@ -1016,7 +1011,7 @@ void cameras_run(MultiCameraState *s) {
|
||||
LOG("-- Starting threads");
|
||||
std::vector<std::thread> threads;
|
||||
threads.push_back(start_process_thread(s, &s->road_cam, process_road_camera));
|
||||
threads.push_back(start_process_thread(s, &s->driver_cam, process_driver_camera));
|
||||
threads.push_back(start_process_thread(s, &s->driver_cam, common_process_driver_camera));
|
||||
threads.push_back(start_process_thread(s, &s->wide_road_cam, process_road_camera));
|
||||
|
||||
// start devices
|
||||
|
||||
@@ -23,7 +23,7 @@ std::string get_url(std::string route_name, const std::string &camera, int segme
|
||||
}
|
||||
|
||||
void camera_init(VisionIpcServer *v, CameraState *s, int camera_id, unsigned int fps, cl_device_id device_id, cl_context ctx, VisionStreamType rgb_type, VisionStreamType yuv_type, const std::string &url) {
|
||||
s->frame = new FrameReader(true);
|
||||
s->frame = new FrameReader();
|
||||
if (!s->frame->load(url)) {
|
||||
printf("failed to load stream from %s", url.c_str());
|
||||
assert(0);
|
||||
@@ -67,12 +67,12 @@ void run_camera(CameraState *s) {
|
||||
}
|
||||
|
||||
void road_camera_thread(CameraState *s) {
|
||||
set_thread_name("replay_road_camera_thread");
|
||||
util::set_thread_name("replay_road_camera_thread");
|
||||
run_camera(s);
|
||||
}
|
||||
|
||||
// void driver_camera_thread(CameraState *s) {
|
||||
// set_thread_name("replay_driver_camera_thread");
|
||||
// util::set_thread_name("replay_driver_camera_thread");
|
||||
// run_camera(s);
|
||||
// }
|
||||
|
||||
@@ -98,9 +98,9 @@ void process_road_camera(MultiCameraState *s, CameraState *c, int cnt) {
|
||||
|
||||
void cameras_init(VisionIpcServer *v, MultiCameraState *s, cl_device_id device_id, cl_context ctx) {
|
||||
camera_init(v, &s->road_cam, CAMERA_ID_LGC920, 20, device_id, ctx,
|
||||
VISION_STREAM_RGB_BACK, VISION_STREAM_YUV_BACK, get_url(road_camera_route, "fcamera", 0));
|
||||
VISION_STREAM_RGB_BACK, VISION_STREAM_ROAD, get_url(road_camera_route, "fcamera", 0));
|
||||
// camera_init(v, &s->driver_cam, CAMERA_ID_LGC615, 10, device_id, ctx,
|
||||
// VISION_STREAM_RGB_FRONT, VISION_STREAM_YUV_FRONT, get_url(driver_camera_route, "dcamera", 0));
|
||||
// VISION_STREAM_RGB_FRONT, VISION_STREAM_DRIVER, get_url(driver_camera_route, "dcamera", 0));
|
||||
s->pm = new PubMaster({"roadCameraState", "driverCameraState", "thumbnail"});
|
||||
}
|
||||
|
||||
|
||||
@@ -55,8 +55,8 @@ static cl_program build_conv_program(cl_device_id device_id, cl_context context,
|
||||
return cl_program_from_file(context, device_id, "imgproc/conv.cl", args);
|
||||
}
|
||||
|
||||
LapConv::LapConv(cl_device_id device_id, cl_context ctx, int rgb_width, int rgb_height, int filter_size)
|
||||
: width(rgb_width / NUM_SEGMENTS_X), height(rgb_height / NUM_SEGMENTS_Y),
|
||||
LapConv::LapConv(cl_device_id device_id, cl_context ctx, int rgb_width, int rgb_height, int rgb_stride, int filter_size)
|
||||
: width(rgb_width / NUM_SEGMENTS_X), height(rgb_height / NUM_SEGMENTS_Y), rgb_stride(rgb_stride),
|
||||
roi_buf(width * height * 3), result_buf(width * height) {
|
||||
|
||||
prg = build_conv_program(device_id, ctx, width, height, filter_size);
|
||||
@@ -81,9 +81,9 @@ uint16_t LapConv::Update(cl_command_queue q, const uint8_t *rgb_buf, const int r
|
||||
const int x_offset = ROI_X_MIN + roi_id % (ROI_X_MAX - ROI_X_MIN + 1);
|
||||
const int y_offset = ROI_Y_MIN + roi_id / (ROI_X_MAX - ROI_X_MIN + 1);
|
||||
|
||||
const uint8_t *rgb_offset = rgb_buf + y_offset * height * FULL_STRIDE_X * 3 + x_offset * width * 3;
|
||||
const uint8_t *rgb_offset = rgb_buf + y_offset * height * rgb_stride + x_offset * width * 3;
|
||||
for (int i = 0; i < height; ++i) {
|
||||
memcpy(&roi_buf[i * width * 3], &rgb_offset[i * FULL_STRIDE_X * 3], width * 3);
|
||||
memcpy(&roi_buf[i * width * 3], &rgb_offset[i * rgb_stride], width * 3);
|
||||
}
|
||||
|
||||
constexpr int local_mem_size = (CONV_LOCAL_WORKSIZE + 2 * (3 / 2)) * (CONV_LOCAL_WORKSIZE + 2 * (3 / 2)) * (3 * sizeof(uint8_t));
|
||||
|
||||
@@ -16,16 +16,11 @@
|
||||
|
||||
#define LM_THRESH 120
|
||||
#define LM_PREC_THRESH 0.9 // 90 perc is blur
|
||||
|
||||
// only apply to QCOM
|
||||
#define FULL_STRIDE_X 1280
|
||||
#define FULL_STRIDE_Y 896
|
||||
|
||||
#define CONV_LOCAL_WORKSIZE 16
|
||||
|
||||
class LapConv {
|
||||
public:
|
||||
LapConv(cl_device_id device_id, cl_context ctx, int rgb_width, int rgb_height, int filter_size);
|
||||
LapConv(cl_device_id device_id, cl_context ctx, int rgb_width, int rgb_height, int rgb_stride, int filter_size);
|
||||
~LapConv();
|
||||
uint16_t Update(cl_command_queue q, const uint8_t *rgb_buf, const int roi_id);
|
||||
|
||||
@@ -34,6 +29,7 @@ private:
|
||||
cl_program prg;
|
||||
cl_kernel krnl;
|
||||
const int width, height;
|
||||
const int rgb_stride;
|
||||
std::vector<uint8_t> roi_buf;
|
||||
std::vector<int16_t> result_buf;
|
||||
};
|
||||
|
||||
@@ -46,9 +46,9 @@ void party(cl_device_id device_id, cl_context context) {
|
||||
int main(int argc, char *argv[]) {
|
||||
if (!Hardware::PC()) {
|
||||
int ret;
|
||||
ret = set_realtime_priority(53);
|
||||
ret = util::set_realtime_priority(53);
|
||||
assert(ret == 0);
|
||||
ret = set_core_affinity({Hardware::EON() ? 2 : 6});
|
||||
ret = util::set_core_affinity({Hardware::EON() ? 2 : 6});
|
||||
assert(ret == 0 || Params().getBool("IsOffroad")); // failure ok while offroad due to offlining cores
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ def extract_image(buf, w, h, stride):
|
||||
|
||||
|
||||
def rois_in_focus(lapres: List[float]) -> float:
|
||||
return sum([1. / len(lapres) for sharpness in lapres if sharpness >= LM_THRESH])
|
||||
return sum(1. / len(lapres) for sharpness in lapres if sharpness >= LM_THRESH)
|
||||
|
||||
|
||||
def get_snapshots(frame="roadCameraState", front_frame="driverCameraState", focus_perc_threshold=0.):
|
||||
|
||||
@@ -99,7 +99,7 @@ def crc8_pedal(data):
|
||||
return crc
|
||||
|
||||
|
||||
def create_gas_command(packer, gas_amount, idx):
|
||||
def create_gas_interceptor_command(packer, gas_amount, idx):
|
||||
# Common gas pedal msg generator
|
||||
enable = gas_amount > 0.001
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import os
|
||||
from common.params import Params
|
||||
from common.basedir import BASEDIR
|
||||
from selfdrive.version import comma_remote, tested_branch
|
||||
from selfdrive.version import get_comma_remote, get_tested_branch
|
||||
from selfdrive.car.fingerprints import eliminate_incompatible_cars, all_legacy_fingerprint_cars
|
||||
from selfdrive.car.vin import get_vin, VIN_UNKNOWN
|
||||
from selfdrive.car.fw_versions import get_fw_versions, match_fw_to_car
|
||||
@@ -14,7 +14,7 @@ EventName = car.CarEvent.EventName
|
||||
|
||||
|
||||
def get_startup_event(car_recognized, controller_available, fw_seen):
|
||||
if comma_remote and tested_branch:
|
||||
if get_comma_remote() and get_tested_branch():
|
||||
event = EventName.startup
|
||||
else:
|
||||
event = EventName.startupMaster
|
||||
|
||||
@@ -31,10 +31,13 @@ class CarState(CarStateBase):
|
||||
|
||||
ret.espDisabled = (cp.vl["TRACTION_BUTTON"]["TRACTION_OFF"] == 1)
|
||||
|
||||
ret.wheelSpeeds.fl = cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_FL"]
|
||||
ret.wheelSpeeds.rr = cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_RR"]
|
||||
ret.wheelSpeeds.rl = cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_RL"]
|
||||
ret.wheelSpeeds.fr = cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_FR"]
|
||||
ret.wheelSpeeds = self.get_wheel_speeds(
|
||||
cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_FL"],
|
||||
cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_FR"],
|
||||
cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_RL"],
|
||||
cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_RR"],
|
||||
unit=1,
|
||||
)
|
||||
ret.vEgoRaw = (cp.vl["SPEED_1"]["SPEED_LEFT"] + cp.vl["SPEED_1"]["SPEED_RIGHT"]) / 2.
|
||||
ret.vEgo, ret.aEgo = self.update_speed_kf(ret.vEgoRaw)
|
||||
ret.standstill = not ret.vEgoRaw > 0.001
|
||||
|
||||
@@ -10,10 +10,14 @@ WHEEL_RADIUS = 0.33
|
||||
class CarState(CarStateBase):
|
||||
def update(self, cp):
|
||||
ret = car.CarState.new_message()
|
||||
ret.wheelSpeeds.rr = cp.vl["WheelSpeed_CG1"]["WhlRr_W_Meas"] * WHEEL_RADIUS
|
||||
ret.wheelSpeeds.rl = cp.vl["WheelSpeed_CG1"]["WhlRl_W_Meas"] * WHEEL_RADIUS
|
||||
ret.wheelSpeeds.fr = cp.vl["WheelSpeed_CG1"]["WhlFr_W_Meas"] * WHEEL_RADIUS
|
||||
ret.wheelSpeeds.fl = cp.vl["WheelSpeed_CG1"]["WhlFl_W_Meas"] * WHEEL_RADIUS
|
||||
|
||||
ret.wheelSpeeds = self.get_wheel_speeds(
|
||||
cp.vl["WheelSpeed_CG1"]["WhlFl_W_Meas"],
|
||||
cp.vl["WheelSpeed_CG1"]["WhlFr_W_Meas"],
|
||||
cp.vl["WheelSpeed_CG1"]["WhlRl_W_Meas"],
|
||||
cp.vl["WheelSpeed_CG1"]["WhlRr_W_Meas"],
|
||||
unit=WHEEL_RADIUS,
|
||||
)
|
||||
ret.vEgoRaw = mean([ret.wheelSpeeds.rr, ret.wheelSpeeds.rl, ret.wheelSpeeds.fr, ret.wheelSpeeds.fl])
|
||||
ret.vEgo, ret.aEgo = self.update_speed_kf(ret.vEgoRaw)
|
||||
ret.standstill = not ret.vEgoRaw > 0.001
|
||||
|
||||
@@ -9,12 +9,6 @@ MAX_ANGLE = 87. # make sure we never command the extremes (0xfff) which cause l
|
||||
class CAR:
|
||||
FUSION = "FORD FUSION 2018"
|
||||
|
||||
FINGERPRINTS = {
|
||||
CAR.FUSION: [{
|
||||
71: 8, 74: 8, 75: 8, 76: 8, 90: 8, 92: 8, 93: 8, 118: 8, 119: 8, 120: 8, 125: 8, 129: 8, 130: 8, 131: 8, 132: 8, 133: 8, 145: 8, 146: 8, 357: 8, 359: 8, 360: 8, 361: 8, 376: 8, 390: 8, 391: 8, 392: 8, 394: 8, 512: 8, 514: 8, 516: 8, 531: 8, 532: 8, 534: 8, 535: 8, 560: 8, 578: 8, 604: 8, 613: 8, 673: 8, 827: 8, 848: 8, 934: 8, 935: 8, 936: 8, 947: 8, 963: 8, 970: 8, 972: 8, 973: 8, 984: 8, 992: 8, 994: 8, 997: 8, 998: 8, 1003: 8, 1034: 8, 1045: 8, 1046: 8, 1053: 8, 1054: 8, 1058: 8, 1059: 8, 1068: 8, 1072: 8, 1073: 8, 1082: 8, 1107: 8, 1108: 8, 1109: 8, 1110: 8, 1200: 8, 1427: 8, 1430: 8, 1438: 8, 1459: 8
|
||||
}],
|
||||
}
|
||||
|
||||
DBC = {
|
||||
CAR.FUSION: dbc_dict('ford_fusion_2018_pt', 'ford_fusion_2018_adas'),
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ HYUNDAI_VERSION_REQUEST_LONG = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER])
|
||||
HYUNDAI_VERSION_REQUEST_MULTI = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + \
|
||||
p16(uds.DATA_IDENTIFIER_TYPE.VEHICLE_MANUFACTURER_SPARE_PART_NUMBER) + \
|
||||
p16(uds.DATA_IDENTIFIER_TYPE.APPLICATION_SOFTWARE_IDENTIFICATION) + \
|
||||
p16(0xf100)
|
||||
p16(0xf100)
|
||||
HYUNDAI_VERSION_RESPONSE = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER + 0x40])
|
||||
|
||||
|
||||
@@ -240,7 +240,7 @@ def match_fw_to_car_exact(fw_versions_dict):
|
||||
addr = ecu[1:]
|
||||
found_version = fw_versions_dict.get(addr, None)
|
||||
ESSENTIAL_ECUS = [Ecu.engine, Ecu.eps, Ecu.esp, Ecu.fwdRadar, Ecu.fwdCamera, Ecu.vsa]
|
||||
if ecu_type == Ecu.esp and candidate in [TOYOTA.RAV4, TOYOTA.COROLLA, TOYOTA.HIGHLANDER] and found_version is None:
|
||||
if ecu_type == Ecu.esp and candidate in [TOYOTA.RAV4, TOYOTA.COROLLA, TOYOTA.HIGHLANDER, TOYOTA.SIENNA, TOYOTA.LEXUS_IS] and found_version is None:
|
||||
continue
|
||||
|
||||
# On some Toyota models, the engine can show on two different addresses
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from cereal import car
|
||||
from common.numpy_fast import mean
|
||||
from selfdrive.config import Conversions as CV
|
||||
from opendbc.can.can_define import CANDefine
|
||||
from opendbc.can.parser import CANParser
|
||||
from selfdrive.car.interfaces import CarStateBase
|
||||
@@ -21,10 +20,12 @@ class CarState(CarStateBase):
|
||||
self.prev_cruise_buttons = self.cruise_buttons
|
||||
self.cruise_buttons = pt_cp.vl["ASCMSteeringButton"]["ACCButtons"]
|
||||
|
||||
ret.wheelSpeeds.fl = pt_cp.vl["EBCMWheelSpdFront"]["FLWheelSpd"] * CV.KPH_TO_MS
|
||||
ret.wheelSpeeds.fr = pt_cp.vl["EBCMWheelSpdFront"]["FRWheelSpd"] * CV.KPH_TO_MS
|
||||
ret.wheelSpeeds.rl = pt_cp.vl["EBCMWheelSpdRear"]["RLWheelSpd"] * CV.KPH_TO_MS
|
||||
ret.wheelSpeeds.rr = pt_cp.vl["EBCMWheelSpdRear"]["RRWheelSpd"] * CV.KPH_TO_MS
|
||||
ret.wheelSpeeds = self.get_wheel_speeds(
|
||||
pt_cp.vl["EBCMWheelSpdFront"]["FLWheelSpd"],
|
||||
pt_cp.vl["EBCMWheelSpdFront"]["FRWheelSpd"],
|
||||
pt_cp.vl["EBCMWheelSpdRear"]["RLWheelSpd"],
|
||||
pt_cp.vl["EBCMWheelSpdRear"]["RRWheelSpd"],
|
||||
)
|
||||
ret.vEgoRaw = mean([ret.wheelSpeeds.fl, ret.wheelSpeeds.fr, ret.wheelSpeeds.rl, ret.wheelSpeeds.rr])
|
||||
ret.vEgo, ret.aEgo = self.update_speed_kf(ret.vEgoRaw)
|
||||
ret.standstill = ret.vEgoRaw < 0.01
|
||||
|
||||
@@ -3,7 +3,7 @@ from cereal import car
|
||||
from common.realtime import DT_CTRL
|
||||
from selfdrive.controls.lib.drive_helpers import rate_limit
|
||||
from common.numpy_fast import clip, interp
|
||||
from selfdrive.car import create_gas_command
|
||||
from selfdrive.car import create_gas_interceptor_command
|
||||
from selfdrive.car.honda import hondacan
|
||||
from selfdrive.car.honda.values import CruiseButtons, VISUAL_HUD, HONDA_BOSCH, HONDA_NIDEC_ALT_PCM_ACCEL, CarControllerParams
|
||||
from opendbc.can.packer import CANPacker
|
||||
@@ -236,7 +236,7 @@ class CarController():
|
||||
apply_gas = clip(gas_mult * (gas - brake + wind_brake*3/4), 0., 1.)
|
||||
else:
|
||||
apply_gas = 0.0
|
||||
can_sends.append(create_gas_command(self.packer, apply_gas, idx))
|
||||
can_sends.append(create_gas_interceptor_command(self.packer, apply_gas, idx))
|
||||
|
||||
hud = HUDData(int(pcm_accel), int(round(hud_v_cruise)), hud_car,
|
||||
hud_lanes, fcw_display, acc_alert, steer_required)
|
||||
@@ -244,6 +244,6 @@ class CarController():
|
||||
# Send dashboard UI commands.
|
||||
if (frame % 10) == 0:
|
||||
idx = (frame//10) % 4
|
||||
can_sends.extend(hondacan.create_ui_commands(self.packer, pcm_speed, hud, CS.CP.carFingerprint, CS.is_metric, idx, CS.CP.openpilotLongitudinalControl, CS.stock_hud))
|
||||
can_sends.extend(hondacan.create_ui_commands(self.packer, CS.CP, pcm_speed, hud, CS.is_metric, idx, CS.stock_hud))
|
||||
|
||||
return can_sends
|
||||
|
||||
@@ -5,7 +5,7 @@ from opendbc.can.can_define import CANDefine
|
||||
from opendbc.can.parser import CANParser
|
||||
from selfdrive.config import Conversions as CV
|
||||
from selfdrive.car.interfaces import CarStateBase
|
||||
from selfdrive.car.honda.values import CAR, DBC, STEER_THRESHOLD, SPEED_FACTOR, HONDA_BOSCH, HONDA_NIDEC_ALT_SCM_MESSAGES, HONDA_BOSCH_ALT_BRAKE_SIGNAL
|
||||
from selfdrive.car.honda.values import CAR, DBC, STEER_THRESHOLD, HONDA_BOSCH, HONDA_NIDEC_ALT_SCM_MESSAGES, HONDA_BOSCH_ALT_BRAKE_SIGNAL
|
||||
|
||||
TransmissionType = car.CarParams.TransmissionType
|
||||
|
||||
@@ -213,16 +213,17 @@ class CarState(CarStateBase):
|
||||
self.brake_error = cp.vl["STANDSTILL"]["BRAKE_ERROR_1"] or cp.vl["STANDSTILL"]["BRAKE_ERROR_2"]
|
||||
ret.espDisabled = cp.vl["VSA_STATUS"]["ESP_DISABLED"] != 0
|
||||
|
||||
speed_factor = SPEED_FACTOR.get(self.CP.carFingerprint, 1.)
|
||||
ret.wheelSpeeds.fl = cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_FL"] * CV.KPH_TO_MS * speed_factor
|
||||
ret.wheelSpeeds.fr = cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_FR"] * CV.KPH_TO_MS * speed_factor
|
||||
ret.wheelSpeeds.rl = cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_RL"] * CV.KPH_TO_MS * speed_factor
|
||||
ret.wheelSpeeds.rr = cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_RR"] * CV.KPH_TO_MS * speed_factor
|
||||
v_wheel = (ret.wheelSpeeds.fl + ret.wheelSpeeds.fr + ret.wheelSpeeds.rl + ret.wheelSpeeds.rr)/4.
|
||||
ret.wheelSpeeds = self.get_wheel_speeds(
|
||||
cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_FL"],
|
||||
cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_FR"],
|
||||
cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_RL"],
|
||||
cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_RR"],
|
||||
)
|
||||
v_wheel = (ret.wheelSpeeds.fl + ret.wheelSpeeds.fr + ret.wheelSpeeds.rl + ret.wheelSpeeds.rr) / 4.0
|
||||
|
||||
# blend in transmission speed at low speed, since it has more low speed accuracy
|
||||
v_weight = interp(v_wheel, v_weight_bp, v_weight_v)
|
||||
ret.vEgoRaw = (1. - v_weight) * cp.vl["ENGINE_DATA"]["XMISSION_SPEED"] * CV.KPH_TO_MS * speed_factor + v_weight * v_wheel
|
||||
ret.vEgoRaw = (1. - v_weight) * cp.vl["ENGINE_DATA"]["XMISSION_SPEED"] * CV.KPH_TO_MS * self.CP.wheelSpeedFactor + v_weight * v_wheel
|
||||
ret.vEgo, ret.aEgo = self.update_speed_kf(ret.vEgoRaw)
|
||||
|
||||
ret.steeringAngleDeg = cp.vl["STEERING_SENSORS"]["STEER_ANGLE"]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from selfdrive.car.honda.values import HONDA_BOSCH, CAR, CarControllerParams
|
||||
from selfdrive.car.honda.values import HondaFlags, HONDA_BOSCH, CAR, CarControllerParams
|
||||
from selfdrive.config import Conversions as CV
|
||||
|
||||
# CAN bus layout with relay
|
||||
@@ -98,14 +98,14 @@ def create_bosch_supplemental_1(packer, car_fingerprint, idx):
|
||||
return packer.make_can_msg("BOSCH_SUPPLEMENTAL_1", bus, values, idx)
|
||||
|
||||
|
||||
def create_ui_commands(packer, pcm_speed, hud, car_fingerprint, is_metric, idx, openpilot_longitudinal_control, stock_hud):
|
||||
def create_ui_commands(packer, CP, pcm_speed, hud, is_metric, idx, stock_hud):
|
||||
commands = []
|
||||
bus_pt = get_pt_bus(car_fingerprint)
|
||||
radar_disabled = car_fingerprint in HONDA_BOSCH and openpilot_longitudinal_control
|
||||
bus_lkas = get_lkas_cmd_bus(car_fingerprint, radar_disabled)
|
||||
bus_pt = get_pt_bus(CP.carFingerprint)
|
||||
radar_disabled = CP.carFingerprint in HONDA_BOSCH and CP.openpilotLongitudinalControl
|
||||
bus_lkas = get_lkas_cmd_bus(CP.carFingerprint, radar_disabled)
|
||||
|
||||
if openpilot_longitudinal_control:
|
||||
if car_fingerprint in HONDA_BOSCH:
|
||||
if CP.openpilotLongitudinalControl:
|
||||
if CP.carFingerprint in HONDA_BOSCH:
|
||||
acc_hud_values = {
|
||||
'CRUISE_SPEED': hud.v_cruise,
|
||||
'ENABLE_MINI_CAR': 1,
|
||||
@@ -142,16 +142,24 @@ def create_ui_commands(packer, pcm_speed, hud, car_fingerprint, is_metric, idx,
|
||||
'SOLID_LANES': hud.lanes,
|
||||
'BEEP': 0,
|
||||
}
|
||||
commands.append(packer.make_can_msg('LKAS_HUD', bus_lkas, lkas_hud_values, idx))
|
||||
|
||||
if radar_disabled and car_fingerprint in HONDA_BOSCH:
|
||||
if not (CP.flags & HondaFlags.BOSCH_EXT_HUD):
|
||||
lkas_hud_values['SET_ME_X48'] = 0x48
|
||||
|
||||
if CP.flags & HondaFlags.BOSCH_EXT_HUD and not CP.openpilotLongitudinalControl:
|
||||
commands.append(packer.make_can_msg('LKAS_HUD_A', bus_lkas, lkas_hud_values, idx))
|
||||
commands.append(packer.make_can_msg('LKAS_HUD_B', bus_lkas, lkas_hud_values, idx))
|
||||
else:
|
||||
commands.append(packer.make_can_msg('LKAS_HUD', bus_lkas, lkas_hud_values, idx))
|
||||
|
||||
if radar_disabled and CP.carFingerprint in HONDA_BOSCH:
|
||||
radar_hud_values = {
|
||||
'CMBS_OFF': 0x01,
|
||||
'SET_TO_1': 0x01,
|
||||
}
|
||||
commands.append(packer.make_can_msg('RADAR_HUD', bus_pt, radar_hud_values, idx))
|
||||
|
||||
if car_fingerprint == CAR.CIVIC_BOSCH:
|
||||
if CP.carFingerprint == CAR.CIVIC_BOSCH:
|
||||
commands.append(packer.make_can_msg("LEGACY_BRAKE_COMMAND", bus_pt, {}, idx))
|
||||
|
||||
return commands
|
||||
|
||||
@@ -3,7 +3,7 @@ from cereal import car
|
||||
from panda import Panda
|
||||
from common.numpy_fast import interp
|
||||
from common.params import Params
|
||||
from selfdrive.car.honda.values import CarControllerParams, CruiseButtons, CAR, HONDA_BOSCH, HONDA_NIDEC_ALT_SCM_MESSAGES, HONDA_BOSCH_ALT_BRAKE_SIGNAL
|
||||
from selfdrive.car.honda.values import CarControllerParams, CruiseButtons, HondaFlags, CAR, HONDA_BOSCH, HONDA_NIDEC_ALT_SCM_MESSAGES, HONDA_BOSCH_ALT_BRAKE_SIGNAL
|
||||
from selfdrive.car import STD_CARGO_KG, CivicParams, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint, get_safety_config
|
||||
from selfdrive.car.interfaces import CarInterfaceBase
|
||||
from selfdrive.car.disable_ecu import disable_ecu
|
||||
@@ -33,7 +33,7 @@ class CarInterface(CarInterfaceBase):
|
||||
ret.carName = "honda"
|
||||
|
||||
if candidate in HONDA_BOSCH:
|
||||
ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.hondaBoschHarness)]
|
||||
ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.hondaBosch)]
|
||||
ret.radarOffCan = True
|
||||
|
||||
# Disable the radar and let openpilot control longitudinal
|
||||
@@ -52,6 +52,10 @@ class CarInterface(CarInterfaceBase):
|
||||
if candidate == CAR.CRV_5G:
|
||||
ret.enableBsm = 0x12f8bfa7 in fingerprint[0]
|
||||
|
||||
# Detect Bosch cars with new HUD msgs
|
||||
if any(0x33DA in f for f in fingerprint.values()):
|
||||
ret.flags |= HondaFlags.BOSCH_EXT_HUD.value
|
||||
|
||||
# Accord 1.5T CVT has different gearbox message
|
||||
if candidate == CAR.ACCORD and 0x191 in fingerprint[1]:
|
||||
ret.transmissionType = TransmissionType.cvt
|
||||
@@ -143,6 +147,7 @@ class CarInterface(CarInterfaceBase):
|
||||
ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 1000], [0, 1000]] # TODO: determine if there is a dead zone at the top end
|
||||
tire_stiffness_factor = 0.444
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.8], [0.24]]
|
||||
ret.wheelSpeedFactor = 1.025
|
||||
|
||||
elif candidate == CAR.CRV_5G:
|
||||
stop_and_go = True
|
||||
@@ -160,6 +165,7 @@ class CarInterface(CarInterfaceBase):
|
||||
ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 3840], [0, 3840]]
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.64], [0.192]]
|
||||
tire_stiffness_factor = 0.677
|
||||
ret.wheelSpeedFactor = 1.025
|
||||
|
||||
elif candidate == CAR.CRV_HYBRID:
|
||||
stop_and_go = True
|
||||
@@ -170,6 +176,7 @@ 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
|
||||
tire_stiffness_factor = 0.677
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.6], [0.18]]
|
||||
ret.wheelSpeedFactor = 1.025
|
||||
|
||||
elif candidate == CAR.FIT:
|
||||
stop_and_go = False
|
||||
@@ -201,6 +208,7 @@ class CarInterface(CarInterfaceBase):
|
||||
ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]]
|
||||
tire_stiffness_factor = 0.5
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.16], [0.025]]
|
||||
ret.wheelSpeedFactor = 1.025
|
||||
|
||||
elif candidate == CAR.ACURA_RDX:
|
||||
stop_and_go = False
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
from enum import IntFlag
|
||||
|
||||
from cereal import car
|
||||
from selfdrive.car import dbc_dict
|
||||
|
||||
@@ -37,6 +39,11 @@ class CarControllerParams():
|
||||
self.STEER_LOOKUP_V = [v * -1 for v in CP.lateralParams.torqueV][1:][::-1] + list(CP.lateralParams.torqueV)
|
||||
|
||||
|
||||
class HondaFlags(IntFlag):
|
||||
# Bosch models with alternate set of LKAS_HUD messages
|
||||
BOSCH_EXT_HUD = 1
|
||||
|
||||
|
||||
# Car button codes
|
||||
class CruiseButtons:
|
||||
RES_ACCEL = 4
|
||||
@@ -84,6 +91,7 @@ class CAR:
|
||||
FW_VERSIONS = {
|
||||
CAR.ACCORD: {
|
||||
(Ecu.programmedFuelInjection, 0x18da10f1, None): [
|
||||
b'37805-6A0-8720\x00\x00',
|
||||
b'37805-6A0-9520\x00\x00',
|
||||
b'37805-6A0-9620\x00\x00',
|
||||
b'37805-6A0-9720\x00\x00',
|
||||
@@ -95,7 +103,9 @@ FW_VERSIONS = {
|
||||
b'37805-6A0-A750\x00\x00',
|
||||
b'37805-6A0-A840\x00\x00',
|
||||
b'37805-6A0-A850\x00\x00',
|
||||
b'37805-6A0-AF30\x00\x00',
|
||||
b'37805-6A0-AG30\x00\x00',
|
||||
b'37805-6B2-C520\x00\x00',
|
||||
b'37805-6A0-C540\x00\x00',
|
||||
b'37805-6A1-H650\x00\x00',
|
||||
b'37805-6B2-A550\x00\x00',
|
||||
@@ -121,6 +131,7 @@ FW_VERSIONS = {
|
||||
b'28101-6A7-A410\x00\x00',
|
||||
b'28101-6A7-A510\x00\x00',
|
||||
b'28101-6A7-A610\x00\x00',
|
||||
b'28101-6A7-A710\x00\x00',
|
||||
b'28101-6A9-H140\x00\x00',
|
||||
b'28101-6A9-H420\x00\x00',
|
||||
b'28102-6B8-A560\x00\x00',
|
||||
@@ -150,6 +161,7 @@ FW_VERSIONS = {
|
||||
b'57114-TVA-C050\x00\x00',
|
||||
b'57114-TVA-C060\x00\x00',
|
||||
b'57114-TVA-C530\x00\x00',
|
||||
b'57114-TVA-E520\x00\x00',
|
||||
b'57114-TVE-H250\x00\x00',
|
||||
],
|
||||
(Ecu.eps, 0x18da30f1, None): [
|
||||
@@ -165,6 +177,7 @@ FW_VERSIONS = {
|
||||
],
|
||||
(Ecu.unknown, 0x18da3af1, None): [
|
||||
b'39390-TVA-A020\x00\x00',
|
||||
b'39390-TVA-A120\x00\x00',
|
||||
],
|
||||
(Ecu.srs, 0x18da53f1, None): [
|
||||
b'77959-TBX-H230\x00\x00',
|
||||
@@ -183,10 +196,12 @@ FW_VERSIONS = {
|
||||
b'78109-TVA-A120\x00\x00',
|
||||
b'78109-TVA-A210\x00\x00',
|
||||
b'78109-TVA-A220\x00\x00',
|
||||
b'78109-TVA-A230\x00\x00',
|
||||
b'78109-TVA-A310\x00\x00',
|
||||
b'78109-TVA-C010\x00\x00',
|
||||
b'78109-TVA-L010\x00\x00',
|
||||
b'78109-TVA-L210\x00\x00',
|
||||
b'78109-TVA-R310\x00\x00',
|
||||
b'78109-TVC-A010\x00\x00',
|
||||
b'78109-TVC-A020\x00\x00',
|
||||
b'78109-TVC-A030\x00\x00',
|
||||
@@ -194,6 +209,7 @@ FW_VERSIONS = {
|
||||
b'78109-TVC-A130\x00\x00',
|
||||
b'78109-TVC-A210\x00\x00',
|
||||
b'78109-TVC-A220\x00\x00',
|
||||
b'78109-TVC-A230\x00\x00',
|
||||
b'78109-TVC-C010\x00\x00',
|
||||
b'78109-TVC-C110\x00\x00',
|
||||
b'78109-TVC-L010\x00\x00',
|
||||
@@ -205,6 +221,7 @@ FW_VERSIONS = {
|
||||
],
|
||||
(Ecu.hud, 0x18da61f1, None): [
|
||||
b'78209-TVA-A010\x00\x00',
|
||||
b'78209-TVA-A110\x00\x00',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x18dab0f1, None): [
|
||||
b'36802-TBX-H140\x00\x00',
|
||||
@@ -253,6 +270,7 @@ FW_VERSIONS = {
|
||||
b'78109-TWA-A030\x00\x00',
|
||||
b'78109-TWA-A110\x00\x00',
|
||||
b'78109-TWA-A120\x00\x00',
|
||||
b'78109-TWA-A130\x00\x00',
|
||||
b'78109-TWA-A210\x00\x00',
|
||||
b'78109-TWA-A220\x00\x00',
|
||||
b'78109-TWA-A230\x00\x00',
|
||||
@@ -271,8 +289,8 @@ FW_VERSIONS = {
|
||||
b'36161-TWA-A330\x00\x00',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x18dab0f1, None): [
|
||||
b'36802-TWA-A080\x00\x00',
|
||||
b'36802-TWA-A070\x00\x00',
|
||||
b'36802-TWA-A080\x00\x00',
|
||||
b'36802-TWA-A330\x00\x00',
|
||||
],
|
||||
(Ecu.eps, 0x18da30f1, None): [
|
||||
@@ -382,6 +400,7 @@ FW_VERSIONS = {
|
||||
(Ecu.programmedFuelInjection, 0x18da10f1, None): [
|
||||
b'37805-5AA-A940\x00\x00',
|
||||
b'37805-5AA-A950\x00\x00',
|
||||
b'37805-5AA-C950\x00\x00',
|
||||
b'37805-5AA-L940\x00\x00',
|
||||
b'37805-5AA-L950\x00\x00',
|
||||
b'37805-5AG-Z910\x00\x00',
|
||||
@@ -397,7 +416,9 @@ FW_VERSIONS = {
|
||||
b'37805-5AN-AG20\x00\x00',
|
||||
b'37805-5AN-AH20\x00\x00',
|
||||
b'37805-5AN-AJ30\x00\x00',
|
||||
b'37805-5AN-AK10\x00\x00',
|
||||
b'37805-5AN-AK20\x00\x00',
|
||||
b'37805-5AN-AR10\x00\x00',
|
||||
b'37805-5AN-AR20\x00\x00',
|
||||
b'37805-5AN-CH20\x00\x00',
|
||||
b'37805-5AN-E630\x00\x00',
|
||||
@@ -492,7 +513,9 @@ FW_VERSIONS = {
|
||||
b'78109-TBA-C340\x00\x00',
|
||||
b'78109-TBA-C910\x00\x00',
|
||||
b'78109-TBC-A740\x00\x00',
|
||||
b'78109-TBC-C540\x00\x00',
|
||||
b'78109-TBG-A110\x00\x00',
|
||||
b'78109-TBH-A710\x00\x00',
|
||||
b'78109-TEG-A720\x00\x00',
|
||||
b'78109-TFJ-G020\x00\x00',
|
||||
b'78109-TGG-9020\x00\x00',
|
||||
@@ -686,6 +709,7 @@ FW_VERSIONS = {
|
||||
b'78109-TLA-A120\x00\x00',
|
||||
b'78109-TLA-A210\x00\x00',
|
||||
b'78109-TLA-A220\x00\x00',
|
||||
b'78109-TLA-C020\x00\x00',
|
||||
b'78109-TLA-C110\x00\x00',
|
||||
b'78109-TLA-C210\x00\x00',
|
||||
b'78109-TLA-C310\x00\x00',
|
||||
@@ -720,6 +744,7 @@ FW_VERSIONS = {
|
||||
b'36161-TMC-Q040\x00\x00',
|
||||
b'36161-TNY-A020\x00\x00',
|
||||
b'36161-TNY-A030\x00\x00',
|
||||
b'36161-TNY-A040\x00\x00',
|
||||
],
|
||||
(Ecu.srs, 0x18da53f1, None): [
|
||||
b'77959-TLA-A240\x00\x00',
|
||||
@@ -1025,6 +1050,7 @@ FW_VERSIONS = {
|
||||
b'36161-TG8-A830\x00\x00',
|
||||
b'36161-TGS-A130\x00\x00',
|
||||
b'36161-TGT-A030\x00\x00',
|
||||
b'36161-TGT-A130\x00\x00',
|
||||
],
|
||||
(Ecu.srs, 0x18da53f1, None): [
|
||||
b'77959-TG7-A210\x00\x00',
|
||||
@@ -1040,7 +1066,9 @@ FW_VERSIONS = {
|
||||
b'78109-TG7-AP10\x00\x00',
|
||||
b'78109-TG7-AP20\x00\x00',
|
||||
b'78109-TG7-AS20\x00\x00',
|
||||
b'78109-TG7-AT20\x00\x00',
|
||||
b'78109-TG7-AU20\x00\x00',
|
||||
b'78109-TG7-AX20\x00\x00',
|
||||
b'78109-TG7-DJ10\x00\x00',
|
||||
b'78109-TG7-YK20\x00\x00',
|
||||
b'78109-TG8-AJ10\x00\x00',
|
||||
@@ -1049,7 +1077,7 @@ FW_VERSIONS = {
|
||||
b'78109-TGS-AK20\x00\x00',
|
||||
b'78109-TGS-AP20\x00\x00',
|
||||
b'78109-TGT-AJ20\x00\x00',
|
||||
b'78109-TG7-AT20\x00\x00',
|
||||
b'78109-TGT-AK30\x00\x00',
|
||||
],
|
||||
(Ecu.vsa, 0x18da28f1, None): [
|
||||
b'57114-TG7-A630\x00\x00',
|
||||
@@ -1147,6 +1175,7 @@ FW_VERSIONS = {
|
||||
b'28102-5YK-A711\x00\x00',
|
||||
b'28102-5YL-A620\x00\x00',
|
||||
b'28102-5YL-A700\x00\x00',
|
||||
b'28102-5YL-A711\x00\x00',
|
||||
],
|
||||
(Ecu.combinationMeter, 0x18da60f1, None): [
|
||||
b'78109-TJB-A140\x00\x00',
|
||||
@@ -1155,6 +1184,7 @@ FW_VERSIONS = {
|
||||
b'78109-TJB-AB10\x00\x00',
|
||||
b'78109-TJB-AD10\x00\x00',
|
||||
b'78109-TJB-AF10\x00\x00',
|
||||
b'78109-TJB-AR10\x00\x00',
|
||||
b'78109-TJB-AS10\000\000',
|
||||
b'78109-TJB-AU10\x00\x00',
|
||||
b'78109-TJB-AW10\x00\x00',
|
||||
@@ -1271,6 +1301,7 @@ FW_VERSIONS = {
|
||||
],
|
||||
(Ecu.combinationMeter, 0x18da60f1, None): [
|
||||
b'78109-THX-A110\x00\x00',
|
||||
b'78109-THX-A120\x00\x00',
|
||||
b'78109-THX-A210\x00\x00',
|
||||
b'78109-THX-A220\x00\x00',
|
||||
b'78109-THX-C220\x00\x00',
|
||||
@@ -1354,18 +1385,9 @@ STEER_THRESHOLD = {
|
||||
CAR.CRV_EU: 400,
|
||||
}
|
||||
|
||||
# TODO: is this real?
|
||||
SPEED_FACTOR = {
|
||||
# default is 1, overrides go here
|
||||
CAR.CRV: 1.025,
|
||||
CAR.CRV_5G: 1.025,
|
||||
CAR.CRV_EU: 1.025,
|
||||
CAR.CRV_HYBRID: 1.025,
|
||||
CAR.HRV: 1.025,
|
||||
}
|
||||
|
||||
HONDA_NIDEC_ALT_PCM_ACCEL = set([CAR.ODYSSEY])
|
||||
HONDA_NIDEC_ALT_SCM_MESSAGES = set([CAR.ACURA_ILX, CAR.ACURA_RDX, CAR.CRV, CAR.CRV_EU, CAR.FIT, CAR.FREED, CAR.HRV, CAR.ODYSSEY_CHN,
|
||||
CAR.PILOT, CAR.PILOT_2019, CAR.PASSPORT, CAR.RIDGELINE])
|
||||
HONDA_BOSCH = set([CAR.ACCORD, CAR.ACCORDH, CAR.CIVIC_BOSCH, CAR.CIVIC_BOSCH_DIESEL, CAR.CRV_5G, CAR.CRV_HYBRID, CAR.INSIGHT, CAR.ACURA_RDX_3G, CAR.HONDA_E])
|
||||
HONDA_BOSCH = set([CAR.ACCORD, CAR.ACCORDH, CAR.CIVIC_BOSCH, CAR.CIVIC_BOSCH_DIESEL, CAR.CRV_5G,
|
||||
CAR.CRV_HYBRID, CAR.INSIGHT, CAR.ACURA_RDX_3G, CAR.HONDA_E])
|
||||
HONDA_BOSCH_ALT_BRAKE_SIGNAL = set([CAR.ACCORD, CAR.CRV_5G, CAR.ACURA_RDX_3G])
|
||||
|
||||
@@ -28,10 +28,12 @@ class CarState(CarStateBase):
|
||||
|
||||
ret.seatbeltUnlatched = cp.vl["CGW1"]["CF_Gway_DrvSeatBeltSw"] == 0
|
||||
|
||||
ret.wheelSpeeds.fl = cp.vl["WHL_SPD11"]["WHL_SPD_FL"] * CV.KPH_TO_MS
|
||||
ret.wheelSpeeds.fr = cp.vl["WHL_SPD11"]["WHL_SPD_FR"] * CV.KPH_TO_MS
|
||||
ret.wheelSpeeds.rl = cp.vl["WHL_SPD11"]["WHL_SPD_RL"] * CV.KPH_TO_MS
|
||||
ret.wheelSpeeds.rr = cp.vl["WHL_SPD11"]["WHL_SPD_RR"] * CV.KPH_TO_MS
|
||||
ret.wheelSpeeds = self.get_wheel_speeds(
|
||||
cp.vl["WHL_SPD11"]["WHL_SPD_FL"],
|
||||
cp.vl["WHL_SPD11"]["WHL_SPD_FR"],
|
||||
cp.vl["WHL_SPD11"]["WHL_SPD_RL"],
|
||||
cp.vl["WHL_SPD11"]["WHL_SPD_RR"],
|
||||
)
|
||||
ret.vEgoRaw = (ret.wheelSpeeds.fl + ret.wheelSpeeds.fr + ret.wheelSpeeds.rl + ret.wheelSpeeds.rr) / 4.
|
||||
ret.vEgo, ret.aEgo = self.update_speed_kf(ret.vEgoRaw)
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ def create_acc_commands(packer, enabled, accel, jerk, idx, lead_visible, set_spe
|
||||
"CR_VSM_Alive": idx % 0xF,
|
||||
}
|
||||
scc12_dat = packer.make_can_msg("SCC12", 0, scc12_values)[2]
|
||||
scc12_values["CR_VSM_ChkSum"] = 0x10 - sum([sum(divmod(i, 16)) for i in scc12_dat]) % 0x10
|
||||
scc12_values["CR_VSM_ChkSum"] = 0x10 - sum(sum(divmod(i, 16)) for i in scc12_dat) % 0x10
|
||||
|
||||
commands.append(packer.make_can_msg("SCC12", 0, scc12_values))
|
||||
|
||||
@@ -127,7 +127,7 @@ def create_acc_commands(packer, enabled, accel, jerk, idx, lead_visible, set_spe
|
||||
"FCA_Status": 1, # AEB disabled
|
||||
}
|
||||
fca11_dat = packer.make_can_msg("FCA11", 0, fca11_values)[2]
|
||||
fca11_values["CR_FCA_ChkSum"] = 0x10 - sum([sum(divmod(i, 16)) for i in fca11_dat]) % 0x10
|
||||
fca11_values["CR_FCA_ChkSum"] = 0x10 - sum(sum(divmod(i, 16)) for i in fca11_dat) % 0x10
|
||||
commands.append(packer.make_can_msg("FCA11", 0, fca11_values))
|
||||
|
||||
return commands
|
||||
|
||||
@@ -283,6 +283,7 @@ FW_VERSIONS = {
|
||||
b'\xf1\x82DNBWN5TMDCXXXG2E',
|
||||
b'\xf1\x82DNCVN5GMCCXXXF0A',
|
||||
b'\xf1\x82DNCVN5GMCCXXXG2B',
|
||||
b'\xf1\x870\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf1\x82DNDWN5TMDCXXXJ1A',
|
||||
b'\xf1\x87391162M003',
|
||||
b'\xf1\x87391162M013',
|
||||
b'\xf1\x87391162M023',
|
||||
@@ -327,6 +328,8 @@ FW_VERSIONS = {
|
||||
b'\xf1\x87SAKFBA2926554GJ2VefVww\x87xwwwww\x88\x87xww\x87wTo\xfb\xffvUo\xff\x8d\x16\xf1\x81U903\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U903\x00\x00\x00\x00\x00\x00SDN8T16NB0z{\xd4v',
|
||||
b'\xf1\x87SAKFBA3030524GJ2UVugww\x97yx\x88\x87\x88vw\x87gww\x87wto\xf9\xfffUo\xff\xa2\x0c\xf1\x81U903\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U903\x00\x00\x00\x00\x00\x00SDN8T16NB0z{\xd4v',
|
||||
b'\xf1\x87SAKFBA3356084GJ2\x86fvgUUuWgw\x86www\x87wffvf\xb6\xcf\xfc\xffeUO\xff\x12\x19\xf1\x81U903\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U903\x00\x00\x00\x00\x00\x00SDN8T16NB0z{\xd4v',
|
||||
b'\xf1\x87SAKFBA3474944GJ2ffvgwwwwg\x88\x86x\x88\x88\x98\x88ffvfeo\xfa\xff\x86fo\xff\t\xae\xf1\x81U903\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U903\x00\x00\x00\x00\x00\x00SDN8T16NB0z{\xd4v',
|
||||
b'\xf1\x87SAKFBA3475714GJ2Vfvgvg\x96yx\x88\x97\x88ww\x87ww\x88\x87xs_\xfb\xffvUO\xff\x0f\xff\xf1\x81U903\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U903\x00\x00\x00\x00\x00\x00SDN8T16NB0z{\xd4v',
|
||||
b'\xf1\x87SALDBA3510954GJ3ww\x87xUUuWx\x88\x87\x88\x87w\x88wvfwfc_\xf9\xff\x98wO\xffl\xe0\xf1\x89HT6WA910A1\xf1\x82SDN8G25NB1\x00\x00\x00\x00\x00\x00',
|
||||
b'\xf1\x87SALDBA3573534GJ3\x89\x98\x89\x88EUuWgwvwwwwww\x88\x87xTo\xfa\xff\x86f\x7f\xffo\x0e\xf1\x89HT6WA910A1\xf1\x82SDN8G25NB1\x00\x00\x00\x00\x00\x00',
|
||||
b'\xf1\x87SALDBA3601464GJ3\x88\x88\x88\x88ffvggwvwvw\x87gww\x87wvo\xfb\xff\x98\x88\x7f\xffjJ\xf1\x89HT6WA910A1\xf1\x82SDN8G25NB1\x00\x00\x00\x00\x00\x00',
|
||||
@@ -336,21 +339,27 @@ FW_VERSIONS = {
|
||||
b'\xf1\x87SALDBA4525334GJ3\x89\x99\x99\x99fevWh\x88\x86\x88fwvgw\x88\x87xfo\xfa\xffuDo\xff\xd1>\xf1\x89HT6WA910A1\xf1\x82SDN8G25NB1\x00\x00\x00\x00\x00\x00',
|
||||
b'\xf1\x87SALDBA4626804GJ3wwww\x88\x87\x88xx\x88\x87\x88wwgw\x88\x88\x98\x88\x95_\xf9\xffuDo\xff|\xe7\xf1\x89HT6WA910A1\xf1\x82SDN8G25NB1\x00\x00\x00\x00\x00\x00',
|
||||
b'\xf1\x87SALDBA4803224GJ3wwwwwvwg\x88\x88\x98\x88wwww\x87\x88\x88xu\x9f\xfc\xff\x87f\x8f\xff\xea\xea\xf1\x89HT6WA910A1\xf1\x82SDN8G25NB1\x00\x00\x00\x00\x00\x00',
|
||||
b'\xf1\x87SALDBA6212564GJ3\x87wwwUTuGg\x88\x86xx\x88\x87\x88\x87\x88\x98xu?\xf9\xff\x97f\x7f\xff\xb8\n\xf1\x89HT6WA910A1\xf1\x82SDN8G25NB1\x00\x00\x00\x00\x00\x00',
|
||||
b'\xf1\x87SALDBA6347404GJ3wwwwff\x86hx\x88\x97\x88\x88\x88\x88\x88vfgf\x88?\xfc\xff\x86Uo\xff\xec/\xf1\x89HT6WA910A1\xf1\x82SDN8G25NB1\x00\x00\x00\x00\x00\x00',
|
||||
b'\xf1\x87SALDBA6901634GJ3UUuWVeVUww\x87wwwwwvUge\x86/\xfb\xff\xbb\x99\x7f\xff]2\xf1\x89HT6WA910A1\xf1\x82SDN8G25NB1\x00\x00\x00\x00\x00\x00',
|
||||
b'\xf1\x87SALDBA7077724GJ3\x98\x88\x88\x88ww\x97ygwvwww\x87ww\x88\x87x\x87_\xfd\xff\xba\x99o\xff\x99\x01\xf1\x89HT6WA910A1\xf1\x82SDN8G25NB1\x00\x00\x00\x00\x00\x00',
|
||||
b'\xf1\x87SALFBA3525114GJ2wvwgvfvggw\x86wffvffw\x86g\x85_\xf9\xff\xa8wo\xffv\xcd\xf1\x81U903\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U903\x00\x00\x00\x00\x00\x00SDN8T16NB0z{\xd4v',
|
||||
b'\xf1\x87SALFBA3624024GJ2\x88\x88\x88\x88wv\x87hx\x88\x97\x88x\x88\x97\x88ww\x87w\x86o\xfa\xffvU\x7f\xff\xd1\xec\xf1\x81U903\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U903\x00\x00\x00\x00\x00\x00SDN8T16NB0z{\xd4v',
|
||||
b'\xf1\x87SALFBA3960824GJ2wwwwff\x86hffvfffffvfwfg_\xf9\xff\xa9\x88\x8f\xffb\x99\xf1\x81U903\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U903\x00\x00\x00\x00\x00\x00SDN8T16NB0z{\xd4v',
|
||||
b'\xf1\x87SALFBA4011074GJ2fgvwwv\x87hw\x88\x87xww\x87wwfgvu_\xfa\xffefo\xff\x87\xc0\xf1\x81U903\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U903\x00\x00\x00\x00\x00\x00SDN8T16NB0z{\xd4v',
|
||||
b'\xf1\x87SALFBA4121304GJ2x\x87xwff\x86hwwwwww\x87wwwww\x84_\xfc\xff\x98\x88\x9f\xffi\xa6\xf1\x81U903\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U903\x00\x00\x00\x00\x00\x00SDN8T16NB0z{\xd4v',
|
||||
b'\xf1\x87SALFBA4195874GJ2EVugvf\x86hgwvwww\x87wgw\x86wc_\xfb\xff\x98\x88\x8f\xff\xe23\xf1\x81U903\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U903\x00\x00\x00\x00\x00\x00SDN8T16NB0z{\xd4v',
|
||||
b'\xf1\x87SALFBA4625294GJ2eVefeUeVx\x88\x97\x88wwwwwwww\xa7o\xfb\xffvw\x9f\xff\xee.\xf1\x81U903\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U903\x00\x00\x00\x00\x00\x00SDN8T16NB0z{\xd4v',
|
||||
b'\xf1\x87SALFBA4728774GJ2vfvg\x87vwgww\x87ww\x88\x97xww\x87w\x86_\xfb\xffeD?\xffk0\xf1\x81U903\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U903\x00\x00\x00\x00\x00\x00SDN8T16NB0z{\xd4v',
|
||||
b'\xf1\x87SALFBA5129064GJ2vfvgwv\x87hx\x88\x87\x88ww\x87www\x87wd_\xfa\xffvfo\xff\x1d\x00\xf1\x81U903\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U903\x00\x00\x00\x00\x00\x00SDN8T16NB0z{\xd4v',
|
||||
b'\xf1\x87SALFBA5454914GJ2\x98\x88\x88\x88\x87vwgx\x88\x87\x88xww\x87ffvf\xa7\x7f\xf9\xff\xa8w\x7f\xff\x1b\x90\xf1\x81U903\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U903\x00\x00\x00\x00\x00\x00SDN8T16NB0z{\xd4v',
|
||||
b'\xf1\x87SALFBA5987784GJ2UVugDDtGx\x88\x87\x88w\x88\x87xwwwwd/\xfb\xff\x97fO\xff\xb0h\xf1\x81U903\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U903\x00\x00\x00\x00\x00\x00SDN8T16NB0z{\xd4v',
|
||||
b'\xf1\x87SALFBA5987864GJ2fgvwUUuWgwvw\x87wxwwwww\x84/\xfc\xff\x97w\x7f\xff\xdf\x1d\xf1\x81U903\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U903\x00\x00\x00\x00\x00\x00SDN8T16NB0z{\xd4v',
|
||||
b'\xf1\x87SALFBA6337644GJ2vgvwwv\x87hgffvwwwwwwww\x85O\xfa\xff\xa7w\x7f\xff\xc5\xfc\xf1\x81U903\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U903\x00\x00\x00\x00\x00\x00SDN8T16NB0z{\xd4v',
|
||||
b'\xf1\x87SALFBA6802004GJ2UUuWUUuWgw\x86www\x87www\x87w\x96?\xf9\xff\xa9\x88\x7f\xff\x9fK\xf1\x81U903\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U903\x00\x00\x00\x00\x00\x00SDN8T16NB0z{\xd4v',
|
||||
b'\xf1\x87SALFBA6892284GJ233S5\x87w\x87xx\x88\x87\x88vwwgww\x87w\x84?\xfb\xff\x98\x88\x8f\xff*\x9e\xf1\x81U903\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U903\x00\x00\x00\x00\x00\x00SDN8T16NB0z{\xd4v',
|
||||
b'\xf1\x87SALFBA7005534GJ2eUuWfg\x86xxww\x87x\x88\x87\x88\x88w\x88\x87\x87O\xfc\xffuUO\xff\xa3k\xf1\x81U913\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U913\x00\x00\x00\x00\x00\x00SDN8T16NB1\xe3\xc10\xa1',
|
||||
b'\xf1\x87SALFBA7152454GJ2gvwgFf\x86hx\x88\x87\x88vfWfffffd?\xfa\xff\xba\x88o\xff,\xcf\xf1\x81U913\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U913\x00\x00\x00\x00\x00\x00SDN8T16NB1\xe3\xc10\xa1',
|
||||
b'\xf1\x87SALFBA7485034GJ2ww\x87xww\x87xfwvgwwwwvfgf\xa5/\xfc\xff\xa9w_\xff40\xf1\x81U913\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U913\x00\x00\x00\x00\x00\x00SDN8T16NB2\n\xdd^\xbc',
|
||||
b'\xf1\x87SAMDBA7743924GJ3wwwwww\x87xgwvw\x88\x88\x88\x88wwww\x85_\xfa\xff\x86f\x7f\xff0\x9d\xf1\x89HT6WAD10A1\xf1\x82SDN8G25NB2\x00\x00\x00\x00\x00\x00',
|
||||
b'\xf1\x87SAMDBA7817334GJ3Vgvwvfvgww\x87wwwwwwfgv\x97O\xfd\xff\x88\x88o\xff\x8e\xeb\xf1\x89HT6WAD10A1\xf1\x82SDN8G25NB2\x00\x00\x00\x00\x00\x00',
|
||||
@@ -529,6 +538,7 @@ FW_VERSIONS = {
|
||||
b'\xf1\x00LX2_ SCC FHCUP 1.00 1.00 99110-S8110 ',
|
||||
b'\xf1\x00LX2_ SCC FHCUP 1.00 1.04 99110-S8100 ',
|
||||
b'\xf1\x00LX2_ SCC FHCUP 1.00 1.05 99110-S8100 ',
|
||||
b'\xf1\x00ON__ FCA FHCUP 1.00 1.02 99110-S9100 ',
|
||||
],
|
||||
(Ecu.esp, 0x7d1, None): [
|
||||
b'\xf1\x00LX ESC \x01 103\x19\t\x10 58910-S8360',
|
||||
@@ -595,11 +605,18 @@ FW_VERSIONS = {
|
||||
b'\xf1\x87LDLVBN757883KF37\x98\x87xw\x98\x87\x88xy\xaa\xb7\x9ag\x88\x96x\x89\x99\xa8\x99e\x7f\xf6\xff\xa9\x88o\xff5\x15\xf1\x81U922\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U922\x00\x00\x00\x00\x00\x00SLX4G38NB4\xd6\xe8\xd7\xa6',
|
||||
b'\xf1\x87LDMVBN778156KF37\x87vWe\xa9\x99\x99\x99y\x99\xb7\x99\x99\x99\x99\x99x\x99\x97\x89\xa8\x7f\xf8\xffwf\x7f\xff\x82_\xf1\x81U922\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U922\x00\x00\x00\x00\x00\x00SLX4G38NB4\xd6\xe8\xd7\xa6',
|
||||
b'\xf1\x87LDMVBN780576KF37\x98\x87hv\x97x\x97\x89x\x99\xa7\x89\x88\x99\x98\x89w\x88\x97x\x98\x7f\xf7\xff\xba\x88\x8f\xff\x1e0\xf1\x81U922\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U922\x00\x00\x00\x00\x00\x00SLX4G38NB4\xd6\xe8\xd7\xa6',
|
||||
b'\xf1\x87LDMVBN783485KF37\x87www\x87vwgy\x99\xa7\x99\x99\x99\xa9\x99Vw\x95g\x89_\xf6\xff\xa9w_\xff\xc5\xd6\xf1\x81U922\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U922\x00\x00\x00\x00\x00\x00SLX4G38NB4\xd6\xe8\xd7\xa6',
|
||||
b'\xf1\x87LDMVBN811844KF37\x87vwgvfffx\x99\xa7\x89Vw\x95gg\x88\xa6xe\x8f\xf6\xff\x97wO\xff\t\x80\xf1\x81U922\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U922\x00\x00\x00\x00\x00\x00SLX4G38NB4\xd6\xe8\xd7\xa6',
|
||||
b'\xf1\x87LDMVBN830601KF37\xa7www\xa8\x87xwx\x99\xa7\x89Uw\x85Ww\x88\x97x\x88o\xf6\xff\x8a\xaa\x7f\xff\xe2:\xf1\x81U922\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U922\x00\x00\x00\x00\x00\x00SLX4G38NB4\xd6\xe8\xd7\xa6',
|
||||
b'\xf1\x87LDMVBN848789KF37\x87w\x87x\x87w\x87xy\x99\xb7\x99\x87\x88\x98x\x88\x99\xa8\x89\x87\x7f\xf6\xfffUo\xff\xe3!\xf1\x81U922\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U922\x00\x00\x00\x00\x00\x00SLX4G38NB5\xb9\x94\xe8\x89',
|
||||
b'\xf1\x87LDMVBN851595KF37\x97wgvvfffx\x99\xb7\x89\x88\x99\x98\x89\x87\x88\x98x\x99\x7f\xf7\xff\x97w\x7f\xff@\xf3\xf1\x81U922\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U922\x00\x00\x00\x00\x00\x00SLX4G38NB5\xb9\x94\xe8\x89',
|
||||
b'\xf1\x87LDMVBN873175KF26\xa8\x88\x88\x88vfVex\x99\xb7\x89\x88\x99\x98\x89x\x88\x97\x88f\x7f\xf7\xff\xbb\xaa\x8f\xff,\x04\xf1\x81U922\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U922\x00\x00\x00\x00\x00\x00SLX4G38NB5\xb9\x94\xe8\x89',
|
||||
b'\xf1\x87LDMVBN879401KF26veVU\xa8\x88\x88\x88g\x88\xa6xVw\x95gx\x88\xa7\x88v\x8f\xf9\xff\xdd\xbb\xbf\xff\xb3\x99\xf1\x81U922\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U922\x00\x00\x00\x00\x00\x00SLX4G38NB5\xb9\x94\xe8\x89',
|
||||
b'\xf1\x87LDMVBN881314KF37\xa8\x88h\x86\x97www\x89\x99\xa8\x99w\x88\x97xx\x99\xa7\x89\xca\x7f\xf8\xff\xba\x99\x8f\xff\xd8v\xf1\x81U922\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U922\x00\x00\x00\x00\x00\x00SLX4G38NB5\xb9\x94\xe8\x89',
|
||||
b'\xf1\x87LDMVBN888651KF37\xa9\x99\x89\x98vfff\x88\x99\x98\x89w\x99\xa7y\x88\x88\x98\x88D\x8f\xf9\xff\xcb\x99\x8f\xff\xa5\x1e\xf1\x81U922\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U922\x00\x00\x00\x00\x00\x00SLX4G38NB5\xb9\x94\xe8\x89',
|
||||
b'\xf1\x87LDMVBN889419KF37\xa9\x99y\x97\x87w\x87xx\x88\x97\x88w\x88\x97x\x88\x99\x98\x89e\x9f\xf9\xffeUo\xff\x901\xf1\x81U922\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U922\x00\x00\x00\x00\x00\x00SLX4G38NB5\xb9\x94\xe8\x89',
|
||||
b'\xf1\x87LDMVBN895969KF37vefV\x87vgfx\x99\xa7\x89\x99\x99\xb9\x99f\x88\x96he_\xf7\xffxwo\xff\x14\xf9\xf1\x81U922\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U922\x00\x00\x00\x00\x00\x00SLX4G38NB5\xb9\x94\xe8\x89',
|
||||
b'\xf1\x87LDMVBN899222KF37\xa8\x88x\x87\x97www\x98\x99\x99\x89\x88\x99\x98\x89f\x88\x96hdo\xf7\xff\xbb\xaa\x9f\xff\xe2U\xf1\x81U922\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U922\x00\x00\x00\x00\x00\x00SLX4G38NB5\xb9\x94\xe8\x89',
|
||||
b"\xf1\x87LBLUFN622950KF36\xa8\x88\x88\x88\x87w\x87xh\x99\x96\x89\x88\x99\x98\x89\x88\x99\x98\x89\x87o\xf6\xff\x98\x88o\xffx'\xf1\x81U891\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U891\x00\x00\x00\x00\x00\x00SLX2G38NB3\xd1\xc3\xf8\xa8",
|
||||
],
|
||||
},
|
||||
@@ -672,6 +689,7 @@ FW_VERSIONS = {
|
||||
CAR.KIA_FORTE: {
|
||||
(Ecu.eps, 0x7D4, None): [
|
||||
b'\xf1\x00BD MDPS C 1.00 1.02 56310-XX000 4BD2C102',
|
||||
b'\xf1\x00BD MDPS C 1.00 1.08 56310/M6300 4BDDC108',
|
||||
b'\xf1\x00BD MDPS C 1.00 1.08 56310M6300\x00 4BDDC108',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x7C4, None): [
|
||||
@@ -688,6 +706,7 @@ FW_VERSIONS = {
|
||||
b'\xf1\x816VGRAH00018.ELF\xf1\x00\x00\x00\x00\x00\x00\x00',
|
||||
],
|
||||
(Ecu.transmission, 0x7e1, None): [
|
||||
b'\xf1\x816U2VC051\x00\x00\xf1\x006U2V0_C2\x00\x006U2VC051\x00\x00DBD0T16SS0\x00\x00\x00\x00',
|
||||
b"\xf1\x816U2VC051\x00\x00\xf1\x006U2V0_C2\x00\x006U2VC051\x00\x00DBD0T16SS0\xcf\x1e'\xc3",
|
||||
],
|
||||
},
|
||||
@@ -696,28 +715,34 @@ FW_VERSIONS = {
|
||||
b'\xf1\000DL3_ SCC FHCUP 1.00 1.03 99110-L2000 ',
|
||||
b'\xf1\x8799110L2000\xf1\000DL3_ SCC FHCUP 1.00 1.03 99110-L2000 ',
|
||||
b'\xf1\x8799110L2100\xf1\x00DL3_ SCC F-CUP 1.00 1.03 99110-L2100 ',
|
||||
b'\xf1\x8799110L2100\xf1\x00DL3_ SCC FHCUP 1.00 1.03 99110-L2100 ',
|
||||
],
|
||||
(Ecu.eps, 0x7D4, None): [
|
||||
b'\xf1\x8756310-L3110\xf1\000DL3 MDPS C 1.00 1.01 56310-L3110 4DLAC101',
|
||||
b'\xf1\x8756310-L3220\xf1\x00DL3 MDPS C 1.00 1.01 56310-L3220 4DLAC101',
|
||||
b'\xf1\x8757700-L3000\xf1\x00DL3 MDPS R 1.00 1.02 57700-L3000 4DLAP102',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x7C4, None): [
|
||||
b'\xf1\x00DL3 MFC AT USA LHD 1.00 1.03 99210-L3000 200915',
|
||||
b'\xf1\x00DL3 MFC AT USA LHD 1.00 1.04 99210-L3000 210208',
|
||||
],
|
||||
(Ecu.esp, 0x7D1, None): [
|
||||
b'\xf1\000DL ESC \006 101 \004\002 58910-L3200',
|
||||
b'\xf1\x8758910-L3200\xf1\000DL ESC \006 101 \004\002 58910-L3200',
|
||||
b'\xf1\x8758910-L3800\xf1\x00DL ESC \t 101 \x07\x02 58910-L3800',
|
||||
b'\xf1\x8758910-L3600\xf1\x00DL ESC \x03 100 \x08\x02 58910-L3600',
|
||||
],
|
||||
(Ecu.engine, 0x7E0, None): [
|
||||
b'\xf1\x87391212MKT0',
|
||||
b'\xf1\x87391212MKV0',
|
||||
b'\xf1\x870\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf1\x82DLDWN5TMDCXXXJ1B',
|
||||
],
|
||||
(Ecu.transmission, 0x7E1, None): [
|
||||
b'\xf1\000bcsh8p54 U913\000\000\000\000\000\000TDL2T16NB1ia\v\xb8',
|
||||
b'\xf1\x87SALFEA5652514GK2UUeV\x88\x87\x88xxwg\x87ww\x87wwfwvd/\xfb\xffvU_\xff\x93\xd3\xf1\x81U913\000\000\000\000\000\000\xf1\000bcsh8p54 U913\000\000\000\000\000\000TDL2T16NB1ia\v\xb8',
|
||||
b'\xf1\x87SALFEA6046104GK2wvwgeTeFg\x88\x96xwwwwffvfe?\xfd\xff\x86fo\xff\x97A\xf1\x81U913\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U913\x00\x00\x00\x00\x00\x00TDL2T16NB1ia\x0b\xb8',
|
||||
b'\xf1\x87SCMSAA8572454GK1\x87x\x87\x88Vf\x86hgwvwvwwgvwwgT?\xfb\xff\x97fo\xffH\xb8\xf1\x81U913\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U913\x00\x00\x00\x00\x00\x00TDL4T16NB05\x94t\x18',
|
||||
b'\xf1\x87954A02N300\x00\x00\x00\x00\x00\xf1\x81T02730A1 \xf1\x00T02601BL T02730A1 WDL3T25XXX730NS2b\x1f\xb8%',
|
||||
],
|
||||
},
|
||||
CAR.KONA_EV: {
|
||||
@@ -750,6 +775,7 @@ FW_VERSIONS = {
|
||||
CAR.KIA_NIRO_EV: {
|
||||
(Ecu.fwdRadar, 0x7D0, None): [
|
||||
b'\xf1\x00DEev SCC F-CUP 1.00 1.00 99110-Q4000 ',
|
||||
b'\xf1\x00DEev SCC F-CUP 1.00 1.02 96400-Q4100 ',
|
||||
b'\xf1\x00DEev SCC F-CUP 1.00 1.03 96400-Q4100 ',
|
||||
b'\xf1\x00OSev SCC F-CUP 1.00 1.01 99110-K4000 ',
|
||||
b'\xf1\x8799110Q4000\xf1\x00DEev SCC F-CUP 1.00 1.00 99110-Q4000 ',
|
||||
@@ -842,13 +868,17 @@ FW_VERSIONS = {
|
||||
b'\xf1\x89F1JF600AISEIU702\xf1\x82F1JF600AISEIU702',
|
||||
],
|
||||
(Ecu.eps, 0x7d4, None): [b'\xf1\x00TM MDPS C 1.00 1.00 56340-S2000 8409'],
|
||||
(Ecu.fwdCamera, 0x7c4, None): [b'\xf1\x00JFA LKAS AT USA LHD 1.00 1.02 95895-D5000 h31'],
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00JFA LKAS AT USA LHD 1.00 1.00 95895-D5001 h32',
|
||||
b'\xf1\x00JFA LKAS AT USA LHD 1.00 1.02 95895-D5000 h31',
|
||||
],
|
||||
(Ecu.transmission, 0x7e1, None): [b'\xf1\x816U2V8051\x00\x00\xf1\x006U2V0_C2\x00\x006U2V8051\x00\x00DJF0T16NL0\t\xd2GW'],
|
||||
},
|
||||
CAR.ELANTRA_2021: {
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00CN7_ SCC FHCUP 1.00 1.01 99110-AA000 ',
|
||||
b'\xf1\x00CN7_ SCC F-CUP 1.00 1.01 99110-AA000 ',
|
||||
b'\xf1\x00CN7_ SCC FHCUP 1.00 1.01 99110-AA000 ',
|
||||
b'\xf1\x8799110AA000\xf1\x00CN7_ SCC FHCUP 1.00 1.01 99110-AA000 ',
|
||||
],
|
||||
(Ecu.eps, 0x7d4, None): [
|
||||
b'\xf1\x87\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf1\x00CN7 MDPS C 1.00 1.06 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 4CNDC106',
|
||||
|
||||
@@ -14,9 +14,7 @@ from selfdrive.controls.lib.vehicle_model import VehicleModel
|
||||
GearShifter = car.CarState.GearShifter
|
||||
EventName = car.CarEvent.EventName
|
||||
|
||||
# WARNING: this value was determined based on the model's training distribution,
|
||||
# model predictions above this speed can be unpredictable
|
||||
MAX_CTRL_SPEED = (V_CRUISE_MAX + 4) * CV.KPH_TO_MS # 135 + 4 = 86 mph
|
||||
MAX_CTRL_SPEED = (V_CRUISE_MAX + 4) * CV.KPH_TO_MS
|
||||
ACCEL_MAX = 2.0
|
||||
ACCEL_MIN = -3.5
|
||||
|
||||
@@ -78,6 +76,7 @@ class CarInterfaceBase():
|
||||
ret.steerMaxBP = [0.]
|
||||
ret.steerMaxV = [1.]
|
||||
ret.minSteerSpeed = 0.
|
||||
ret.wheelSpeedFactor = 1.0
|
||||
|
||||
ret.pcmCruise = True # openpilot's state is tied to the PCM's cruise state on most cars
|
||||
ret.minEnableSpeed = -1. # enable is done by stock ACC, so ignore this
|
||||
@@ -210,6 +209,16 @@ class CarStateBase:
|
||||
v_ego_x = self.v_ego_kf.update(v_ego_raw)
|
||||
return float(v_ego_x[0]), float(v_ego_x[1])
|
||||
|
||||
def get_wheel_speeds(self, fl, fr, rl, rr, unit=CV.KPH_TO_MS):
|
||||
factor = unit * self.CP.wheelSpeedFactor
|
||||
|
||||
wheelSpeeds = car.CarState.WheelSpeeds.new_message()
|
||||
wheelSpeeds.fl = fl * factor
|
||||
wheelSpeeds.fr = fr * factor
|
||||
wheelSpeeds.rl = rl * factor
|
||||
wheelSpeeds.rr = rr * factor
|
||||
return wheelSpeeds
|
||||
|
||||
def update_blinker_from_lamp(self, blinker_time: int, left_blinker_lamp: bool, right_blinker_lamp: bool):
|
||||
"""Update blinkers from lights. Enable output when light was seen within the last `blinker_time`
|
||||
iterations"""
|
||||
|
||||
@@ -20,10 +20,12 @@ class CarState(CarStateBase):
|
||||
def update(self, cp, cp_cam):
|
||||
|
||||
ret = car.CarState.new_message()
|
||||
ret.wheelSpeeds.fl = cp.vl["WHEEL_SPEEDS"]["FL"] * CV.KPH_TO_MS
|
||||
ret.wheelSpeeds.fr = cp.vl["WHEEL_SPEEDS"]["FR"] * CV.KPH_TO_MS
|
||||
ret.wheelSpeeds.rl = cp.vl["WHEEL_SPEEDS"]["RL"] * CV.KPH_TO_MS
|
||||
ret.wheelSpeeds.rr = cp.vl["WHEEL_SPEEDS"]["RR"] * CV.KPH_TO_MS
|
||||
ret.wheelSpeeds = self.get_wheel_speeds(
|
||||
cp.vl["WHEEL_SPEEDS"]["FL"],
|
||||
cp.vl["WHEEL_SPEEDS"]["FR"],
|
||||
cp.vl["WHEEL_SPEEDS"]["RL"],
|
||||
cp.vl["WHEEL_SPEEDS"]["RR"],
|
||||
)
|
||||
ret.vEgoRaw = (ret.wheelSpeeds.fl + ret.wheelSpeeds.fr + ret.wheelSpeeds.rl + ret.wheelSpeeds.rr) / 4.
|
||||
ret.vEgo, ret.aEgo = self.update_speed_kf(ret.vEgoRaw)
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ class CAR:
|
||||
CX9 = "MAZDA CX-9"
|
||||
MAZDA3 = "MAZDA 3"
|
||||
MAZDA6 = "MAZDA 6"
|
||||
CX9_2021 = "Mazda CX-9 2021" # No Steer Lockout
|
||||
CX9_2021 = "MAZDA CX-9 2021" # No Steer Lockout
|
||||
|
||||
class LKAS_LIMITS:
|
||||
STEER_THRESHOLD = 15
|
||||
|
||||
@@ -35,11 +35,12 @@ class CarState(CarStateBase):
|
||||
elif self.CP.carFingerprint in [CAR.LEAF, CAR.LEAF_IC]:
|
||||
ret.brakePressed = bool(cp.vl["CRUISE_THROTTLE"]["USER_BRAKE_PRESSED"])
|
||||
|
||||
ret.wheelSpeeds.fl = cp.vl["WHEEL_SPEEDS_FRONT"]["WHEEL_SPEED_FL"] * CV.KPH_TO_MS
|
||||
ret.wheelSpeeds.fr = cp.vl["WHEEL_SPEEDS_FRONT"]["WHEEL_SPEED_FR"] * CV.KPH_TO_MS
|
||||
ret.wheelSpeeds.rl = cp.vl["WHEEL_SPEEDS_REAR"]["WHEEL_SPEED_RL"] * CV.KPH_TO_MS
|
||||
ret.wheelSpeeds.rr = cp.vl["WHEEL_SPEEDS_REAR"]["WHEEL_SPEED_RR"] * CV.KPH_TO_MS
|
||||
|
||||
ret.wheelSpeeds = self.get_wheel_speeds(
|
||||
cp.vl["WHEEL_SPEEDS_FRONT"]["WHEEL_SPEED_FL"],
|
||||
cp.vl["WHEEL_SPEEDS_FRONT"]["WHEEL_SPEED_FR"],
|
||||
cp.vl["WHEEL_SPEEDS_REAR"]["WHEEL_SPEED_RL"],
|
||||
cp.vl["WHEEL_SPEEDS_REAR"]["WHEEL_SPEED_RR"],
|
||||
)
|
||||
ret.vEgoRaw = (ret.wheelSpeeds.fl + ret.wheelSpeeds.fr + ret.wheelSpeeds.rl + ret.wheelSpeeds.rr) / 4.
|
||||
|
||||
ret.vEgo, ret.aEgo = self.update_speed_kf(ret.vEgoRaw)
|
||||
|
||||
@@ -23,10 +23,12 @@ class CarState(CarStateBase):
|
||||
else:
|
||||
ret.brakePressed = cp.vl["Brake_Status"]["Brake"] == 1
|
||||
|
||||
ret.wheelSpeeds.fl = cp.vl["Wheel_Speeds"]["FL"] * CV.KPH_TO_MS
|
||||
ret.wheelSpeeds.fr = cp.vl["Wheel_Speeds"]["FR"] * CV.KPH_TO_MS
|
||||
ret.wheelSpeeds.rl = cp.vl["Wheel_Speeds"]["RL"] * CV.KPH_TO_MS
|
||||
ret.wheelSpeeds.rr = cp.vl["Wheel_Speeds"]["RR"] * CV.KPH_TO_MS
|
||||
ret.wheelSpeeds = self.get_wheel_speeds(
|
||||
cp.vl["Wheel_Speeds"]["FL"],
|
||||
cp.vl["Wheel_Speeds"]["FR"],
|
||||
cp.vl["Wheel_Speeds"]["RL"],
|
||||
cp.vl["Wheel_Speeds"]["RR"],
|
||||
)
|
||||
ret.vEgoRaw = (ret.wheelSpeeds.fl + ret.wheelSpeeds.fr + ret.wheelSpeeds.rl + ret.wheelSpeeds.rr) / 4.
|
||||
# Kalman filter, even though Subaru raw wheel speed is heaviliy filtered by default
|
||||
ret.vEgo, ret.aEgo = self.update_speed_kf(ret.vEgoRaw)
|
||||
|
||||
@@ -1,39 +1,22 @@
|
||||
from cereal import car
|
||||
from common.numpy_fast import clip, interp
|
||||
from selfdrive.car import apply_toyota_steer_torque_limits, create_gas_command, make_can_msg
|
||||
from selfdrive.car import apply_toyota_steer_torque_limits, create_gas_interceptor_command, make_can_msg
|
||||
from selfdrive.car.toyota.toyotacan import create_steer_command, create_ui_command, \
|
||||
create_accel_command, create_acc_cancel_command, \
|
||||
create_fcw_command, create_lta_steer_command
|
||||
from selfdrive.car.toyota.values import CAR, STATIC_DSU_MSGS, NO_STOP_TIMER_CAR, TSS2_CAR, \
|
||||
MIN_ACC_SPEED, PEDAL_HYST_GAP, PEDAL_SCALE, CarControllerParams
|
||||
MIN_ACC_SPEED, PEDAL_TRANSITION, CarControllerParams
|
||||
from opendbc.can.packer import CANPacker
|
||||
VisualAlert = car.CarControl.HUDControl.VisualAlert
|
||||
|
||||
|
||||
def accel_hysteresis(accel, accel_steady, enabled):
|
||||
|
||||
# for small accel oscillations within ACCEL_HYST_GAP, don't change the accel command
|
||||
if not enabled:
|
||||
# send 0 when disabled, otherwise acc faults
|
||||
accel_steady = 0.
|
||||
elif accel > accel_steady + CarControllerParams.ACCEL_HYST_GAP:
|
||||
accel_steady = accel - CarControllerParams.ACCEL_HYST_GAP
|
||||
elif accel < accel_steady - CarControllerParams.ACCEL_HYST_GAP:
|
||||
accel_steady = accel + CarControllerParams.ACCEL_HYST_GAP
|
||||
accel = accel_steady
|
||||
|
||||
return accel, accel_steady
|
||||
|
||||
|
||||
class CarController():
|
||||
def __init__(self, dbc_name, CP, VM):
|
||||
self.last_steer = 0
|
||||
self.accel_steady = 0.
|
||||
self.alert_active = False
|
||||
self.last_standstill = False
|
||||
self.standstill_req = False
|
||||
self.steer_rate_limited = False
|
||||
self.use_interceptor = False
|
||||
|
||||
self.packer = CANPacker(dbc_name)
|
||||
|
||||
@@ -43,25 +26,22 @@ class CarController():
|
||||
# *** compute control surfaces ***
|
||||
|
||||
# gas and brake
|
||||
interceptor_gas_cmd = 0.
|
||||
pcm_accel_cmd = actuators.accel
|
||||
|
||||
if CS.CP.enableGasInterceptor:
|
||||
# handle hysteresis when around the minimum acc speed
|
||||
if CS.out.vEgo < MIN_ACC_SPEED:
|
||||
self.use_interceptor = True
|
||||
elif CS.out.vEgo > MIN_ACC_SPEED + PEDAL_HYST_GAP:
|
||||
self.use_interceptor = False
|
||||
|
||||
if self.use_interceptor and active:
|
||||
# only send negative accel when using interceptor. gas handles acceleration
|
||||
# +0.18 m/s^2 offset to reduce ABS pump usage when OP is engaged
|
||||
MAX_INTERCEPTOR_GAS = interp(CS.out.vEgo, [0.0, MIN_ACC_SPEED], [0.2, 0.5])
|
||||
interceptor_gas_cmd = clip(actuators.accel / PEDAL_SCALE, 0., MAX_INTERCEPTOR_GAS)
|
||||
pcm_accel_cmd = 0.18 - max(0, -actuators.accel)
|
||||
|
||||
pcm_accel_cmd, self.accel_steady = accel_hysteresis(pcm_accel_cmd, self.accel_steady, enabled)
|
||||
pcm_accel_cmd = clip(pcm_accel_cmd, CarControllerParams.ACCEL_MIN, CarControllerParams.ACCEL_MAX)
|
||||
if CS.CP.enableGasInterceptor and enabled:
|
||||
MAX_INTERCEPTOR_GAS = 0.5
|
||||
# RAV4 has very sensitive gas pedal
|
||||
if CS.CP.carFingerprint in [CAR.RAV4, CAR.RAV4H, CAR.HIGHLANDER, CAR.HIGHLANDERH]:
|
||||
PEDAL_SCALE = interp(CS.out.vEgo, [0.0, MIN_ACC_SPEED, MIN_ACC_SPEED + PEDAL_TRANSITION], [0.15, 0.3, 0.0])
|
||||
elif CS.CP.carFingerprint in [CAR.COROLLA]:
|
||||
PEDAL_SCALE = interp(CS.out.vEgo, [0.0, MIN_ACC_SPEED, MIN_ACC_SPEED + PEDAL_TRANSITION], [0.3, 0.4, 0.0])
|
||||
else:
|
||||
PEDAL_SCALE = interp(CS.out.vEgo, [0.0, MIN_ACC_SPEED, MIN_ACC_SPEED + PEDAL_TRANSITION], [0.4, 0.5, 0.0])
|
||||
# offset for creep and windbrake
|
||||
pedal_offset = interp(CS.out.vEgo, [0.0, 2.3, MIN_ACC_SPEED + PEDAL_TRANSITION], [-.4, 0.0, 0.2])
|
||||
pedal_command = PEDAL_SCALE * (actuators.accel + pedal_offset)
|
||||
interceptor_gas_cmd = clip(pedal_command, 0., MAX_INTERCEPTOR_GAS)
|
||||
else:
|
||||
interceptor_gas_cmd = 0.
|
||||
pcm_accel_cmd = clip(actuators.accel, CarControllerParams.ACCEL_MIN, CarControllerParams.ACCEL_MAX)
|
||||
|
||||
# steer torque
|
||||
new_steer = int(round(actuators.steer * CarControllerParams.STEER_MAX))
|
||||
@@ -88,7 +68,6 @@ class CarController():
|
||||
self.standstill_req = False
|
||||
|
||||
self.last_steer = apply_steer
|
||||
self.last_accel = pcm_accel_cmd
|
||||
self.last_standstill = CS.out.standstill
|
||||
|
||||
can_sends = []
|
||||
@@ -113,7 +92,7 @@ class CarController():
|
||||
lead = lead or CS.out.vEgo < 12. # at low speed we always assume the lead is present do ACC can be engaged
|
||||
|
||||
# Lexus IS uses a different cancellation message
|
||||
if pcm_cancel_cmd and CS.CP.carFingerprint == CAR.LEXUS_IS:
|
||||
if pcm_cancel_cmd and CS.CP.carFingerprint in [CAR.LEXUS_IS, CAR.LEXUS_RC]:
|
||||
can_sends.append(create_acc_cancel_command(self.packer))
|
||||
elif CS.CP.openpilotLongitudinalControl:
|
||||
can_sends.append(create_accel_command(self.packer, pcm_accel_cmd, pcm_cancel_cmd, self.standstill_req, lead, CS.acc_type))
|
||||
@@ -123,7 +102,7 @@ class CarController():
|
||||
if frame % 2 == 0 and CS.CP.enableGasInterceptor:
|
||||
# send exactly zero if gas cmd is zero. Interceptor will send the max between read value and gas cmd.
|
||||
# This prevents unexpected pedal range rescaling
|
||||
can_sends.append(create_gas_command(self.packer, interceptor_gas_cmd, frame // 2))
|
||||
can_sends.append(create_gas_interceptor_command(self.packer, interceptor_gas_cmd, frame // 2))
|
||||
|
||||
# ui mesg is at 100Hz but we send asap if:
|
||||
# - there is something to display
|
||||
|
||||
@@ -41,10 +41,12 @@ class CarState(CarStateBase):
|
||||
ret.gas = cp.vl["GAS_PEDAL"]["GAS_PEDAL"]
|
||||
ret.gasPressed = cp.vl["PCM_CRUISE"]["GAS_RELEASED"] == 0
|
||||
|
||||
ret.wheelSpeeds.fl = cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_FL"] * CV.KPH_TO_MS
|
||||
ret.wheelSpeeds.fr = cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_FR"] * CV.KPH_TO_MS
|
||||
ret.wheelSpeeds.rl = cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_RL"] * CV.KPH_TO_MS
|
||||
ret.wheelSpeeds.rr = cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_RR"] * CV.KPH_TO_MS
|
||||
ret.wheelSpeeds = self.get_wheel_speeds(
|
||||
cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_FL"],
|
||||
cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_FR"],
|
||||
cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_RL"],
|
||||
cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_RR"],
|
||||
)
|
||||
ret.vEgoRaw = mean([ret.wheelSpeeds.fl, ret.wheelSpeeds.fr, ret.wheelSpeeds.rl, ret.wheelSpeeds.rr])
|
||||
ret.vEgo, ret.aEgo = self.update_speed_kf(ret.vEgoRaw)
|
||||
|
||||
@@ -79,7 +81,7 @@ class CarState(CarStateBase):
|
||||
ret.steeringPressed = abs(ret.steeringTorque) > STEER_THRESHOLD
|
||||
ret.steerWarning = cp.vl["EPS_STATUS"]["LKA_STATE"] not in [1, 5]
|
||||
|
||||
if self.CP.carFingerprint == CAR.LEXUS_IS:
|
||||
if self.CP.carFingerprint in [CAR.LEXUS_IS, CAR.LEXUS_RC]:
|
||||
ret.cruiseState.available = cp.vl["DSU_CRUISE"]["MAIN_ON"] != 0
|
||||
ret.cruiseState.speed = cp.vl["DSU_CRUISE"]["SET_SPEED"] * CV.KPH_TO_MS
|
||||
else:
|
||||
@@ -93,7 +95,7 @@ class CarState(CarStateBase):
|
||||
# these cars are identified by an ACC_TYPE value of 2.
|
||||
# TODO: it is possible to avoid the lockout and gain stop and go if you
|
||||
# send your own ACC_CONTROL msg on startup with ACC_TYPE set to 1
|
||||
if (self.CP.carFingerprint not in TSS2_CAR and self.CP.carFingerprint != CAR.LEXUS_IS) or \
|
||||
if (self.CP.carFingerprint not in TSS2_CAR and self.CP.carFingerprint not in [CAR.LEXUS_IS, CAR.LEXUS_RC]) or \
|
||||
(self.CP.carFingerprint in TSS2_CAR and self.acc_type == 1):
|
||||
self.low_speed_lockout = cp.vl["PCM_CRUISE_2"]["LOW_SPEED_LOCKOUT"] == 2
|
||||
|
||||
@@ -168,7 +170,7 @@ class CarState(CarStateBase):
|
||||
("STEER_TORQUE_SENSOR", 50),
|
||||
]
|
||||
|
||||
if CP.carFingerprint == CAR.LEXUS_IS:
|
||||
if CP.carFingerprint in [CAR.LEXUS_IS, CAR.LEXUS_RC]:
|
||||
signals.append(("MAIN_ON", "DSU_CRUISE", 0))
|
||||
signals.append(("SET_SPEED", "DSU_CRUISE", 0))
|
||||
checks.append(("DSU_CRUISE", 5))
|
||||
|
||||
@@ -65,7 +65,6 @@ class CarInterface(CarInterfaceBase):
|
||||
ret.mass = 4387. * CV.LB_TO_KG + STD_CARGO_KG
|
||||
set_lat_tune(ret.lateralTuning, LatTunes.PID_B)
|
||||
|
||||
|
||||
elif candidate == CAR.LEXUS_RXH:
|
||||
stop_and_go = True
|
||||
ret.wheelbase = 2.79
|
||||
@@ -81,6 +80,7 @@ class CarInterface(CarInterfaceBase):
|
||||
tire_stiffness_factor = 0.5533 # not optimized yet
|
||||
ret.mass = 4387. * CV.LB_TO_KG + STD_CARGO_KG
|
||||
set_lat_tune(ret.lateralTuning, LatTunes.PID_D)
|
||||
ret.wheelSpeedFactor = 1.035
|
||||
|
||||
elif candidate == CAR.LEXUS_RXH_TSS2:
|
||||
stop_and_go = True
|
||||
@@ -89,6 +89,7 @@ class CarInterface(CarInterfaceBase):
|
||||
tire_stiffness_factor = 0.444 # not optimized yet
|
||||
ret.mass = 4481.0 * CV.LB_TO_KG + STD_CARGO_KG # mean between min and max
|
||||
set_lat_tune(ret.lateralTuning, LatTunes.PID_E)
|
||||
ret.wheelSpeedFactor = 1.035
|
||||
|
||||
elif candidate in [CAR.CHR, CAR.CHRH]:
|
||||
stop_and_go = True
|
||||
@@ -186,6 +187,15 @@ class CarInterface(CarInterfaceBase):
|
||||
ret.mass = 3736.8 * CV.LB_TO_KG + STD_CARGO_KG
|
||||
set_lat_tune(ret.lateralTuning, LatTunes.PID_L)
|
||||
|
||||
elif candidate == CAR.LEXUS_RC:
|
||||
ret.safetyConfigs[0].safetyParam = 77
|
||||
stop_and_go = False
|
||||
ret.wheelbase = 2.73050
|
||||
ret.steerRatio = 13.3
|
||||
tire_stiffness_factor = 0.444
|
||||
ret.mass = 3736.8 * CV.LB_TO_KG + STD_CARGO_KG
|
||||
set_lat_tune(ret.lateralTuning, LatTunes.PID_L)
|
||||
|
||||
elif candidate == CAR.LEXUS_CTH:
|
||||
ret.safetyConfigs[0].safetyParam = 100
|
||||
stop_and_go = True
|
||||
@@ -206,7 +216,7 @@ class CarInterface(CarInterfaceBase):
|
||||
elif candidate == CAR.PRIUS_TSS2:
|
||||
stop_and_go = True
|
||||
ret.wheelbase = 2.70002 # from toyota online sepc.
|
||||
ret.steerRatio = 13.4 # True steerRation from older prius
|
||||
ret.steerRatio = 13.4 # True steerRatio from older prius
|
||||
tire_stiffness_factor = 0.6371 # hand-tune
|
||||
ret.mass = 3115. * CV.LB_TO_KG + STD_CARGO_KG
|
||||
set_lat_tune(ret.lateralTuning, LatTunes.PID_N)
|
||||
@@ -259,7 +269,8 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
if ret.enableGasInterceptor:
|
||||
set_long_tune(ret.longitudinalTuning, LongTunes.PEDAL)
|
||||
elif candidate in [CAR.COROLLA_TSS2, CAR.COROLLAH_TSS2, CAR.RAV4_TSS2, CAR.RAV4H_TSS2, CAR.LEXUS_NX_TSS2]:
|
||||
elif candidate in [CAR.COROLLA_TSS2, CAR.COROLLAH_TSS2, CAR.RAV4_TSS2, CAR.RAV4H_TSS2, CAR.LEXUS_NX_TSS2,
|
||||
CAR.HIGHLANDER_TSS2, CAR.HIGHLANDERH_TSS2, CAR.PRIUS_TSS2]:
|
||||
set_long_tune(ret.longitudinalTuning, LongTunes.TSS2)
|
||||
ret.stoppingDecelRate = 0.3 # reach stopping target smoothly
|
||||
ret.startingAccelRate = 6.0 # release brakes fast
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
from enum import Enum
|
||||
from selfdrive.car.toyota.values import MIN_ACC_SPEED, PEDAL_HYST_GAP
|
||||
|
||||
|
||||
class LongTunes(Enum):
|
||||
@@ -29,15 +28,8 @@ class LatTunes(Enum):
|
||||
|
||||
###### LONG ######
|
||||
def set_long_tune(tune, name):
|
||||
if name == LongTunes.PEDAL:
|
||||
tune.deadzoneBP = [0.]
|
||||
tune.deadzoneV = [0.]
|
||||
tune.kpBP = [0., 5., MIN_ACC_SPEED, MIN_ACC_SPEED + PEDAL_HYST_GAP, 35.]
|
||||
tune.kpV = [1.2, 0.8, 0.765, 2.255, 1.5]
|
||||
tune.kiBP = [0., MIN_ACC_SPEED, MIN_ACC_SPEED + PEDAL_HYST_GAP, 35.]
|
||||
tune.kiV = [0.18, 0.165, 0.489, 0.36]
|
||||
# Improved longitudinal tune
|
||||
elif name == LongTunes.TSS2:
|
||||
if name == LongTunes.TSS2 or name == LongTunes.PEDAL:
|
||||
tune.deadzoneBP = [0., 8.05]
|
||||
tune.deadzoneV = [.0, .14]
|
||||
tune.kpBP = [0., 5., 20.]
|
||||
|
||||
@@ -6,12 +6,10 @@ from selfdrive.config import Conversions as CV
|
||||
|
||||
Ecu = car.CarParams.Ecu
|
||||
MIN_ACC_SPEED = 19. * CV.MPH_TO_MS
|
||||
PEDAL_TRANSITION = 10. * CV.MPH_TO_MS
|
||||
|
||||
PEDAL_HYST_GAP = 3. * CV.MPH_TO_MS
|
||||
PEDAL_SCALE = 3.0
|
||||
|
||||
class CarControllerParams:
|
||||
ACCEL_HYST_GAP = 0.06 # don't change accel command for small oscilalitons within this value
|
||||
ACCEL_MAX = 1.5 # m/s2, lower than allowed 2.0 m/s2 for tuning reasons
|
||||
ACCEL_MIN = -3.5 # m/s2
|
||||
|
||||
@@ -58,6 +56,7 @@ class CAR:
|
||||
LEXUS_NX = "LEXUS NX 2018"
|
||||
LEXUS_NXH = "LEXUS NX HYBRID 2018"
|
||||
LEXUS_NX_TSS2 = "LEXUS NX 2020"
|
||||
LEXUS_RC = "LEXUS RC 2020"
|
||||
LEXUS_RX = "LEXUS RX 2016"
|
||||
LEXUS_RXH = "LEXUS RX HYBRID 2017"
|
||||
LEXUS_RX_TSS2 = "LEXUS RX 2020"
|
||||
@@ -347,10 +346,11 @@ FW_VERSIONS = {
|
||||
b'\x018966306T3200\x00\x00\x00\x00',
|
||||
b'\x018966306T4100\x00\x00\x00\x00',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x750, 15): [
|
||||
(Ecu.fwdRadar, 0x750, 0xf): [
|
||||
b'\x018821F6201200\x00\x00\x00\x00',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x750, 109): [
|
||||
(Ecu.fwdCamera, 0x750, 0x6d): [
|
||||
b'\x028646F0602200\x00\x00\x00\x008646G5301200\x00\x00\x00\x00',
|
||||
b'\x028646F3305200\x00\x00\x00\x008646G5301200\x00\x00\x00\x00',
|
||||
b'\x028646F3305300\x00\x00\x00\x008646G5301200\x00\x00\x00\x00',
|
||||
],
|
||||
@@ -434,6 +434,7 @@ FW_VERSIONS = {
|
||||
},
|
||||
CAR.CHRH: {
|
||||
(Ecu.engine, 0x700, None): [
|
||||
b'\x0289663F405100\x00\x00\x00\x008966A4703000\x00\x00\x00\x00',
|
||||
b'\x02896631013200\x00\x00\x00\x008966A4703000\x00\x00\x00\x00',
|
||||
b'\x0289663F405000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00',
|
||||
b'\x0289663F418000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00',
|
||||
@@ -442,6 +443,7 @@ FW_VERSIONS = {
|
||||
b'\x0189663F438000\x00\x00\x00\x00',
|
||||
],
|
||||
(Ecu.esp, 0x7b0, None): [
|
||||
b'F152610012\x00\x00\x00\x00\x00\x00',
|
||||
b'F152610013\x00\x00\x00\x00\x00\x00',
|
||||
b'F152610014\x00\x00\x00\x00\x00\x00',
|
||||
b'F152610040\x00\x00\x00\x00\x00\x00',
|
||||
@@ -455,6 +457,7 @@ FW_VERSIONS = {
|
||||
b'8821FF402400 ',
|
||||
b'8821FF404000 ',
|
||||
b'8821FF404100 ',
|
||||
b'8821FF405000 ',
|
||||
b'8821FF406000 ',
|
||||
b'8821FF407100 ',
|
||||
],
|
||||
@@ -470,10 +473,12 @@ FW_VERSIONS = {
|
||||
b'8821FF402400 ',
|
||||
b'8821FF404000 ',
|
||||
b'8821FF404100 ',
|
||||
b'8821FF405000 ',
|
||||
b'8821FF406000 ',
|
||||
b'8821FF407100 ',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x750, 0x6d): [
|
||||
b'8646FF401700 ',
|
||||
b'8646FF402100 ',
|
||||
b'8646FF404000 ',
|
||||
b'8646FF406000 ',
|
||||
@@ -542,6 +547,7 @@ FW_VERSIONS = {
|
||||
b'\x018966312W9000\x00\x00\x00\x00',
|
||||
],
|
||||
(Ecu.engine, 0x7e0, None): [
|
||||
b'\x0230A10000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00',
|
||||
b'\x0230A11000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00',
|
||||
b'\x0230ZN4000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00',
|
||||
b'\x03312K7000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203402\x00\x00\x00\x00',
|
||||
@@ -568,6 +574,7 @@ FW_VERSIONS = {
|
||||
b'\x01F152602560\x00\x00\x00\x00\x00\x00',
|
||||
b'\x01F152602590\x00\x00\x00\x00\x00\x00',
|
||||
b'\x01F152602650\x00\x00\x00\x00\x00\x00',
|
||||
b"\x01F15260A010\x00\x00\x00\x00\x00\x00",
|
||||
b'\x01F15260A050\x00\x00\x00\x00\x00\x00',
|
||||
b'\x01F152612641\x00\x00\x00\x00\x00\x00',
|
||||
b'\x01F152612651\x00\x00\x00\x00\x00\x00',
|
||||
@@ -666,6 +673,7 @@ FW_VERSIONS = {
|
||||
b'\x028646F1202000\x00\x00\x00\x008646G2601200\x00\x00\x00\x00',
|
||||
b'\x028646F1202100\x00\x00\x00\x008646G2601400\x00\x00\x00\x00',
|
||||
b'\x028646F1202200\x00\x00\x00\x008646G2601500\x00\x00\x00\x00',
|
||||
b"\x028646F1601300\x00\x00\x00\x008646G2601400\x00\x00\x00\x00",
|
||||
b'\x028646F4203400\x00\x00\x00\x008646G2601200\x00\x00\x00\x00',
|
||||
b'\x028646F76020C0\x00\x00\x00\x008646G26011A0\x00\x00\x00\x00',
|
||||
b'\x028646F7603100\x00\x00\x00\x008646G2601200\x00\x00\x00\x00',
|
||||
@@ -801,13 +809,14 @@ FW_VERSIONS = {
|
||||
},
|
||||
CAR.LEXUS_IS: {
|
||||
(Ecu.engine, 0x700, None): [
|
||||
b'\x018966353M7000\x00\x00\x00\x00',
|
||||
b'\x018966353M7100\x00\x00\x00\x00',
|
||||
b'\x018966353Q2000\x00\x00\x00\x00',
|
||||
b'\x018966353Q2300\x00\x00\x00\x00',
|
||||
b'\x018966353Q4000\x00\x00\x00\x00',
|
||||
b'\x018966353R1100\x00\x00\x00\x00',
|
||||
b'\x018966353R7100\x00\x00\x00\x00',
|
||||
b'\x018966353R8100\x00\x00\x00\x00',
|
||||
b'\x018966353Q4000\x00\x00\x00\x00',
|
||||
],
|
||||
(Ecu.engine, 0x7e0, None): [
|
||||
b'\x0232480000\x00\x00\x00\x00\x00\x00\x00\x00A4701000\x00\x00\x00\x00\x00\x00\x00\x00',
|
||||
@@ -815,6 +824,7 @@ FW_VERSIONS = {
|
||||
b'\x02353P9000\x00\x00\x00\x00\x00\x00\x00\x00553C1000\x00\x00\x00\x00\x00\x00\x00\x00',
|
||||
],
|
||||
(Ecu.esp, 0x7b0, None): [
|
||||
b'F152653300\x00\x00\x00\x00\x00\x00',
|
||||
b'F152653301\x00\x00\x00\x00\x00\x00',
|
||||
b'F152653310\x00\x00\x00\x00\x00\x00',
|
||||
b'F152653330\x00\x00\x00\x00\x00\x00',
|
||||
@@ -837,9 +847,10 @@ FW_VERSIONS = {
|
||||
b'8821F4702100\x00\x00\x00\x00',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x750, 0x6d): [
|
||||
b'8646F5301101\x00\x00\x00\x00',
|
||||
b'8646F5301200\x00\x00\x00\x00',
|
||||
b'8646F5301300\x00\x00\x00\x00',
|
||||
b'8646F5301400\x00\x00\x00\x00',
|
||||
b'8646F5301200\x00\x00\x00\x00',
|
||||
],
|
||||
},
|
||||
CAR.PRIUS: {
|
||||
@@ -1157,6 +1168,7 @@ FW_VERSIONS = {
|
||||
b'\x01896630851000\x00\x00\x00\x00',
|
||||
b'\x01896630851100\x00\x00\x00\x00',
|
||||
b'\x01896630851200\x00\x00\x00\x00',
|
||||
b'\x01896630852000\x00\x00\x00\x00',
|
||||
b'\x01896630852100\x00\x00\x00\x00',
|
||||
b'\x01896630859000\x00\x00\x00\x00',
|
||||
b'\x01896630860000\x00\x00\x00\x00',
|
||||
@@ -1204,15 +1216,18 @@ FW_VERSIONS = {
|
||||
b'\x018966333T5000\x00\x00\x00\x00',
|
||||
b'\x018966333T5100\x00\x00\x00\x00',
|
||||
b'\x018966333X6000\x00\x00\x00\x00',
|
||||
b'\x01896633T07000\x00\x00\x00\x00',
|
||||
],
|
||||
(Ecu.esp, 0x7b0, None): [
|
||||
b'\x01F152606281\x00\x00\x00\x00\x00\x00',
|
||||
b'\x01F152606340\x00\x00\x00\x00\x00\x00',
|
||||
b'\x01F152606461\x00\x00\x00\x00\x00\x00',
|
||||
b'\x01F15260E031\x00\x00\x00\x00\x00\x00',
|
||||
],
|
||||
(Ecu.eps, 0x7a1, None): [
|
||||
b'8965B33252\x00\x00\x00\x00\x00\x00',
|
||||
b'8965B33590\x00\x00\x00\x00\x00\x00',
|
||||
b'8965B33690\x00\x00\x00\x00\x00\x00',
|
||||
b'8965B48271\x00\x00\x00\x00\x00\x00',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x750, 0xf): [
|
||||
@@ -1224,6 +1239,7 @@ FW_VERSIONS = {
|
||||
b'\x028646F33030D0\x00\x00\x00\x008646G26011A0\x00\x00\x00\x00',
|
||||
b'\x028646F3303200\x00\x00\x00\x008646G26011A0\x00\x00\x00\x00',
|
||||
b'\x028646F3304100\x00\x00\x00\x008646G2601200\x00\x00\x00\x00',
|
||||
b'\x028646F3304300\x00\x00\x00\x008646G2601500\x00\x00\x00\x00',
|
||||
b'\x028646F4810200\x00\x00\x00\x008646G2601400\x00\x00\x00\x00',
|
||||
],
|
||||
},
|
||||
@@ -1288,6 +1304,7 @@ FW_VERSIONS = {
|
||||
b'\x01896637851000\x00\x00\x00\x00',
|
||||
b'\x01896637852000\x00\x00\x00\x00',
|
||||
b'\x01896637854000\x00\x00\x00\x00',
|
||||
b'\x01896637878000\x00\x00\x00\x00',
|
||||
],
|
||||
(Ecu.esp, 0x7b0, None): [
|
||||
b'F152678130\x00\x00\x00\x00\x00\x00',
|
||||
@@ -1295,6 +1312,7 @@ FW_VERSIONS = {
|
||||
],
|
||||
(Ecu.dsu, 0x791, None): [
|
||||
b'881517803100\x00\x00\x00\x00',
|
||||
b'881517803300\x00\x00\x00\x00',
|
||||
],
|
||||
(Ecu.eps, 0x7a1, None): [
|
||||
b'8965B78060\x00\x00\x00\x00\x00\x00',
|
||||
@@ -1306,6 +1324,7 @@ FW_VERSIONS = {
|
||||
],
|
||||
(Ecu.fwdCamera, 0x750, 0x6d): [
|
||||
b'8646F7801100\x00\x00\x00\x00',
|
||||
b'8646F7801300\x00\x00\x00\x00',
|
||||
],
|
||||
},
|
||||
CAR.LEXUS_NX_TSS2: {
|
||||
@@ -1358,6 +1377,26 @@ FW_VERSIONS = {
|
||||
b'8646F7801100\x00\x00\x00\x00',
|
||||
],
|
||||
},
|
||||
CAR.LEXUS_RC: {
|
||||
(Ecu.engine, 0x7e0, None): [
|
||||
b'\x0232484000\x00\x00\x00\x00\x00\x00\x00\x0052422000\x00\x00\x00\x00\x00\x00\x00\x00',
|
||||
],
|
||||
(Ecu.esp, 0x7b0, None): [
|
||||
b'F152624221\x00\x00\x00\x00\x00\x00',
|
||||
],
|
||||
(Ecu.dsu, 0x791, None): [
|
||||
b'881512409100\x00\x00\x00\x00',
|
||||
],
|
||||
(Ecu.eps, 0x7a1, None): [
|
||||
b'8965B24081\x00\x00\x00\x00\x00\x00',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x750, 0xf): [
|
||||
b'8821F4702300\x00\x00\x00\x00',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x750, 0x6d): [
|
||||
b'8646F2402200\x00\x00\x00\x00',
|
||||
],
|
||||
},
|
||||
CAR.LEXUS_RX: {
|
||||
(Ecu.engine, 0x700, None): [
|
||||
b'\x01896630E36200\x00\x00\x00\x00',
|
||||
@@ -1369,6 +1408,7 @@ FW_VERSIONS = {
|
||||
b'\x01896630E41200\x00\x00\x00\x00',
|
||||
b'\x01896630E41500\x00\x00\x00\x00',
|
||||
b'\x01896630EA3100\x00\x00\x00\x00',
|
||||
b'\x01896630EA3400\x00\x00\x00\x00',
|
||||
b'\x01896630EA4100\x00\x00\x00\x00',
|
||||
b'\x01896630EA4300\x00\x00\x00\x00',
|
||||
b'\x01896630EA4400\x00\x00\x00\x00',
|
||||
@@ -1558,6 +1598,7 @@ DBC = {
|
||||
CAR.RAV4: dbc_dict('toyota_rav4_2017_pt_generated', 'toyota_adas'),
|
||||
CAR.PRIUS: dbc_dict('toyota_prius_2017_pt_generated', 'toyota_adas'),
|
||||
CAR.COROLLA: dbc_dict('toyota_corolla_2017_pt_generated', 'toyota_adas'),
|
||||
CAR.LEXUS_RC: dbc_dict('lexus_is_2018_pt_generated', 'toyota_adas'),
|
||||
CAR.LEXUS_RX: dbc_dict('lexus_rx_350_2016_pt_generated', 'toyota_adas'),
|
||||
CAR.LEXUS_RXH: dbc_dict('lexus_rx_hybrid_2017_pt_generated', 'toyota_adas'),
|
||||
CAR.LEXUS_RX_TSS2: dbc_dict('toyota_nodsu_pt_generated', 'toyota_tss2_adas'),
|
||||
|
||||
@@ -86,27 +86,28 @@ class CarController():
|
||||
|
||||
# FIXME: this entire section is in desperate need of refactoring
|
||||
|
||||
if frame > self.graMsgStartFramePrev + P.GRA_VBP_STEP:
|
||||
if not enabled and CS.out.cruiseState.enabled:
|
||||
# Cancel ACC if it's engaged with OP disengaged.
|
||||
self.graButtonStatesToSend = BUTTON_STATES.copy()
|
||||
self.graButtonStatesToSend["cancel"] = True
|
||||
elif enabled and CS.out.standstill:
|
||||
# Blip the Resume button if we're engaged at standstill.
|
||||
# FIXME: This is a naive implementation, improve with visiond or radar input.
|
||||
self.graButtonStatesToSend = BUTTON_STATES.copy()
|
||||
self.graButtonStatesToSend["resumeCruise"] = True
|
||||
if CS.CP.pcmCruise:
|
||||
if frame > self.graMsgStartFramePrev + P.GRA_VBP_STEP:
|
||||
if not enabled and CS.out.cruiseState.enabled:
|
||||
# Cancel ACC if it's engaged with OP disengaged.
|
||||
self.graButtonStatesToSend = BUTTON_STATES.copy()
|
||||
self.graButtonStatesToSend["cancel"] = True
|
||||
elif enabled and CS.esp_hold_confirmation:
|
||||
# Blip the Resume button if we're engaged at standstill.
|
||||
# FIXME: This is a naive implementation, improve with visiond or radar input.
|
||||
self.graButtonStatesToSend = BUTTON_STATES.copy()
|
||||
self.graButtonStatesToSend["resumeCruise"] = True
|
||||
|
||||
if CS.graMsgBusCounter != self.graMsgBusCounterPrev:
|
||||
self.graMsgBusCounterPrev = CS.graMsgBusCounter
|
||||
if self.graButtonStatesToSend is not None:
|
||||
if self.graMsgSentCount == 0:
|
||||
self.graMsgStartFramePrev = frame
|
||||
idx = (CS.graMsgBusCounter + 1) % 16
|
||||
can_sends.append(volkswagencan.create_mqb_acc_buttons_control(self.packer_pt, ext_bus, self.graButtonStatesToSend, CS, idx))
|
||||
self.graMsgSentCount += 1
|
||||
if self.graMsgSentCount >= P.GRA_VBP_COUNT:
|
||||
self.graButtonStatesToSend = None
|
||||
self.graMsgSentCount = 0
|
||||
if CS.graMsgBusCounter != self.graMsgBusCounterPrev:
|
||||
self.graMsgBusCounterPrev = CS.graMsgBusCounter
|
||||
if self.graButtonStatesToSend is not None:
|
||||
if self.graMsgSentCount == 0:
|
||||
self.graMsgStartFramePrev = frame
|
||||
idx = (CS.graMsgBusCounter + 1) % 16
|
||||
can_sends.append(volkswagencan.create_mqb_acc_buttons_control(self.packer_pt, ext_bus, self.graButtonStatesToSend, CS, idx))
|
||||
self.graMsgSentCount += 1
|
||||
if self.graMsgSentCount >= P.GRA_VBP_COUNT:
|
||||
self.graButtonStatesToSend = None
|
||||
self.graMsgSentCount = 0
|
||||
|
||||
return can_sends
|
||||
|
||||
@@ -20,14 +20,16 @@ class CarState(CarStateBase):
|
||||
def update(self, pt_cp, cam_cp, ext_cp, trans_type):
|
||||
ret = car.CarState.new_message()
|
||||
# Update vehicle speed and acceleration from ABS wheel speeds.
|
||||
ret.wheelSpeeds.fl = pt_cp.vl["ESP_19"]["ESP_VL_Radgeschw_02"] * CV.KPH_TO_MS
|
||||
ret.wheelSpeeds.fr = pt_cp.vl["ESP_19"]["ESP_VR_Radgeschw_02"] * CV.KPH_TO_MS
|
||||
ret.wheelSpeeds.rl = pt_cp.vl["ESP_19"]["ESP_HL_Radgeschw_02"] * CV.KPH_TO_MS
|
||||
ret.wheelSpeeds.rr = pt_cp.vl["ESP_19"]["ESP_HR_Radgeschw_02"] * CV.KPH_TO_MS
|
||||
ret.wheelSpeeds = self.get_wheel_speeds(
|
||||
pt_cp.vl["ESP_19"]["ESP_VL_Radgeschw_02"],
|
||||
pt_cp.vl["ESP_19"]["ESP_VR_Radgeschw_02"],
|
||||
pt_cp.vl["ESP_19"]["ESP_HL_Radgeschw_02"],
|
||||
pt_cp.vl["ESP_19"]["ESP_HR_Radgeschw_02"],
|
||||
)
|
||||
|
||||
ret.vEgoRaw = float(np.mean([ret.wheelSpeeds.fl, ret.wheelSpeeds.fr, ret.wheelSpeeds.rl, ret.wheelSpeeds.rr]))
|
||||
ret.vEgo, ret.aEgo = self.update_speed_kf(ret.vEgoRaw)
|
||||
ret.standstill = bool(pt_cp.vl["ESP_21"]["ESP_Haltebestaetigung"])
|
||||
ret.standstill = ret.vEgo < 0.1
|
||||
|
||||
# Update steering angle, rate, yaw rate, and driver input torque. VW send
|
||||
# the sign/direction in a separate signal so they must be recombined.
|
||||
@@ -47,6 +49,7 @@ class CarState(CarStateBase):
|
||||
ret.gasPressed = ret.gas > 0
|
||||
ret.brake = pt_cp.vl["ESP_05"]["ESP_Bremsdruck"] / 250.0 # FIXME: this is pressure in Bar, not sure what OP expects
|
||||
ret.brakePressed = bool(pt_cp.vl["ESP_05"]["ESP_Fahrer_bremst"])
|
||||
self.esp_hold_confirmation = pt_cp.vl["ESP_21"]["ESP_Haltebestaetigung"]
|
||||
|
||||
# Update gear and/or clutch position data.
|
||||
if trans_type == TransmissionType.automatic:
|
||||
@@ -94,13 +97,13 @@ class CarState(CarStateBase):
|
||||
ret.stockAeb = bool(ext_cp.vl["ACC_10"]["ANB_Teilbremsung_Freigabe"]) or bool(ext_cp.vl["ACC_10"]["ANB_Zielbremsung_Freigabe"])
|
||||
|
||||
# Update ACC radar status.
|
||||
accStatus = pt_cp.vl["TSK_06"]["TSK_Status"]
|
||||
if accStatus == 2:
|
||||
self.tsk_status = pt_cp.vl["TSK_06"]["TSK_Status"]
|
||||
if self.tsk_status == 2:
|
||||
# ACC okay and enabled, but not currently engaged
|
||||
ret.cruiseState.available = True
|
||||
ret.cruiseState.enabled = False
|
||||
elif accStatus in [3, 4, 5]:
|
||||
# ACC okay and enabled, currently engaged and regulating speed (3) or engaged with driver accelerating (4) or overrun (5)
|
||||
elif self.tsk_status in [3, 4, 5]:
|
||||
# ACC okay and enabled, currently regulating speed (3) or driver accel override (4) or overrun coast-down (5)
|
||||
ret.cruiseState.available = True
|
||||
ret.cruiseState.enabled = True
|
||||
else:
|
||||
@@ -110,9 +113,10 @@ class CarState(CarStateBase):
|
||||
|
||||
# Update ACC setpoint. When the setpoint is zero or there's an error, the
|
||||
# radar sends a set-speed of ~90.69 m/s / 203mph.
|
||||
ret.cruiseState.speed = ext_cp.vl["ACC_02"]["ACC_Wunschgeschw"] * CV.KPH_TO_MS
|
||||
if ret.cruiseState.speed > 90:
|
||||
ret.cruiseState.speed = 0
|
||||
if self.CP.pcmCruise:
|
||||
ret.cruiseState.speed = ext_cp.vl["ACC_02"]["ACC_Wunschgeschw"] * CV.KPH_TO_MS
|
||||
if ret.cruiseState.speed > 90:
|
||||
ret.cruiseState.speed = 0
|
||||
|
||||
# Update control button states for turn signals and ACC controls.
|
||||
self.buttonStates["accelCruise"] = bool(pt_cp.vl["GRA_ACC_01"]["GRA_Tip_Hoch"])
|
||||
|
||||
@@ -43,7 +43,7 @@ class CarInterface(CarInterfaceBase):
|
||||
else:
|
||||
ret.networkLocation = NetworkLocation.fwdCamera
|
||||
|
||||
# Global tuning defaults, can be overridden per-vehicle
|
||||
# Global lateral tuning defaults, can be overridden per-vehicle
|
||||
|
||||
ret.steerActuatorDelay = 0.05
|
||||
ret.steerRateCost = 1.0
|
||||
@@ -115,6 +115,10 @@ class CarInterface(CarInterfaceBase):
|
||||
ret.mass = 1205 + STD_CARGO_KG
|
||||
ret.wheelbase = 2.61
|
||||
|
||||
elif candidate == CAR.AUDI_Q3_MK2:
|
||||
ret.mass = 1623 + STD_CARGO_KG
|
||||
ret.wheelbase = 2.68
|
||||
|
||||
elif candidate == CAR.SEAT_ATECA_MK1:
|
||||
ret.mass = 1900 + STD_CARGO_KG
|
||||
ret.wheelbase = 2.64
|
||||
@@ -190,6 +194,8 @@ class CarInterface(CarInterfaceBase):
|
||||
# Vehicle health and operation safety checks
|
||||
if self.CS.parkingBrakeSet:
|
||||
events.add(EventName.parkBrake)
|
||||
if self.CS.tsk_status in [6, 7]:
|
||||
events.add(EventName.accFaulted)
|
||||
|
||||
# Low speed steer alert hysteresis logic
|
||||
if self.CP.minSteerSpeed > 0. and ret.vEgo < (self.CP.minSteerSpeed + 1.):
|
||||
|
||||
@@ -79,6 +79,7 @@ class CAR:
|
||||
TROC_MK1 = "VOLKSWAGEN T-ROC 1ST GEN" # Chassis A1, Mk1 VW VW T-Roc and variants
|
||||
AUDI_A3_MK3 = "AUDI A3 3RD GEN" # Chassis 8V/FF, Mk3 Audi A3 and variants
|
||||
AUDI_Q2_MK1 = "AUDI Q2 1ST GEN" # Chassis GA, Mk1 Audi Q2 (RoW) and Q2L (China only)
|
||||
AUDI_Q3_MK2 = "AUDI Q3 2ND GEN" # Chassis 8U/F3/FS, Mk2 Audi Q3 and variants
|
||||
SEAT_ATECA_MK1 = "SEAT ATECA 1ST GEN" # Chassis 5F, Mk1 SEAT Ateca and CUPRA Ateca
|
||||
SEAT_LEON_MK3 = "SEAT LEON 3RD GEN" # Chassis 5F, Mk3 SEAT Leon and variants
|
||||
SKODA_KAMIQ_MK1 = "SKODA KAMIQ 1ST GEN" # Chassis NW, Mk1 Skoda Kamiq
|
||||
@@ -121,6 +122,7 @@ FW_VERSIONS = {
|
||||
b'\xf1\x8703H906026F \xf1\x896696',
|
||||
b'\xf1\x8703H906026F \xf1\x899970',
|
||||
b'\xf1\x8703H906026J \xf1\x896026',
|
||||
b'\xf1\x8703H906026J \xf1\x899971',
|
||||
b'\xf1\x8703H906026S \xf1\x896693',
|
||||
b'\xf1\x8703H906026S \xf1\x899970',
|
||||
],
|
||||
@@ -147,6 +149,7 @@ FW_VERSIONS = {
|
||||
(Ecu.engine, 0x7e0, None): [
|
||||
b'\xf1\x8704E906016A \xf1\x897697',
|
||||
b'\xf1\x8704E906016AD\xf1\x895758',
|
||||
b'\xf1\x8704E906016CE\xf1\x899096',
|
||||
b'\xf1\x8704E906023AG\xf1\x891726',
|
||||
b'\xf1\x8704E906023BN\xf1\x894518',
|
||||
b'\xf1\x8704E906024K \xf1\x896811',
|
||||
@@ -187,6 +190,7 @@ FW_VERSIONS = {
|
||||
b'\xf1\x870CW300042F \xf1\x891604',
|
||||
b'\xf1\x870CW300043B \xf1\x891601',
|
||||
b'\xf1\x870CW300044S \xf1\x894530',
|
||||
b'\xf1\x870CW300044T \xf1\x895245',
|
||||
b'\xf1\x870CW300045 \xf1\x894531',
|
||||
b'\xf1\x870CW300047D \xf1\x895261',
|
||||
b'\xf1\x870CW300048J \xf1\x890611',
|
||||
@@ -269,6 +273,7 @@ FW_VERSIONS = {
|
||||
],
|
||||
(Ecu.fwdRadar, 0x757, None): [
|
||||
b'\xf1\x875Q0907567G \xf1\x890390\xf1\x82\00101',
|
||||
b'\xf1\x875Q0907567J \xf1\x890396\xf1\x82\x0101',
|
||||
b'\xf1\x875Q0907572A \xf1\x890141\xf1\x82\00101',
|
||||
b'\xf1\x875Q0907572B \xf1\x890200\xf1\x82\00101',
|
||||
b'\xf1\x875Q0907572C \xf1\x890210\xf1\x82\00101',
|
||||
@@ -552,6 +557,29 @@ FW_VERSIONS = {
|
||||
b'\xf1\x872Q0907572M \xf1\x890233',
|
||||
],
|
||||
},
|
||||
CAR.AUDI_Q3_MK2: {
|
||||
(Ecu.engine, 0x7e0, None): [
|
||||
b'\xf1\x8705E906018N \xf1\x899970',
|
||||
b'\xf1\x8783A906259 \xf1\x890001',
|
||||
b'\xf1\x8783A906259 \xf1\x890005',
|
||||
],
|
||||
(Ecu.transmission, 0x7e1, None): [
|
||||
b'\xf1\x8709G927158CN\xf1\x893608',
|
||||
b'\xf1\x870GC300046F \xf1\x892701',
|
||||
],
|
||||
(Ecu.srs, 0x715, None): [
|
||||
b'\xf1\x875Q0959655BF\xf1\x890403\xf1\x82\x1321211111211200311121232152219321422111',
|
||||
b'\xf1\x875Q0959655CC\xf1\x890421\xf1\x82\x131111111111120031111237116A119321532111',
|
||||
],
|
||||
(Ecu.eps, 0x712, None): [
|
||||
b'\xf1\x875Q0910143C \xf1\x892211\xf1\x82\x0567G6000300',
|
||||
b'\xf1\x875Q0910143C \xf1\x892211\xf1\x82\x0567G6000800',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x757, None): [
|
||||
b'\xf1\x872Q0907572R \xf1\x890372',
|
||||
b'\xf1\x872Q0907572T \xf1\x890383',
|
||||
],
|
||||
},
|
||||
CAR.SEAT_ATECA_MK1: {
|
||||
(Ecu.engine, 0x7e0, None): [
|
||||
b'\xf1\x8704E906027KA\xf1\x893749',
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include "selfdrive/common/mat.h"
|
||||
#include "selfdrive/hardware/hw.h"
|
||||
|
||||
const int TRAJECTORY_SIZE = 33;
|
||||
const int LAT_MPC_N = 16;
|
||||
@@ -36,10 +38,14 @@ const std::array<double, TRAJECTORY_SIZE> X_IDXS = {
|
||||
168.75 , 180.1875, 192.};
|
||||
const auto X_IDXS_FLOAT = convert_array_to_type<double, float, TRAJECTORY_SIZE>(X_IDXS);
|
||||
|
||||
#ifdef __cplusplus
|
||||
const int TICI_CAM_WIDTH = 1928;
|
||||
|
||||
namespace tici_dm_crop {
|
||||
const int x_offset = -72;
|
||||
const int y_offset = -144;
|
||||
const int width = 954;
|
||||
};
|
||||
|
||||
#include "selfdrive/common/mat.h"
|
||||
#include "selfdrive/hardware/hw.h"
|
||||
const mat3 fcam_intrinsic_matrix =
|
||||
Hardware::EON() ? (mat3){{910., 0., 1164.0 / 2,
|
||||
0., 910., 874.0 / 2,
|
||||
@@ -62,5 +68,3 @@ static inline mat3 get_model_yuv_transform(bool bayer = true) {
|
||||
}};
|
||||
return bayer ? transform_scale_buffer(transform, db_s) : transform;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -130,11 +130,13 @@ std::unordered_map<std::string, uint32_t> keys = {
|
||||
{"JoystickDebugMode", CLEAR_ON_MANAGER_START | CLEAR_ON_IGNITION_OFF},
|
||||
{"LastAthenaPingTime", CLEAR_ON_MANAGER_START},
|
||||
{"LastGPSPosition", PERSISTENT},
|
||||
{"LastPowerDropDetected", CLEAR_ON_MANAGER_START},
|
||||
{"LastUpdateException", PERSISTENT},
|
||||
{"LastUpdateTime", PERSISTENT},
|
||||
{"LiveParameters", PERSISTENT},
|
||||
{"NavDestination", CLEAR_ON_MANAGER_START | CLEAR_ON_IGNITION_OFF},
|
||||
{"NavSettingTime24h", PERSISTENT},
|
||||
{"NavdRender", PERSISTENT},
|
||||
{"OpenpilotEnabledToggle", PERSISTENT},
|
||||
{"PandaHeartbeatLost", CLEAR_ON_MANAGER_START | CLEAR_ON_IGNITION_OFF},
|
||||
{"Passive", PERSISTENT},
|
||||
@@ -151,7 +153,6 @@ std::unordered_map<std::string, uint32_t> keys = {
|
||||
{"TrainingVersion", PERSISTENT},
|
||||
{"UpdateAvailable", CLEAR_ON_MANAGER_START},
|
||||
{"UpdateFailedCount", CLEAR_ON_MANAGER_START},
|
||||
{"UploadRaw", PERSISTENT},
|
||||
{"Version", PERSISTENT},
|
||||
{"VisionRadarToggle", PERSISTENT},
|
||||
{"ApiCache_Device", PERSISTENT},
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#include <sched.h>
|
||||
#endif // __linux__
|
||||
|
||||
namespace util {
|
||||
|
||||
void set_thread_name(const char* name) {
|
||||
#ifdef __linux__
|
||||
// pthread_setname_np is dumb (fails instead of truncates)
|
||||
@@ -56,8 +58,6 @@ int set_core_affinity(std::vector<int> cores) {
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace util {
|
||||
|
||||
std::string read_file(const std::string& fn) {
|
||||
std::ifstream f(fn, std::ios::binary | std::ios::in);
|
||||
if (f.is_open()) {
|
||||
|
||||
@@ -37,13 +37,12 @@ const double MS_TO_MPH = MS_TO_KPH * KM_TO_MILE;
|
||||
const double METER_TO_MILE = KM_TO_MILE / 1000.0;
|
||||
const double METER_TO_FOOT = 3.28084;
|
||||
|
||||
void set_thread_name(const char* name);
|
||||
namespace util {
|
||||
|
||||
void set_thread_name(const char* name);
|
||||
int set_realtime_priority(int level);
|
||||
int set_core_affinity(std::vector<int> cores);
|
||||
|
||||
namespace util {
|
||||
|
||||
// ***** Time helpers *****
|
||||
struct tm get_time();
|
||||
bool time_valid(struct tm sys_time);
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMMA_VERSION "0.8.11"
|
||||
#define COMMA_VERSION "0.8.12"
|
||||
|
||||
@@ -28,6 +28,7 @@ from selfdrive.locationd.calibrationd import Calibration
|
||||
from selfdrive.hardware import HARDWARE, TICI, EON
|
||||
from selfdrive.manager.process_config import managed_processes
|
||||
|
||||
SOFT_DISABLE_TIME = 3 # seconds
|
||||
LDW_MIN_SPEED = 31 * CV.MPH_TO_MS
|
||||
LANE_DEPARTURE_THRESHOLD = 0.1
|
||||
STEER_ANGLE_SATURATION_TIMEOUT = 1.0 / DT_CTRL
|
||||
@@ -300,7 +301,7 @@ class Controls:
|
||||
# Check for mismatch between openpilot and car's PCM
|
||||
cruise_mismatch = CS.cruiseState.enabled and (not self.enabled or not self.CP.pcmCruise)
|
||||
self.cruise_mismatch_counter = self.cruise_mismatch_counter + 1 if cruise_mismatch else 0
|
||||
if self.cruise_mismatch_counter > int(1. / DT_CTRL):
|
||||
if self.cruise_mismatch_counter > int(3. / DT_CTRL):
|
||||
self.events.add(EventName.cruiseMismatch)
|
||||
|
||||
# Check for FCW
|
||||
@@ -430,7 +431,7 @@ class Controls:
|
||||
if self.state == State.enabled:
|
||||
if self.events.any(ET.SOFT_DISABLE):
|
||||
self.state = State.softDisabling
|
||||
self.soft_disable_timer = int(3 / DT_CTRL)
|
||||
self.soft_disable_timer = int(SOFT_DISABLE_TIME / DT_CTRL)
|
||||
self.current_alert_types.append(ET.SOFT_DISABLE)
|
||||
|
||||
# SOFT DISABLING
|
||||
@@ -540,8 +541,9 @@ class Controls:
|
||||
|
||||
if len(lat_plan.dPathPoints):
|
||||
# Check if we deviated from the path
|
||||
left_deviation = actuators.steer > 0 and lat_plan.dPathPoints[0] < -0.1
|
||||
right_deviation = actuators.steer < 0 and lat_plan.dPathPoints[0] > 0.1
|
||||
# TODO use desired vs actual curvature
|
||||
left_deviation = actuators.steer > 0 and lat_plan.dPathPoints[0] < -0.20
|
||||
right_deviation = actuators.steer < 0 and lat_plan.dPathPoints[0] > 0.20
|
||||
|
||||
if left_deviation or right_deviation:
|
||||
self.events.add(EventName.steerSaturated)
|
||||
@@ -612,8 +614,8 @@ class Controls:
|
||||
self.events.add(EventName.ldw)
|
||||
|
||||
clear_event = ET.WARNING if ET.WARNING not in self.current_alert_types else None
|
||||
alerts = self.events.create_alerts(self.current_alert_types, [self.CP, self.sm, self.is_metric])
|
||||
self.AM.add_many(self.sm.frame, alerts, self.enabled)
|
||||
alerts = self.events.create_alerts(self.current_alert_types, [self.CP, self.sm, self.is_metric, self.soft_disable_timer])
|
||||
self.AM.add_many(self.sm.frame, alerts)
|
||||
self.AM.process_alerts(self.sm.frame, clear_event)
|
||||
CC.hudControl.visualAlert = self.AM.visual_alert
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ from typing import List, Dict, Optional
|
||||
from cereal import car, log
|
||||
from common.basedir import BASEDIR
|
||||
from common.params import Params
|
||||
from common.realtime import DT_CTRL
|
||||
from selfdrive.controls.lib.events import Alert
|
||||
|
||||
|
||||
@@ -33,14 +32,17 @@ class AlertEntry:
|
||||
start_frame: int = -1
|
||||
end_frame: int = -1
|
||||
|
||||
def active(self, frame: int) -> bool:
|
||||
return frame <= self.end_frame
|
||||
|
||||
class AlertManager:
|
||||
|
||||
def __init__(self):
|
||||
self.reset()
|
||||
self.activealerts: Dict[str, AlertEntry] = defaultdict(AlertEntry)
|
||||
self.alerts: Dict[str, AlertEntry] = defaultdict(AlertEntry)
|
||||
|
||||
def reset(self) -> None:
|
||||
self.alert: Optional[Alert] = None
|
||||
self.alert_type: str = ""
|
||||
self.alert_text_1: str = ""
|
||||
self.alert_text_2: str = ""
|
||||
@@ -50,37 +52,39 @@ class AlertManager:
|
||||
self.audible_alert = car.CarControl.HUDControl.AudibleAlert.none
|
||||
self.alert_rate: float = 0.
|
||||
|
||||
def add_many(self, frame: int, alerts: List[Alert], enabled: bool = True) -> None:
|
||||
def add_many(self, frame: int, alerts: List[Alert]) -> None:
|
||||
for alert in alerts:
|
||||
self.activealerts[alert.alert_type].alert = alert
|
||||
self.activealerts[alert.alert_type].start_frame = frame
|
||||
self.activealerts[alert.alert_type].end_frame = frame + int(alert.duration / DT_CTRL)
|
||||
key = alert.alert_type
|
||||
self.alerts[key].alert = alert
|
||||
if not self.alerts[key].active(frame):
|
||||
self.alerts[key].start_frame = frame
|
||||
min_end_frame = self.alerts[key].start_frame + alert.duration
|
||||
self.alerts[key].end_frame = max(frame + 1, min_end_frame)
|
||||
|
||||
def process_alerts(self, frame: int, clear_event_type=None) -> None:
|
||||
current_alert = AlertEntry()
|
||||
for k, v in self.activealerts.items():
|
||||
for k, v in self.alerts.items():
|
||||
if v.alert is None:
|
||||
continue
|
||||
|
||||
if v.alert.event_type == clear_event_type:
|
||||
self.activealerts[k].end_frame = -1
|
||||
if clear_event_type is not None and v.alert.event_type == clear_event_type:
|
||||
self.alerts[k].end_frame = -1
|
||||
|
||||
# sort by priority first and then by start_frame
|
||||
active = self.activealerts[k].end_frame > frame
|
||||
greater = current_alert.alert is None or (v.alert.priority, v.start_frame) > (current_alert.alert.priority, current_alert.start_frame)
|
||||
if active and greater:
|
||||
if v.active(frame) and greater:
|
||||
current_alert = v
|
||||
|
||||
# clear current alert
|
||||
self.reset()
|
||||
|
||||
a = current_alert.alert
|
||||
if a is not None:
|
||||
self.alert_type = a.alert_type
|
||||
self.audible_alert = a.audible_alert
|
||||
self.visual_alert = a.visual_alert
|
||||
self.alert_text_1 = a.alert_text_1
|
||||
self.alert_text_2 = a.alert_text_2
|
||||
self.alert_status = a.alert_status
|
||||
self.alert_size = a.alert_size
|
||||
self.alert_rate = a.alert_rate
|
||||
self.alert = current_alert.alert
|
||||
if self.alert is not None:
|
||||
self.alert_type = self.alert.alert_type
|
||||
self.audible_alert = self.alert.audible_alert
|
||||
self.visual_alert = self.alert.visual_alert
|
||||
self.alert_text_1 = self.alert.alert_text_1
|
||||
self.alert_text_2 = self.alert.alert_text_2
|
||||
self.alert_status = self.alert.alert_status
|
||||
self.alert_size = self.alert.alert_size
|
||||
self.alert_rate = self.alert.alert_rate
|
||||
|
||||
@@ -5,10 +5,11 @@ from common.realtime import DT_MDL
|
||||
from selfdrive.config import Conversions as CV
|
||||
from selfdrive.modeld.constants import T_IDXS
|
||||
|
||||
# kph
|
||||
V_CRUISE_MAX = 135
|
||||
V_CRUISE_MIN = 8
|
||||
V_CRUISE_ENABLE_MIN = 40
|
||||
# WARNING: this value was determined based on the model's training distribution,
|
||||
# model predictions above this speed can be unpredictable
|
||||
V_CRUISE_MAX = 145 # kph
|
||||
V_CRUISE_MIN = 8 # kph
|
||||
V_CRUISE_ENABLE_MIN = 40 # kph
|
||||
|
||||
LAT_MPC_N = 16
|
||||
LON_MPC_N = 32
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from enum import IntEnum
|
||||
from typing import Dict, Union, Callable, Any
|
||||
from typing import Dict, Union, Callable
|
||||
|
||||
from cereal import log, car
|
||||
import cereal.messaging as messaging
|
||||
@@ -123,7 +123,7 @@ class Alert:
|
||||
self.visual_alert = visual_alert
|
||||
self.audible_alert = audible_alert
|
||||
|
||||
self.duration = duration
|
||||
self.duration = int(duration / DT_CTRL)
|
||||
|
||||
self.alert_rate = alert_rate
|
||||
self.creation_delay = creation_delay
|
||||
@@ -139,11 +139,10 @@ class Alert:
|
||||
|
||||
|
||||
class NoEntryAlert(Alert):
|
||||
def __init__(self, alert_text_2, audible_alert=AudibleAlert.chimeError,
|
||||
visual_alert=VisualAlert.none):
|
||||
def __init__(self, alert_text_2, visual_alert=VisualAlert.none):
|
||||
super().__init__("openpilot Unavailable", alert_text_2, AlertStatus.normal,
|
||||
AlertSize.mid, Priority.LOW, visual_alert,
|
||||
audible_alert, 3.)
|
||||
AudibleAlert.refuse, 3.)
|
||||
|
||||
|
||||
class SoftDisableAlert(Alert):
|
||||
@@ -151,7 +150,14 @@ class SoftDisableAlert(Alert):
|
||||
super().__init__("TAKE CONTROL IMMEDIATELY", alert_text_2,
|
||||
AlertStatus.userPrompt, AlertSize.full,
|
||||
Priority.MID, VisualAlert.steerRequired,
|
||||
AudibleAlert.chimeWarningRepeatInfinite, 2.),
|
||||
AudibleAlert.warningSoft, 2.),
|
||||
|
||||
|
||||
# less harsh version of SoftDisable, where the condition is user-triggered
|
||||
class UserSoftDisableAlert(SoftDisableAlert):
|
||||
def __init__(self, alert_text_2):
|
||||
super().__init__(alert_text_2),
|
||||
self.alert_text_1 = "openpilot will disengage"
|
||||
|
||||
|
||||
class ImmediateDisableAlert(Alert):
|
||||
@@ -159,7 +165,7 @@ class ImmediateDisableAlert(Alert):
|
||||
super().__init__("TAKE CONTROL IMMEDIATELY", alert_text_2,
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.HIGHEST, VisualAlert.steerRequired,
|
||||
AudibleAlert.chimeWarningRepeatInfinite, 4.),
|
||||
AudibleAlert.warningImmediate, 4.),
|
||||
|
||||
|
||||
class EngagementAlert(Alert):
|
||||
@@ -192,19 +198,39 @@ def get_display_speed(speed_ms: float, metric: bool) -> str:
|
||||
|
||||
|
||||
# ********** alert callback functions **********
|
||||
def below_engage_speed_alert(CP: car.CarParams, sm: messaging.SubMaster, metric: bool) -> Alert:
|
||||
|
||||
AlertCallbackType = Callable[[car.CarParams, messaging.SubMaster, bool, int], Alert]
|
||||
|
||||
|
||||
def soft_disable_alert(alert_text_2: str) -> AlertCallbackType:
|
||||
def func(CP: car.CarParams, sm: messaging.SubMaster, metric: bool, soft_disable_time: int) -> Alert:
|
||||
if soft_disable_time < int(0.5 / DT_CTRL):
|
||||
return ImmediateDisableAlert(alert_text_2)
|
||||
return SoftDisableAlert(alert_text_2)
|
||||
return func
|
||||
|
||||
|
||||
def user_soft_disable_alert(alert_text_2: str) -> AlertCallbackType:
|
||||
def func(CP: car.CarParams, sm: messaging.SubMaster, metric: bool, soft_disable_time: int) -> Alert:
|
||||
if soft_disable_time < int(0.5 / DT_CTRL):
|
||||
return ImmediateDisableAlert(alert_text_2)
|
||||
return UserSoftDisableAlert(alert_text_2)
|
||||
return func
|
||||
|
||||
|
||||
def below_engage_speed_alert(CP: car.CarParams, sm: messaging.SubMaster, metric: bool, soft_disable_time: int) -> Alert:
|
||||
return NoEntryAlert(f"Speed Below {get_display_speed(CP.minEnableSpeed, metric)}")
|
||||
|
||||
|
||||
def below_steer_speed_alert(CP: car.CarParams, sm: messaging.SubMaster, metric: bool) -> Alert:
|
||||
def below_steer_speed_alert(CP: car.CarParams, sm: messaging.SubMaster, metric: bool, soft_disable_time: int) -> Alert:
|
||||
return Alert(
|
||||
f"Steer Unavailable Below {get_display_speed(CP.minSteerSpeed, metric)}",
|
||||
"",
|
||||
AlertStatus.userPrompt, AlertSize.small,
|
||||
Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimePrompt, 0.4)
|
||||
Priority.MID, VisualAlert.steerRequired, AudibleAlert.prompt, 0.4)
|
||||
|
||||
|
||||
def calibration_incomplete_alert(CP: car.CarParams, sm: messaging.SubMaster, metric: bool) -> Alert:
|
||||
def calibration_incomplete_alert(CP: car.CarParams, sm: messaging.SubMaster, metric: bool, soft_disable_time: int) -> Alert:
|
||||
return Alert(
|
||||
"Calibration in Progress: %d%%" % sm['liveCalibration'].calPerc,
|
||||
f"Drive Above {get_display_speed(MIN_SPEED_FILTER, metric)}",
|
||||
@@ -212,7 +238,7 @@ def calibration_incomplete_alert(CP: car.CarParams, sm: messaging.SubMaster, met
|
||||
Priority.LOWEST, VisualAlert.none, AudibleAlert.none, .2)
|
||||
|
||||
|
||||
def no_gps_alert(CP: car.CarParams, sm: messaging.SubMaster, metric: bool) -> Alert:
|
||||
def no_gps_alert(CP: car.CarParams, sm: messaging.SubMaster, metric: bool, soft_disable_time: int) -> Alert:
|
||||
gps_integrated = sm['peripheralState'].pandaType in [log.PandaState.PandaType.uno, log.PandaState.PandaType.dos]
|
||||
return Alert(
|
||||
"Poor GPS reception",
|
||||
@@ -221,21 +247,22 @@ def no_gps_alert(CP: car.CarParams, sm: messaging.SubMaster, metric: bool) -> Al
|
||||
Priority.LOWER, VisualAlert.none, AudibleAlert.none, .2, creation_delay=300.)
|
||||
|
||||
|
||||
def wrong_car_mode_alert(CP: car.CarParams, sm: messaging.SubMaster, metric: bool) -> Alert:
|
||||
def wrong_car_mode_alert(CP: car.CarParams, sm: messaging.SubMaster, metric: bool, soft_disable_time: int) -> Alert:
|
||||
text = "Cruise Mode Disabled"
|
||||
if CP.carName == "honda":
|
||||
text = "Main Switch Off"
|
||||
return NoEntryAlert(text)
|
||||
|
||||
|
||||
def joystick_alert(CP: car.CarParams, sm: messaging.SubMaster, metric: bool) -> Alert:
|
||||
def joystick_alert(CP: car.CarParams, sm: messaging.SubMaster, metric: bool, soft_disable_time: int) -> Alert:
|
||||
axes = sm['testJoystick'].axes
|
||||
gb, steer = list(axes)[:2] if len(axes) else (0., 0.)
|
||||
vals = f"Gas: {round(gb * 100.)}%, Steer: {round(steer * 100.)}%"
|
||||
return NormalPermanentAlert("Joystick Mode", vals)
|
||||
|
||||
|
||||
EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, bool], Alert]]]] = {
|
||||
|
||||
EVENTS: Dict[int, Dict[str, Union[Alert, AlertCallbackType]]] = {
|
||||
# ********** events with no alerts **********
|
||||
|
||||
EventName.stockFcw: {},
|
||||
@@ -248,7 +275,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
|
||||
},
|
||||
|
||||
EventName.controlsInitializing: {
|
||||
ET.NO_ENTRY: NoEntryAlert("Controls Initializing"),
|
||||
ET.NO_ENTRY: NoEntryAlert("System Initializing"),
|
||||
},
|
||||
|
||||
EventName.startup: {
|
||||
@@ -282,7 +309,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
|
||||
},
|
||||
|
||||
EventName.invalidLkasSetting: {
|
||||
ET.PERMANENT: NormalPermanentAlert("Stock LKAS is turned on",
|
||||
ET.PERMANENT: NormalPermanentAlert("Stock LKAS is on",
|
||||
"Turn off stock LKAS to engage"),
|
||||
},
|
||||
|
||||
@@ -294,8 +321,8 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
|
||||
# detects the use of a community feature it switches to dashcam mode
|
||||
# until these features are allowed using a toggle in settings.
|
||||
EventName.communityFeatureDisallowed: {
|
||||
ET.PERMANENT: NormalPermanentAlert("openpilot Not Available",
|
||||
"Enable Community Features in Settings to Engage"),
|
||||
ET.PERMANENT: NormalPermanentAlert("openpilot Unavailable",
|
||||
"Enable Community Features in Settings"),
|
||||
},
|
||||
|
||||
# openpilot doesn't recognize the car. This switches openpilot into a
|
||||
@@ -321,22 +348,22 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
|
||||
"BRAKE!",
|
||||
"Risk of Collision",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.HIGHEST, VisualAlert.fcw, AudibleAlert.chimeWarningRepeatInfinite, 2.),
|
||||
Priority.HIGHEST, VisualAlert.fcw, AudibleAlert.warningSoft, 2.),
|
||||
},
|
||||
|
||||
EventName.ldw: {
|
||||
ET.PERMANENT: Alert(
|
||||
"TAKE CONTROL",
|
||||
"Lane Departure Detected",
|
||||
AlertStatus.userPrompt, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.ldw, AudibleAlert.chimePrompt, 3.),
|
||||
"",
|
||||
AlertStatus.userPrompt, AlertSize.small,
|
||||
Priority.LOW, VisualAlert.ldw, AudibleAlert.prompt, 3.),
|
||||
},
|
||||
|
||||
# ********** events only containing alerts that display while engaged **********
|
||||
|
||||
EventName.gasPressed: {
|
||||
ET.PRE_ENABLE: Alert(
|
||||
"openpilot will not brake while gas pressed",
|
||||
"Release Gas Pedal to Engage",
|
||||
"",
|
||||
AlertStatus.normal, AlertSize.small,
|
||||
Priority.LOWEST, VisualAlert.none, AudibleAlert.none, .1, creation_delay=1.),
|
||||
@@ -352,7 +379,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
|
||||
# bad alignment or bad sensor data. If this happens consistently consider creating an issue on GitHub
|
||||
EventName.vehicleModelInvalid: {
|
||||
ET.NO_ENTRY: NoEntryAlert("Vehicle Parameter Identification Failed"),
|
||||
ET.SOFT_DISABLE: SoftDisableAlert("Vehicle Parameter Identification Failed"),
|
||||
ET.SOFT_DISABLE: soft_disable_alert("Vehicle Parameter Identification Failed"),
|
||||
},
|
||||
|
||||
EventName.steerTempUnavailableSilent: {
|
||||
@@ -360,12 +387,12 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
|
||||
"Steering Temporarily Unavailable",
|
||||
"",
|
||||
AlertStatus.userPrompt, AlertSize.small,
|
||||
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.chimePrompt, 1.),
|
||||
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.prompt, 1.),
|
||||
},
|
||||
|
||||
EventName.preDriverDistracted: {
|
||||
ET.WARNING: Alert(
|
||||
"KEEP EYES ON ROAD: Driver Distracted",
|
||||
"Pay Attention",
|
||||
"",
|
||||
AlertStatus.normal, AlertSize.small,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.none, .1),
|
||||
@@ -373,10 +400,10 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
|
||||
|
||||
EventName.promptDriverDistracted: {
|
||||
ET.WARNING: Alert(
|
||||
"KEEP EYES ON ROAD",
|
||||
"Pay Attention",
|
||||
"Driver Distracted",
|
||||
AlertStatus.userPrompt, AlertSize.mid,
|
||||
Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarning2RepeatInfinite, .1),
|
||||
Priority.MID, VisualAlert.steerRequired, AudibleAlert.promptDistracted, .1),
|
||||
},
|
||||
|
||||
EventName.driverDistracted: {
|
||||
@@ -384,12 +411,12 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
|
||||
"DISENGAGE IMMEDIATELY",
|
||||
"Driver Distracted",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeatInfinite, .1),
|
||||
Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.warningImmediate, .1),
|
||||
},
|
||||
|
||||
EventName.preDriverUnresponsive: {
|
||||
ET.WARNING: Alert(
|
||||
"TOUCH STEERING WHEEL: No Face Detected",
|
||||
"Touch Steering Wheel: No Face Detected",
|
||||
"",
|
||||
AlertStatus.normal, AlertSize.small,
|
||||
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.none, .1, alert_rate=0.75),
|
||||
@@ -397,10 +424,10 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
|
||||
|
||||
EventName.promptDriverUnresponsive: {
|
||||
ET.WARNING: Alert(
|
||||
"TOUCH STEERING WHEEL",
|
||||
"Touch Steering Wheel",
|
||||
"Driver Unresponsive",
|
||||
AlertStatus.userPrompt, AlertSize.mid,
|
||||
Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarning2RepeatInfinite, .1),
|
||||
Priority.MID, VisualAlert.steerRequired, AudibleAlert.promptDistracted, .1),
|
||||
},
|
||||
|
||||
EventName.driverUnresponsive: {
|
||||
@@ -408,7 +435,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
|
||||
"DISENGAGE IMMEDIATELY",
|
||||
"Driver Unresponsive",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeatInfinite, .1),
|
||||
Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.warningImmediate, .1),
|
||||
},
|
||||
|
||||
EventName.manualRestart: {
|
||||
@@ -422,7 +449,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
|
||||
EventName.resumeRequired: {
|
||||
ET.WARNING: Alert(
|
||||
"STOPPED",
|
||||
"Press Resume to Move",
|
||||
"Press Resume to Go",
|
||||
AlertStatus.userPrompt, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.none, .2),
|
||||
},
|
||||
@@ -452,7 +479,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
|
||||
"Car Detected in Blindspot",
|
||||
"",
|
||||
AlertStatus.userPrompt, AlertSize.small,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimePrompt, .1),
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.prompt, .1),
|
||||
},
|
||||
|
||||
EventName.laneChange: {
|
||||
@@ -465,10 +492,10 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
|
||||
|
||||
EventName.steerSaturated: {
|
||||
ET.WARNING: Alert(
|
||||
"TAKE CONTROL",
|
||||
"Take Control",
|
||||
"Turn Exceeds Steering Limit",
|
||||
AlertStatus.userPrompt, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.chimeWarning2RepeatInfinite, 1.),
|
||||
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.promptRepeat, 1.),
|
||||
},
|
||||
|
||||
# Thrown when the fan is driven at >50% but is not rotating
|
||||
@@ -496,49 +523,49 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
|
||||
# ********** events that affect controls state transitions **********
|
||||
|
||||
EventName.pcmEnable: {
|
||||
ET.ENABLE: EngagementAlert(AudibleAlert.chimeEngage),
|
||||
ET.ENABLE: EngagementAlert(AudibleAlert.engage),
|
||||
},
|
||||
|
||||
EventName.buttonEnable: {
|
||||
ET.ENABLE: EngagementAlert(AudibleAlert.chimeEngage),
|
||||
ET.ENABLE: EngagementAlert(AudibleAlert.engage),
|
||||
},
|
||||
|
||||
EventName.pcmDisable: {
|
||||
ET.USER_DISABLE: EngagementAlert(AudibleAlert.chimeDisengage),
|
||||
ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage),
|
||||
},
|
||||
|
||||
EventName.buttonCancel: {
|
||||
ET.USER_DISABLE: EngagementAlert(AudibleAlert.chimeDisengage),
|
||||
ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage),
|
||||
},
|
||||
|
||||
EventName.brakeHold: {
|
||||
ET.USER_DISABLE: EngagementAlert(AudibleAlert.chimeDisengage),
|
||||
ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage),
|
||||
ET.NO_ENTRY: NoEntryAlert("Brake Hold Active"),
|
||||
},
|
||||
|
||||
EventName.parkBrake: {
|
||||
ET.USER_DISABLE: EngagementAlert(AudibleAlert.chimeDisengage),
|
||||
ET.NO_ENTRY: NoEntryAlert("Park Brake Engaged"),
|
||||
ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage),
|
||||
ET.NO_ENTRY: NoEntryAlert("Parking Brake Engaged"),
|
||||
},
|
||||
|
||||
EventName.pedalPressed: {
|
||||
ET.USER_DISABLE: EngagementAlert(AudibleAlert.chimeDisengage),
|
||||
ET.NO_ENTRY: NoEntryAlert("Pedal Pressed During Attempt",
|
||||
ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage),
|
||||
ET.NO_ENTRY: NoEntryAlert("Pedal Pressed",
|
||||
visual_alert=VisualAlert.brakePressed),
|
||||
},
|
||||
|
||||
EventName.wrongCarMode: {
|
||||
ET.USER_DISABLE: EngagementAlert(AudibleAlert.chimeDisengage),
|
||||
ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage),
|
||||
ET.NO_ENTRY: wrong_car_mode_alert,
|
||||
},
|
||||
|
||||
EventName.wrongCruiseMode: {
|
||||
ET.USER_DISABLE: EngagementAlert(AudibleAlert.chimeDisengage),
|
||||
ET.NO_ENTRY: NoEntryAlert("Enable Adaptive Cruise"),
|
||||
ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage),
|
||||
ET.NO_ENTRY: NoEntryAlert("Adaptive Cruise Disabled"),
|
||||
},
|
||||
|
||||
EventName.steerTempUnavailable: {
|
||||
ET.SOFT_DISABLE: SoftDisableAlert("Steering Temporarily Unavailable"),
|
||||
ET.SOFT_DISABLE: soft_disable_alert("Steering Temporarily Unavailable"),
|
||||
ET.NO_ENTRY: NoEntryAlert("Steering Temporarily Unavailable"),
|
||||
},
|
||||
|
||||
@@ -575,12 +602,12 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
|
||||
|
||||
EventName.overheat: {
|
||||
ET.PERMANENT: NormalPermanentAlert("System Overheated"),
|
||||
ET.SOFT_DISABLE: SoftDisableAlert("System Overheated"),
|
||||
ET.SOFT_DISABLE: soft_disable_alert("System Overheated"),
|
||||
ET.NO_ENTRY: NoEntryAlert("System Overheated"),
|
||||
},
|
||||
|
||||
EventName.wrongGear: {
|
||||
ET.SOFT_DISABLE: SoftDisableAlert("Gear not D"),
|
||||
ET.SOFT_DISABLE: user_soft_disable_alert("Gear not D"),
|
||||
ET.NO_ENTRY: NoEntryAlert("Gear not D"),
|
||||
},
|
||||
|
||||
@@ -591,33 +618,33 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
|
||||
# See https://comma.ai/setup for more information
|
||||
EventName.calibrationInvalid: {
|
||||
ET.PERMANENT: NormalPermanentAlert("Calibration Invalid", "Remount Device and Recalibrate"),
|
||||
ET.SOFT_DISABLE: SoftDisableAlert("Calibration Invalid: Remount Device & Recalibrate"),
|
||||
ET.SOFT_DISABLE: soft_disable_alert("Calibration Invalid: Remount Device & Recalibrate"),
|
||||
ET.NO_ENTRY: NoEntryAlert("Calibration Invalid: Remount Device & Recalibrate"),
|
||||
},
|
||||
|
||||
EventName.calibrationIncomplete: {
|
||||
ET.PERMANENT: calibration_incomplete_alert,
|
||||
ET.SOFT_DISABLE: SoftDisableAlert("Calibration in Progress"),
|
||||
ET.SOFT_DISABLE: soft_disable_alert("Calibration in Progress"),
|
||||
ET.NO_ENTRY: NoEntryAlert("Calibration in Progress"),
|
||||
},
|
||||
|
||||
EventName.doorOpen: {
|
||||
ET.SOFT_DISABLE: SoftDisableAlert("Door Open"),
|
||||
ET.SOFT_DISABLE: user_soft_disable_alert("Door Open"),
|
||||
ET.NO_ENTRY: NoEntryAlert("Door Open"),
|
||||
},
|
||||
|
||||
EventName.seatbeltNotLatched: {
|
||||
ET.SOFT_DISABLE: SoftDisableAlert("Seatbelt Unlatched"),
|
||||
ET.SOFT_DISABLE: user_soft_disable_alert("Seatbelt Unlatched"),
|
||||
ET.NO_ENTRY: NoEntryAlert("Seatbelt Unlatched"),
|
||||
},
|
||||
|
||||
EventName.espDisabled: {
|
||||
ET.SOFT_DISABLE: SoftDisableAlert("ESP Off"),
|
||||
ET.SOFT_DISABLE: soft_disable_alert("ESP Off"),
|
||||
ET.NO_ENTRY: NoEntryAlert("ESP Off"),
|
||||
},
|
||||
|
||||
EventName.lowBattery: {
|
||||
ET.SOFT_DISABLE: SoftDisableAlert("Low Battery"),
|
||||
ET.SOFT_DISABLE: soft_disable_alert("Low Battery"),
|
||||
ET.NO_ENTRY: NoEntryAlert("Low Battery"),
|
||||
},
|
||||
|
||||
@@ -626,19 +653,17 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
|
||||
# is thrown. This can mean a service crashed, did not broadcast a message for
|
||||
# ten times the regular interval, or the average interval is more than 10% too high.
|
||||
EventName.commIssue: {
|
||||
ET.SOFT_DISABLE: SoftDisableAlert("Communication Issue between Processes"),
|
||||
ET.NO_ENTRY: NoEntryAlert("Communication Issue between Processes",
|
||||
audible_alert=AudibleAlert.chimeDisengage),
|
||||
ET.SOFT_DISABLE: soft_disable_alert("Communication Issue between Processes"),
|
||||
ET.NO_ENTRY: NoEntryAlert("Communication Issue between Processes"),
|
||||
},
|
||||
|
||||
# Thrown when manager detects a service exited unexpectedly while driving
|
||||
EventName.processNotRunning: {
|
||||
ET.NO_ENTRY: NoEntryAlert("System Malfunction: Reboot Your Device",
|
||||
audible_alert=AudibleAlert.chimeDisengage),
|
||||
ET.NO_ENTRY: NoEntryAlert("System Malfunction: Reboot Your Device"),
|
||||
},
|
||||
|
||||
EventName.radarFault: {
|
||||
ET.SOFT_DISABLE: SoftDisableAlert("Radar Error: Restart the Car"),
|
||||
ET.SOFT_DISABLE: soft_disable_alert("Radar Error: Restart the Car"),
|
||||
ET.NO_ENTRY: NoEntryAlert("Radar Error: Restart the Car"),
|
||||
},
|
||||
|
||||
@@ -646,7 +671,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
|
||||
# is not processing frames fast enough they have to be dropped. This alert is
|
||||
# thrown when over 20% of frames are dropped.
|
||||
EventName.modeldLagging: {
|
||||
ET.SOFT_DISABLE: SoftDisableAlert("Driving model lagging"),
|
||||
ET.SOFT_DISABLE: soft_disable_alert("Driving model lagging"),
|
||||
ET.NO_ENTRY: NoEntryAlert("Driving model lagging"),
|
||||
},
|
||||
|
||||
@@ -656,29 +681,27 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
|
||||
# usually means the model has trouble understanding the scene. This is used
|
||||
# as a heuristic to warn the driver.
|
||||
EventName.posenetInvalid: {
|
||||
ET.SOFT_DISABLE: SoftDisableAlert("Model Output Uncertain"),
|
||||
ET.SOFT_DISABLE: soft_disable_alert("Model Output Uncertain"),
|
||||
ET.NO_ENTRY: NoEntryAlert("Model Output Uncertain"),
|
||||
},
|
||||
|
||||
# When the localizer detects an acceleration of more than 40 m/s^2 (~4G) we
|
||||
# alert the driver the device might have fallen from the windshield.
|
||||
EventName.deviceFalling: {
|
||||
ET.SOFT_DISABLE: SoftDisableAlert("Device Fell Off Mount"),
|
||||
ET.SOFT_DISABLE: soft_disable_alert("Device Fell Off Mount"),
|
||||
ET.NO_ENTRY: NoEntryAlert("Device Fell Off Mount"),
|
||||
},
|
||||
|
||||
EventName.lowMemory: {
|
||||
ET.SOFT_DISABLE: SoftDisableAlert("Low Memory: Reboot Your Device"),
|
||||
ET.SOFT_DISABLE: soft_disable_alert("Low Memory: Reboot Your Device"),
|
||||
ET.PERMANENT: NormalPermanentAlert("Low Memory", "Reboot your Device"),
|
||||
ET.NO_ENTRY: NoEntryAlert("Low Memory: Reboot Your Device",
|
||||
audible_alert=AudibleAlert.chimeDisengage),
|
||||
ET.NO_ENTRY: NoEntryAlert("Low Memory: Reboot Your Device"),
|
||||
},
|
||||
|
||||
EventName.highCpuUsage: {
|
||||
#ET.SOFT_DISABLE: SoftDisableAlert("System Malfunction: Reboot Your Device"),
|
||||
#ET.SOFT_DISABLE: soft_disable_alert("System Malfunction: Reboot Your Device"),
|
||||
#ET.PERMANENT: NormalPermanentAlert("System Malfunction", "Reboot your Device"),
|
||||
ET.NO_ENTRY: NoEntryAlert("System Malfunction: Reboot Your Device",
|
||||
audible_alert=AudibleAlert.chimeDisengage),
|
||||
ET.NO_ENTRY: NoEntryAlert("System Malfunction: Reboot Your Device"),
|
||||
},
|
||||
|
||||
EventName.accFaulted: {
|
||||
@@ -712,7 +735,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
|
||||
# Sometimes the USB stack on the device can get into a bad state
|
||||
# causing the connection to the panda to be lost
|
||||
EventName.usbError: {
|
||||
ET.SOFT_DISABLE: SoftDisableAlert("USB Error: Reboot Your Device"),
|
||||
ET.SOFT_DISABLE: soft_disable_alert("USB Error: Reboot Your Device"),
|
||||
ET.PERMANENT: NormalPermanentAlert("USB Error: Reboot Your Device", ""),
|
||||
ET.NO_ENTRY: NoEntryAlert("USB Error: Reboot Your Device"),
|
||||
},
|
||||
@@ -782,7 +805,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
|
||||
"openpilot Canceled",
|
||||
"No close lead car",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.HIGH, VisualAlert.none, AudibleAlert.chimeDisengage, 3.),
|
||||
Priority.HIGH, VisualAlert.none, AudibleAlert.disengage, 3.),
|
||||
ET.NO_ENTRY: NoEntryAlert("No Close Lead Car"),
|
||||
},
|
||||
|
||||
@@ -791,16 +814,16 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
|
||||
"openpilot Canceled",
|
||||
"Speed too low",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.HIGH, VisualAlert.none, AudibleAlert.chimeDisengage, 3.),
|
||||
Priority.HIGH, VisualAlert.none, AudibleAlert.disengage, 3.),
|
||||
},
|
||||
|
||||
# When the car is driving faster than most cars in the training data the model outputs can be unpredictable
|
||||
# When the car is driving faster than most cars in the training data, the model outputs can be unpredictable.
|
||||
EventName.speedTooHigh: {
|
||||
ET.WARNING: Alert(
|
||||
"Speed Too High",
|
||||
"Model uncertain at this speed",
|
||||
AlertStatus.userPrompt, AlertSize.mid,
|
||||
Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.chimeWarning2RepeatInfinite, 4.),
|
||||
Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.promptRepeat, 4.),
|
||||
ET.NO_ENTRY: NoEntryAlert("Slow down to engage"),
|
||||
},
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import math
|
||||
|
||||
from cereal import log
|
||||
|
||||
|
||||
@@ -21,5 +22,7 @@ class LatControlAngle():
|
||||
angle_steers_des += params.angleOffsetDeg
|
||||
|
||||
angle_log.saturated = False
|
||||
angle_log.steeringAngleDeg = angle_steers_des
|
||||
angle_log.steeringAngleDeg = float(CS.steeringAngleDeg)
|
||||
angle_log.steeringAngleDesiredDeg = angle_steers_des
|
||||
|
||||
return 0, float(angle_steers_des), angle_log
|
||||
|
||||
@@ -95,14 +95,16 @@ class LatControlINDI():
|
||||
|
||||
steers_des = VM.get_steer_from_curvature(-curvature, CS.vEgo)
|
||||
steers_des += math.radians(params.angleOffsetDeg)
|
||||
indi_log.steeringAngleDesiredDeg = math.degrees(steers_des)
|
||||
|
||||
rate_des = VM.get_steer_from_curvature(-curvature_rate, CS.vEgo)
|
||||
indi_log.steeringRateDesiredDeg = math.degrees(rate_des)
|
||||
|
||||
if CS.vEgo < 0.3 or not active:
|
||||
indi_log.active = False
|
||||
self.output_steer = 0.0
|
||||
self.steer_filter.x = 0.0
|
||||
else:
|
||||
|
||||
rate_des = VM.get_steer_from_curvature(-curvature_rate, CS.vEgo)
|
||||
|
||||
# Expected actuator value
|
||||
self.steer_filter.update_alpha(self.RC)
|
||||
self.steer_filter.update(self.output_steer)
|
||||
|
||||
@@ -57,6 +57,7 @@ class LatControlLQR():
|
||||
|
||||
instant_offset = params.angleOffsetDeg - params.angleOffsetAverageDeg
|
||||
desired_angle += instant_offset # Only add offset that originates from vehicle model errors
|
||||
lqr_log.steeringAngleDesiredDeg = desired_angle
|
||||
|
||||
# Update Kalman filter
|
||||
angle_steers_k = float(self.C.dot(self.x_hat))
|
||||
@@ -93,7 +94,7 @@ class LatControlLQR():
|
||||
check_saturation = (CS.vEgo > 10) and not CS.steeringRateLimited and not CS.steeringPressed
|
||||
saturated = self._check_saturation(output_steer, check_saturation, steers_max)
|
||||
|
||||
lqr_log.steeringAngleDeg = angle_steers_k + params.angleOffsetAverageDeg
|
||||
lqr_log.steeringAngleDeg = angle_steers_k
|
||||
lqr_log.i = self.i_lqr
|
||||
lqr_log.output = output_steer
|
||||
lqr_log.lqrOutput = lqr_output
|
||||
|
||||
@@ -24,6 +24,7 @@ class LatControlPID():
|
||||
angle_steers_des_no_offset = math.degrees(VM.get_steer_from_curvature(-desired_curvature, CS.vEgo))
|
||||
angle_steers_des = angle_steers_des_no_offset + params.angleOffsetDeg
|
||||
|
||||
pid_log.steeringAngleDesiredDeg = angle_steers_des
|
||||
pid_log.angleError = angle_steers_des - CS.steeringAngleDeg
|
||||
if CS.vEgo < 0.3 or not active:
|
||||
output_steer = 0.0
|
||||
|
||||
@@ -38,7 +38,7 @@ DESIRES = {
|
||||
}
|
||||
|
||||
|
||||
class LateralPlanner():
|
||||
class LateralPlanner:
|
||||
def __init__(self, CP, use_lanelines=True, wide_camera=False):
|
||||
self.use_lanelines = use_lanelines
|
||||
self.LP = LanePlanner(wide_camera)
|
||||
@@ -55,8 +55,8 @@ class LateralPlanner():
|
||||
self.prev_one_blinker = False
|
||||
self.desire = log.LateralPlan.Desire.none
|
||||
|
||||
self.path_xyz = np.zeros((TRAJECTORY_SIZE,3))
|
||||
self.path_xyz_stds = np.ones((TRAJECTORY_SIZE,3))
|
||||
self.path_xyz = np.zeros((TRAJECTORY_SIZE, 3))
|
||||
self.path_xyz_stds = np.ones((TRAJECTORY_SIZE, 3))
|
||||
self.plan_yaw = np.zeros((TRAJECTORY_SIZE,))
|
||||
self.t_idxs = np.arange(TRAJECTORY_SIZE)
|
||||
self.y_pts = np.zeros(TRAJECTORY_SIZE)
|
||||
@@ -67,12 +67,8 @@ class LateralPlanner():
|
||||
def reset_mpc(self, x0=np.zeros(6)):
|
||||
self.x0 = x0
|
||||
self.lat_mpc.reset(x0=self.x0)
|
||||
self.desired_curvature = 0.0
|
||||
self.safe_desired_curvature = 0.0
|
||||
self.desired_curvature_rate = 0.0
|
||||
self.safe_desired_curvature_rate = 0.0
|
||||
|
||||
def update(self, sm, CP):
|
||||
def update(self, sm):
|
||||
v_ego = sm['carState'].vEgo
|
||||
active = sm['controlsState'].active
|
||||
measured_curvature = sm['controlsState'].curvature
|
||||
@@ -110,7 +106,7 @@ class LateralPlanner():
|
||||
self.lane_change_direction = LaneChangeDirection.none
|
||||
|
||||
torque_applied = sm['carState'].steeringPressed and \
|
||||
((sm['carState'].steeringTorque > 0 and self.lane_change_direction == LaneChangeDirection.left) or
|
||||
((sm['carState'].steeringTorque > 0 and self.lane_change_direction == LaneChangeDirection.left) or
|
||||
(sm['carState'].steeringTorque < 0 and self.lane_change_direction == LaneChangeDirection.right))
|
||||
|
||||
blindspot_detected = ((sm['carState'].leftBlindspot and self.lane_change_direction == LaneChangeDirection.left) or
|
||||
@@ -124,7 +120,7 @@ class LateralPlanner():
|
||||
# LaneChangeState.laneChangeStarting
|
||||
elif self.lane_change_state == LaneChangeState.laneChangeStarting:
|
||||
# fade out over .5s
|
||||
self.lane_change_ll_prob = max(self.lane_change_ll_prob - 2*DT_MDL, 0.0)
|
||||
self.lane_change_ll_prob = max(self.lane_change_ll_prob - 2 * DT_MDL, 0.0)
|
||||
|
||||
# 98% certainty
|
||||
lane_change_prob = self.LP.l_lane_change_prob + self.LP.r_lane_change_prob
|
||||
@@ -167,14 +163,14 @@ class LateralPlanner():
|
||||
self.LP.rll_prob *= self.lane_change_ll_prob
|
||||
if self.use_lanelines:
|
||||
d_path_xyz = self.LP.get_d_path(v_ego, self.t_idxs, self.path_xyz)
|
||||
self.lat_mpc.set_weights(MPC_COST_LAT.PATH, MPC_COST_LAT.HEADING, CP.steerRateCost)
|
||||
self.lat_mpc.set_weights(MPC_COST_LAT.PATH, MPC_COST_LAT.HEADING, self.steer_rate_cost)
|
||||
else:
|
||||
d_path_xyz = self.path_xyz
|
||||
path_cost = np.clip(abs(self.path_xyz[0,1]/self.path_xyz_stds[0,1]), 0.5, 1.5) * MPC_COST_LAT.PATH
|
||||
path_cost = np.clip(abs(self.path_xyz[0, 1] / self.path_xyz_stds[0, 1]), 0.5, 1.5) * MPC_COST_LAT.PATH
|
||||
# Heading cost is useful at low speed, otherwise end of plan can be off-heading
|
||||
heading_cost = interp(v_ego, [5.0, 10.0], [MPC_COST_LAT.HEADING, 0.0])
|
||||
self.lat_mpc.set_weights(path_cost, heading_cost, CP.steerRateCost)
|
||||
y_pts = np.interp(v_ego * self.t_idxs[:LAT_MPC_N + 1], np.linalg.norm(d_path_xyz, axis=1), d_path_xyz[:,1])
|
||||
self.lat_mpc.set_weights(path_cost, heading_cost, self.steer_rate_cost)
|
||||
y_pts = np.interp(v_ego * self.t_idxs[:LAT_MPC_N + 1], np.linalg.norm(d_path_xyz, axis=1), d_path_xyz[:, 1])
|
||||
heading_pts = np.interp(v_ego * self.t_idxs[:LAT_MPC_N + 1], np.linalg.norm(self.path_xyz, axis=1), self.plan_yaw)
|
||||
self.y_pts = y_pts
|
||||
|
||||
@@ -187,11 +183,10 @@ class LateralPlanner():
|
||||
y_pts,
|
||||
heading_pts)
|
||||
# init state for next
|
||||
self.x0[3] = interp(DT_MDL, self.t_idxs[:LAT_MPC_N + 1], self.lat_mpc.x_sol[:,3])
|
||||
self.x0[3] = interp(DT_MDL, self.t_idxs[:LAT_MPC_N + 1], self.lat_mpc.x_sol[:, 3])
|
||||
|
||||
|
||||
# Check for infeasable MPC solution
|
||||
mpc_nans = any(math.isnan(x) for x in self.lat_mpc.x_sol[:,3])
|
||||
# Check for infeasible MPC solution
|
||||
mpc_nans = any(math.isnan(x) for x in self.lat_mpc.x_sol[:, 3])
|
||||
t = sec_since_boot()
|
||||
if mpc_nans or self.lat_mpc.solution_status != 0:
|
||||
self.reset_mpc()
|
||||
@@ -212,8 +207,8 @@ class LateralPlanner():
|
||||
plan_send.lateralPlan.laneWidth = float(self.LP.lane_width)
|
||||
plan_send.lateralPlan.dPathPoints = [float(x) for x in self.y_pts]
|
||||
plan_send.lateralPlan.psis = [float(x) for x in self.lat_mpc.x_sol[0:CONTROL_N, 2]]
|
||||
plan_send.lateralPlan.curvatures = [float(x) for x in self.lat_mpc.x_sol[0:CONTROL_N,3]]
|
||||
plan_send.lateralPlan.curvatureRates = [float(x) for x in self.lat_mpc.u_sol[0:CONTROL_N-1]] +[0.0]
|
||||
plan_send.lateralPlan.curvatures = [float(x) for x in self.lat_mpc.x_sol[0:CONTROL_N, 3]]
|
||||
plan_send.lateralPlan.curvatureRates = [float(x) for x in self.lat_mpc.u_sol[0:CONTROL_N - 1]] + [0.0]
|
||||
plan_send.lateralPlan.lProb = float(self.LP.lll_prob)
|
||||
plan_send.lateralPlan.rProb = float(self.LP.rll_prob)
|
||||
plan_send.lateralPlan.dProb = float(self.LP.d_prob)
|
||||
|
||||
@@ -10,20 +10,20 @@ LongCtrlState = car.CarControl.Actuators.LongControlState
|
||||
STOPPING_TARGET_SPEED_OFFSET = 0.01
|
||||
|
||||
# As per ISO 15622:2018 for all speeds
|
||||
ACCEL_MIN_ISO = -3.5 # m/s^2
|
||||
ACCEL_MAX_ISO = 2.0 # m/s^2
|
||||
ACCEL_MIN_ISO = -3.5 # m/s^2
|
||||
ACCEL_MAX_ISO = 2.0 # m/s^2
|
||||
|
||||
|
||||
def long_control_state_trans(CP, active, long_control_state, v_ego, v_target, v_pid,
|
||||
def long_control_state_trans(CP, active, long_control_state, v_ego, v_target_future, v_pid,
|
||||
output_accel, brake_pressed, cruise_standstill, min_speed_can):
|
||||
"""Update longitudinal control state machine"""
|
||||
stopping_target_speed = min_speed_can + STOPPING_TARGET_SPEED_OFFSET
|
||||
stopping_condition = (v_ego < 2.0 and cruise_standstill) or \
|
||||
(v_ego < CP.vEgoStopping and
|
||||
((v_pid < stopping_target_speed and v_target < stopping_target_speed) or
|
||||
((v_pid < stopping_target_speed and v_target_future < stopping_target_speed) or
|
||||
brake_pressed))
|
||||
|
||||
starting_condition = v_target > CP.vEgoStarting and not cruise_standstill
|
||||
starting_condition = v_target_future > CP.vEgoStarting and not cruise_standstill
|
||||
|
||||
if not active:
|
||||
long_control_state = LongCtrlState.off
|
||||
@@ -75,13 +75,10 @@ class LongControl():
|
||||
|
||||
v_target_upper = interp(CP.longitudinalActuatorDelayUpperBound, T_IDXS[:CONTROL_N], long_plan.speeds)
|
||||
a_target_upper = 2 * (v_target_upper - long_plan.speeds[0])/CP.longitudinalActuatorDelayUpperBound - long_plan.accels[0]
|
||||
|
||||
v_target = min(v_target_lower, v_target_upper)
|
||||
a_target = min(a_target_lower, a_target_upper)
|
||||
|
||||
v_target_future = long_plan.speeds[-1]
|
||||
else:
|
||||
v_target = 0.0
|
||||
v_target_future = 0.0
|
||||
a_target = 0.0
|
||||
|
||||
@@ -103,11 +100,11 @@ class LongControl():
|
||||
|
||||
# tracking objects and driving
|
||||
elif self.long_control_state == LongCtrlState.pid:
|
||||
self.v_pid = v_target
|
||||
self.v_pid = long_plan.speeds[0]
|
||||
|
||||
# Toyota starts braking more when it thinks you want to stop
|
||||
# Freeze the integrator so we don't accelerate to compensate, and don't allow positive acceleration
|
||||
prevent_overshoot = not CP.stoppingControl and CS.vEgo < 1.5 and v_target_future < 0.7
|
||||
prevent_overshoot = not CP.stoppingControl and CS.vEgo < 1.5 and v_target_future < 0.7 and v_target_future < self.v_pid
|
||||
deadzone = interp(CS.vEgo, CP.longitudinalTuning.deadzoneBP, CP.longitudinalTuning.deadzoneV)
|
||||
freeze_integrator = prevent_overshoot
|
||||
|
||||
|
||||
@@ -49,15 +49,15 @@ T_IDXS_LST = [index_function(idx, max_val=MAX_T, max_idx=N+1) for idx in range(N
|
||||
T_IDXS = np.array(T_IDXS_LST)
|
||||
T_DIFFS = np.diff(T_IDXS, prepend=[0.])
|
||||
MIN_ACCEL = -3.5
|
||||
T_REACT = 1.8
|
||||
MAX_BRAKE = 9.81
|
||||
|
||||
T_FOLLOW = 1.45
|
||||
COMFORT_BRAKE = 2.5
|
||||
STOP_DISTANCE = 6.0
|
||||
|
||||
def get_stopped_equivalence_factor(v_lead):
|
||||
return T_REACT * v_lead + (v_lead*v_lead) / (2 * MAX_BRAKE)
|
||||
return (v_lead**2) / (2 * COMFORT_BRAKE)
|
||||
|
||||
def get_safe_obstacle_distance(v_ego):
|
||||
return 2 * T_REACT * v_ego + (v_ego*v_ego) / (2 * MAX_BRAKE) + 4.0
|
||||
return (v_ego**2) / (2 * COMFORT_BRAKE) + T_FOLLOW * v_ego + STOP_DISTANCE
|
||||
|
||||
def desired_follow_distance(v_ego, v_lead):
|
||||
return get_safe_obstacle_distance(v_ego) - get_stopped_equivalence_factor(v_lead)
|
||||
@@ -203,7 +203,7 @@ class LongitudinalMpc():
|
||||
self.solver = AcadosOcpSolverFast('long', N, EXPORT_DIR)
|
||||
self.v_solution = [0.0 for i in range(N+1)]
|
||||
self.a_solution = [0.0 for i in range(N+1)]
|
||||
self.prev_a = self.a_solution
|
||||
self.prev_a = np.array(self.a_solution)
|
||||
self.j_solution = [0.0 for i in range(N)]
|
||||
self.yref = np.zeros((N+1, COST_DIM))
|
||||
for i in range(N):
|
||||
@@ -255,7 +255,7 @@ class LongitudinalMpc():
|
||||
self.solver.cost_set(i, 'Zl', Zl)
|
||||
|
||||
def set_cur_state(self, v, a):
|
||||
if abs(self.x0[1] - v) > 1.:
|
||||
if abs(self.x0[1] - v) > 2.:
|
||||
self.x0[1] = v
|
||||
self.x0[2] = a
|
||||
for i in range(0, N+1):
|
||||
@@ -298,8 +298,9 @@ class LongitudinalMpc():
|
||||
self.cruise_min_a = min_a
|
||||
self.cruise_max_a = max_a
|
||||
|
||||
def update(self, carstate, radarstate, v_cruise):
|
||||
def update(self, carstate, radarstate, v_cruise, prev_accel_constraint=False):
|
||||
v_ego = self.x0[1]
|
||||
a_ego = self.x0[2]
|
||||
self.status = radarstate.leadOne.status or radarstate.leadTwo.status
|
||||
|
||||
lead_xv_0 = self.process_lead(radarstate.leadOne)
|
||||
@@ -317,17 +318,20 @@ class LongitudinalMpc():
|
||||
|
||||
# Fake an obstacle for cruise, this ensures smooth acceleration to set speed
|
||||
# when the leads are no factor.
|
||||
cruise_lower_bound = v_ego + (3/4) * self.cruise_min_a * T_IDXS
|
||||
cruise_upper_bound = v_ego + (3/4) * self.cruise_max_a * T_IDXS
|
||||
v_lower = v_ego + (T_IDXS * self.cruise_min_a * 1.05)
|
||||
v_upper = v_ego + (T_IDXS * self.cruise_max_a * 1.05)
|
||||
v_cruise_clipped = np.clip(v_cruise * np.ones(N+1),
|
||||
cruise_lower_bound,
|
||||
cruise_upper_bound)
|
||||
cruise_obstacle = T_IDXS*v_cruise_clipped + get_safe_obstacle_distance(v_cruise_clipped)
|
||||
v_lower,
|
||||
v_upper)
|
||||
cruise_obstacle = np.cumsum(T_DIFFS * v_cruise_clipped) + get_safe_obstacle_distance(v_cruise_clipped)
|
||||
|
||||
x_obstacles = np.column_stack([lead_0_obstacle, lead_1_obstacle, cruise_obstacle])
|
||||
self.source = SOURCES[np.argmin(x_obstacles[0])]
|
||||
self.params[:,2] = np.min(x_obstacles, axis=1)
|
||||
self.params[:,3] = np.copy(self.prev_a)
|
||||
if prev_accel_constraint:
|
||||
self.params[:,3] = np.copy(self.prev_a)
|
||||
else:
|
||||
self.params[:,3] = a_ego
|
||||
|
||||
self.run()
|
||||
if (np.any(lead_xv_0[:,0] - self.x_sol[:,0] < CRASH_DISTANCE) and
|
||||
@@ -348,7 +352,7 @@ class LongitudinalMpc():
|
||||
x_obstacle = 1e5*np.ones((N+1))
|
||||
self.params = np.concatenate([self.accel_limit_arr,
|
||||
x_obstacle[:,None],
|
||||
self.prev_a], axis=1)
|
||||
self.prev_a[:,None]], axis=1)
|
||||
self.run()
|
||||
|
||||
|
||||
@@ -367,7 +371,7 @@ class LongitudinalMpc():
|
||||
self.a_solution = self.x_sol[:,2]
|
||||
self.j_solution = self.u_sol[:,0]
|
||||
|
||||
self.prev_a = interp(T_IDXS + 0.05, T_IDXS, self.a_solution)
|
||||
self.prev_a = np.interp(T_IDXS + 0.05, T_IDXS, self.a_solution)
|
||||
|
||||
t = sec_since_boot()
|
||||
if self.solution_status != 0:
|
||||
|
||||
@@ -14,7 +14,7 @@ from selfdrive.controls.lib.drive_helpers import V_CRUISE_MAX, CONTROL_N
|
||||
from selfdrive.swaglog import cloudlog
|
||||
|
||||
LON_MPC_STEP = 0.2 # first step is 0.2s
|
||||
AWARENESS_DECEL = -0.2 # car smoothly decel at .2m/s^2 when user is distracted
|
||||
AWARENESS_DECEL = -0.2 # car smoothly decel at .2m/s^2 when user is distracted
|
||||
A_CRUISE_MIN = -1.2
|
||||
A_CRUISE_MAX_VALS = [1.2, 1.2, 0.8, 0.6]
|
||||
A_CRUISE_MAX_BP = [0., 15., 25., 40.]
|
||||
@@ -35,13 +35,13 @@ def limit_accel_in_turns(v_ego, angle_steers, a_target, CP):
|
||||
"""
|
||||
|
||||
a_total_max = interp(v_ego, _A_TOTAL_MAX_BP, _A_TOTAL_MAX_V)
|
||||
a_y = v_ego**2 * angle_steers * CV.DEG_TO_RAD / (CP.steerRatio * CP.wheelbase)
|
||||
a_x_allowed = math.sqrt(max(a_total_max**2 - a_y**2, 0.))
|
||||
a_y = v_ego ** 2 * angle_steers * CV.DEG_TO_RAD / (CP.steerRatio * CP.wheelbase)
|
||||
a_x_allowed = math.sqrt(max(a_total_max ** 2 - a_y ** 2, 0.))
|
||||
|
||||
return [a_target[0], min(a_target[1], a_x_allowed)]
|
||||
|
||||
|
||||
class Planner():
|
||||
class Planner:
|
||||
def __init__(self, CP, init_v=0.0, init_a=0.0):
|
||||
self.CP = CP
|
||||
self.mpc = LongitudinalMpc()
|
||||
@@ -50,14 +50,13 @@ class Planner():
|
||||
|
||||
self.v_desired = init_v
|
||||
self.a_desired = init_a
|
||||
self.alpha = np.exp(-DT_MDL/2.0)
|
||||
self.alpha = np.exp(-DT_MDL / 2.0)
|
||||
|
||||
self.v_desired_trajectory = np.zeros(CONTROL_N)
|
||||
self.a_desired_trajectory = np.zeros(CONTROL_N)
|
||||
self.j_desired_trajectory = np.zeros(CONTROL_N)
|
||||
|
||||
|
||||
def update(self, sm, CP):
|
||||
def update(self, sm):
|
||||
v_ego = sm['carState'].vEgo
|
||||
a_ego = sm['carState'].aEgo
|
||||
|
||||
@@ -68,10 +67,12 @@ class Planner():
|
||||
long_control_state = sm['controlsState'].longControlState
|
||||
force_slow_decel = sm['controlsState'].forceDecel
|
||||
|
||||
enabled = (long_control_state == LongCtrlState.pid) or (long_control_state == LongCtrlState.stopping)
|
||||
if not enabled or sm['carState'].gasPressed:
|
||||
prev_accel_constraint = True
|
||||
if long_control_state == LongCtrlState.off or sm['carState'].gasPressed:
|
||||
self.v_desired = v_ego
|
||||
self.a_desired = a_ego
|
||||
# Smoothly changing between accel trajectory is only relevant when OP is driving
|
||||
prev_accel_constraint = False
|
||||
|
||||
# Prevent divergence, smooth in current v_ego
|
||||
self.v_desired = self.alpha * self.v_desired + (1 - self.alpha) * v_ego
|
||||
@@ -88,12 +89,12 @@ class Planner():
|
||||
accel_limits_turns[1] = max(accel_limits_turns[1], self.a_desired - 0.05)
|
||||
self.mpc.set_accel_limits(accel_limits_turns[0], accel_limits_turns[1])
|
||||
self.mpc.set_cur_state(self.v_desired, self.a_desired)
|
||||
self.mpc.update(sm['carState'], sm['radarState'], v_cruise)
|
||||
self.mpc.update(sm['carState'], sm['radarState'], v_cruise, prev_accel_constraint=prev_accel_constraint)
|
||||
self.v_desired_trajectory = np.interp(T_IDXS[:CONTROL_N], T_IDXS_MPC, self.mpc.v_solution)
|
||||
self.a_desired_trajectory = np.interp(T_IDXS[:CONTROL_N], T_IDXS_MPC, self.mpc.a_solution)
|
||||
self.j_desired_trajectory = np.interp(T_IDXS[:CONTROL_N], T_IDXS_MPC[:-1], self.mpc.j_solution)
|
||||
|
||||
#TODO counter is only needed because radar is glitchy, remove once radar is gone
|
||||
# TODO counter is only needed because radar is glitchy, remove once radar is gone
|
||||
self.fcw = self.mpc.crash_cnt > 5
|
||||
if self.fcw:
|
||||
cloudlog.info("FCW triggered")
|
||||
@@ -101,7 +102,7 @@ class Planner():
|
||||
# Interpolate 0.05 seconds and save as starting point for next iteration
|
||||
a_prev = self.a_desired
|
||||
self.a_desired = float(interp(DT_MDL, T_IDXS[:CONTROL_N], self.a_desired_trajectory))
|
||||
self.v_desired = self.v_desired + DT_MDL * (self.a_desired + a_prev)/2.0
|
||||
self.v_desired = self.v_desired + DT_MDL * (self.a_desired + a_prev) / 2.0
|
||||
|
||||
def publish(self, sm, pm):
|
||||
plan_send = messaging.new_message('longitudinalPlan')
|
||||
|
||||
@@ -36,9 +36,9 @@ def plannerd_thread(sm=None, pm=None):
|
||||
sm.update()
|
||||
|
||||
if sm.updated['modelV2']:
|
||||
lateral_planner.update(sm, CP)
|
||||
lateral_planner.update(sm)
|
||||
lateral_planner.publish(sm, pm)
|
||||
longitudinal_planner.update(sm, CP)
|
||||
longitudinal_planner.update(sm)
|
||||
longitudinal_planner.publish(sm, pm)
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
"""Install exception handler for process crash."""
|
||||
from selfdrive.swaglog import cloudlog
|
||||
from selfdrive.version import version
|
||||
from selfdrive.version import get_version
|
||||
|
||||
import sentry_sdk
|
||||
from sentry_sdk.integrations.threading import ThreadingIntegration
|
||||
@@ -24,4 +24,4 @@ def bind_extra(**kwargs) -> None:
|
||||
def init() -> None:
|
||||
sentry_sdk.init("https://a8dc76b5bfb34908a601d67e2aa8bcf9@o33823.ingest.sentry.io/77924",
|
||||
default_integrations=False, integrations=[ThreadingIntegration(propagate_hub=True)],
|
||||
release=version)
|
||||
release=get_version())
|
||||
|
||||
@@ -66,7 +66,7 @@ if __name__ == "__main__":
|
||||
for p in psutil.process_iter():
|
||||
if p == psutil.Process():
|
||||
continue
|
||||
matched = any([l for l in p.cmdline() if any([pn for pn in monitored_proc_names if re.match(r'.*{}.*'.format(pn), l, re.M | re.I)])])
|
||||
matched = any(l for l in p.cmdline() if any(pn for pn in monitored_proc_names if re.match(r'.*{}.*'.format(pn), l, re.M | re.I)))
|
||||
if matched:
|
||||
k = ' '.join(p.cmdline())
|
||||
print('Add monitored proc:', k)
|
||||
@@ -119,5 +119,5 @@ if __name__ == "__main__":
|
||||
for x in l:
|
||||
print(x[2])
|
||||
print('avg sum: {0:.2%} over {1} samples {2} seconds\n'.format(
|
||||
sum([stat['avg']['total'] for k, stat in stats.items()]), i, i * SLEEP_INTERVAL
|
||||
sum(stat['avg']['total'] for k, stat in stats.items()), i, i * SLEEP_INTERVAL
|
||||
))
|
||||
|
||||
@@ -7,18 +7,31 @@ import time
|
||||
|
||||
from cereal import car, log
|
||||
import cereal.messaging as messaging
|
||||
from common.realtime import DT_CTRL
|
||||
from selfdrive.car.honda.interface import CarInterface
|
||||
from selfdrive.controls.lib.events import ET, EVENTS, Events
|
||||
from selfdrive.controls.lib.alertmanager import AlertManager
|
||||
|
||||
EventName = car.CarEvent.EventName
|
||||
|
||||
def cycle_alerts(duration=2000, is_metric=False):
|
||||
alerts = list(EVENTS.keys())
|
||||
print(alerts)
|
||||
def cycle_alerts(duration=200, is_metric=False):
|
||||
# all alerts
|
||||
#alerts = list(EVENTS.keys())
|
||||
|
||||
alerts = [EventName.preDriverDistracted, EventName.promptDriverDistracted, EventName.driverDistracted]
|
||||
#alerts = [EventName.preLaneChangeLeft, EventName.preLaneChangeRight]
|
||||
# this plays each type of audible alert
|
||||
alerts = [
|
||||
(EventName.buttonEnable, ET.ENABLE),
|
||||
(EventName.buttonCancel, ET.USER_DISABLE),
|
||||
(EventName.wrongGear, ET.NO_ENTRY),
|
||||
|
||||
(EventName.vehicleModelInvalid, ET.SOFT_DISABLE),
|
||||
(EventName.accFaulted, ET.IMMEDIATE_DISABLE),
|
||||
|
||||
# DM sequence
|
||||
(EventName.preDriverDistracted, ET.WARNING),
|
||||
(EventName.promptDriverDistracted, ET.WARNING),
|
||||
(EventName.driverDistracted, ET.WARNING),
|
||||
]
|
||||
|
||||
CP = CarInterface.get_params("HONDA CIVIC 2016")
|
||||
sm = messaging.SubMaster(['deviceState', 'pandaStates', 'roadCameraState', 'modelV2', 'liveCalibration',
|
||||
@@ -30,43 +43,45 @@ def cycle_alerts(duration=2000, is_metric=False):
|
||||
AM = AlertManager()
|
||||
|
||||
frame = 0
|
||||
idx, last_alert_millis = 0, 0
|
||||
while 1:
|
||||
if frame % duration == 0:
|
||||
idx = (idx + 1) % len(alerts)
|
||||
events.clear()
|
||||
events.add(alerts[idx])
|
||||
|
||||
|
||||
while True:
|
||||
current_alert_types = [ET.PERMANENT, ET.USER_DISABLE, ET.IMMEDIATE_DISABLE,
|
||||
ET.SOFT_DISABLE, ET.PRE_ENABLE, ET.NO_ENTRY,
|
||||
ET.ENABLE, ET.WARNING]
|
||||
a = events.create_alerts(current_alert_types, [CP, sm, is_metric])
|
||||
AM.add_many(frame, a)
|
||||
AM.process_alerts(frame)
|
||||
|
||||
dat = messaging.new_message()
|
||||
dat.init('controlsState')
|
||||
dat.controlsState.alertText1 = AM.alert_text_1
|
||||
dat.controlsState.alertText2 = AM.alert_text_2
|
||||
dat.controlsState.alertSize = AM.alert_size
|
||||
dat.controlsState.alertStatus = AM.alert_status
|
||||
dat.controlsState.alertBlinkingRate = AM.alert_rate
|
||||
dat.controlsState.alertType = AM.alert_type
|
||||
dat.controlsState.alertSound = AM.audible_alert
|
||||
pm.send('controlsState', dat)
|
||||
for alert, et in alerts:
|
||||
events.clear()
|
||||
events.add(alert)
|
||||
|
||||
dat = messaging.new_message()
|
||||
dat.init('deviceState')
|
||||
dat.deviceState.started = True
|
||||
pm.send('deviceState', dat)
|
||||
a = events.create_alerts([et, ], [CP, sm, is_metric, 0])
|
||||
AM.add_many(frame, a)
|
||||
AM.process_alerts(frame)
|
||||
print(AM.alert)
|
||||
for _ in range(duration):
|
||||
dat = messaging.new_message()
|
||||
dat.init('controlsState')
|
||||
dat.controlsState.enabled = True
|
||||
|
||||
dat = messaging.new_message('pandaStates', 1)
|
||||
dat.pandaStates[0].ignitionLine = True
|
||||
dat.pandaStates[0].pandaType = log.PandaState.PandaType.uno
|
||||
pm.send('pandaStates', dat)
|
||||
dat.controlsState.alertText1 = AM.alert_text_1
|
||||
dat.controlsState.alertText2 = AM.alert_text_2
|
||||
dat.controlsState.alertSize = AM.alert_size
|
||||
dat.controlsState.alertStatus = AM.alert_status
|
||||
dat.controlsState.alertBlinkingRate = AM.alert_rate
|
||||
dat.controlsState.alertType = AM.alert_type
|
||||
dat.controlsState.alertSound = AM.audible_alert
|
||||
pm.send('controlsState', dat)
|
||||
|
||||
time.sleep(0.01)
|
||||
dat = messaging.new_message()
|
||||
dat.init('deviceState')
|
||||
dat.deviceState.started = True
|
||||
pm.send('deviceState', dat)
|
||||
|
||||
dat = messaging.new_message('pandaStates', 1)
|
||||
dat.pandaStates[0].ignitionLine = True
|
||||
dat.pandaStates[0].pandaType = log.PandaState.PandaType.uno
|
||||
pm.send('pandaStates', dat)
|
||||
|
||||
frame += 1
|
||||
time.sleep(DT_CTRL)
|
||||
|
||||
if __name__ == '__main__':
|
||||
cycle_alerts()
|
||||
|
||||
@@ -52,25 +52,26 @@ def main():
|
||||
cloudlog.event("android service pid changed", proc=p, cur=cur[p], prev=procs[p])
|
||||
procs.update(cur)
|
||||
|
||||
# check modem state
|
||||
state = get_modem_state()
|
||||
if state != modem_state and not modem_killed:
|
||||
cloudlog.event("modem state changed", state=state)
|
||||
modem_state = state
|
||||
if os.path.exists(MODEM_PATH):
|
||||
# check modem state
|
||||
state = get_modem_state()
|
||||
if state != modem_state and not modem_killed:
|
||||
cloudlog.event("modem state changed", state=state)
|
||||
modem_state = state
|
||||
|
||||
# check modem crashes
|
||||
cnt = get_modem_crash_count()
|
||||
if cnt is not None:
|
||||
if cnt > crash_count:
|
||||
cloudlog.event("modem crash", count=cnt)
|
||||
crash_count = cnt
|
||||
# check modem crashes
|
||||
cnt = get_modem_crash_count()
|
||||
if cnt is not None:
|
||||
if cnt > crash_count:
|
||||
cloudlog.event("modem crash", count=cnt)
|
||||
crash_count = cnt
|
||||
|
||||
# handle excessive modem crashes
|
||||
if crash_count > MAX_MODEM_CRASHES and not modem_killed:
|
||||
cloudlog.event("killing modem")
|
||||
with open("/sys/kernel/debug/msm_subsys/modem", "w") as f:
|
||||
f.write("put")
|
||||
modem_killed = True
|
||||
# handle excessive modem crashes
|
||||
if crash_count > MAX_MODEM_CRASHES and not modem_killed:
|
||||
cloudlog.event("killing modem")
|
||||
with open("/sys/kernel/debug/msm_subsys/modem", "w") as f:
|
||||
f.write("put")
|
||||
modem_killed = True
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
[
|
||||
{
|
||||
"name": "boot",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/boot-ab4b6f64a90617ddbebe250f977616d70a25864f82c9c6ea9d88ebc5fe80e37c.img.xz",
|
||||
"hash": "ab4b6f64a90617ddbebe250f977616d70a25864f82c9c6ea9d88ebc5fe80e37c",
|
||||
"hash_raw": "ab4b6f64a90617ddbebe250f977616d70a25864f82c9c6ea9d88ebc5fe80e37c",
|
||||
"size": 14772224,
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/boot-5ad783213b7de18400f5fd3609fe75677fec80780ae31cbdf5a8ee7106675d7c.img.xz",
|
||||
"hash": "5ad783213b7de18400f5fd3609fe75677fec80780ae31cbdf5a8ee7106675d7c",
|
||||
"hash_raw": "5ad783213b7de18400f5fd3609fe75677fec80780ae31cbdf5a8ee7106675d7c",
|
||||
"size": 14768128,
|
||||
"sparse": false,
|
||||
"full_check": true,
|
||||
"has_ab": true
|
||||
@@ -41,9 +41,9 @@
|
||||
},
|
||||
{
|
||||
"name": "system",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/system-a778d523851d88a78ad7440ab602a80e09decdd1877f9f31ea36a7d7f15970dd.img.xz",
|
||||
"hash": "540ee7184cc6d8c14f94e652a062027dcc7559e47f4b347b6f8abac570521ec6",
|
||||
"hash_raw": "a778d523851d88a78ad7440ab602a80e09decdd1877f9f31ea36a7d7f15970dd",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/system-0fee88a42385d067756e9b25d57a80228835310deb7b5eef7b7bed5c22c45515.img.xz",
|
||||
"hash": "a043cba1ae08ca6d17704a8a0978b1e27e5bc79abb85b97efd35203ae26ae1ea",
|
||||
"hash_raw": "0fee88a42385d067756e9b25d57a80228835310deb7b5eef7b7bed5c22c45515",
|
||||
"size": 10737418240,
|
||||
"sparse": true,
|
||||
"full_check": false,
|
||||
|
||||
@@ -5,6 +5,7 @@ import hashlib
|
||||
import requests
|
||||
import struct
|
||||
import subprocess
|
||||
import time
|
||||
import os
|
||||
from typing import Generator
|
||||
|
||||
@@ -224,7 +225,6 @@ def verify_agnos_update(manifest_path: str, target_slot_number: int) -> bool:
|
||||
|
||||
if __name__ == "__main__":
|
||||
import logging
|
||||
import time
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(description="Flash and verify AGNOS update",
|
||||
|
||||
@@ -31,17 +31,18 @@ BASE_CONFIG = [
|
||||
AmpConfig("Enable PLL2", 0b1, 0x1A, 7, 0b10000000),
|
||||
AmpConfig("DAI1: I2S mode", 0b00100, 0x14, 2, 0b01111100),
|
||||
AmpConfig("DAI2: I2S mode", 0b00100, 0x1C, 2, 0b01111100),
|
||||
AmpConfig("Right speaker output volume", 0x1a, 0x3E, 0, 0b00011111),
|
||||
AmpConfig("Right speaker output volume", 0x1c, 0x3E, 0, 0b00011111),
|
||||
AmpConfig("DAI1 Passband filtering: music mode", 0b1, 0x18, 7, 0b10000000),
|
||||
AmpConfig("DAI1 voice mode gain (DV1G)", 0b00, 0x2F, 4, 0b00110000),
|
||||
AmpConfig("DAI1 attenuation (DV1)", 0x0, 0x2F, 0, 0b00001111),
|
||||
AmpConfig("DAI2 attenuation (DV2)", 0x0, 0x31, 0, 0b00001111),
|
||||
AmpConfig("DAI2: DC blocking", 0b1, 0x20, 0, 0b00000001),
|
||||
AmpConfig("DAI2: High sample rate", 0b0, 0x20, 3, 0b00001000),
|
||||
AmpConfig("ALC enable", 0b0, 0x43, 7, 0b10000000),
|
||||
AmpConfig("ALC enable", 0b1, 0x43, 7, 0b10000000),
|
||||
AmpConfig("ALC/excursion limiter release time", 0b101, 0x43, 4, 0b01110000),
|
||||
AmpConfig("ALC multiband enable", 0b1, 0x43, 3, 0b00001000),
|
||||
AmpConfig("DAI1 EQ enable", 0b0, 0x49, 0, 0b00000001),
|
||||
AmpConfig("DAI2 EQ enable", 0b0, 0x49, 1, 0b00000010),
|
||||
AmpConfig("DAI2 EQ enable", 0b1, 0x49, 1, 0b00000010),
|
||||
AmpConfig("DAI2 EQ clip detection disabled", 0b1, 0x32, 4, 0b00010000),
|
||||
AmpConfig("DAI2 EQ attenuation", 0x5, 0x32, 0, 0b00001111),
|
||||
AmpConfig("Excursion limiter upper corner freq", 0b100, 0x41, 4, 0b01110000),
|
||||
@@ -62,11 +63,11 @@ BASE_CONFIG = [
|
||||
AmpConfig("Zero-crossing detection disabled", 0b0, 0x49, 5, 0b00100000),
|
||||
]
|
||||
|
||||
BASE_CONFIG += configs_from_eq_params(0x84, EQParams(0x65C4, 0xC07C, 0x3D66, 0x07D9, 0x120F))
|
||||
BASE_CONFIG += configs_from_eq_params(0x84, EQParams(0x274F, 0xC0FF, 0x3BF9, 0x0B3C, 0x1656))
|
||||
BASE_CONFIG += configs_from_eq_params(0x8E, EQParams(0x1009, 0xC6BF, 0x2952, 0x1C97, 0x30DF))
|
||||
BASE_CONFIG += configs_from_eq_params(0x98, EQParams(0x2822, 0xC1C7, 0x3B50, 0x0EF8, 0x180A))
|
||||
BASE_CONFIG += configs_from_eq_params(0xA2, EQParams(0x1009, 0xC5C2, 0x271F, 0x1A87, 0x32A6))
|
||||
BASE_CONFIG += configs_from_eq_params(0xAC, EQParams(0x2000, 0xCA1E, 0x4000, 0x2287, 0x0000))
|
||||
BASE_CONFIG += configs_from_eq_params(0x98, EQParams(0x0F75, 0xCBE5, 0x0ED2, 0x2528, 0x3E42))
|
||||
BASE_CONFIG += configs_from_eq_params(0xA2, EQParams(0x091F, 0x3D4C, 0xCE11, 0x1266, 0x2807))
|
||||
BASE_CONFIG += configs_from_eq_params(0xAC, EQParams(0x0A9E, 0x3F20, 0xE573, 0x0A8B, 0x3A3B))
|
||||
|
||||
class Amplifier:
|
||||
AMP_I2C_BUS = 0
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
|
||||
class HardwareTici : public HardwareNone {
|
||||
public:
|
||||
static constexpr float MAX_VOLUME = 1.0;
|
||||
static constexpr float MIN_VOLUME = 0.4;
|
||||
static constexpr float MAX_VOLUME = 0.9;
|
||||
static constexpr float MIN_VOLUME = 0.2;
|
||||
static bool TICI() { return true; }
|
||||
static std::string get_os_version() {
|
||||
return "AGNOS " + util::read_file("/VERSION");
|
||||
|
||||
@@ -303,6 +303,13 @@ class Tici(HardwareBase):
|
||||
val = "0" if powersave_enabled else "1"
|
||||
os.system(f"sudo su -c 'echo {val} > /sys/devices/system/cpu/cpu{i}/online'")
|
||||
|
||||
for n in ('0', '4'):
|
||||
gov = 'userspace' if powersave_enabled else 'performance'
|
||||
os.system(f"sudo su -c 'echo {gov} > /sys/devices/system/cpu/cpufreq/policy{n}/scaling_governor'")
|
||||
|
||||
if powersave_enabled:
|
||||
os.system(f"sudo su -c 'echo 979200 > /sys/devices/system/cpu/cpufreq/policy{n}/scaling_setspeed'")
|
||||
|
||||
def get_gpu_usage_percent(self):
|
||||
try:
|
||||
used, total = open('/sys/class/kgsl/kgsl-3d0/gpubusy').read().strip().split()
|
||||
|
||||
@@ -18,6 +18,7 @@ const double MIN_STD_SANITY_CHECK = 1e-5; // m or rad
|
||||
const double VALID_TIME_SINCE_RESET = 1.0; // s
|
||||
const double VALID_POS_STD = 50.0; // m
|
||||
const double MAX_RESET_TRACKER = 5.0;
|
||||
const double SANE_GPS_UNCERTAINTY = 1500.0; // m
|
||||
|
||||
static VectorXd floatlist2vector(const capnp::List<float, capnp::Kind::PRIMITIVE>::Reader& floatlist) {
|
||||
VectorXd res(floatlist.size());
|
||||
@@ -130,16 +131,16 @@ void Localizer::build_live_location(cereal::LiveLocationKalman::Builder& fix) {
|
||||
Vector3d nans = Vector3d(NAN, NAN, NAN);
|
||||
|
||||
// write measurements to msg
|
||||
init_measurement(fix.initPositionGeodetic(), fix_pos_geo_vec, nans, this->last_gps_fix > 0);
|
||||
init_measurement(fix.initPositionECEF(), fix_ecef, fix_ecef_std, this->last_gps_fix > 0);
|
||||
init_measurement(fix.initVelocityECEF(), vel_ecef, vel_ecef_std, this->last_gps_fix > 0);
|
||||
init_measurement(fix.initVelocityNED(), ned_vel, nans, this->last_gps_fix > 0);
|
||||
init_measurement(fix.initPositionGeodetic(), fix_pos_geo_vec, nans, this->gps_mode);
|
||||
init_measurement(fix.initPositionECEF(), fix_ecef, fix_ecef_std, this->gps_mode);
|
||||
init_measurement(fix.initVelocityECEF(), vel_ecef, vel_ecef_std, this->gps_mode);
|
||||
init_measurement(fix.initVelocityNED(), ned_vel, nans, this->gps_mode);
|
||||
init_measurement(fix.initVelocityDevice(), vel_device, vel_device_std, true);
|
||||
init_measurement(fix.initAccelerationDevice(), accDevice, accDeviceErr, true);
|
||||
init_measurement(fix.initOrientationECEF(), orientation_ecef, orientation_ecef_std, this->last_gps_fix > 0);
|
||||
init_measurement(fix.initCalibratedOrientationECEF(), calibrated_orientation_ecef, nans, this->calibrated && this->last_gps_fix > 0);
|
||||
init_measurement(fix.initOrientationNED(), orientation_ned, nans, this->last_gps_fix > 0);
|
||||
init_measurement(fix.initCalibratedOrientationNED(), calibrated_orientation_ned, nans, this->calibrated && this->last_gps_fix > 0);
|
||||
init_measurement(fix.initOrientationECEF(), orientation_ecef, orientation_ecef_std, this->gps_mode);
|
||||
init_measurement(fix.initCalibratedOrientationECEF(), calibrated_orientation_ecef, nans, this->calibrated && this->gps_mode);
|
||||
init_measurement(fix.initOrientationNED(), orientation_ned, nans, this->gps_mode);
|
||||
init_measurement(fix.initCalibratedOrientationNED(), calibrated_orientation_ned, nans, this->calibrated && this->gps_mode);
|
||||
init_measurement(fix.initAngularVelocityDevice(), angVelocityDevice, angVelocityDeviceErr, true);
|
||||
init_measurement(fix.initVelocityCalibrated(), vel_calib, vel_calib_std, this->calibrated);
|
||||
init_measurement(fix.initAngularVelocityCalibrated(), ang_vel_calib, ang_vel_calib_std, this->calibrated);
|
||||
@@ -243,27 +244,39 @@ void Localizer::handle_sensors(double current_time, const capnp::List<cereal::Se
|
||||
}
|
||||
}
|
||||
|
||||
void Localizer::input_fake_gps_observations(double current_time) {
|
||||
// This is done to make sure that the error estimate of the position does not blow up
|
||||
// when the filter is in no-gps mode
|
||||
// Steps : first predict -> observe current obs with reasonable STD
|
||||
this->kf->predict(current_time);
|
||||
|
||||
VectorXd current_x = this->kf->get_x();
|
||||
VectorXd ecef_pos = current_x.segment<STATE_ECEF_POS_LEN>(STATE_ECEF_POS_START);
|
||||
VectorXd ecef_vel = current_x.segment<STATE_ECEF_VELOCITY_LEN>(STATE_ECEF_VELOCITY_START);
|
||||
MatrixXdr ecef_pos_R = this->kf->get_fake_gps_pos_cov();
|
||||
MatrixXdr ecef_vel_R = this->kf->get_fake_gps_vel_cov();
|
||||
|
||||
this->kf->predict_and_observe(current_time, OBSERVATION_ECEF_POS, { ecef_pos }, { ecef_pos_R });
|
||||
this->kf->predict_and_observe(current_time, OBSERVATION_ECEF_VEL, { ecef_vel }, { ecef_vel_R });
|
||||
}
|
||||
|
||||
void Localizer::handle_gps(double current_time, const cereal::GpsLocationData::Reader& log) {
|
||||
// ignore the message if the fix is invalid
|
||||
if (log.getFlags() % 2 == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Sanity checks
|
||||
if ((log.getVerticalAccuracy() <= 0) || (log.getSpeedAccuracy() <= 0) || (log.getBearingAccuracyDeg() <= 0)) {
|
||||
return;
|
||||
}
|
||||
bool gps_invalid_flag = (log.getFlags() % 2 == 0);
|
||||
bool gps_unreasonable = (Vector2d(log.getAccuracy(), log.getVerticalAccuracy()).norm() >= SANE_GPS_UNCERTAINTY);
|
||||
bool gps_accuracy_insane = ((log.getVerticalAccuracy() <= 0) || (log.getSpeedAccuracy() <= 0) || (log.getBearingAccuracyDeg() <= 0));
|
||||
bool gps_lat_lng_alt_insane = ((std::abs(log.getLatitude()) > 90) || (std::abs(log.getLongitude()) > 180) || (std::abs(log.getAltitude()) > ALTITUDE_SANITY_CHECK));
|
||||
bool gps_vel_insane = (floatlist2vector(log.getVNED()).norm() > TRANS_SANITY_CHECK);
|
||||
|
||||
if ((std::abs(log.getLatitude()) > 90) || (std::abs(log.getLongitude()) > 180) || (std::abs(log.getAltitude()) > ALTITUDE_SANITY_CHECK)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (floatlist2vector(log.getVNED()).norm() > TRANS_SANITY_CHECK) {
|
||||
if (gps_invalid_flag || gps_unreasonable || gps_accuracy_insane || gps_lat_lng_alt_insane || gps_vel_insane){
|
||||
this->determine_gps_mode(current_time);
|
||||
return;
|
||||
}
|
||||
|
||||
// Process message
|
||||
this->last_gps_fix = current_time;
|
||||
this->gps_mode = true;
|
||||
Geodetic geodetic = { log.getLatitude(), log.getLongitude(), log.getAltitude() };
|
||||
this->converter = std::make_unique<LocalCoord>(geodetic);
|
||||
|
||||
@@ -273,7 +286,7 @@ void Localizer::handle_gps(double current_time, const cereal::GpsLocationData::R
|
||||
MatrixXdr ecef_vel_R = Vector3d::Constant(std::pow(log.getSpeedAccuracy() * 10.0, 2)).asDiagonal();
|
||||
|
||||
this->unix_timestamp_millis = log.getTimestamp();
|
||||
double gps_est_error = (this->kf->get_x().head(3) - ecef_pos).norm();
|
||||
double gps_est_error = (this->kf->get_x().segment<STATE_ECEF_POS_LEN>(STATE_ECEF_POS_START) - ecef_pos).norm();
|
||||
|
||||
VectorXd orientation_ecef = quat2euler(vector2quat(this->kf->get_x().segment<STATE_ECEF_ORIENTATION_LEN>(STATE_ECEF_ORIENTATION_START)));
|
||||
VectorXd orientation_ned = ned_euler_from_ecef({ ecef_pos(0), ecef_pos(1), ecef_pos(2) }, orientation_ecef);
|
||||
@@ -290,11 +303,11 @@ void Localizer::handle_gps(double current_time, const cereal::GpsLocationData::R
|
||||
|
||||
if (ecef_vel.norm() > 5.0 && orientation_error.norm() > 1.0) {
|
||||
LOGE("Locationd vs ubloxLocation orientation difference too large, kalman reset");
|
||||
this->reset_kalman(NAN, initial_pose_ecef_quat, ecef_pos);
|
||||
this->reset_kalman(NAN, initial_pose_ecef_quat, ecef_pos, ecef_vel, ecef_pos_R, ecef_vel_R);
|
||||
this->kf->predict_and_observe(current_time, OBSERVATION_ECEF_ORIENTATION_FROM_GPS, { initial_pose_ecef_quat });
|
||||
} else if (gps_est_error > 100.0) {
|
||||
LOGE("Locationd vs ubloxLocation position difference too large, kalman reset");
|
||||
this->reset_kalman(NAN, initial_pose_ecef_quat, ecef_pos);
|
||||
this->reset_kalman(NAN, initial_pose_ecef_quat, ecef_pos, ecef_vel, ecef_pos_R, ecef_vel_R);
|
||||
}
|
||||
|
||||
this->kf->predict_and_observe(current_time, OBSERVATION_ECEF_POS, { ecef_pos }, { ecef_pos_R });
|
||||
@@ -358,7 +371,8 @@ void Localizer::handle_live_calib(double current_time, const cereal::LiveCalibra
|
||||
|
||||
void Localizer::reset_kalman(double current_time) {
|
||||
VectorXd init_x = this->kf->get_initial_x();
|
||||
this->reset_kalman(current_time, init_x.segment<4>(3), init_x.head(3));
|
||||
MatrixXdr init_P = this->kf->get_initial_P();
|
||||
this->reset_kalman(current_time, init_x, init_P);
|
||||
}
|
||||
|
||||
void Localizer::finite_check(double current_time) {
|
||||
@@ -390,13 +404,27 @@ void Localizer::update_reset_tracker() {
|
||||
}
|
||||
}
|
||||
|
||||
void Localizer::reset_kalman(double current_time, VectorXd init_orient, VectorXd init_pos) {
|
||||
void Localizer::reset_kalman(double current_time, VectorXd init_orient, VectorXd init_pos, VectorXd init_vel, MatrixXdr init_pos_R, MatrixXdr init_vel_R) {
|
||||
// too nonlinear to init on completely wrong
|
||||
VectorXd init_x = this->kf->get_initial_x();
|
||||
VectorXd current_x = this->kf->get_x();
|
||||
MatrixXdr current_P = this->kf->get_P();
|
||||
MatrixXdr init_P = this->kf->get_initial_P();
|
||||
init_x.segment<4>(3) = init_orient;
|
||||
init_x.head(3) = init_pos;
|
||||
MatrixXdr reset_orientation_P = this->kf->get_reset_orientation_P();
|
||||
int non_ecef_state_err_len = init_P.rows() - (STATE_ECEF_POS_ERR_LEN + STATE_ECEF_ORIENTATION_ERR_LEN + STATE_ECEF_VELOCITY_ERR_LEN);
|
||||
|
||||
current_x.segment<STATE_ECEF_ORIENTATION_LEN>(STATE_ECEF_ORIENTATION_START) = init_orient;
|
||||
current_x.segment<STATE_ECEF_VELOCITY_LEN>(STATE_ECEF_VELOCITY_START) = init_vel;
|
||||
current_x.segment<STATE_ECEF_POS_LEN>(STATE_ECEF_POS_START) = init_pos;
|
||||
|
||||
init_P.block<STATE_ECEF_POS_ERR_LEN, STATE_ECEF_POS_ERR_LEN>(STATE_ECEF_POS_ERR_START, STATE_ECEF_POS_ERR_START).diagonal() = init_pos_R.diagonal();
|
||||
init_P.block<STATE_ECEF_ORIENTATION_ERR_LEN, STATE_ECEF_ORIENTATION_ERR_LEN>(STATE_ECEF_ORIENTATION_ERR_START, STATE_ECEF_ORIENTATION_ERR_START).diagonal() = reset_orientation_P.diagonal();
|
||||
init_P.block<STATE_ECEF_VELOCITY_ERR_LEN, STATE_ECEF_VELOCITY_ERR_LEN>(STATE_ECEF_VELOCITY_ERR_START, STATE_ECEF_VELOCITY_ERR_START).diagonal() = init_vel_R.diagonal();
|
||||
init_P.block(STATE_ANGULAR_VELOCITY_ERR_START, STATE_ANGULAR_VELOCITY_ERR_START, non_ecef_state_err_len, non_ecef_state_err_len).diagonal() = current_P.block(STATE_ANGULAR_VELOCITY_ERR_START, STATE_ANGULAR_VELOCITY_ERR_START, non_ecef_state_err_len, non_ecef_state_err_len).diagonal();
|
||||
|
||||
this->reset_kalman(current_time, current_x, init_P);
|
||||
}
|
||||
|
||||
void Localizer::reset_kalman(double current_time, VectorXd init_x, MatrixXdr init_P) {
|
||||
this->kf->init_state(init_x, init_P, current_time);
|
||||
this->last_reset_time = current_time;
|
||||
this->reset_tracker += 1.0;
|
||||
@@ -447,14 +475,28 @@ bool Localizer::isGpsOK() {
|
||||
return this->kf->get_filter_time() - this->last_gps_fix < 1.0;
|
||||
}
|
||||
|
||||
void Localizer::determine_gps_mode(double current_time) {
|
||||
// 1. If the pos_std is greater than what's not acceptible and localizer is in gps-mode, reset to no-gps-mode
|
||||
// 2. If the pos_std is greater than what's not acceptible and localizer is in no-gps-mode, fake obs
|
||||
// 3. If the pos_std is smaller than what's not acceptible, let gps-mode be whatever it is
|
||||
VectorXd current_pos_std = this->kf->get_P().block<STATE_ECEF_POS_ERR_LEN, STATE_ECEF_POS_ERR_LEN>(STATE_ECEF_POS_ERR_START, STATE_ECEF_POS_ERR_START).diagonal().array().sqrt();
|
||||
if (current_pos_std.norm() > SANE_GPS_UNCERTAINTY){
|
||||
if (this->gps_mode){
|
||||
this->gps_mode = false;
|
||||
this->reset_kalman(current_time);
|
||||
}
|
||||
else{
|
||||
this->input_fake_gps_observations(current_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Localizer::locationd_thread() {
|
||||
const std::initializer_list<const char *> service_list =
|
||||
{ "gpsLocationExternal", "sensorEvents", "cameraOdometry", "liveCalibration", "carState" };
|
||||
PubMaster pm({ "liveLocationKalman" });
|
||||
SubMaster sm(service_list, nullptr, { "gpsLocationExternal" });
|
||||
|
||||
Params params;
|
||||
|
||||
while (!do_exit) {
|
||||
sm.update();
|
||||
for (const char* service : service_list) {
|
||||
@@ -479,8 +521,8 @@ int Localizer::locationd_thread() {
|
||||
std::string lastGPSPosJSON = util::string_format(
|
||||
"{\"latitude\": %.15f, \"longitude\": %.15f, \"altitude\": %.15f}", posGeo(0), posGeo(1), posGeo(2));
|
||||
|
||||
std::thread([¶ms] (const std::string gpsjson) {
|
||||
params.put("LastGPSPosition", gpsjson);
|
||||
std::thread([] (const std::string gpsjson) {
|
||||
Params().put("LastGPSPosition", gpsjson);
|
||||
}, lastGPSPosJSON).detach();
|
||||
}
|
||||
}
|
||||
@@ -489,7 +531,7 @@ int Localizer::locationd_thread() {
|
||||
}
|
||||
|
||||
int main() {
|
||||
set_realtime_priority(5);
|
||||
util::set_realtime_priority(5);
|
||||
|
||||
Localizer localizer;
|
||||
return localizer.locationd_thread();
|
||||
|
||||
@@ -27,11 +27,13 @@ public:
|
||||
int locationd_thread();
|
||||
|
||||
void reset_kalman(double current_time = NAN);
|
||||
void reset_kalman(double current_time, Eigen::VectorXd init_orient, Eigen::VectorXd init_pos);
|
||||
void reset_kalman(double current_time, Eigen::VectorXd init_orient, Eigen::VectorXd init_pos, Eigen::VectorXd init_vel, MatrixXdr init_pos_R, MatrixXdr init_vel_R);
|
||||
void reset_kalman(double current_time, Eigen::VectorXd init_x, MatrixXdr init_P);
|
||||
void finite_check(double current_time = NAN);
|
||||
void time_check(double current_time = NAN);
|
||||
void update_reset_tracker();
|
||||
bool isGpsOK();
|
||||
void determine_gps_mode(double current_time);
|
||||
|
||||
kj::ArrayPtr<capnp::byte> get_message_bytes(MessageBuilder& msg_builder, uint64_t logMonoTime,
|
||||
bool inputsOK, bool sensorsOK, bool gpsOK);
|
||||
@@ -49,6 +51,8 @@ public:
|
||||
void handle_cam_odo(double current_time, const cereal::CameraOdometry::Reader& log);
|
||||
void handle_live_calib(double current_time, const cereal::LiveCalibrationData::Reader& log);
|
||||
|
||||
void input_fake_gps_observations(double current_time);
|
||||
|
||||
private:
|
||||
std::unique_ptr<LiveKalman> kf;
|
||||
|
||||
@@ -67,4 +71,5 @@ private:
|
||||
double last_gps_fix = 0;
|
||||
double reset_tracker = 0.0;
|
||||
bool device_fell = false;
|
||||
bool gps_mode = false;
|
||||
};
|
||||
|
||||
@@ -28,11 +28,14 @@ std::vector<Eigen::Map<MatrixXdr>> get_vec_mapmat(std::vector<MatrixXdr>& mat_ve
|
||||
}
|
||||
|
||||
LiveKalman::LiveKalman() {
|
||||
this->dim_state = 26;
|
||||
this->dim_state_err = 25;
|
||||
this->dim_state = live_initial_x.rows();
|
||||
this->dim_state_err = live_initial_P_diag.rows();
|
||||
|
||||
this->initial_x = live_initial_x;
|
||||
this->initial_P = live_initial_P_diag.asDiagonal();
|
||||
this->fake_gps_pos_cov = live_fake_gps_pos_cov_diag.asDiagonal();
|
||||
this->fake_gps_vel_cov = live_fake_gps_vel_cov_diag.asDiagonal();
|
||||
this->reset_orientation_P = live_reset_orientation_diag.asDiagonal();
|
||||
this->Q = live_Q_diag.asDiagonal();
|
||||
for (auto& pair : live_obs_noise_diag) {
|
||||
this->obs_noise[pair.first] = pair.second.asDiagonal();
|
||||
@@ -87,6 +90,10 @@ std::optional<Estimate> LiveKalman::predict_and_observe(double t, int kind, std:
|
||||
return r;
|
||||
}
|
||||
|
||||
void LiveKalman::predict(double t) {
|
||||
this->filter->predict(t);
|
||||
}
|
||||
|
||||
Eigen::VectorXd LiveKalman::get_initial_x() {
|
||||
return this->initial_x;
|
||||
}
|
||||
@@ -95,6 +102,18 @@ MatrixXdr LiveKalman::get_initial_P() {
|
||||
return this->initial_P;
|
||||
}
|
||||
|
||||
MatrixXdr LiveKalman::get_fake_gps_pos_cov() {
|
||||
return this->fake_gps_pos_cov;
|
||||
}
|
||||
|
||||
MatrixXdr LiveKalman::get_fake_gps_vel_cov() {
|
||||
return this->fake_gps_vel_cov;
|
||||
}
|
||||
|
||||
MatrixXdr LiveKalman::get_reset_orientation_P() {
|
||||
return this->reset_orientation_P;
|
||||
}
|
||||
|
||||
MatrixXdr LiveKalman::H(VectorXd in) {
|
||||
assert(in.size() == 6);
|
||||
Matrix<double, 3, 6, Eigen::RowMajor> res;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user