c++ replay: support local routes (#22288)

* support local route

* kind of works

* works

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
pull/22530/head
Dean Lee 4 years ago committed by GitHub
parent b6514a5cb3
commit 43a846843f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      selfdrive/debug/can_printer.py
  2. 3
      selfdrive/ui/replay/main.cc
  3. 4
      selfdrive/ui/replay/replay.cc
  4. 3
      selfdrive/ui/replay/replay.h
  5. 70
      selfdrive/ui/replay/route.cc
  6. 4
      selfdrive/ui/replay/route.h

@ -27,7 +27,7 @@ def can_printer(bus, max_msg, addr):
a = msgs[addr][-1].decode('ascii', 'backslashreplace')
x = binascii.hexlify(msgs[addr][-1]).decode('ascii')
if max_msg is None or addr < max_msg:
dd += "%04X(%4d)(%6d) %s \"%s\"\n" % (addr, addr, len(msgs[addr]), x, a)
dd += "%04X(%4d)(%6d) %s \"%s\"\n" % (addr, addr, len(msgs[addr]), x.ljust(20), a)
print(dd)
lp = sec_since_boot()

@ -83,6 +83,7 @@ int main(int argc, char *argv[]){
parser.addOption({{"b", "block"}, "blacklist of services to send", "block"});
parser.addOption({{"s", "start"}, "start from <seconds>", "seconds"});
parser.addOption({"demo", "use a demo route instead of providing your own"});
parser.addOption({"data_dir", "local directory with routes", "data_dir"});
parser.addOption({"dcam", "load driver camera"});
parser.addOption({"ecam", "load wide road camera"});
@ -96,7 +97,7 @@ int main(int argc, char *argv[]){
QStringList allow = parser.value("allow").isEmpty() ? QStringList{} : parser.value("allow").split(",");
QStringList block = parser.value("block").isEmpty() ? QStringList{} : parser.value("block").split(",");
Replay *replay = new Replay(route, allow, block, nullptr, parser.isSet("dcam"), parser.isSet("ecam"), &app);
Replay *replay = new Replay(route, allow, block, nullptr, parser.isSet("dcam"), parser.isSet("ecam"), parser.value("data_dir"), &app);
if (!replay->load()) {
return 0;
}

@ -9,7 +9,7 @@
#include "selfdrive/hardware/hw.h"
#include "selfdrive/ui/replay/util.h"
Replay::Replay(QString route, QStringList allow, QStringList block, SubMaster *sm_, bool dcam, bool ecam, QObject *parent)
Replay::Replay(QString route, QStringList allow, QStringList block, SubMaster *sm_, bool dcam, bool ecam, QString data_dir, QObject *parent)
: sm(sm_), load_dcam(dcam), load_ecam(ecam), QObject(parent) {
std::vector<const char *> s;
auto event_struct = capnp::Schema::from<cereal::Event>().asStruct();
@ -27,7 +27,7 @@ Replay::Replay(QString route, QStringList allow, QStringList block, SubMaster *s
if (sm == nullptr) {
pm = new PubMaster(s);
}
route_ = std::make_unique<Route>(route);
route_ = std::make_unique<Route>(route, data_dir);
events_ = new std::vector<Event *>();
// doSeek & queueSegment are always executed in the same thread
connect(this, &Replay::seekTo, this, &Replay::doSeek);

@ -12,7 +12,8 @@ class Replay : public QObject {
Q_OBJECT
public:
Replay(QString route, QStringList allow, QStringList block, SubMaster *sm = nullptr, bool dcam = false, bool ecam = false, QObject *parent = 0);
Replay(QString route, QStringList allow, QStringList block, SubMaster *sm = nullptr, bool dcam = false, bool ecam = false,
QString data_dir="", QObject *parent = 0);
~Replay();
bool load();
void start(int seconds = 0);

@ -12,23 +12,27 @@
#include "selfdrive/ui/qt/api.h"
#include "selfdrive/ui/replay/util.h"
Route::Route(const QString &route) : route_(route) {}
Route::Route(const QString &route, const QString &data_dir) : route_(route), data_dir_(data_dir) {}
bool Route::load() {
QEventLoop loop;
auto onError = [&loop](const QString &err) { loop.quit(); };
bool ret = false;
HttpRequest http(nullptr, !Hardware::PC());
QObject::connect(&http, &HttpRequest::failedResponse, onError);
QObject::connect(&http, &HttpRequest::timeoutResponse, onError);
QObject::connect(&http, &HttpRequest::receivedResponse, [&](const QString json) {
ret = loadFromJson(json);
loop.quit();
});
http.sendRequest("https://api.commadotai.com/v1/route/" + route_ + "/files");
loop.exec();
return ret;
if (data_dir_.isEmpty()) {
QEventLoop loop;
auto onError = [&loop](const QString &err) { loop.quit(); };
bool ret = false;
HttpRequest http(nullptr, !Hardware::PC());
QObject::connect(&http, &HttpRequest::failedResponse, onError);
QObject::connect(&http, &HttpRequest::timeoutResponse, onError);
QObject::connect(&http, &HttpRequest::receivedResponse, [&](const QString json) {
ret = loadFromJson(json);
loop.quit();
});
http.sendRequest("https://api.commadotai.com/v1/route/" + route_ + "/files");
loop.exec();
return ret;
} else {
return loadFromLocal();
}
}
bool Route::loadFromJson(const QString &json) {
@ -66,6 +70,40 @@ bool Route::loadFromJson(const QString &json) {
return true;
}
bool Route::loadFromLocal() {
QString prefix = route_.split('|').last();
if (prefix.isEmpty()) return false;
QDir log_dir(data_dir_);
QStringList folders = log_dir.entryList(QDir::Dirs | QDir::NoDot | QDir::NoDotDot, QDir::NoSort);
if (folders.isEmpty()) return false;
for (auto folder : folders) {
const int seg_num = folder.split("--")[2].toInt();
if (segments_.size() <= seg_num) {
segments_.resize(seg_num + 1);
}
QDir segment_dir(log_dir.filePath(folder));
for (auto f : segment_dir.entryList(QDir::Files)) {
const QString file_path = segment_dir.absoluteFilePath(f);
if (f.startsWith("rlog")) {
segments_[seg_num].rlog = file_path;
} else if (f.startsWith("qlog")) {
segments_[seg_num].qlog = file_path;
} else if (f.startsWith("fcamera")) {
segments_[seg_num].road_cam = file_path;
} else if (f.startsWith("dcamera")) {
segments_[seg_num].driver_cam = file_path;
} else if (f.startsWith("ecamera")) {
segments_[seg_num].wide_road_cam = file_path;
} else if (f.startsWith("qcamera")) {
segments_[seg_num].qcamera = file_path;
}
}
}
return true;
}
// class Segment
Segment::Segment(int n, const SegmentFile &segment_files, bool load_dcam, bool load_ecam) : seg_num_(n), files_(segment_files) {
@ -154,7 +192,7 @@ void Segment::load() {
}
QString Segment::localPath(const QUrl &url) {
if (url.isLocalFile()) return url.toString();
if (url.isLocalFile() || QFile(url.toString()).exists()) return url.toString();
QByteArray url_no_query = url.toString(QUrl::RemoveQuery).toUtf8();
return CACHE_DIR.filePath(QString(QCryptographicHash::hash(url_no_query, QCryptographicHash::Sha256).toHex()));

@ -23,15 +23,17 @@ struct SegmentFile {
class Route {
public:
Route(const QString &route);
Route(const QString &route, const QString &data_dir = {});
bool load();
inline const QString &name() const { return route_; };
inline int size() const { return segments_.size(); }
inline SegmentFile &at(int n) { return segments_[n]; }
protected:
bool loadFromLocal();
bool loadFromJson(const QString &json);
QString route_;
QString data_dir_;
std::vector<SegmentFile> segments_;
};

Loading…
Cancel
Save