mirror of
https://github.com/dragonpilot/dragonpilot.git
synced 2026-06-22 22:42:05 +08:00
replay: parse route string, replay from the specified segment (#22503)
* parse segment name * return 0 * update regexp * with | * dd * use struct * move to class Route * refactor loadFromLoacal * simplify loadFromJson * cleanup load from server * const ref
This commit is contained in:
@@ -70,7 +70,7 @@ bool Replay::load() {
|
||||
}
|
||||
|
||||
void Replay::start(int seconds) {
|
||||
seekTo(seconds, false);
|
||||
seekTo(route_->identifier().segment_id * 60 + seconds, false);
|
||||
}
|
||||
|
||||
void Replay::updateEvents(const std::function<bool()> &lambda) {
|
||||
|
||||
@@ -9,69 +9,62 @@
|
||||
#include "selfdrive/ui/qt/api.h"
|
||||
#include "selfdrive/ui/replay/util.h"
|
||||
|
||||
Route::Route(const QString &route, const QString &data_dir) : route_(parseRoute(route)), data_dir_(data_dir) {}
|
||||
|
||||
RouteIdentifier Route::parseRoute(const QString &str) {
|
||||
QRegExp rx(R"(^([a-z0-9]{16})([|_/])(\d{4}-\d{2}-\d{2}--\d{2}-\d{2}-\d{2})(?:(--|/)(\d*))?$)");
|
||||
if (rx.indexIn(str) == -1) return {};
|
||||
|
||||
const QStringList list = rx.capturedTexts();
|
||||
return {list[1], list[3], list[5].toInt(), list[1] + "|" + list[3]};
|
||||
}
|
||||
|
||||
bool Route::load() {
|
||||
if (data_dir_.isEmpty()) {
|
||||
return loadFromServer();
|
||||
} else {
|
||||
return loadFromLocal();
|
||||
if (route_.str.isEmpty()) {
|
||||
qInfo() << "invalid route format";
|
||||
return false;
|
||||
}
|
||||
return data_dir_.isEmpty() ? loadFromServer() : loadFromLocal();
|
||||
}
|
||||
|
||||
bool Route::loadFromServer() {
|
||||
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();
|
||||
QObject::connect(&http, &HttpRequest::failedResponse, [&] { loop.exit(0); });
|
||||
QObject::connect(&http, &HttpRequest::timeoutResponse, [&] { loop.exit(0); });
|
||||
QObject::connect(&http, &HttpRequest::receivedResponse, [&](const QString &json) {
|
||||
loop.exit(loadFromJson(json));
|
||||
});
|
||||
http.sendRequest("https://api.commadotai.com/v1/route/" + route_ + "/files");
|
||||
loop.exec();
|
||||
return ret;
|
||||
http.sendRequest("https://api.commadotai.com/v1/route/" + route_.str + "/files");
|
||||
return loop.exec();
|
||||
}
|
||||
|
||||
bool Route::loadFromJson(const QString &json) {
|
||||
QJsonObject route_files = QJsonDocument::fromJson(json.trimmed().toUtf8()).object();
|
||||
if (route_files.empty()) {
|
||||
qInfo() << "JSON Parse failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
QRegExp rx(R"(\/(\d+)\/)");
|
||||
for (const QString &key : route_files.keys()) {
|
||||
for (const auto &url : route_files[key].toArray()) {
|
||||
for (const auto &value : QJsonDocument::fromJson(json.trimmed().toUtf8()).object()) {
|
||||
for (const auto &url : value.toArray()) {
|
||||
QString url_str = url.toString();
|
||||
if (rx.indexIn(url_str) != -1) {
|
||||
addFileToSegment(rx.cap(1).toInt(), url_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return !segments_.empty();
|
||||
}
|
||||
|
||||
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) {
|
||||
int seg_num_pos = folder.lastIndexOf("--");
|
||||
if (seg_num_pos != -1) {
|
||||
const int seg_num = folder.mid(seg_num_pos + 2).toInt();
|
||||
for (const auto &folder : log_dir.entryList(QDir::Dirs | QDir::NoDot | QDir::NoDotDot, QDir::NoSort)) {
|
||||
int pos = folder.lastIndexOf("--");
|
||||
if (pos != -1 && folder.left(pos) == route_.timestamp) {
|
||||
const int seg_num = folder.mid(pos + 2).toInt();
|
||||
QDir segment_dir(log_dir.filePath(folder));
|
||||
for (auto f : segment_dir.entryList(QDir::Files)) {
|
||||
for (const auto &f : segment_dir.entryList(QDir::Files)) {
|
||||
addFileToSegment(seg_num, segment_dir.absoluteFilePath(f));
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return !segments_.empty();
|
||||
}
|
||||
|
||||
void Route::addFileToSegment(int n, const QString &file) {
|
||||
@@ -97,7 +90,7 @@ Segment::Segment(int n, const SegmentFile &files, bool load_dcam, bool load_ecam
|
||||
static std::once_flag once_flag;
|
||||
std::call_once(once_flag, [=]() { if (!CACHE_DIR.exists()) QDir().mkdir(CACHE_DIR.absolutePath()); });
|
||||
|
||||
// the order is [RoadCam, DriverCam, WideRoadCam, log]. fallback to qcamera/qlog
|
||||
// [RoadCam, DriverCam, WideRoadCam, log]. fallback to qcamera/qlog
|
||||
const QString file_list[] = {
|
||||
files.road_cam.isEmpty() ? files.qcamera : files.road_cam,
|
||||
load_dcam ? files.driver_cam : "",
|
||||
|
||||
@@ -9,6 +9,13 @@
|
||||
|
||||
const QDir CACHE_DIR(util::getenv("COMMA_CACHE", "/tmp/comma_download_cache/").c_str());
|
||||
|
||||
struct RouteIdentifier {
|
||||
QString dongle_id;
|
||||
QString timestamp;
|
||||
int segment_id;
|
||||
QString str;
|
||||
};
|
||||
|
||||
struct SegmentFile {
|
||||
QString rlog;
|
||||
QString qlog;
|
||||
@@ -20,18 +27,20 @@ struct SegmentFile {
|
||||
|
||||
class Route {
|
||||
public:
|
||||
Route(const QString &route, const QString &data_dir = {}) : route_(route), data_dir_(data_dir) {};
|
||||
Route(const QString &route, const QString &data_dir = {});
|
||||
bool load();
|
||||
inline const QString &name() const { return route_; };
|
||||
inline const QString &name() const { return route_.str; }
|
||||
inline const RouteIdentifier &identifier() const { return route_; }
|
||||
inline const std::map<int, SegmentFile> &segments() const { return segments_; }
|
||||
inline const SegmentFile &at(int n) { return segments_.at(n); }
|
||||
static RouteIdentifier parseRoute(const QString &str);
|
||||
|
||||
protected:
|
||||
bool loadFromLocal();
|
||||
bool loadFromServer();
|
||||
bool loadFromJson(const QString &json);
|
||||
void addFileToSegment(int seg_num, const QString &file);
|
||||
QString route_;
|
||||
RouteIdentifier route_ = {};
|
||||
QString data_dir_;
|
||||
std::map<int, SegmentFile> segments_;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user