openpilot is an open source driver assistance system. openpilot performs the functions of Automated Lane Centering and Adaptive Cruise Control for over 200 supported car makes and models.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

139 lines
3.8 KiB

#include "tools/clip/application.h"
#include <QApplication>
#include <QTranslator>
#include <selfdrive/ui/qt/util.h>
#include <selfdrive/ui/qt/window.h>
#include "recorder/widget.h"
Application::Application(int argc, char *argv[], QObject *parent) : QObject(parent) {
argc_ = argc;
argv_ = argv;
initApp(argc_, argv_);
app = new QApplication(argc_, argv_);
QCommandLineParser parser;
parser.setApplicationDescription("Clip your ride!");
parser.addHelpOption();
const QCommandLineOption start({"s", "start"}, "start time", "start");
parser.addOption(start);
const QCommandLineOption output({"o", "output"}, "output file", "output");
parser.addOption(output);
parser.addPositionalArgument("route", "route string");
parser.process(*app);
int startTime = 0;
if (parser.isSet(start)) {
bool ok;
int parsed = parser.value(start).toInt(&ok);
if (!ok) {
qDebug() << "start time must be an integer\n";
fprintf(stderr, "%s", parser.helpText().toStdString().c_str());
exit(1);
}
startTime = parsed;
}
if (!parser.isSet(output)) {
qDebug() << "output is required\n";
fprintf(stderr, "%s", parser.helpText().toStdString().c_str());
exit(1);
}
QString outputFile = parser.value(output);
QString route;
QStringList positionalArgs = parser.positionalArguments();
if (!positionalArgs.isEmpty()) {
route = positionalArgs.at(0);
} else {
qDebug() << "No file specified\n";
fprintf(stderr, "%s", parser.helpText().toStdString().c_str());
exit(1);
}
QTranslator translator;
QString translation_file = QString::fromStdString(Params().get("LanguageSetting"));
if (!translator.load(QString(":/%1").arg(translation_file)) && translation_file.length()) {
qCritical() << "Failed to load translation file:" << translation_file;
}
app->installTranslator(&translator);
window = new OnroadWindow();
recorderThread = new QThread;
recorder = new Recorder(outputFile.toStdString());
recorder->moveToThread(recorderThread);
QObject::connect(recorderThread, &QThread::finished, recorder, &QObject::deleteLater);
QObject::connect(window, &OnroadWindow::redrew, this, [&]() {
recorder->saveFrame(std::make_shared<QPixmap>(std::move(window->grab())));
}, Qt::DirectConnection);
QObject::connect(app, &QCoreApplication::aboutToQuit, recorderThread, &QThread::quit);
window->setAttribute(Qt::WA_DontShowOnScreen);
window->setAttribute(Qt::WA_Mapped);
window->setAttribute(Qt::WA_NoSystemBackground);
recorderThread->start();
// Initialize and start replay
initReplay(route.toStdString());
replayThread = QThread::create([this, startTime] { startReplay(startTime); });
replayThread->start();
}
void Application::initReplay(const std::string& route) {
std::vector<std::string> allow;
std::vector<std::string> block;
replay = std::make_unique<Replay>(route, allow, block, nullptr, REPLAY_FLAG_NONE);
replay->setSegmentCacheLimit(1);
}
void Application::startReplay(int start) {
if (!replay || !replay->load()) {
qWarning() << "Failed to load replay";
QApplication::instance()->quit();
}
qInfo() << "Replay started.";
replayRunning = true;
replay->setEndSeconds(start + 60);
replay->start(start + 2);
replay->waitUntilEnd();
qInfo() << "Replay ended.";
replayRunning = false;
QMetaObject::invokeMethod(app, "quit", Qt::QueuedConnection);
}
Application::~Application() {
if (replayThread) {
replayThread->quit();
replayThread->wait();
delete replayThread;
}
if (recorderThread) {
recorderThread->quit();
recorderThread->wait();
}
delete window;
delete app;
}
int Application::exec() const {
// TODO: modify Replay to block until all OnroadWindow required messages have been broadcast at least once
std::this_thread::sleep_for(std::chrono::seconds(5));
setMainWindow(window);
return app->exec();
}