mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-09-08 09:03:42 +08:00
Merge branch commaai/openpilot:master into branch sunnypilot/sunnypilot:master-new
This commit is contained in:
@@ -29,7 +29,7 @@ cabana_lib = cabana_env.Library("cabana_lib", ['mainwin.cc', 'streams/socketcans
|
||||
'streams/routes.cc', 'dbc/dbc.cc', 'dbc/dbcfile.cc', 'dbc/dbcmanager.cc',
|
||||
'utils/export.cc', 'utils/util.cc',
|
||||
'chart/chartswidget.cc', 'chart/chart.cc', 'chart/signalselector.cc', 'chart/tiplabel.cc', 'chart/sparkline.cc',
|
||||
'commands.cc', 'messageswidget.cc', 'streamselector.cc', 'settings.cc', 'detailwidget.cc', 'tools/findsimilarbits.cc', 'tools/findsignal.cc'], LIBS=cabana_libs, FRAMEWORKS=base_frameworks)
|
||||
'commands.cc', 'messageswidget.cc', 'streamselector.cc', 'settings.cc', 'detailwidget.cc', 'tools/findsimilarbits.cc', 'tools/findsignal.cc', 'tools/routeinfo.cc'], LIBS=cabana_libs, FRAMEWORKS=base_frameworks)
|
||||
cabana_env.Program('cabana', ['cabana.cc', cabana_lib, assets], LIBS=cabana_libs, FRAMEWORKS=base_frameworks)
|
||||
|
||||
if GetOption('extras'):
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
#include "tools/cabana/tools/routeinfo.h"
|
||||
#include <QHeaderView>
|
||||
#include <QScrollBar>
|
||||
#include <QTableWidget>
|
||||
#include <QVBoxLayout>
|
||||
#include "tools/cabana/streams/replaystream.h"
|
||||
|
||||
RouteInfoDlg::RouteInfoDlg(QWidget *parent) : QDialog(parent) {
|
||||
auto *replay = qobject_cast<ReplayStream *>(can)->getReplay();
|
||||
setWindowTitle(tr("Route: %1").arg(QString::fromStdString(replay->route().name())));
|
||||
|
||||
auto *table = new QTableWidget(replay->route().segments().size(), 7, this);
|
||||
table->setToolTip(tr("Click on a row to seek to the corresponding segment."));
|
||||
table->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
table->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
table->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
table->setHorizontalHeaderLabels({"", "rlog", "fcam", "ecam", "dcam", "qlog", "qcam"});
|
||||
table->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
table->verticalHeader()->setVisible(false);
|
||||
table->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
|
||||
int row = 0;
|
||||
for (const auto &[seg_num, seg] : replay->route().segments()) {
|
||||
table->setItem(row, 0, new QTableWidgetItem(QString::number(seg_num)));
|
||||
table->setItem(row, 1, new QTableWidgetItem(seg.rlog.empty() ? "--" : "Yes"));
|
||||
table->setItem(row, 2, new QTableWidgetItem(seg.road_cam.empty() ? "--" : "Yes"));
|
||||
table->setItem(row, 3, new QTableWidgetItem(seg.wide_road_cam.empty() ? "--" : "Yes"));
|
||||
table->setItem(row, 4, new QTableWidgetItem(seg.driver_cam.empty() ? "--" : "Yes"));
|
||||
table->setItem(row, 5, new QTableWidgetItem(seg.qlog.empty() ? "--" : "Yes"));
|
||||
table->setItem(row, 6, new QTableWidgetItem(seg.qcamera.empty() ? "--" : "Yes"));
|
||||
++row;
|
||||
}
|
||||
table->setMinimumWidth(table->horizontalHeader()->length() + table->verticalScrollBar()->sizeHint().width());
|
||||
table->setMinimumHeight(table->rowHeight(0) * std::min(table->rowCount(), 13) + table->horizontalHeader()->height() + table->frameWidth() * 2);
|
||||
|
||||
connect(table, &QTableWidget::itemClicked, [](QTableWidgetItem *item) { can->seekTo(item->row() * 60.0); });
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
layout->addWidget(table);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
#include <QDialog>
|
||||
|
||||
class RouteInfoDlg : public QDialog {
|
||||
Q_OBJECT
|
||||
public:
|
||||
RouteInfoDlg(QWidget *parent = nullptr);
|
||||
};
|
||||
@@ -11,6 +11,8 @@
|
||||
#include <QVBoxLayout>
|
||||
#include <QtConcurrent>
|
||||
|
||||
#include "tools/cabana/tools/routeinfo.h"
|
||||
|
||||
const int MIN_VIDEO_HEIGHT = 100;
|
||||
const int THUMBNAIL_MARGIN = 3;
|
||||
|
||||
@@ -100,9 +102,12 @@ void VideoWidget::createPlaybackController() {
|
||||
|
||||
if (!can->liveStreaming()) {
|
||||
toolbar->addAction(utils::icon("repeat"), tr("Loop playback"), this, &VideoWidget::loopPlaybackClicked);
|
||||
createSpeedDropdown(toolbar);
|
||||
toolbar->addSeparator();
|
||||
toolbar->addAction(utils::icon("info-circle"), tr("View route details"), this, &VideoWidget::showRouteInfo);
|
||||
} else {
|
||||
createSpeedDropdown(toolbar);
|
||||
}
|
||||
|
||||
createSpeedDropdown(toolbar);
|
||||
}
|
||||
|
||||
void VideoWidget::createSpeedDropdown(QToolBar *toolbar) {
|
||||
@@ -230,6 +235,12 @@ void VideoWidget::showThumbnail(double seconds) {
|
||||
slider->update();
|
||||
}
|
||||
|
||||
void VideoWidget::showRouteInfo() {
|
||||
RouteInfoDlg *route_info = new RouteInfoDlg(this);
|
||||
route_info->setAttribute(Qt::WA_DeleteOnClose);
|
||||
route_info->show();
|
||||
}
|
||||
|
||||
bool VideoWidget::eventFilter(QObject *obj, QEvent *event) {
|
||||
if (event->type() == QEvent::MouseMove) {
|
||||
auto [min_sec, max_sec] = can->timeRange().value_or(std::make_pair(can->minSeconds(), can->maxSeconds()));
|
||||
|
||||
@@ -71,6 +71,7 @@ protected:
|
||||
void createSpeedDropdown(QToolBar *toolbar);
|
||||
void loopPlaybackClicked();
|
||||
void vipcAvailableStreamsUpdated(std::set<VisionStreamType> streams);
|
||||
void showRouteInfo();
|
||||
|
||||
StreamCameraView *cam_widget;
|
||||
QAction *time_display_action = nullptr;
|
||||
|
||||
+89
-18
@@ -5,6 +5,7 @@ import logging
|
||||
import os
|
||||
import platform
|
||||
import shutil
|
||||
import sys
|
||||
import time
|
||||
from argparse import ArgumentParser, ArgumentTypeError
|
||||
from collections.abc import Sequence
|
||||
@@ -15,8 +16,10 @@ from typing import Literal
|
||||
|
||||
from cereal.messaging import SubMaster
|
||||
from openpilot.common.basedir import BASEDIR
|
||||
from openpilot.common.params import Params, UnknownKeyName
|
||||
from openpilot.common.prefix import OpenpilotPrefix
|
||||
from openpilot.tools.lib.route import Route
|
||||
from openpilot.tools.lib.logreader import LogReader
|
||||
|
||||
DEFAULT_OUTPUT = 'output.mp4'
|
||||
DEMO_START = 90
|
||||
@@ -28,6 +31,7 @@ RESOLUTION = '2160x1080'
|
||||
SECONDS_TO_WARM = 2
|
||||
PROC_WAIT_SECONDS = 30
|
||||
|
||||
OPENPILOT_FONT = str(Path(BASEDIR, 'selfdrive/assets/fonts/Inter-Regular.ttf').resolve())
|
||||
REPLAY = str(Path(BASEDIR, 'tools/replay/replay').resolve())
|
||||
UI = str(Path(BASEDIR, 'selfdrive/ui/ui').resolve())
|
||||
|
||||
@@ -60,18 +64,23 @@ def escape_ffmpeg_text(value: str):
|
||||
return value
|
||||
|
||||
|
||||
def get_meta_text(route: Route):
|
||||
metadata = route.get_metadata()
|
||||
origin_parts = metadata['git_remote'].split('/')
|
||||
def get_logreader(route: Route):
|
||||
return LogReader(route.qlog_paths()[0] if len(route.qlog_paths()) else route.name.canonical_name)
|
||||
|
||||
|
||||
def get_meta_text(lr: LogReader, route: Route):
|
||||
init_data = lr.first('initData')
|
||||
car_params = lr.first('carParams')
|
||||
origin_parts = init_data.gitRemote.split('/')
|
||||
origin = origin_parts[3] if len(origin_parts) > 3 else 'unknown'
|
||||
return ', '.join([
|
||||
f"openpilot v{metadata['version']}",
|
||||
f"route: {metadata['fullname']}",
|
||||
f"car: {metadata['platform']}",
|
||||
f"openpilot v{init_data.version}",
|
||||
f"route: {route.name.canonical_name}",
|
||||
f"car: {car_params.carFingerprint}",
|
||||
f"origin: {origin}",
|
||||
f"branch: {metadata['git_branch']}",
|
||||
f"commit: {metadata['git_commit'][:7]}",
|
||||
f"modified: {str(metadata['git_dirty']).lower()}",
|
||||
f"branch: {init_data.gitBranch}",
|
||||
f"commit: {init_data.gitCommit[:7]}",
|
||||
f"modified: {str(init_data.dirty).lower()}",
|
||||
])
|
||||
|
||||
|
||||
@@ -112,6 +121,22 @@ def parse_args(parser: ArgumentParser):
|
||||
return args
|
||||
|
||||
|
||||
def populate_car_params(lr: LogReader):
|
||||
init_data = lr.first('initData')
|
||||
assert init_data is not None
|
||||
|
||||
params = Params()
|
||||
entries = init_data.params.entries
|
||||
for cp in entries:
|
||||
key, value = cp.key, cp.value
|
||||
try:
|
||||
params.put(key, value)
|
||||
except UnknownKeyName:
|
||||
# forks of openpilot may have other Params keys configured. ignore these
|
||||
logger.warning(f"unknown Params key '{key}', skipping")
|
||||
logger.debug('persisted CarParams')
|
||||
|
||||
|
||||
def start_proc(args: list[str], env: dict[str, str]):
|
||||
return Popen(args, env=env, stdout=PIPE, stderr=PIPE)
|
||||
|
||||
@@ -155,8 +180,19 @@ def wait_for_frames(procs: list[Popen]):
|
||||
check_for_failure(proc)
|
||||
|
||||
|
||||
def clip(data_dir: str | None, quality: Literal['low', 'high'], prefix: str, route: Route, out: str, start: int, end: int, target_mb: int, title: str | None):
|
||||
def clip(
|
||||
data_dir: str | None,
|
||||
quality: Literal['low', 'high'],
|
||||
prefix: str,
|
||||
route: Route,
|
||||
out: str,
|
||||
start: int,
|
||||
end: int,
|
||||
target_mb: int,
|
||||
title: str | None,
|
||||
):
|
||||
logger.info(f'clipping route {route.name.canonical_name}, start={start} end={end} quality={quality} target_filesize={target_mb}MB')
|
||||
lr = get_logreader(route)
|
||||
|
||||
begin_at = max(start - SECONDS_TO_WARM, 0)
|
||||
duration = end - start
|
||||
@@ -165,20 +201,40 @@ def clip(data_dir: str | None, quality: Literal['low', 'high'], prefix: str, rou
|
||||
# TODO: evaluate creating fn that inspects /tmp/.X11-unix and creates unused display to avoid possibility of collision
|
||||
display = f':{randint(99, 999)}'
|
||||
|
||||
meta_text = get_meta_text(route)
|
||||
box_style = 'box=1:boxcolor=black@0.33:boxborderw=7'
|
||||
meta_text = get_meta_text(lr, route)
|
||||
overlays = [
|
||||
f"drawtext=text='{escape_ffmpeg_text(meta_text)}':fontfile=Inter.tff:fontcolor=white:fontsize=18:box=1:boxcolor=black@0.33:boxborderw=7:x=(w-text_w)/2:y=5.5:enable='between(t,1,5)'"
|
||||
# metadata overlay
|
||||
f"drawtext=text='{escape_ffmpeg_text(meta_text)}':fontfile={OPENPILOT_FONT}:fontcolor=white:fontsize=15:{box_style}:x=(w-text_w)/2:y=5.5:enable='between(t,1,5)'",
|
||||
# route time overlay
|
||||
f"drawtext=text='%{{eif\\:floor(({start}+t)/60)\\:d\\:2}}\\:%{{eif\\:mod({start}+t\\,60)\\:d\\:2}}':fontfile={OPENPILOT_FONT}:fontcolor=white:fontsize=24:{box_style}:x=w-text_w-38:y=38"
|
||||
]
|
||||
if title:
|
||||
overlays.append(f"drawtext=text='{escape_ffmpeg_text(title)}':fontfile=Inter.tff:fontcolor=white:fontsize=32:box=1:boxcolor=black@0.33:boxborderw=10:x=(w-text_w)/2:y=53")
|
||||
overlays.append(f"drawtext=text='{escape_ffmpeg_text(title)}':fontfile={OPENPILOT_FONT}:fontcolor=white:fontsize=32:{box_style}:x=(w-text_w)/2:y=53")
|
||||
|
||||
ffmpeg_cmd = [
|
||||
'ffmpeg', '-y', '-video_size', RESOLUTION, '-framerate', str(FRAMERATE), '-f', 'x11grab', '-draw_mouse', '0',
|
||||
'-i', display, '-c:v', 'libx264', '-maxrate', f'{bit_rate_kbps}k', '-bufsize', f'{bit_rate_kbps*2}k', '-crf', '23',
|
||||
'-filter:v', ','.join(overlays), '-preset', 'ultrafast', '-pix_fmt', 'yuv420p', '-movflags', '+faststart', '-f', 'mp4', '-t', str(duration), out
|
||||
'ffmpeg', '-y',
|
||||
'-video_size', RESOLUTION,
|
||||
'-framerate', str(FRAMERATE),
|
||||
'-f', 'x11grab',
|
||||
'-rtbufsize', '100M',
|
||||
'-draw_mouse', '0',
|
||||
'-i', display,
|
||||
'-c:v', 'libx264',
|
||||
'-maxrate', f'{bit_rate_kbps}k',
|
||||
'-bufsize', f'{bit_rate_kbps*2}k',
|
||||
'-crf', '23',
|
||||
'-filter:v', ','.join(overlays),
|
||||
'-preset', 'ultrafast',
|
||||
'-tune', 'zerolatency',
|
||||
'-pix_fmt', 'yuv420p',
|
||||
'-movflags', '+faststart',
|
||||
'-f', 'mp4',
|
||||
'-t', str(duration),
|
||||
out,
|
||||
]
|
||||
|
||||
replay_cmd = [REPLAY, '-c', '1', '-s', str(begin_at), '--prefix', prefix]
|
||||
replay_cmd = [REPLAY, '--ecam', '-c', '1', '-s', str(begin_at), '--prefix', prefix]
|
||||
if data_dir:
|
||||
replay_cmd.extend(['--data_dir', data_dir])
|
||||
if quality == 'low':
|
||||
@@ -189,6 +245,8 @@ def clip(data_dir: str | None, quality: Literal['low', 'high'], prefix: str, rou
|
||||
xvfb_cmd = ['Xvfb', display, '-terminate', '-screen', '0', f'{RESOLUTION}x{PIXEL_DEPTH}']
|
||||
|
||||
with OpenpilotPrefix(prefix, shared_download_cache=True):
|
||||
populate_car_params(lr)
|
||||
|
||||
env = os.environ.copy()
|
||||
env['DISPLAY'] = display
|
||||
|
||||
@@ -234,14 +292,27 @@ def main():
|
||||
p.add_argument('-s', '--start', help='start clipping at <start> seconds', type=int)
|
||||
p.add_argument('-t', '--title', help='overlay this title on the video (e.g. "Chill driving across the Golden Gate Bridge")', type=validate_title)
|
||||
args = parse_args(p)
|
||||
exit_code = 1
|
||||
try:
|
||||
clip(args.data_dir, args.quality, args.prefix, args.route, args.output, args.start, args.end, args.file_size, args.title)
|
||||
clip(
|
||||
data_dir=args.data_dir,
|
||||
quality=args.quality,
|
||||
prefix=args.prefix,
|
||||
route=args.route,
|
||||
out=args.output,
|
||||
start=args.start,
|
||||
end=args.end,
|
||||
target_mb=args.file_size,
|
||||
title=args.title,
|
||||
)
|
||||
exit_code = 0
|
||||
except KeyboardInterrupt as e:
|
||||
logger.exception('interrupted by user', exc_info=e)
|
||||
except Exception as e:
|
||||
logger.exception('encountered error', exc_info=e)
|
||||
finally:
|
||||
atexit._run_exitfuncs()
|
||||
sys.exit(exit_code)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -33,7 +33,6 @@ function install_ubuntu_common_requirements() {
|
||||
git \
|
||||
git-lfs \
|
||||
ffmpeg \
|
||||
fonts-inter \
|
||||
libavformat-dev \
|
||||
libavcodec-dev \
|
||||
libavdevice-dev \
|
||||
|
||||
@@ -10,7 +10,7 @@ from openpilot.common.params import Params
|
||||
from openpilot.common.swaglog import cloudlog
|
||||
|
||||
LongCtrlState = car.CarControl.Actuators.LongControlState
|
||||
MAX_LAT_ACCEL = 2.5
|
||||
MAX_LAT_ACCEL = 3.0
|
||||
|
||||
|
||||
def joystickd_thread():
|
||||
|
||||
@@ -87,8 +87,8 @@ class GithubUtils:
|
||||
def comment_on_pr(self, comment, pr_branch, commenter="", overwrite=False):
|
||||
pr_number = self.get_pr_number(pr_branch)
|
||||
data = f'{{"body": "{comment}"}}'
|
||||
github_path = f'issues/{pr_number}/comments'
|
||||
if overwrite:
|
||||
github_path = f'issues/{pr_number}/comments'
|
||||
r = self.api_call(github_path)
|
||||
comments = [x['id'] for x in r.json() if x['user']['login'] == commenter]
|
||||
if comments:
|
||||
@@ -96,7 +96,6 @@ class GithubUtils:
|
||||
self.api_call(github_path, data=data, method=HTTPMethod.PATCH)
|
||||
return
|
||||
|
||||
github_path=f'issues/{pr_number}/comments'
|
||||
self.api_call(github_path, data=data, method=HTTPMethod.POST)
|
||||
|
||||
# upload files to github and comment them on the pr
|
||||
|
||||
+27
-10
@@ -1,12 +1,13 @@
|
||||
import os
|
||||
import re
|
||||
import requests
|
||||
from functools import cache
|
||||
from urllib.parse import urlparse
|
||||
from collections import defaultdict
|
||||
from itertools import chain
|
||||
|
||||
from openpilot.tools.lib.auth_config import get_token
|
||||
from openpilot.tools.lib.api import CommaApi
|
||||
from openpilot.tools.lib.api import APIError, CommaApi
|
||||
from openpilot.tools.lib.helpers import RE
|
||||
|
||||
QLOG_FILENAMES = ['qlog', 'qlog.bz2', 'qlog.zst']
|
||||
@@ -19,15 +20,22 @@ ECAMERA_FILENAMES = ['ecamera.hevc']
|
||||
|
||||
class Route:
|
||||
def __init__(self, name, data_dir=None):
|
||||
self._metadata = None
|
||||
self._name = RouteName(name)
|
||||
self.files = None
|
||||
self.metadata = None
|
||||
if data_dir is not None:
|
||||
self._segments = self._get_segments_local(data_dir)
|
||||
else:
|
||||
self._segments = self._get_segments_remote()
|
||||
self.max_seg_number = self._segments[-1].name.segment_num
|
||||
|
||||
@property
|
||||
def metadata(self):
|
||||
if not self._metadata:
|
||||
api = CommaApi(get_token())
|
||||
self._metadata = api.get('v1/route/' + self.name.canonical_name)
|
||||
return self._metadata
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
@@ -60,12 +68,6 @@ class Route:
|
||||
qcamera_path_by_seg_num = {s.name.segment_num: s.qcamera_path for s in self._segments}
|
||||
return [qcamera_path_by_seg_num.get(i, None) for i in range(self.max_seg_number + 1)]
|
||||
|
||||
def get_metadata(self):
|
||||
if not self.metadata:
|
||||
api = CommaApi(get_token())
|
||||
self.metadata = api.get('v1/route/' + self.name.canonical_name)
|
||||
return self.metadata
|
||||
|
||||
# TODO: refactor this, it's super repetitive
|
||||
def _get_segments_remote(self):
|
||||
api = CommaApi(get_token())
|
||||
@@ -85,6 +87,7 @@ class Route:
|
||||
url if fn in DCAMERA_FILENAMES else segments[segment_name].dcamera_path,
|
||||
url if fn in ECAMERA_FILENAMES else segments[segment_name].ecamera_path,
|
||||
url if fn in QCAMERA_FILENAMES else segments[segment_name].qcamera_path,
|
||||
self.metadata['url'],
|
||||
)
|
||||
else:
|
||||
segments[segment_name] = Segment(
|
||||
@@ -95,6 +98,7 @@ class Route:
|
||||
url if fn in DCAMERA_FILENAMES else None,
|
||||
url if fn in ECAMERA_FILENAMES else None,
|
||||
url if fn in QCAMERA_FILENAMES else None,
|
||||
self.metadata['url'],
|
||||
)
|
||||
|
||||
return sorted(segments.values(), key=lambda seg: seg.name.segment_num)
|
||||
@@ -160,7 +164,7 @@ class Route:
|
||||
except StopIteration:
|
||||
qcamera_path = None
|
||||
|
||||
segments.append(Segment(segment, log_path, qlog_path, camera_path, dcamera_path, ecamera_path, qcamera_path))
|
||||
segments.append(Segment(segment, log_path, qlog_path, camera_path, dcamera_path, ecamera_path, qcamera_path, self.metadata['url']))
|
||||
|
||||
if len(segments) == 0:
|
||||
raise ValueError(f'Could not find segments for route {self.name.canonical_name} in data directory {data_dir}')
|
||||
@@ -168,8 +172,10 @@ class Route:
|
||||
|
||||
|
||||
class Segment:
|
||||
def __init__(self, name, log_path, qlog_path, camera_path, dcamera_path, ecamera_path, qcamera_path):
|
||||
def __init__(self, name, log_path, qlog_path, camera_path, dcamera_path, ecamera_path, qcamera_path, url):
|
||||
self._events = None
|
||||
self._name = SegmentName(name)
|
||||
self.url = f'{url}/{self._name.segment_num}'
|
||||
self.log_path = log_path
|
||||
self.qlog_path = qlog_path
|
||||
self.camera_path = camera_path
|
||||
@@ -181,6 +187,17 @@ class Segment:
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def events(self):
|
||||
if not self._events:
|
||||
try:
|
||||
resp = requests.get(f'{self.url}/events.json')
|
||||
resp.raise_for_status()
|
||||
self._events = resp.json()
|
||||
except Exception as e:
|
||||
raise APIError(f'error getting events for segment {self._name}') from e
|
||||
return self._events
|
||||
|
||||
|
||||
class RouteName:
|
||||
def __init__(self, name_str: str):
|
||||
|
||||
+8
-1
@@ -254,7 +254,7 @@ function op_setup() {
|
||||
|
||||
function op_auth() {
|
||||
op_before_cmd
|
||||
op_run_command tools/lib/auth.py
|
||||
op_run_command tools/lib/auth.py "$@"
|
||||
}
|
||||
|
||||
function op_activate_venv() {
|
||||
@@ -293,6 +293,11 @@ function op_check() {
|
||||
unset VERBOSE
|
||||
}
|
||||
|
||||
function op_esim() {
|
||||
op_before_cmd
|
||||
op_run_command system/hardware/esim.py "$@"
|
||||
}
|
||||
|
||||
function op_build() {
|
||||
CDIR=$(pwd)
|
||||
op_before_cmd
|
||||
@@ -392,6 +397,7 @@ function op_default() {
|
||||
echo -e "${BOLD}${UNDERLINE}Commands [System]:${NC}"
|
||||
echo -e " ${BOLD}auth${NC} Authenticate yourself for API use"
|
||||
echo -e " ${BOLD}check${NC} Check the development environment (git, os, python) to start using openpilot"
|
||||
echo -e " ${BOLD}esim${NC} Manage eSIM profiles on your comma device"
|
||||
echo -e " ${BOLD}venv${NC} Activate the python virtual environment"
|
||||
echo -e " ${BOLD}setup${NC} Install openpilot dependencies"
|
||||
echo -e " ${BOLD}build${NC} Run the openpilot build system in the current working directory"
|
||||
@@ -448,6 +454,7 @@ function _op() {
|
||||
auth ) shift 1; op_auth "$@" ;;
|
||||
venv ) shift 1; op_venv "$@" ;;
|
||||
check ) shift 1; op_check "$@" ;;
|
||||
esim ) shift 1; op_esim "$@" ;;
|
||||
setup ) shift 1; op_setup "$@" ;;
|
||||
build ) shift 1; op_build "$@" ;;
|
||||
juggle ) shift 1; op_juggle "$@" ;;
|
||||
|
||||
@@ -18,6 +18,6 @@ if __name__ == "__main__":
|
||||
params.put_bool("SshEnabled", True)
|
||||
params.put("GithubSshKeys", keys.text)
|
||||
params.put("GithubUsername", username)
|
||||
print("Setup ssh keys successfully")
|
||||
print("Set up ssh keys successfully")
|
||||
else:
|
||||
print("Error getting public keys from github")
|
||||
|
||||
Reference in New Issue
Block a user