Files
StarPilot/tools/replay/timeline.cc
T
Jason Wen e682957101 Sync: commaai/openpilot:master into sunnypilot/sunnypilot:master-new (#533)
* cabana: enhance message heatmap visualization (#34239)

* enhance message heatmap visualization

* TODO

* improve log_factor

* typo

* bit_flip_counts

* Openpilot webcam support improved (#34215)

* control webcam with ENV vars

* WIP: actual instructions

* wording

* file no longer exists

* this is expected behavior, just untested

* more readable

* tested on fresh install

* wording tweaks

* explicit USE_WEBCAM toggle required

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>

* debug-ability improved

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>

* newline removed

---------

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>

* Update metadrive wheel (#34292)

* test

* new wheel

* fix IR power scaling (#34293)

* fix IR power scaling

* Update system/hardware/tici/hardware.h

* replay: Update video immediately after seek when paused. (#34237)

replay: Update video immediately after seeking when paused.

Otherwise, if paused then have to resume playback for the video
frame to update and show the new location.

Implemented by temporarily un-pausing replay for a single
frame time.

* cabana: add live and time-window heatmap modes for enhanced signal analysis (#34296)

add live and time-window heatmap modes

* timed: diff against absolute value of timedelta (#34299)

* cabana: miscellaneous bug fixes and enhancements (#34297)

* toHexString

* use QToolBar

* fix incorrect groove rect

* limit CAN_MAX_DATA_BYTES

* add series type selector to chart toolbar

* dim inactive messages

* rename

* add help to chart

* cleanup

* cabana: real-time cursor and video frame sync for chart and video (#34301)

* sync cursor and thumbnail between chart and video

* Revert "replay: Update video immediately after seek when paused. (#34237)"

This reverts commit 3363881844.

* use thumbnails while scrubing

* draw alert

* no update on resume

* draw timestamp

* cleanup

* replay:  fix various synchronization and event handling issues (#34254)

fix various synchronization and event handling issues

* cabana: fix crash in live streaming mode by skipping thumbnail display (#34302)

resolve crash in live streaming mode

* bump panda

* [bot] Update Python packages (#34304)

Update Python packages

Co-authored-by: Vehicle Researcher <user@comma.ai>

* cleanup touch_replay (#34305)

mathematics

* uv from brew doesn't have self update

* Skip registration on newer devices (#34316)

* tici: fix cpp device type (#34315)

fix cpp

* Tinygrad upstream master (#34325)

Upstream master

* [bot] Update Python packages (#34320)

Update Python packages

Co-authored-by: Vehicle Researcher <user@comma.ai>

* cabana: fix missing transmitter after undoing DBC message removal (#34329)

fix missing transmitter after undoing DBC message removal

* Quick GC pass heading into 2025 (#34330)

* first pass

* bye bye snpe

* [bot] Update Python packages (#34334)

Update Python packages

Co-authored-by: Vehicle Researcher <user@comma.ai>

* Notre Dame model in tinygrad (#34324)

* release model: 6f23a03f-486b-4d3e-a314-19d149644c7c/700

* old style model in tinygrad

* fix desire

* tg hack

* 20Hz

* no gas probs

* No gas here

* better indexing

---------

Co-authored-by: Yassine Yousfi <yyousfi1@binghamton.edu>

---------

Co-authored-by: Dean Lee <deanlee3@gmail.com>
Co-authored-by: Mike Busuttil <31480000+MikeBusuttil@users.noreply.github.com>
Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
Co-authored-by: Maxime Desroches <desroches.maxime@gmail.com>
Co-authored-by: Angus Gratton <gus@projectgus.com>
Co-authored-by: commaci-public <60409688+commaci-public@users.noreply.github.com>
Co-authored-by: Vehicle Researcher <user@comma.ai>
Co-authored-by: Harald Schäfer <harald.the.engineer@gmail.com>
Co-authored-by: Yassine Yousfi <yyousfi1@binghamton.edu>
2025-01-07 06:28:20 +00:00

112 lines
4.3 KiB
C++

#include "tools/replay/timeline.h"
#include <algorithm>
#include <array>
#include "cereal/gen/cpp/log.capnp.h"
Timeline::~Timeline() {
should_exit_.store(true);
if (thread_.joinable()) {
thread_.join();
}
}
void Timeline::initialize(const Route &route, uint64_t route_start_ts, bool local_cache,
std::function<void(std::shared_ptr<LogReader>)> callback) {
thread_ = std::thread(&Timeline::buildTimeline, this, route, route_start_ts, local_cache, callback);
}
std::optional<uint64_t> Timeline::find(double cur_ts, FindFlag flag) const {
for (const auto &entry : *getEntries()) {
if (entry.type == TimelineType::Engaged) {
if (flag == FindFlag::nextEngagement && entry.start_time > cur_ts) {
return entry.start_time;
} else if (flag == FindFlag::nextDisEngagement && entry.end_time > cur_ts) {
return entry.end_time;
}
} else if (entry.start_time > cur_ts) {
if ((flag == FindFlag::nextUserFlag && entry.type == TimelineType::UserFlag) ||
(flag == FindFlag::nextInfo && entry.type == TimelineType::AlertInfo) ||
(flag == FindFlag::nextWarning && entry.type == TimelineType::AlertWarning) ||
(flag == FindFlag::nextCritical && entry.type == TimelineType::AlertCritical)) {
return entry.start_time;
}
}
}
return std::nullopt;
}
std::optional<Timeline::Entry> Timeline::findAlertAtTime(double target_time) const {
for (const auto &entry : *getEntries()) {
if (entry.start_time > target_time) break;
if (entry.end_time >= target_time && entry.type >= TimelineType::AlertInfo) {
return entry;
}
}
return std::nullopt;
}
void Timeline::buildTimeline(const Route &route, uint64_t route_start_ts, bool local_cache,
std::function<void(std::shared_ptr<LogReader>)> callback) {
std::optional<size_t> current_engaged_idx, current_alert_idx;
for (const auto &segment : route.segments()) {
if (should_exit_) break;
auto log = std::make_shared<LogReader>();
if (!log->load(segment.second.qlog, &should_exit_, local_cache, 0, 3) || log->events.empty()) {
continue; // Skip if log loading fails or no events
}
for (const Event &e : log->events) {
double seconds = (e.mono_time - route_start_ts) / 1e9;
if (e.which == cereal::Event::Which::SELFDRIVE_STATE) {
capnp::FlatArrayMessageReader reader(e.data);
auto cs = reader.getRoot<cereal::Event>().getSelfdriveState();
updateEngagementStatus(cs, current_engaged_idx, seconds);
updateAlertStatus(cs, current_alert_idx, seconds);
} else if (e.which == cereal::Event::Which::USER_FLAG) {
staging_entries_.emplace_back(Entry{seconds, seconds, TimelineType::UserFlag});
}
}
// Sort and finalize the timeline entries
auto entries = std::make_shared<std::vector<Entry>>(staging_entries_);
std::sort(entries->begin(), entries->end(), [](auto &a, auto &b) { return a.start_time < b.start_time; });
std::atomic_store(&timeline_entries_, std::move(entries));
callback(log); // Notify the callback once the log is processed
}
}
void Timeline::updateEngagementStatus(const cereal::SelfdriveState::Reader &cs, std::optional<size_t> &idx, double seconds) {
if (idx) staging_entries_[*idx].end_time = seconds;
if (cs.getEnabled()) {
if (!idx) {
idx = staging_entries_.size();
staging_entries_.emplace_back(Entry{seconds, seconds, TimelineType::Engaged});
}
} else {
idx.reset();
}
}
void Timeline::updateAlertStatus(const cereal::SelfdriveState::Reader &cs, std::optional<size_t> &idx, double seconds) {
static auto alert_types = std::array{TimelineType::AlertInfo, TimelineType::AlertWarning, TimelineType::AlertCritical};
Entry *entry = idx ? &staging_entries_[*idx] : nullptr;
if (entry) entry->end_time = seconds;
if (cs.getAlertSize() != cereal::SelfdriveState::AlertSize::NONE) {
auto type = alert_types[(int)cs.getAlertStatus()];
std::string text1 = cs.getAlertText1().cStr();
std::string text2 = cs.getAlertText2().cStr();
if (!entry || entry->type != type || entry->text1 != text1 || entry->text2 != text2) {
idx = staging_entries_.size();
staging_entries_.emplace_back(Entry{seconds, seconds, type, text1, text2}); // Start a new entry
}
} else {
idx.reset();
}
}