Merge remote-tracking branch 'upstream/master' into no-capnp-cars-simple

pull/33208/head
Shane Smiskol 1 year ago
commit daf3ff7b2b
  1. 22
      docs/CONTRIBUTING.md
  2. 2
      selfdrive/car/honda/interface.py
  3. 2
      selfdrive/controls/lib/longitudinal_mpc_lib/SConscript
  4. 4
      selfdrive/pandad/panda.cc
  5. 4
      system/hardware/tici/updater
  6. 17
      tools/install_ubuntu_dependencies.sh
  7. 4
      tools/lib/logreader.py
  8. 21
      tools/op.sh
  9. 50
      tools/rerun/README.md
  10. 5
      tools/rerun/camera_reader.py
  11. 96
      tools/rerun/run.py
  12. 9
      tools/rerun/run.sh
  13. 3
      tools/setup.sh
  14. 1
      tools/webcam/camera.py
  15. 10
      tools/webcam/camerad.py

@ -1,6 +1,8 @@
# How to contribute # How to contribute
Our software is open source so you can solve your own problems without needing help from others. And if you solve a problem and are so kind, you can upstream it for the rest of the world to use. Check out our [post about externalization](https://blog.comma.ai/a-2020-theme-externalization/). Development activity is coordinated through our GitHub Issues, [GitHub Discussions](https://github.com/commaai/openpilot/discussions), and [Discord](https://discord.comma.ai). Our software is open source so you can solve your own problems without needing help from others. And if you solve a problem and are so kind, you can upstream it for the rest of the world to use. Check out our [post about externalization](https://blog.comma.ai/a-2020-theme-externalization/).
Development is coordinated through [Discord](https://discord.comma.ai) and GitHub.
### Getting Started ### Getting Started
@ -11,7 +13,8 @@ Our software is open source so you can solve your own problems without needing h
## What contributions are we looking for? ## What contributions are we looking for?
**openpilot's priorities are [safety](SAFETY.md), stability, quality, and features, in that order.** openpilot is part of comma's mission to *solve self-driving cars while delivering shippable intermediaries*, and **all** development is towards that goal. **openpilot's priorities are [safety](SAFETY.md), stability, quality, and features, in that order.**
openpilot is part of comma's mission to *solve self-driving cars while delivering shippable intermediaries*, and all development is towards that goal.
### What gets merged? ### What gets merged?
@ -27,24 +30,21 @@ All of these are examples of good PRs:
### What doesn't get merged? ### What doesn't get merged?
* **arbitrary style changes**: code is art, and it's up to the author to make it beautiful * **style changes**: code is art, and it's up to the author to make it beautiful
* **500+ line PRs**: clean it up, break it up into smaller PRs, or both * **500+ line PRs**: clean it up, break it up into smaller PRs, or both
* **PRs without a clear goal**: every PR must have a singular and clear goal * **PRs without a clear goal**: every PR must have a singular and clear goal
* **UI design changes**: we do not have a good review process for this yet * **UI design**: we do not have a good review process for this yet
* **New features**: We believe openpilot is mostly feature-complete, and the rest is a matter of refinement and fixing bugs. As a result of this, most feature PRs will be immediately closed, however the beauty of open source is that forks can and do offer features that upstream openpilot doesn't. * **New features**: We believe openpilot is mostly feature-complete, and the rest is a matter of refinement and fixing bugs. As a result of this, most feature PRs will be immediately closed, however the beauty of open source is that forks can and do offer features that upstream openpilot doesn't.
* **Negative expected value**: This a class of PRs that makes an improvement, but the risk or validation costs more than the improvement. The risk can be mitigated by first getting a failing test merged.
### First contribution ### First contribution
Check out any [good first issue](https://github.com/commaai/openpilot/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) to get started. [Bounties](https://comma.ai/bounties) are the best place to get started.
There's lot of bounties that don't require a comma 3/3X or a car.
### What do I need to contribute?
A lot of openpilot work requires only a PC, and some requires a comma device.
Most car-related contributions require access to that car, plus a comma device installed in the car.
## Pull Requests ## Pull Requests
Pull requests should be against the master branch. If you're unsure about a contribution, feel free to open a discussion, issue, or draft PR to discuss the problem you're trying to solve. Pull requests should be against the master branch.
A good pull request has all of the following: A good pull request has all of the following:
* a clearly stated purpose * a clearly stated purpose

@ -209,7 +209,7 @@ class CarInterface(CarInterfaceBase):
# to a negative value, so it won't matter. Otherwise, add 0.5 mph margin to not # to a negative value, so it won't matter. Otherwise, add 0.5 mph margin to not
# conflict with PCM acc # conflict with PCM acc
ret.autoResumeSng = candidate in (HONDA_BOSCH | {CAR.HONDA_CIVIC}) ret.autoResumeSng = candidate in (HONDA_BOSCH | {CAR.HONDA_CIVIC})
ret.minEnableSpeed = -1. if ret.autoResumeSng else 25.5 * CV.MPH_TO_MS ret.minEnableSpeed = -1. if ret.autoResumeSng else 25.51 * CV.MPH_TO_MS
ret.steerActuatorDelay = 0.1 ret.steerActuatorDelay = 0.1
ret.steerLimitTimer = 0.8 ret.steerLimitTimer = 0.8

@ -73,6 +73,8 @@ lenv["CXXFLAGS"].append("-DACADOS_WITH_QPOASES")
lenv["CCFLAGS"].append("-Wno-unused") lenv["CCFLAGS"].append("-Wno-unused")
if arch != "Darwin": if arch != "Darwin":
lenv["LINKFLAGS"].append("-Wl,--disable-new-dtags") lenv["LINKFLAGS"].append("-Wl,--disable-new-dtags")
else:
lenv["LINKFLAGS"].append("-Wl,-install_name,@loader_path/libacados_ocp_solver_long.dylib")
lib_solver = lenv.SharedLibrary(f"{gen}/acados_ocp_solver_long", lib_solver = lenv.SharedLibrary(f"{gen}/acados_ocp_solver_long",
build_files, build_files,
LIBS=['m', 'acados', 'hpipm', 'blasfeo', 'qpOASES_e']) LIBS=['m', 'acados', 'hpipm', 'blasfeo', 'qpOASES_e'])

@ -10,6 +10,8 @@
#include "common/swaglog.h" #include "common/swaglog.h"
#include "common/util.h" #include "common/util.h"
const bool PANDAD_MAXOUT = getenv("PANDAD_MAXOUT") != nullptr;
Panda::Panda(std::string serial, uint32_t bus_offset) : bus_offset(bus_offset) { Panda::Panda(std::string serial, uint32_t bus_offset) : bus_offset(bus_offset) {
// try USB first, then SPI // try USB first, then SPI
try { try {
@ -219,7 +221,7 @@ bool Panda::can_receive(std::vector<can_frame>& out_vec) {
return false; return false;
} }
if (getenv("PANDAD_MAXOUT") != NULL) { if (PANDAD_MAXOUT) {
static uint8_t junk[RECV_SIZE]; static uint8_t junk[RECV_SIZE];
handle->bulk_read(0xab, junk, RECV_SIZE - recv); handle->bulk_read(0xab, junk, RECV_SIZE - recv);
} }

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:f74ea28934c6b9477a98dc6a38e6bfcd53e94e6af31dba5b6d11bc5310f7d995 oid sha256:8db3f973663e59921fcc9e5d5600a346c1e229a2e8481a874ef996d97303dc4e
size 8135168 size 16631712

@ -148,6 +148,23 @@ if [ -f "/etc/os-release" ]; then
if [[ "$INSTALL_EXTRA_PACKAGES" == "yes" ]]; then if [[ "$INSTALL_EXTRA_PACKAGES" == "yes" ]]; then
install_extra_packages install_extra_packages
fi fi
if [[ -d "/etc/udev/rules.d/" ]]; then
# Setup panda udev rules
$SUDO tee /etc/udev/rules.d/12-panda_jungle.rules > /dev/null <<EOF
SUBSYSTEM=="usb", ATTRS{idVendor}=="bbaa", ATTRS{idProduct}=="ddcf", MODE="0666"
SUBSYSTEM=="usb", ATTRS{idVendor}=="bbaa", ATTRS{idProduct}=="ddef", MODE="0666"
EOF
# Setup jungle udev rules
$SUDO tee /etc/udev/rules.d/11-panda.rules > /dev/null <<EOF
SUBSYSTEM=="usb", ATTRS{idVendor}=="bbaa", ATTRS{idProduct}=="ddcc", MODE="0666"
SUBSYSTEM=="usb", ATTRS{idVendor}=="bbaa", ATTRS{idProduct}=="ddee", MODE="0666"
EOF
$SUDO udevadm control --reload-rules && $SUDO udevadm trigger || true
fi
else else
echo "No /etc/os-release in the system. Make sure you're running on Ubuntu, or similar." echo "No /etc/os-release in the system. Make sure you're running on Ubuntu, or similar."
exit 1 exit 1

@ -293,11 +293,11 @@ are uploaded or auto fallback to qlogs with '/a' selector at the end of the rout
def _run_on_segment(self, func, i): def _run_on_segment(self, func, i):
return func(self._get_lr(i)) return func(self._get_lr(i))
def run_across_segments(self, num_processes, func): def run_across_segments(self, num_processes, func, desc=None):
with multiprocessing.Pool(num_processes) as pool: with multiprocessing.Pool(num_processes) as pool:
ret = [] ret = []
num_segs = len(self.logreader_identifiers) num_segs = len(self.logreader_identifiers)
for p in tqdm.tqdm(pool.imap(partial(self._run_on_segment, func), range(num_segs)), total=num_segs): for p in tqdm.tqdm(pool.imap(partial(self._run_on_segment, func), range(num_segs)), total=num_segs, desc=desc):
ret.extend(p) ret.extend(p)
return ret return ret

@ -14,6 +14,7 @@ UNDERLINE='\033[4m'
BOLD='\033[1m' BOLD='\033[1m'
NC='\033[0m' NC='\033[0m'
SHELL_NAME="$(basename ${SHELL})"
RC_FILE="${HOME}/.$(basename ${SHELL})rc" RC_FILE="${HOME}/.$(basename ${SHELL})rc"
if [ "$(uname)" == "Darwin" ] && [ $SHELL == "/bin/bash" ]; then if [ "$(uname)" == "Darwin" ] && [ $SHELL == "/bin/bash" ]; then
RC_FILE="$HOME/.bash_profile" RC_FILE="$HOME/.bash_profile"
@ -145,7 +146,7 @@ function op_check_python() {
function op_check_venv() { function op_check_venv() {
echo "Checking for venv..." echo "Checking for venv..."
if source $OPENPILOT_ROOT/.venv/bin/activate; then if [[ -f $OPENPILOT_ROOT/.venv/bin/activate ]]; then
echo -e " ↳ [${GREEN}${NC}] venv detected." echo -e " ↳ [${GREEN}${NC}] venv detected."
else else
echo -e " ↳ [${RED}${NC}] Can't activate venv in $OPENPILOT_ROOT. Assuming global env!" echo -e " ↳ [${RED}${NC}] Can't activate venv in $OPENPILOT_ROOT. Assuming global env!"
@ -223,12 +224,28 @@ function op_setup() {
} }
function op_activate_venv() { function op_activate_venv() {
# bash 3.2 can't handle this without the 'set +e'
set +e
source $OPENPILOT_ROOT/.venv/bin/activate &> /dev/null || true source $OPENPILOT_ROOT/.venv/bin/activate &> /dev/null || true
set -e
} }
function op_venv() { function op_venv() {
op_before_cmd op_before_cmd
bash --rcfile <(echo "source $RC_FILE; source $OPENPILOT_ROOT/.venv/bin/activate")
if [[ ! -f $OPENPILOT_ROOT/.venv/bin/activate ]]; then
echo -e "No venv found in $OPENPILOT_ROOT"
return 1
fi
case $SHELL_NAME in
"zsh")
ZSHRC_DIR=$(mktemp -d 2>/dev/null || mktemp -d -t 'tmp_zsh')
echo "source $RC_FILE; source $OPENPILOT_ROOT/.venv/bin/activate" >> $ZSHRC_DIR/.zshrc
ZDOTDIR=$ZSHRC_DIR zsh ;;
*)
bash --rcfile <(echo "source $RC_FILE; source $OPENPILOT_ROOT/.venv/bin/activate") ;;
esac
} }
function op_check() { function op_check() {

@ -5,53 +5,33 @@ Rerun is a tool to quickly visualize time series data. It supports all openpilot
## Usage ## Usage
``` ```
usage: run.py [-h] [--demo] [--qcam] [--fcam] [--ecam] [--dcam] [--print_services] [--services [SERVICES ...]] [route_or_segment_name] usage: run.py [-h] [--demo] [--qcam] [--fcam] [--ecam] [--dcam] [route_or_segment_name]
A helper to run rerun on openpilot routes A helper to run rerun on openpilot routes
positional arguments:
route_or_segment_name
The route or segment name to plot (default: None)
options: options:
-h, --help show this help message and exit -h, --help show this help message and exit
--demo Use the demo route instead of providing one (default: False) --demo Use the demo route instead of providing one (default: False)
--qcam Log decimated driving camera (default: False) --qcam Show low-res road camera (default: False)
--fcam Log driving camera (default: False) --fcam Show driving camera (default: False)
--ecam Log wide camera (default: False) --ecam Show wide camera (default: False)
--dcam Log driver monitoring camera (default: False) --dcam Show driver monitoring camera (default: False)
--print_services List out openpilot services (default: False)
--services [SERVICES ...] Specify openpilot services that will be logged. No service will be logged if not specified.
To log all services include 'all' as one of your services (default: [])
--route [ROUTE] The route or segment name to plot (default: None)
``` ```
Examples using route name to observe accelerometer and qcamera: Examples using route name to observe accelerometer and qcamera:
`./run.py --services accelerometer --qcam --route "a2a0ccea32023010/2023-07-27--13-01-19"` `./run.sh --qcam "a2a0ccea32023010/2023-07-27--13-01-19"`
Examples using segment range (more on [SegmentRange](https://github.com/commaai/openpilot/tree/master/tools/lib)): Examples using segment range (more on [SegmentRange](https://github.com/commaai/openpilot/tree/master/tools/lib)):
`./run.py --qcam --route "a2a0ccea32023010/2023-07-27--13-01-19/2:4"` `./run.sh --qcam "a2a0ccea32023010/2023-07-27--13-01-19/2:4"`
## Cautions: ## Cautions:
- You can specify `--services all` to visualize all `logMessage`, but it will draw a lot of memory usage and take a long time to log all messages. Rerun isn't ready for logging big number of data. - Showing hevc videos (`--fcam`, `--ecam`, and `--dcam`) are expensive, and it's recommended to use `--qcam` for optimized performance. If possible, limiting your route to a few segments using `SegmentRange` will speed up logging and reduce memory usage
- Logging hevc videos (`--fcam`, `--ecam`, and `--dcam`) are expensive, and it's recommended to use `--qcam` for optimized performance. If possible, limiting your route to a few segments using `SegmentRange` will speed up logging and reduce memory usage
This example draws 13GB of memory:
`./run.py --services accelerometer --qcam --route "a2a0ccea32023010/2023-07-27--13-01-19"`
## Openpilot services
To list all openpilot services:
`./run.py --print_services`
Examples including openpilot services:
`./run.py --services accelerometer cameraodometry --route "a2a0ccea32023010/2023-07-27--13-01-19/0/q"`
Examples including all services:
`./run.py --services all --route "a2a0ccea32023010/2023-07-27--13-01-19/0/q"`
## Demo ## Demo
`./run.py --services accelerometer carcontrol caroutput --qcam --demo` `./run.sh --qcam --demo`

@ -37,6 +37,7 @@ class _FrameReader:
frame_sz = self.w * self.h * 3 // 2 frame_sz = self.w * self.h * 3 // 2
proc = subprocess.Popen( proc = subprocess.Popen(
["ffmpeg", "-v", "quiet", "-i", self.camera_path, "-f", "rawvideo", "-pix_fmt", "nv12", "-"], ["ffmpeg", "-v", "quiet", "-i", self.camera_path, "-f", "rawvideo", "-pix_fmt", "nv12", "-"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL stderr=subprocess.DEVNULL
) )
@ -84,9 +85,9 @@ class CameraReader:
def _run_on_segment(self, func, i): def _run_on_segment(self, func, i):
return func(self._get_fr(i)) return func(self._get_fr(i))
def run_across_segments(self, num_processes, func): def run_across_segments(self, num_processes, func, desc=None):
with multiprocessing.Pool(num_processes) as pool: with multiprocessing.Pool(num_processes) as pool:
num_segs = len(self.seg_idxs) num_segs = len(self.seg_idxs)
for _ in tqdm.tqdm(pool.imap_unordered(partial(self._run_on_segment, func), self.seg_idxs), total=num_segs): for _ in tqdm.tqdm(pool.imap_unordered(partial(self._run_on_segment, func), self.seg_idxs), total=num_segs, desc=desc):
continue continue

@ -1,10 +1,12 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import sys import sys
import argparse import argparse
import multiprocessing import multiprocessing
import rerun as rr import rerun as rr
import rerun.blueprint as rrb import rerun.blueprint as rrb
from functools import partial from functools import partial
from collections import defaultdict
from cereal.services import SERVICE_LIST from cereal.services import SERVICE_LIST
from openpilot.tools.rerun.camera_reader import probe_packet_info, CameraReader, CameraConfig, CameraType from openpilot.tools.rerun.camera_reader import probe_packet_info, CameraReader, CameraConfig, CameraType
@ -20,19 +22,16 @@ RR_WIN = "openpilot logs"
""" """
Relevant upstream Rerun issues: Relevant upstream Rerun issues:
- large time series: https://github.com/rerun-io/rerun/issues/5967
- loading videos directly: https://github.com/rerun-io/rerun/issues/6532 - loading videos directly: https://github.com/rerun-io/rerun/issues/6532
""" """
class Rerunner: class Rerunner:
def __init__(self, route, segment_range, camera_config, enabled_services): def __init__(self, route, segment_range, camera_config):
self.enabled_services = [s.lower() for s in enabled_services]
self.log_all = "all" in self.enabled_services
self.lr = LogReader(route_or_segment_name) self.lr = LogReader(route_or_segment_name)
# hevc files don't have start_time. We get it from qcamera.ts # hevc files don't have start_time. We get it from qcamera.ts
start_time = 0 start_time = 0
dat = probe_packet_info(r.qcamera_paths()[0]) dat = probe_packet_info(route.qcamera_paths()[0])
for d in dat: for d in dat:
if d.startswith("pts_time="): if d.startswith("pts_time="):
start_time = float(d.split('=')[1]) start_time = float(d.split('=')[1])
@ -49,34 +48,30 @@ class Rerunner:
if dcam: if dcam:
self.camera_readers[CameraType.dcam] = CameraReader(route.dcamera_paths(), start_time, segment_range.seg_idxs) self.camera_readers[CameraType.dcam] = CameraReader(route.dcamera_paths(), start_time, segment_range.seg_idxs)
def _start_rerun(self):
self.blueprint = self._create_blueprint()
rr.init(RR_WIN, spawn=True)
def _create_blueprint(self): def _create_blueprint(self):
blueprint = None blueprint = None
service_views = [] service_views = []
log_msg_visible = len(self.enabled_services) <= 3 and not self.log_all
for topic in sorted(SERVICE_LIST.keys()): for topic in sorted(SERVICE_LIST.keys()):
if not self.log_all and topic.lower() not in self.enabled_services:
continue
View = rrb.TimeSeriesView if topic != "thumbnail" else rrb.Spatial2DView View = rrb.TimeSeriesView if topic != "thumbnail" else rrb.Spatial2DView
service_views.append(View(name=topic, origin=f"/{topic}/", visible=log_msg_visible)) service_views.append(View(name=topic, origin=f"/{topic}/", visible=False))
rr.log(topic, rr.SeriesLine(name=topic), timeless=True) rr.log(topic, rr.SeriesLine(name=topic), timeless=True)
center_view = [rrb.Vertical(*service_views, name="streams")]
if len(self.camera_readers):
center_view.append(rrb.Vertical(*[rrb.Spatial2DView(name=cam_type, origin=cam_type) for cam_type in self.camera_readers.keys()], name="cameras"))
blueprint = rrb.Blueprint( blueprint = rrb.Blueprint(
rrb.Horizontal( rrb.Horizontal(
rrb.Vertical(*service_views), *center_view
rrb.Vertical(*[rrb.Spatial2DView(name=cam_type, origin=cam_type) for cam_type in self.camera_readers.keys()]),
), ),
rrb.SelectionPanel(expanded=False), rrb.SelectionPanel(expanded=False),
rrb.TimePanel(expanded=False) rrb.TimePanel(expanded=False),
) )
return blueprint return blueprint
@staticmethod @staticmethod
def _log_msg(msg, parent_key=''): def _parse_msg(msg, parent_key=''):
stack = [(msg, parent_key)] stack = [(msg, parent_key)]
while stack: while stack:
current_msg, current_parent_key = stack.pop() current_msg, current_parent_key = stack.pop()
@ -84,40 +79,47 @@ class Rerunner:
for index, item in enumerate(current_msg): for index, item in enumerate(current_msg):
new_key = f"{current_parent_key}/{index}" new_key = f"{current_parent_key}/{index}"
if isinstance(item, (int, float)): if isinstance(item, (int, float)):
rr.log(new_key, rr.Scalar(item)) yield new_key, item
elif isinstance(item, dict): elif isinstance(item, dict):
stack.append((item, new_key)) stack.append((item, new_key))
elif isinstance(current_msg, dict): elif isinstance(current_msg, dict):
for key, value in current_msg.items(): for key, value in current_msg.items():
new_key = f"{current_parent_key}/{key}" new_key = f"{current_parent_key}/{key}"
if isinstance(value, (int, float)): if isinstance(value, (int, float)):
rr.log(new_key, rr.Scalar(value)) yield new_key, value
elif isinstance(value, dict): elif isinstance(value, dict):
stack.append((value, new_key)) stack.append((value, new_key))
elif isinstance(value, list): elif isinstance(value, list):
for index, item in enumerate(value): for index, item in enumerate(value):
if isinstance(item, (int, float)): if isinstance(item, (int, float)):
rr.log(f"{new_key}/{index}", rr.Scalar(item)) yield f"{new_key}/{index}", item
else: else:
pass # Not a plottable value pass # Not a plottable value
@staticmethod @staticmethod
@rr.shutdown_at_exit @rr.shutdown_at_exit
def _process_log_msgs(blueprint, enabled_services, log_all, lr): def _process_log_msgs(blueprint, lr):
rr.init(RR_WIN) rr.init(RR_WIN)
rr.connect(default_blueprint=blueprint) rr.connect()
rr.send_blueprint(blueprint)
log_msgs = defaultdict(lambda: defaultdict(list))
for msg in lr: for msg in lr:
rr.set_time_nanos(RR_TIMELINE_NAME, msg.logMonoTime)
msg_type = msg.which() msg_type = msg.which()
if not log_all and msg_type.lower() not in enabled_services: if msg_type == "thumbnail":
continue continue
if msg_type != "thumbnail": for entity_path, dat in Rerunner._parse_msg(msg.to_dict()[msg_type], msg_type):
Rerunner._log_msg(msg.to_dict()[msg.which()], msg.which()) log_msgs[entity_path]["times"].append(msg.logMonoTime / 1e9)
else: log_msgs[entity_path]["data"].append(dat)
rr.log("/thumbnail", rr.ImageEncoded(contents=msg.to_dict()[msg.which()].get("thumbnail")))
for entity_path, log_msg in log_msgs.items():
rr.log_temporal_batch(
entity_path,
times=[rr.TimeSecondsBatch(RR_TIMELINE_NAME, log_msg["times"])],
components=[rr.components.ScalarBatch(log_msg["data"])]
)
return [] return []
@ -125,18 +127,22 @@ class Rerunner:
@rr.shutdown_at_exit @rr.shutdown_at_exit
def _process_cam_readers(blueprint, cam_type, h, w, fr): def _process_cam_readers(blueprint, cam_type, h, w, fr):
rr.init(RR_WIN) rr.init(RR_WIN)
rr.connect(default_blueprint=blueprint) rr.connect()
rr.send_blueprint(blueprint)
for ts, frame in fr: for ts, frame in fr:
rr.set_time_nanos(RR_TIMELINE_NAME, int(ts * 1e9)) rr.set_time_nanos(RR_TIMELINE_NAME, int(ts * 1e9))
rr.log(cam_type, rr.Image(bytes=frame, width=w, height=h, pixel_format=rr.PixelFormat.NV12)) rr.log(cam_type, rr.Image(bytes=frame, width=w, height=h, pixel_format=rr.PixelFormat.NV12))
def load_data(self): def load_data(self):
self._start_rerun() rr.init(RR_WIN, spawn=True)
if len(self.enabled_services) > 0:
self.lr.run_across_segments(NUM_CPUS, partial(self._process_log_msgs, self.blueprint, self.enabled_services, self.log_all)) startup_blueprint = self._create_blueprint()
self.lr.run_across_segments(NUM_CPUS, partial(self._process_log_msgs, startup_blueprint), desc="Log messages")
for cam_type, cr in self.camera_readers.items(): for cam_type, cr in self.camera_readers.items():
cr.run_across_segments(NUM_CPUS, partial(self._process_cam_readers, self.blueprint, cam_type, cr.h, cr.w)) cr.run_across_segments(NUM_CPUS, partial(self._process_cam_readers, startup_blueprint, cam_type, cr.h, cr.w), desc=cam_type)
rr.send_blueprint(self._create_blueprint())
if __name__ == '__main__': if __name__ == '__main__':
@ -147,34 +153,28 @@ if __name__ == '__main__':
parser.add_argument("--fcam", action="store_true", help="Show driving camera") parser.add_argument("--fcam", action="store_true", help="Show driving camera")
parser.add_argument("--ecam", action="store_true", help="Show wide camera") parser.add_argument("--ecam", action="store_true", help="Show wide camera")
parser.add_argument("--dcam", action="store_true", help="Show driver monitoring camera") parser.add_argument("--dcam", action="store_true", help="Show driver monitoring camera")
parser.add_argument("--print_services", action="store_true", help="List out openpilot services") parser.add_argument("route_or_segment_name", nargs='?', help="The route or segment name to plot")
parser.add_argument("--services", default=[], nargs='*', help="Specify openpilot services that will be logged.\
No service will be logged if not specified.\
To log all services include 'all' as one of your services")
parser.add_argument("--route", nargs='?', help="The route or segment name to plot")
args = parser.parse_args() args = parser.parse_args()
if not args.demo and not args.route: if not args.demo and not args.route_or_segment_name:
parser.print_help() parser.print_help()
sys.exit() sys.exit()
if args.print_services:
print("\n".join(SERVICE_LIST.keys()))
sys.exit()
camera_config = CameraConfig(args.qcam, args.fcam, args.ecam, args.dcam) camera_config = CameraConfig(args.qcam, args.fcam, args.ecam, args.dcam)
route_or_segment_name = DEMO_ROUTE if args.demo else args.route_or_segment_name.strip()
route_or_segment_name = DEMO_ROUTE if args.demo else args.route.strip()
sr = SegmentRange(route_or_segment_name) sr = SegmentRange(route_or_segment_name)
r = Route(sr.route_name) r = Route(sr.route_name)
if len(sr.seg_idxs) > 10: hevc_requested = any(camera_config[1:])
print("You're requesting more than 10 segments of the route, " + \ if len(sr.seg_idxs) > 1 and hevc_requested:
"please be aware that might take a lot of memory") print("You're requesting more than 1 segment with hevc videos, " + \
"please be aware that might take a lot of memory " + \
"since rerun isn't yet well supported for high resolution video logging")
response = input("Do you wish to continue? (Y/n): ") response = input("Do you wish to continue? (Y/n): ")
if response.strip().lower() != "y": if response.strip().lower() != "y":
sys.exit() sys.exit()
rerunner = Rerunner(r, sr, camera_config, args.services) rerunner = Rerunner(r, sr, camera_config)
rerunner.load_data() rerunner.load_data()

@ -0,0 +1,9 @@
#! /bin/bash
# TODO: remove this file once Rerun has interface to set log message level
set -e
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
RUST_LOG=warn $DIR/run.py $@

@ -44,6 +44,7 @@ function sentry_send_event() {
PLATFORM=$(uname -s) PLATFORM=$(uname -s)
ARCH=$(uname -m) ARCH=$(uname -m)
SYSTEM=$(uname -a)
if [[ $PLATFORM == "Darwin" ]]; then if [[ $PLATFORM == "Darwin" ]]; then
OS="macos" OS="macos"
elif [[ $PLATFORM == "Linux" ]]; then elif [[ $PLATFORM == "Linux" ]]; then
@ -60,7 +61,7 @@ function sentry_send_event() {
BRANCH=$(echo $(git -C $OPENPILOT_ROOT rev-parse --abbrev-ref HEAD 2> /dev/null || echo "NA")) BRANCH=$(echo $(git -C $OPENPILOT_ROOT rev-parse --abbrev-ref HEAD 2> /dev/null || echo "NA"))
COMMIT=$(echo $(git -C $OPENPILOT_ROOT rev-parse HEAD 2> /dev/null || echo "NA")) COMMIT=$(echo $(git -C $OPENPILOT_ROOT rev-parse HEAD 2> /dev/null || echo "NA"))
curl -s -o /dev/null -X POST -g --data "{ \"exception\": { \"values\": [{ \"type\": \"$EVENT\" }] }, \"tags\" : { \"event_type\" : \"$EVENT_TYPE\", \"event_log\" : \"$EVENT_LOG\", \"os\" : \"$OS\", \"arch\" : \"$ARCH\", \"python_version\" : \"$PYTHON_VERSION\" , \"git_branch\" : \"$BRANCH\", \"git_commit\" : \"$COMMIT\" } }" \ curl -s -o /dev/null -X POST -g --data "{ \"exception\": { \"values\": [{ \"type\": \"$EVENT\" }] }, \"tags\" : { \"event_type\" : \"$EVENT_TYPE\", \"event_log\" : \"$EVENT_LOG\", \"os\" : \"$OS\", \"arch\" : \"$ARCH\", \"python_version\" : \"$PYTHON_VERSION\" , \"git_branch\" : \"$BRANCH\", \"git_commit\" : \"$COMMIT\", \"system\" : \"$SYSTEM\" } }" \
-H 'Content-Type: application/json' \ -H 'Content-Type: application/json' \
-H "X-Sentry-Auth: Sentry sentry_version=7, sentry_key=$SENTRY_KEY, sentry_client=op_setup/0.1" \ -H "X-Sentry-Auth: Sentry sentry_version=7, sentry_key=$SENTRY_KEY, sentry_client=op_setup/0.1" \
$SENTRY_URL 2> /dev/null $SENTRY_URL 2> /dev/null

@ -11,6 +11,7 @@ class Camera:
self.cur_frame_id = 0 self.cur_frame_id = 0
self.container = av.open(camera_id) self.container = av.open(camera_id)
assert self.container.streams.video, f"Can't open video stream for camera {camera_id}"
self.video_stream = self.container.streams.video[0] self.video_stream = self.container.streams.video[0]
self.W = self.video_stream.codec_context.width self.W = self.video_stream.codec_context.width
self.H = self.video_stream.codec_context.height self.H = self.video_stream.codec_context.height

@ -26,7 +26,6 @@ class Camerad:
self.cameras = [] self.cameras = []
for c in CAMERAS: for c in CAMERAS:
cam = Camera(c.msg_name, c.stream_type, c.cam_id) cam = Camera(c.msg_name, c.stream_type, c.cam_id)
assert cam.cap.isOpened(), f"Can't find camera {c}"
self.cameras.append(cam) self.cameras.append(cam)
self.vipc_server.create_buffers(c.stream_type, 20, False, cam.W, cam.H) self.vipc_server.create_buffers(c.stream_type, 20, False, cam.W, cam.H)
@ -47,11 +46,10 @@ class Camerad:
def camera_runner(self, cam): def camera_runner(self, cam):
rk = Ratekeeper(20, None) rk = Ratekeeper(20, None)
while cam.cap.isOpened(): for yuv in cam.read_frames():
for yuv in cam.read_frames(): self._send_yuv(yuv, cam.cur_frame_id, cam.cam_type_state, cam.stream_type)
self._send_yuv(yuv, cam.cur_frame_id, cam.cam_type_state, cam.stream_type) cam.cur_frame_id += 1
cam.cur_frame_id += 1 rk.keep_time()
rk.keep_time()
def run(self): def run(self):
threads = [] threads = []

Loading…
Cancel
Save