Merge remote-tracking branch 'upstream/master' into enable-planner

pull/24873/head
Shane Smiskol 3 years ago
commit b7b425e530
  1. 1
      .github/workflows/selfdrive_tests.yaml
  2. 3
      common/swaglog.cc
  3. 7
      release/files_common
  4. 2
      selfdrive/car/honda/carcontroller.py
  5. 4
      selfdrive/car/honda/hondacan.py
  6. 2
      selfdrive/common/tests/.gitignore
  7. 15
      selfdrive/locationd/laikad.py
  8. 41
      selfdrive/test/process_replay/process_replay.py
  9. 2
      selfdrive/test/process_replay/ref_commit
  10. 4
      selfdrive/test/process_replay/test_processes.py
  11. 2
      selfdrive/test/test_onroad.py
  12. 2
      selfdrive/ui/qt/offroad/onboarding.cc
  13. 2
      selfdrive/ui/qt/offroad/settings.cc
  14. 6
      selfdrive/ui/qt/onroad.cc
  15. 6
      selfdrive/ui/qt/util.cc
  16. 11
      selfdrive/ui/qt/widgets/cameraview.cc
  17. 1
      selfdrive/ui/qt/widgets/cameraview.h
  18. 4
      selfdrive/ui/qt/widgets/ssh_keys.cc
  19. 50
      selfdrive/ui/tests/test_translations.py
  20. 3
      selfdrive/ui/translations/languages.json
  21. 20
      selfdrive/ui/ui.cc
  22. 12
      selfdrive/ui/ui.h
  23. 37
      selfdrive/ui/update_translations.py
  24. 9
      system/camerad/cameras/camera_common.cc
  25. 10
      system/camerad/cameras/camera_common.h
  26. 49
      tools/ssh/README.md

@ -307,6 +307,7 @@ jobs:
$UNIT_TEST tools/lib/tests && \
./selfdrive/ui/tests/create_test_translations.sh && \
QT_QPA_PLATFORM=offscreen ./selfdrive/ui/tests/test_translations && \
./selfdrive/ui/tests/test_translations.py && \
./common/tests/test_util && \
./common/tests/test_swaglog && \
./selfdrive/boardd/tests/test_boardd_usbprotocol && \

