add flag to auto load a route from the most suitable source

pull/34863/head
deanlee 1 month ago
parent 049193b178
commit 997df1694e
  1. 4
      tools/cabana/cabana.cc
  2. 5
      tools/cabana/streams/replaystream.cc
  3. 2
      tools/cabana/streams/replaystream.h
  4. 16
      tools/lib/logreader.py
  5. 4
      tools/replay/replay.cc
  6. 2
      tools/replay/replay.h
  7. 21
      tools/replay/route.cc
  8. 4
      tools/replay/route.h
  9. 4
      tools/replay/seg_mgr.h

@ -23,6 +23,7 @@ int main(int argc, char *argv[]) {
cmd_parser.addHelpOption();
cmd_parser.addPositionalArgument("route", "the drive to replay. find your drives at connect.comma.ai");
cmd_parser.addOption({"demo", "use a demo route instead of providing your own"});
cmd_parser.addOption({"auto", "auto load a route from the most suitable source"});
cmd_parser.addOption({"qcam", "load qcamera"});
cmd_parser.addOption({"ecam", "load wide road camera"});
cmd_parser.addOption({"dcam", "load driver camera"});
@ -69,7 +70,8 @@ int main(int argc, char *argv[]) {
}
if (!route.isEmpty()) {
auto replay_stream = std::make_unique<ReplayStream>(&app);
if (!replay_stream->loadRoute(route, cmd_parser.value("data_dir"), replay_flags)) {
bool auto_source = cmd_parser.isSet("auto");
if (!replay_stream->loadRoute(route, cmd_parser.value("data_dir"), replay_flags, auto_source)) {
return 0;
}
stream = replay_stream.release();

@ -7,6 +7,7 @@
#include <QPushButton>
#include "common/timing.h"
#include "common/util.h"
#include "tools/cabana/streams/routes.h"
ReplayStream::ReplayStream(QObject *parent) : AbstractStream(parent) {
@ -45,9 +46,9 @@ void ReplayStream::mergeSegments() {
}
}
bool ReplayStream::loadRoute(const QString &route, const QString &data_dir, uint32_t replay_flags) {
bool ReplayStream::loadRoute(const QString &route, const QString &data_dir, uint32_t replay_flags, bool auto_source) {
replay.reset(new Replay(route.toStdString(), {"can", "roadEncodeIdx", "driverEncodeIdx", "wideRoadEncodeIdx", "carParams"},
{}, nullptr, replay_flags, data_dir.toStdString()));
{}, nullptr, replay_flags, data_dir.toStdString(), auto_source));
replay->setSegmentCacheLimit(settings.max_cached_minutes);
replay->installEventFilter([this](const Event *event) { return eventFilter(event); });

@ -18,7 +18,7 @@ class ReplayStream : public AbstractStream {
public:
ReplayStream(QObject *parent);
void start() override { replay->start(); }
bool loadRoute(const QString &route, const QString &data_dir, uint32_t replay_flags = REPLAY_FLAG_NONE);
bool loadRoute(const QString &route, const QString &data_dir, uint32_t replay_flags = REPLAY_FLAG_NONE, bool auto_source = false);
bool eventFilter(const Event *event);
void seekTo(double ts) override { replay->seekTo(std::max(double(0), ts), false); }
bool liveStreaming() const override { return false; }

@ -6,12 +6,12 @@ import capnp
import enum
import os
import pathlib
import sys
import tqdm
import urllib.parse
import warnings
import zstandard as zstd
from argparse import ArgumentParser
from collections.abc import Callable, Iterable, Iterator
from urllib.parse import parse_qs, urlparse
@ -333,7 +333,17 @@ if __name__ == "__main__":
# capnproto <= 0.8.0 throws errors converting byte data to string
# below line catches those errors and replaces the bytes with \x__
codecs.register_error("strict", codecs.backslashreplace_errors)
log_path = sys.argv[1]
lr = LogReader(log_path, sort_by_time=True)
parser = ArgumentParser(description="Process a log file and print identifiers or full messages.")
parser.add_argument("log_path", help="Path to the log file")
parser.add_argument(
"--identifiers-only", action="store_true", help="Print only log identifiers instead of full messages"
)
args = parser.parse_args()
lr = LogReader(args.log_path, sort_by_time=True)
if args.identifiers_only:
print("\n".join(lr.logreader_identifiers))
else:
for msg in lr:
print(msg)

@ -15,8 +15,8 @@ void notifyEvent(Callback &callback, Args &&...args) {
}
Replay::Replay(const std::string &route, std::vector<std::string> allow, std::vector<std::string> block,
SubMaster *sm, uint32_t flags, const std::string &data_dir)
: sm_(sm), flags_(flags), seg_mgr_(std::make_unique<SegmentManager>(route, flags, data_dir)) {
SubMaster *sm, uint32_t flags, const std::string &data_dir, bool auto_source)
: sm_(sm), flags_(flags), seg_mgr_(std::make_unique<SegmentManager>(route, flags, data_dir, auto_source)) {
std::signal(SIGUSR1, interrupt_sleep_handler);
if (!(flags_ & REPLAY_FLAG_ALL_SERVICES)) {

@ -29,7 +29,7 @@ enum REPLAY_FLAGS {
class Replay {
public:
Replay(const std::string &route, std::vector<std::string> allow, std::vector<std::string> block, SubMaster *sm = nullptr,
uint32_t flags = REPLAY_FLAG_NONE, const std::string &data_dir = "");
uint32_t flags = REPLAY_FLAG_NONE, const std::string &data_dir = "", bool auto_source = false);
~Replay();
bool load();
RouteLoadError lastRouteError() const { return route().lastError(); }

@ -10,8 +10,11 @@
#include "tools/replay/replay.h"
#include "tools/replay/util.h"
Route::Route(const std::string &route, const std::string &data_dir) : data_dir_(data_dir) {
Route::Route(const std::string &route, const std::string &data_dir, bool auto_source)
: route_string_(route), data_dir_(data_dir), auto_source_(auto_source) {
if (!auto_source) {
route_ = parseRoute(route);
}
}
RouteIdentifier Route::parseRoute(const std::string &str) {
@ -45,6 +48,22 @@ RouteIdentifier Route::parseRoute(const std::string &str) {
bool Route::load() {
err_ = RouteLoadError::None;
if (auto_source_) {
auto cmd = util::string_format("python ../lib/logreader.py \"%s\" --identifiers-only", route_string_.c_str());
auto output = util::check_output(cmd);
auto log_files = split(output, '\n');
for (int i = 0; i < log_files.size(); ++i) {
addFileToSegment(i, log_files[i]);
}
route_.begin_segment = 0;
route_.end_segment = log_files.size() - 1;
route_.dongle_id = route_string_;
route_.str = route_string_;
route_.timestamp = "";
return !segments_.empty();
}
if (route_.str.empty() || (data_dir_.empty() && route_.dongle_id.empty())) {
rInfo("invalid route format");
return false;

@ -40,7 +40,7 @@ struct SegmentFile {
class Route {
public:
Route(const std::string &route, const std::string &data_dir = {});
Route(const std::string &route, const std::string &data_dir = {}, bool auto_source = false);
bool load();
RouteLoadError lastError() const { return err_; }
inline const std::string &name() const { return route_.str; }
@ -61,6 +61,8 @@ protected:
std::map<int, SegmentFile> segments_;
std::time_t date_time_;
RouteLoadError err_ = RouteLoadError::None;
bool auto_source_ = false;
std::string route_string_;
};
class Segment {

@ -20,8 +20,8 @@ public:
bool isSegmentLoaded(int n) const { return segments.find(n) != segments.end(); }
};
SegmentManager(const std::string &route_name, uint32_t flags, const std::string &data_dir = "")
: flags_(flags), route_(route_name, data_dir), event_data_(std::make_shared<EventData>()) {}
SegmentManager(const std::string &route_name, uint32_t flags, const std::string &data_dir = "", bool auto_source = false)
: flags_(flags), route_(route_name, data_dir, auto_source), event_data_(std::make_shared<EventData>()) {}
~SegmentManager();
bool load();

Loading…
Cancel
Save