mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-06-28 01:52:06 +08:00
c++ replay: support local routes (#22288)
* support local route * kind of works * works Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com> old-commit-hash: 43a846843f1a8af33c21afb10195899e8880d775
This commit is contained in:
@@ -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,9 +97,9 @@ 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;
|
||||
return 0;
|
||||
}
|
||||
replay->start(parser.value("start").toInt());
|
||||
// start keyboard control thread
|
||||
|
||||
@@ -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(); };
|
||||
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;
|
||||
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_;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user