@ -66,8 +66,9 @@ static void log(int levelnum, const char* filename, int lineno, const char* func
char levelnum_c = levelnum;
zmq_send(s.sock, (levelnum_c + log_s).c_str(), log_s.length() + 1, ZMQ_NOBLOCK);
}
static void cloudlog_common(int levelnum, const char* filename, int lineno, const char* func,
char* msg_buf, json11::Json::object msg_j={}) {
char* msg_buf, const json11::Json::object &msg_j={}) {
std::lock_guard lk(s.lock);
if (!s.initialized) s.initialize();

@ -60,6 +60,8 @@ release/*
tools/lib/*
tools/joystick/*
tools/replay/*.cc
tools/replay/*.h
selfdrive/__init__.py
selfdrive/sentry.py
@ -287,6 +289,7 @@ selfdrive/ui/soundd/*.cc
selfdrive/ui/soundd/*.h
selfdrive/ui/soundd/soundd
selfdrive/ui/soundd/.gitignore
selfdrive/ui/translations/*
selfdrive/ui/qt/*.cc
selfdrive/ui/qt/*.h
@ -295,10 +298,6 @@ selfdrive/ui/qt/offroad/*.h
selfdrive/ui/qt/offroad/*.qml
selfdrive/ui/qt/widgets/*.cc
selfdrive/ui/qt/widgets/*.h
tools/replay/*.cc
tools/replay/*.h
selfdrive/ui/qt/maps/*.cc
selfdrive/ui/qt/maps/*.h

@ -241,7 +241,7 @@ class CarController:
idx = (self.frame // 10) % 4
hud = HUDData(int(pcm_accel), int(round(hud_v_cruise)), hud_control.leadVisible,
hud_control.lanesVisible, fcw_display, acc_alert, steer_required)
can_sends.extend(hondacan.create_ui_commands(self.packer, self.CP, CC.enabled, pcm_speed, hud, CS.is_metric, idx, CS.stock_hud, self.frame))
can_sends.extend(hondacan.create_ui_commands(self.packer, self.CP, CC.enabled, pcm_speed, hud, CS.is_metric, idx, CS.stock_hud))
if self.CP.openpilotLongitudinalControl and self.CP.carFingerprint not in HONDA_BOSCH:
self.speed = pcm_speed

@ -101,7 +101,7 @@ 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, CP, enabled, pcm_speed, hud, is_metric, idx, stock_hud, frame):
def create_ui_commands(packer, CP, enabled, pcm_speed, hud, is_metric, idx, stock_hud):
commands = []
bus_pt = get_pt_bus(CP.carFingerprint)
radar_disabled = CP.carFingerprint in HONDA_BOSCH and CP.openpilotLongitudinalControl
@ -141,8 +141,6 @@ def create_ui_commands(packer, CP, enabled, pcm_speed, hud, is_metric, idx, stoc
if CP.carFingerprint in HONDA_BOSCH_RADARLESS:
lkas_hud_values['LANE_LINES'] = 3
lkas_hud_values['DASHED_LANES'] = hud.lanes_visible
# TODO: understand this better, does car need to see it fall after start up?
lkas_hud_values['LKAS_PROBLEM'] = 0 if frame > 200 else 1
if not (CP.flags & HondaFlags.BOSCH_EXT_HUD):
lkas_hud_values['SET_ME_X48'] = 0x48

@ -1,2 +0,0 @@
test_util
test_swaglog

@ -1,5 +1,6 @@
#!/usr/bin/env python3
import json
import math
import os
import time
from collections import defaultdict
@ -29,11 +30,12 @@ CACHE_VERSION = 0.1
class Laikad:
def __init__(self, valid_const=("GPS", "GLONASS"), auto_update=False, valid_ephem_types=(EphemerisType.ULTRA_RAPID_ORBIT, EphemerisType.NAV),
def __init__(self, valid_const=("GPS", "GLONASS"), auto_fetch_orbits=True, auto_update=False, valid_ephem_types=(EphemerisType.ULTRA_RAPID_ORBIT, EphemerisType.NAV),
save_ephemeris=False, last_known_position=None):
self.astro_dog = AstroDog(valid_const=valid_const, auto_update=auto_update, valid_ephem_types=valid_ephem_types, clear_old_ephemeris=True)
self.gnss_kf = GNSSKalman(GENERATED_DIR, cython=True)
self.auto_fetch_orbits = auto_fetch_orbits
self.orbit_fetch_executor: Optional[ProcessPoolExecutor] = None
self.orbit_fetch_future: Optional[Future] = None
@ -41,6 +43,7 @@ class Laikad:
self.last_cached_t = None
self.save_ephemeris = save_ephemeris
self.load_cache()
self.posfix_functions = {constellation: get_posfix_sympy_fun(constellation) for constellation in (ConstellationId.GPS, ConstellationId.GLONASS)}
self.last_pos_fix = last_known_position if last_known_position is not None else []
self.last_pos_residual = []
@ -85,7 +88,8 @@ class Laikad:
report = ublox_msg.measurementReport
if report.gpsWeek > 0:
latest_msg_t = GPSTime(report.gpsWeek, report.rcvTow)
self.fetch_orbits(latest_msg_t + SECS_IN_MIN, block)
if self.auto_fetch_orbits:
self.fetch_orbits(latest_msg_t + SECS_IN_MIN, block)
new_meas = read_raw_ublox(report)
processed_measurements = process_measurements(new_meas, self.astro_dog)
@ -146,8 +150,8 @@ class Laikad:
def kf_valid(self, t: float) -> List[bool]:
filter_time = self.gnss_kf.filter.get_filter_time()
return [filter_time is not None,
filter_time is not None and abs(t - filter_time) < MAX_TIME_GAP,
return [not math.isnan(filter_time),
abs(t - filter_time) < MAX_TIME_GAP,
all(np.isfinite(self.gnss_kf.x[GStates.ECEF_POS]))]
def init_gnss_localizer(self, est_pos):
@ -275,7 +279,8 @@ def main(sm=None, pm=None):
replay = "REPLAY" in os.environ
# todo get last_known_position
laikad = Laikad(save_ephemeris=not replay)
use_internet = "LAIKAD_NO_INTERNET" not in os.environ
laikad = Laikad(save_ephemeris=not replay, auto_fetch_orbits=use_internet)
while True:
sm.update()

@ -27,14 +27,14 @@ TIMEOUT = 15
PROC_REPLAY_DIR = os.path.dirname(os.path.abspath(__file__))
FAKEDATA = os.path.join(PROC_REPLAY_DIR, "fakedata/")
ProcessConfig = namedtuple('ProcessConfig', ['proc_name', 'pub_sub', 'ignore', 'init_callback', 'should_recv_callback', 'tolerance', 'fake_pubsubmaster', 'submaster_config'], defaults=({},))
ProcessConfig = namedtuple('ProcessConfig', ['proc_name', 'pub_sub', 'ignore', 'init_callback', 'should_recv_callback', 'tolerance', 'fake_pubsubmaster', 'submaster_config', 'environ', 'subtest_name'], defaults=({}, {}, ""))
def wait_for_event(evt):
if not evt.wait(TIMEOUT):
if threading.currentThread().getName() == "MainThread":
# tested process likely died. don't let test just hang
raise Exception("Timeout reached. Tested process likely crashed.")
raise Exception(f"Timeout reached. Tested process {os.environ['PROC_NAME']} likely crashed.")
else:
# done testing this process, let it die
sys.exit(0)
@ -190,6 +190,7 @@ def get_car_params(msgs, fsm, can_sock, fingerprint):
_, CP = get_car(can, sendcan)
Params().put("CarParams", CP.to_bytes())
def controlsd_rcv_callback(msg, CP, cfg, fsm):
# no sendcan until controlsd is initialized
socks = [s for s in cfg.pub_sub[msg.which()] if
@ -198,6 +199,7 @@ def controlsd_rcv_callback(msg, CP, cfg, fsm):
socks.remove("sendcan")
return socks, len(socks) > 0
def radar_rcv_callback(msg, CP, cfg, fsm):
if msg.which() != "can":
return [], False
@ -240,7 +242,7 @@ def laika_rcv_callback(msg, CP, cfg, fsm):
if msg.ubloxGnss.which() == "measurementReport":
return ["gnssMeasurements"], True
else:
return [], False
return [], True
CONFIGS = [
@ -345,6 +347,19 @@ CONFIGS = [
tolerance=None,
fake_pubsubmaster=False,
),
ProcessConfig(
proc_name="laikad",
subtest_name="Offline",
pub_sub={
"ubloxGnss": ["gnssMeasurements"],
},
ignore=["logMonoTime"],
init_callback=get_car_params,
should_recv_callback=laika_rcv_callback,
tolerance=NUMPY_TOLERANCE,
fake_pubsubmaster=True,
environ={"LAIKAD_NO_INTERNET": "1"},
),
ProcessConfig(
proc_name="laikad",
pub_sub={
@ -366,7 +381,8 @@ def replay_process(cfg, lr, fingerprint=None):
else:
return cpp_replay_process(cfg, lr, fingerprint)
def setup_env(simulation=False, CP=None):
def setup_env(simulation=False, CP=None, cfg=None):
params = Params()
params.clear_all()
params.put_bool("OpenpilotEnabledToggle", True)
@ -380,6 +396,16 @@ def setup_env(simulation=False, CP=None):
os.environ['SKIP_FW_QUERY'] = ""
os.environ['FINGERPRINT'] = ""
if cfg is not None:
# Clear all custom processConfig environment variables
for cfg in CONFIGS:
for k, _ in cfg.environ.items():
if k in os.environ:
del os.environ[k]
os.environ.update(cfg.environ)
os.environ['PROC_NAME'] = cfg.proc_name
if simulation:
os.environ["SIMULATION"] = "1"
elif "SIMULATION" in os.environ:
@ -396,6 +422,7 @@ def setup_env(simulation=False, CP=None):
os.environ['SKIP_FW_QUERY'] = "1"
os.environ['FINGERPRINT'] = CP.carFingerprint
def python_replay_process(cfg, lr, fingerprint=None):
sub_sockets = [s for _, sub in cfg.pub_sub.items() for s in sub]
pub_sockets = [s for s in cfg.pub_sub.keys() if s != 'can']
@ -413,10 +440,10 @@ def python_replay_process(cfg, lr, fingerprint=None):
if fingerprint is not None:
os.environ['SKIP_FW_QUERY'] = "1"
os.environ['FINGERPRINT'] = fingerprint
setup_env()
setup_env(cfg=cfg)
else:
CP = [m for m in lr if m.which() == 'carParams'][0].carParams
setup_env(CP=CP)
setup_env(CP=CP, cfg=cfg)
assert(type(managed_processes[cfg.proc_name]) is PythonProcess)
managed_processes[cfg.proc_name].prepare()
@ -477,7 +504,7 @@ def cpp_replay_process(cfg, lr, fingerprint=None):
log_msgs = []
# We need to fake SubMaster alive since we can't inject a fake clock
setup_env(simulation=True)
setup_env(simulation=True, cfg=cfg)
managed_processes[cfg.proc_name].prepare()
managed_processes[cfg.proc_name].start()

@ -1 +1 @@
a0b5ce7b2e0b9c073e51ac8908402d53e1d99722
a9adebff7ce27d6233d443217a30337b761898ee

@ -200,11 +200,11 @@ if __name__ == "__main__":
if cfg.proc_name not in tested_procs:
continue
cur_log_fn = os.path.join(FAKEDATA, f"{segment}_{cfg.proc_name}_{cur_commit}.bz2")
cur_log_fn = os.path.join(FAKEDATA, f"{segment}_{cfg.proc_name}{cfg.subtest_name}_{cur_commit}.bz2")
if args.update_refs: # reference logs will not exist if routes were just regenerated
ref_log_path = get_url(*segment.rsplit("--", 1))
else:
ref_log_fn = os.path.join(FAKEDATA, f"{segment}_{cfg.proc_name}_{ref_commit}.bz2")
ref_log_fn = os.path.join(FAKEDATA, f"{segment}_{cfg.proc_name}{cfg.subtest_name}_{ref_commit}.bz2")
ref_log_path = ref_log_fn if os.path.exists(ref_log_fn) else BASE_URL + os.path.basename(ref_log_fn)
dat = None if args.upload_only else log_data[segment]

@ -24,7 +24,7 @@ PROCS = {
"selfdrive.controls.controlsd": 35.0,
"./loggerd": 10.0,
"./encoderd": 12.5,
"./camerad": 16.5,
"./camerad": 14.5,
"./locationd": 9.1,
"selfdrive.controls.plannerd": 11.7,
"./_ui": 19.2,

@ -151,7 +151,7 @@ void DeclinePage::showEvent(QShowEvent *event) {
QObject::connect(back_btn, &QPushButton::clicked, this, &DeclinePage::getBack);
QPushButton *uninstall_btn = new QPushButton(QString(tr("Decline, uninstall %1")).arg(getBrand()));
QPushButton *uninstall_btn = new QPushButton(tr("Decline, uninstall %1").arg(getBrand()));
uninstall_btn->setStyleSheet("background-color: #B73D3D");
buttons->addWidget(uninstall_btn);
QObject::connect(uninstall_btn, &QPushButton::clicked, [=]() {

@ -179,7 +179,7 @@ void DevicePanel::updateCalibDescription() {
if (calib.getCalStatus() != 0) {
double pitch = calib.getRpyCalib()[1] * (180 / M_PI);
double yaw = calib.getRpyCalib()[2] * (180 / M_PI);
desc += QString(tr(" Your device is pointed %1° %2 and %3° %4."))
desc += tr(" Your device is pointed %1° %2 and %3° %4.")
.arg(QString::number(std::abs(pitch), 'g', 1), pitch > 0 ? tr("down") : tr("up"),
QString::number(std::abs(yaw), 'g', 1), yaw > 0 ? tr("left") : tr("right"));
}

@ -430,13 +430,13 @@ void NvgWindow::drawLaneLines(QPainter &painter, const UIState *s) {
// lanelines
for (int i = 0; i < std::size(scene.lane_line_vertices); ++i) {
painter.setBrush(QColor::fromRgbF(1.0, 1.0, 1.0, std::clamp<float>(scene.lane_line_probs[i], 0.0, 0.7)));
painter.drawPolygon(scene.lane_line_vertices[i].v, scene.lane_line_vertices[i].cnt);
painter.drawPolygon(scene.lane_line_vertices[i]);
}
// road edges
for (int i = 0; i < std::size(scene.road_edge_vertices); ++i) {
painter.setBrush(QColor::fromRgbF(1.0, 0, 0, std::clamp<float>(1.0 - scene.road_edge_stds[i], 0.0, 1.0)));
painter.drawPolygon(scene.road_edge_vertices[i].v, scene.road_edge_vertices[i].cnt);
painter.drawPolygon(scene.road_edge_vertices[i]);
}
// paint path
@ -455,7 +455,7 @@ void NvgWindow::drawLaneLines(QPainter &painter, const UIState *s) {
bg.setColorAt(0.75 / 1.5, QColor::fromHslF(curve_hue / 360., 1.0, 0.68, 0.35));
bg.setColorAt(1.0, QColor::fromHslF(curve_hue / 360., 1.0, 0.68, 0.0));
painter.setBrush(bg);
painter.drawPolygon(scene.track_vertices.v, scene.track_vertices.cnt);
painter.drawPolygon(scene.track_vertices);
painter.restore();
}

@ -63,13 +63,13 @@ QString timeAgo(const QDateTime &date) {
s = "now";
} else if (diff < 60 * 60) {
int minutes = diff / 60;
s = QString(QObject::tr("%1 minute%2 ago")).arg(minutes).arg(minutes > 1 ? "s" : "");
s = QObject::tr("%1 minute%2 ago").arg(minutes).arg(minutes > 1 ? "s" : "");
} else if (diff < 60 * 60 * 24) {
int hours = diff / (60 * 60);
s = QString(QObject::tr("%1 hour%2 ago")).arg(hours).arg(hours > 1 ? "s" : "");
s = QObject::tr("%1 hour%2 ago").arg(hours).arg(hours > 1 ? "s" : "");
} else if (diff < 3600 * 24 * 7) {
int days = diff / (60 * 60 * 24);
s = QString(QObject::tr("%1 day%2 ago")).arg(days).arg(days > 1 ? "s" : "");
s = QObject::tr("%1 day%2 ago").arg(days).arg(days > 1 ? "s" : "");
} else {
s = date.date().toString();
}

@ -243,13 +243,12 @@ void CameraViewWidget::paintGL() {
// }
// Log duplicate/dropped frames
static int prev_id = 0;
if (frames[frame_idx].first == prev_id) {
qInfo() << "Drawing same frame twice" << frames[frame_idx].first;
} else if (frames[frame_idx].first != prev_id + 1) {
qInfo() << "Skipped frame" << frames[frame_idx].first;
if (frames[frame_idx].first == prev_frame_id) {
qDebug() << "Drawing same frame twice" << frames[frame_idx].first;
} else if (frames[frame_idx].first != prev_frame_id + 1) {
qDebug() << "Skipped frame" << frames[frame_idx].first;
}
prev_id = frames[frame_idx].first;
prev_frame_id = frames[frame_idx].first;
glViewport(0, 0, width(), height());
glBindVertexArray(frame_vao);

@ -78,6 +78,7 @@ protected:
std::deque<std::pair<uint32_t, VisionBuf*>> frames;
uint32_t draw_frame_id = 0;
int prev_frame_id = 0;
protected slots:
void vipcConnected(VisionIpcClient *vipc_client);

@ -47,13 +47,13 @@ void SshControl::getUserKeys(const QString &username) {
params.put("GithubUsername", username.toStdString());
params.put("GithubSshKeys", resp.toStdString());
} else {
ConfirmationDialog::alert(QString(tr("Username '%1' has no keys on GitHub")).arg(username), this);
ConfirmationDialog::alert(tr("Username '%1' has no keys on GitHub").arg(username), this);
}
} else {
if (request->timeout()) {
ConfirmationDialog::alert(tr("Request timed out"), this);
} else {
ConfirmationDialog::alert(QString(tr("Username '%1' doesn't exist on GitHub")).arg(username), this);
ConfirmationDialog::alert(tr("Username '%1' doesn't exist on GitHub").arg(username), this);
}
}

@ -0,0 +1,50 @@
#!/usr/bin/env python3
import json
import os
import unittest
from selfdrive.ui.update_translations import TRANSLATIONS_DIR, LANGUAGES_FILE, update_translations
class TestTranslations(unittest.TestCase):
@classmethod
def setUpClass(cls):
with open(LANGUAGES_FILE, "r") as f:
cls.translation_files = json.load(f)
def test_missing_translation_files(self):
for name, file in self.translation_files.items():
with self.subTest(name=name, file=file):
if not len(file):
self.skipTest(f"{name} translation has no file")
self.assertTrue(os.path.exists(os.path.join(TRANSLATIONS_DIR, f"{file}.ts")),
f"{name} has no XML translation file, run selfdrive/ui/update_translations.py")
self.assertTrue(os.path.exists(os.path.join(TRANSLATIONS_DIR, f"{file}.qm")),
f"{name} has no compiled QM translation file, run selfdrive/ui/update_translations.py --release")
def test_translations_updated(self):
suffix = "_test"
update_translations(suffix=suffix)
for name, file in self.translation_files.items():
with self.subTest(name=name, file=file):
cur_tr_file = os.path.join(TRANSLATIONS_DIR, f"{file}.ts")
new_tr_file = os.path.join(TRANSLATIONS_DIR, f"{file}{suffix}.ts")
if not len(file):
self.skipTest(f"{name} translation has no file")
elif not os.path.exists(cur_tr_file):
self.skipTest(f"{name} missing translation file") # caught by test_missing_translation_files
with open(cur_tr_file, "r") as f:
cur_translations = f.read()
with open(new_tr_file, "r") as f:
new_translations = f.read()
self.assertEqual(cur_translations, new_translations,
f"{name} translation file out of date. Run selfdrive/ui/update_translations.py to update the translation files")
if __name__ == "__main__":
unittest.main()

@ -55,10 +55,13 @@ static void update_leads(UIState *s, const cereal::RadarState::Reader &radar_sta
}
static void update_line_data(const UIState *s, const cereal::ModelDataV2::XYZTData::Reader &line,
float y_off, float z_off, line_vertices_data *pvd, int max_idx, bool allow_invert=true) {
float y_off, float z_off, QPolygonF *pvd, int max_idx, bool allow_invert=true) {
const auto line_x = line.getX(), line_y = line.getY(), line_z = line.getZ();
std::vector<QPointF> left_points, right_points;
QPolygonF left_points, right_points;
left_points.reserve(max_idx + 1);
right_points.reserve(max_idx + 1);
for (int i = 0; i <= max_idx; i++) {
QPointF left, right;
bool l = calib_frame_to_full_frame(s, line_x[i], line_y[i] - y_off, line_z[i] + z_off, &left);
@ -69,19 +72,10 @@ static void update_line_data(const UIState *s, const cereal::ModelDataV2::XYZTDa
continue;
}
left_points.push_back(left);
right_points.push_back(right);
right_points.push_front(right);
}
}
pvd->cnt = 2 * left_points.size();
assert(left_points.size() == right_points.size());
assert(pvd->cnt <= std::size(pvd->v));
for (int left_idx = 0; left_idx < left_points.size(); left_idx++){
int right_idx = 2 * left_points.size() - left_idx - 1;
pvd->v[left_idx] = left_points[left_idx];
pvd->v[right_idx] = right_points[left_idx];
}
*pvd = left_points + right_points;
}
static void update_model(UIState *s, const cereal::ModelDataV2::Reader &model) {

@ -8,6 +8,7 @@
#include <QTimer>
#include <QColor>
#include <QFuture>
#include <QPolygonF>
#include <QTransform>
#include "cereal/messaging/messaging.h"
@ -84,11 +85,6 @@ const QColor bg_colors [] = {
[STATUS_ALERT] = QColor(0xC9, 0x22, 0x31, 0xf1),
};
typedef struct {
QPointF v[TRAJECTORY_SIZE * 2];
int cnt;
} line_vertices_data;
typedef struct UIScene {
bool calibration_valid = false;
mat3 view_from_calib = DEFAULT_CALIBRATION;
@ -97,9 +93,9 @@ typedef struct UIScene {
// modelV2
float lane_line_probs[4];
float road_edge_stds[2];
line_vertices_data track_vertices;
line_vertices_data lane_line_vertices[4];
line_vertices_data road_edge_vertices[2];
QPolygonF track_vertices;
QPolygonF lane_line_vertices[4];
QPolygonF road_edge_vertices[2];
// lead
QPointF lead_vertices[2];

@ -0,0 +1,37 @@
#!/usr/bin/env python3
import argparse
import os
import json
from common.basedir import BASEDIR
UI_DIR = os.path.join(BASEDIR, "selfdrive", "ui")
TRANSLATIONS_DIR = os.path.join(UI_DIR, "translations")
LANGUAGES_FILE = os.path.join(TRANSLATIONS_DIR, "languages.json")
def update_translations(release=False, suffix=""):
with open(LANGUAGES_FILE, "r") as f:
translation_files = json.load(f)
for name, file in translation_files.items():
if not len(file):
print(f"{name} has no translation file, skipping...")
continue
tr_file = os.path.join(TRANSLATIONS_DIR, f"{file}{suffix}.ts")
ret = os.system(f"lupdate -recursive {UI_DIR} -ts {tr_file}")
assert ret == 0
if release:
ret = os.system(f"lrelease {tr_file}")
assert ret == 0
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Update translation files for UI",
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument("--release", action="store_true", help="Create compiled QM translation files used by UI")
args = parser.parse_args()
update_translations(args.release)

@ -66,11 +66,10 @@ private:
bool hdr_;
};
void CameraBuf::init(cl_device_id device_id, cl_context context, CameraState *s, VisionIpcServer * v, int frame_cnt, VisionStreamType init_rgb_type, VisionStreamType init_yuv_type, release_cb init_release_callback) {
void CameraBuf::init(cl_device_id device_id, cl_context context, CameraState *s, VisionIpcServer * v, int frame_cnt, VisionStreamType init_rgb_type, VisionStreamType init_yuv_type) {
vipc_server = v;
this->rgb_type = init_rgb_type;
this->yuv_type = init_yuv_type;
this->release_callback = init_release_callback;
const CameraInfo *ci = &s->ci;
camera_state = s;
@ -127,7 +126,7 @@ CameraBuf::~CameraBuf() {
}
bool CameraBuf::acquire() {
if (!safe_queue.try_pop(cur_buf_idx, 1)) return false;
if (!safe_queue.try_pop(cur_buf_idx, 50)) return false;
if (camera_bufs_metadata[cur_buf_idx].frame_id == -1) {
LOGE("no frame data? wtf");
@ -169,9 +168,7 @@ bool CameraBuf::acquire() {
}
void CameraBuf::release() {
if (release_callback) {
release_callback((void*)camera_state, cur_buf_idx);
}
// Empty
}
void CameraBuf::queue(size_t buf_idx) {

@ -48,8 +48,6 @@ const bool env_disable_driver = getenv("DISABLE_DRIVER") != NULL;
const bool env_debug_frames = getenv("DEBUG_FRAMES") != NULL;
const bool env_log_raw_frames = getenv("LOG_RAW_FRAMES") != NULL;
typedef void (*release_cb)(void *cookie, int buf_idx);
typedef struct CameraInfo {
uint32_t frame_width, frame_height;
uint32_t frame_stride;
@ -85,11 +83,6 @@ typedef struct FrameMetadata {
float processing_time;
} FrameMetadata;
typedef struct CameraExpInfo {
int op_id;
float grey_frac;
} CameraExpInfo;
struct MultiCameraState;
struct CameraState;
class Debayer;
@ -108,7 +101,6 @@ private:
SafeQueue<int> safe_queue;
int frame_buf_count;
release_cb release_callback;
public:
cl_command_queue q;
@ -124,7 +116,7 @@ public:
CameraBuf() = default;
~CameraBuf();
void init(cl_device_id device_id, cl_context context, CameraState *s, VisionIpcServer * v, int frame_cnt, VisionStreamType rgb_type, VisionStreamType yuv_type, release_cb release_callback=nullptr);
void init(cl_device_id device_id, cl_context context, CameraState *s, VisionIpcServer * v, int frame_cnt, VisionStreamType rgb_type, VisionStreamType yuv_type);
bool acquire();
void release();
void queue(size_t buf_idx);

@ -22,3 +22,52 @@ The public keys are only fetched from your GitHub account once. In order to upda
The `id_rsa` key in this directory only works while your device is in the setup state with no software installed. After installation, that default key will be removed.
See the [community wiki](https://github.com/commaai/openpilot/wiki/SSH) for more detailed instructions and information.
# Connecting to ssh.comma.ai
SSH into your comma device from anywhere with `ssh.comma.ai`.
## Setup
With software version 0.6.1 or newer, enter your GitHub username on your device under Developer Settings. Your GitHub authorized public keys will become your authorized SSH keys for `ssh.comma.ai`. You can add any additional keys in `/system/comma/home/.ssh/authorized_keys.persist`.
Requires [comma SIM with comma prime](https://comma.ai/shop) activated with comma connect, available on iOS and Android. comma two and EON ship with a pre-inserted comma SIM.
## Recommended .ssh/config
With the below ssh configuration, you can type `ssh comma-{dongleid}` to connect to your device through `ssh.comma.ai`. For example, `ssh comma-ffffffffffffffff`.
```
Host comma-*
Port 22
User comma
IdentityFile ~/.ssh/my_github_key
ProxyCommand ssh %h@ssh.comma.ai -W %h:%p
Host ssh.comma.ai
Hostname ssh.comma.ai
Port 22
IdentityFile ~/.ssh/my_github_key
```
## One-off connection
```
ssh -i ~/.ssh/my_github_key -o ProxyCommand="ssh -i ~/.ssh/my_github_key -W %h:%p -p %p %h@ssh.comma.ai" comma@ffffffffffffffff
```
(Replace `ffffffffffffffff` with your dongle_id)
## ssh.comma.ai host key fingerprint
```
Host key fingerprint is SHA256:X22GOmfjGb9J04IA2+egtdaJ7vW9Fbtmpz9/x8/W1X4
+---[RSA 4096]----+
| |
| |
| . |
| + o |
| S = + +..|
| + @ = .=|
| . B @ ++=|
| o * B XE|
| .o o OB/|
+----[SHA256]-----+
```

Loading…
Cancel
Save