IQ.Pilot Release Commit @ 0b96bd5

This commit is contained in:
IQ.Lvbs CI [bot]
2026-09-02 16:46:45 -05:00
parent 4fb3da761f
commit 7745f48100
162 changed files with 12835 additions and 9476 deletions

View File

@@ -0,0 +1,206 @@
#include <cstdio>
#include <cstring>
#include <filesystem>
#include <memory>
#include <optional>
#include <string>
#include "tools/cabana/streams/devicestream.h"
#include "tools/cabana/streams/pandastream.h"
#include "tools/cabana/streams/replaystream.h"
#ifdef __linux__
#include "tools/cabana/streams/socketcanstream.h"
#endif
#include "tools/cabana/ui/app.h"
#include "tools/cabana/ui/dialogs/messagebox.h"
#include "tools/cabana/utils/util.h"
#ifdef __GLIBC__
#include <malloc.h>
#endif
namespace {
struct CabanaArgs {
bool demo = false;
bool auto_source = false;
bool qcam = false;
bool wide_road = false;
bool cabin = false;
bool msgq = false;
bool panda = false;
bool no_vipc = false;
bool no_cache = false;
std::string panda_serial;
std::string socketcan;
std::string zmq;
std::string bridge;
std::string data_dir;
std::string dbc;
std::string route;
};
void printUsage(const char *argv0) {
fprintf(stderr,
"Usage: %s [options] [route]\n"
"\n"
" route local path or Konn3kt route to replay\n"
"\n"
"Options:\n"
" --help show this help\n"
" --demo use a demo route instead of providing your own\n"
" --auto Auto load the route from the best available source (no video):\n"
" internal, openpilotci, comma_api, car_segments, testing_closet\n"
" --qcam load qcamera\n"
" --wide-road load wide road camera (alias: --ecam)\n"
" --cabin load cabin camera (alias: --dcam)\n"
" --msgq read can messages from the msgq\n"
" --panda read can messages from panda\n"
" --panda-serial <serial> read can messages from panda with given serial\n"
#ifdef __linux__
" --socketcan <device> read can messages from given SocketCAN device\n"
#endif
" --zmq <ip-address> read can messages from zmq at the specified ip-address\n"
" --bridge <ip-address> bridge remote ZMQ into local msgq\n"
" --data_dir <dir> local directory with routes\n"
" --no-vipc do not output video\n"
" --no-cache turn off the local route file cache\n"
" --dbc <file> dbc file to open\n",
argv0);
}
bool takeValue(int argc, char *argv[], int &i, std::string &out) {
if (i + 1 >= argc) {
fprintf(stderr, "error: %s requires a value\n", argv[i]);
return false;
}
out = argv[++i];
return true;
}
std::optional<int> parseArgs(int argc, char *argv[], CabanaArgs &args) {
for (int i = 1; i < argc; ++i) {
const char *a = argv[i];
if (std::strcmp(a, "--help") == 0 || std::strcmp(a, "-h") == 0) {
printUsage(argv[0]);
return 0;
} else if (std::strcmp(a, "--demo") == 0) {
args.demo = true;
} else if (std::strcmp(a, "--auto") == 0) {
args.auto_source = true;
} else if (std::strcmp(a, "--qcam") == 0) {
args.qcam = true;
} else if (std::strcmp(a, "--wide-road") == 0 || std::strcmp(a, "--ecam") == 0) {
args.wide_road = true;
} else if (std::strcmp(a, "--cabin") == 0 || std::strcmp(a, "--dcam") == 0) {
args.cabin = true;
} else if (std::strcmp(a, "--msgq") == 0) {
args.msgq = true;
} else if (std::strcmp(a, "--panda") == 0) {
args.panda = true;
} else if (std::strcmp(a, "--panda-serial") == 0) {
if (!takeValue(argc, argv, i, args.panda_serial)) return 1;
args.panda = true;
} else if (std::strcmp(a, "--socketcan") == 0) {
if (!takeValue(argc, argv, i, args.socketcan)) return 1;
#ifndef __linux__
fprintf(stderr, "error: --socketcan is only supported on Linux\n");
return 1;
#endif
} else if (std::strcmp(a, "--zmq") == 0) {
if (!takeValue(argc, argv, i, args.zmq)) return 1;
} else if (std::strcmp(a, "--bridge") == 0) {
if (!takeValue(argc, argv, i, args.bridge)) return 1;
} else if (std::strcmp(a, "--data_dir") == 0) {
if (!takeValue(argc, argv, i, args.data_dir)) return 1;
} else if (std::strcmp(a, "--no-vipc") == 0) {
args.no_vipc = true;
} else if (std::strcmp(a, "--no-cache") == 0) {
args.no_cache = true;
} else if (std::strcmp(a, "--dbc") == 0) {
if (!takeValue(argc, argv, i, args.dbc)) return 1;
} else if (a[0] == '-') {
fprintf(stderr, "error: unknown option %s\n", a);
printUsage(argv[0]);
return 1;
} else if (args.route.empty()) {
args.route = a;
} else {
fprintf(stderr, "error: unexpected argument %s\n", a);
printUsage(argv[0]);
return 1;
}
}
return std::nullopt;
}
}
int main(int argc, char *argv[]) {
#ifdef __GLIBC__
mallopt(M_ARENA_MAX, 1);
#endif
std::error_code ec;
std::filesystem::current_path(executableDir(), ec);
CabanaArgs args;
if (auto code = parseArgs(argc, argv, args)) return *code;
std::unique_ptr<AbstractStream> stream;
StreamLoader stream_loader;
if (args.msgq) {
stream = std::make_unique<DeviceStream>();
} else if (!args.zmq.empty()) {
stream = std::make_unique<DeviceStream>(DeviceStream::Mode::Zmq, args.zmq);
} else if (!args.bridge.empty()) {
stream = std::make_unique<DeviceStream>(DeviceStream::Mode::Bridge, args.bridge);
} else if (args.panda) {
try {
stream = std::make_unique<PandaStream>(PandaStreamConfig{.serial = args.panda_serial});
} catch (std::exception &e) {
fprintf(stderr, "%s\n", e.what());
return 1;
}
#ifdef __linux__
} else if (!args.socketcan.empty()) {
if (!SocketCanStream::available()) {
fprintf(stderr, "error: SocketCAN is not available on this system\n");
return 1;
}
stream = std::make_unique<SocketCanStream>(SocketCanStreamConfig{.device = args.socketcan});
#endif
} else {
uint32_t replay_flags = REPLAY_FLAG_NONE;
if (args.wide_road) replay_flags |= REPLAY_FLAG_ECAM;
if (args.qcam) replay_flags |= REPLAY_FLAG_QCAMERA;
if (args.cabin) replay_flags |= REPLAY_FLAG_DCAM;
if (args.no_vipc) replay_flags |= REPLAY_FLAG_NO_VIPC;
if (args.no_cache) replay_flags |= REPLAY_FLAG_NO_FILE_CACHE;
std::string route;
if (!args.route.empty()) {
route = args.route;
} else if (args.demo) {
route = DEMO_ROUTE;
}
if (!route.empty()) {
stream_loader = [route, data_dir = args.data_dir, replay_flags, auto_source = args.auto_source]() -> std::unique_ptr<AbstractStream> {
auto replay_stream = std::make_unique<ReplayStream>();
Connection err = replay_stream->error.connect([](const std::string &msg) {
fprintf(stderr, "%s\n", msg.c_str());
utils::runOnMainThread([msg]() { MessageBox::warning("Error", msg); });
});
if (!replay_stream->loadRoute(route, data_dir, replay_flags, auto_source)) {
return nullptr;
}
return replay_stream;
};
}
}
return run(std::move(stream), std::move(stream_loader), args.dbc);
}