Skip to content

Commit 85efde2

Browse files
pd0wmmitchellgoffpcharaschaxadeebshihadehComma Device
authored
bigmodel (commaai#23684)
* Added wide cam vipc client and bigmodel transform logic * Added wide_frame to ModelState, should still work normally * Refactored image input into addImage method, should still work normally * Updated thneed/compile.cc * Bigmodel, untested: 44f83118-b375-4d4c-ae12-2017124f0cf4/200 * Have to initialize extra buffer in SNPEModel * Default paramater value in the wrong place I think * Move USE_EXTRA to SConscript * New model: 6c34d59a-acc3-4877-84bd-904c10745ba6/250 * move use extra check to runtime, not on C2 * this is always true * more C2 checks * log if frames are out of sync * more logging on no frame * store in pointer * print sof * add sync logic * log based on sof difference as well * keep both models * less assumptions * define above thneed * typo * simplify * no need for second client is main is already wide * more comments update * no optional reference * more logging to debug lags * add to release files * both defines * New model: 6831a77f-2574-4bfb-8077-79b0972a2771/950 * Path offset no longer relevant * Remove duplicate execute * Moved bigmodel back to big_supercombo.dlc * add wide vipc stream * Tici must be tici * Needs state too * add wide cam support to model replay * handle syncing better * ugh, c2 * print that * handle ecam lag * skip first one * so close * update refs Co-authored-by: mitchellgoffpc <mitchellgoffpc@gmail.com> Co-authored-by: Harald Schafer <harald.the.engineer@gmail.com> Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com> Co-authored-by: Comma Device <device@comma.ai>
1 parent 9a046e2 commit 85efde2

20 files changed

+417
-131
lines changed

models/big_supercombo.dlc

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:ba3fe3e61853cc1434e3e220f40c8e9d1f1b9bab8458196ba3bea6a10b82c6ed
3+
size 72718099

models/big_supercombo.onnx

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:bda57c1a66944f5a633ecd739a24d62702c717a234f2fdcc499dfa1d61c3c19e
3+
size 73147489

release/files_common

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ common/transformations/transformations.pyx
5858
common/api/__init__.py
5959

6060
models/supercombo.dlc
61+
models/big_supercombo.dlc
6162
models/dmonitoring_model_q.dlc
6263

6364
release/*

selfdrive/controls/lib/lane_planner.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,16 @@
99

1010
TRAJECTORY_SIZE = 33
1111
# camera offset is meters from center car to camera
12-
# model path is in the frame of EON's camera. TICI is 0.1 m away,
13-
# however the average measured path difference is 0.04 m
12+
# model path is in the frame of the camera. Empirically
13+
# the model knows the difference between TICI and EON
14+
# so a path offset is not needed
15+
PATH_OFFSET = 0.00
1416
if EON:
1517
CAMERA_OFFSET = -0.06
16-
PATH_OFFSET = 0.0
1718
elif TICI:
1819
CAMERA_OFFSET = 0.04
19-
PATH_OFFSET = 0.04
2020
else:
2121
CAMERA_OFFSET = 0.0
22-
PATH_OFFSET = 0.0
2322

2423

2524
class LanePlanner:

selfdrive/modeld/SConscript

+4-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ thneed_src = [
3131

3232
use_thneed = not GetOption('no_thneed')
3333

34+
use_extra = True # arch == "larch64"
35+
lenv['CXXFLAGS'].append('-DUSE_EXTRA=true' if use_extra else '-DUSE_EXTRA=false')
36+
3437
if arch == "aarch64" or arch == "larch64":
3538
libs += ['gsl', 'CB']
3639
libs += ['gnustl_shared'] if arch == "aarch64" else ['pthread', 'dl']
@@ -65,7 +68,7 @@ common_model = lenv.Object(common_src)
6568

6669
# build thneed model
6770
if use_thneed and arch in ("aarch64", "larch64"):
68-
fn = "../../models/supercombo"
71+
fn = "../../models/big_supercombo" if use_extra else "../../models/supercombo"
6972
compiler = lenv.Program('thneed/compile', ["thneed/compile.cc"]+common_model, LIBS=libs)
7073
cmd = f"cd {Dir('.').abspath} && {compiler[0].abspath} {fn}.dlc {fn}.thneed --binary"
7174

selfdrive/modeld/modeld.cc

+105-31
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <cstdio>
22
#include <cstdlib>
33
#include <mutex>
4+
#include <cmath>
45

56
#include <eigen3/Eigen/Dense>
67

@@ -15,42 +16,42 @@
1516

1617
ExitHandler do_exit;
1718

18-
mat3 update_calibration(cereal::LiveCalibrationData::Reader live_calib, bool wide_camera) {
19+
mat3 update_calibration(Eigen::Matrix<float, 3, 4> &extrinsics, bool wide_camera, bool bigmodel_frame) {
1920
/*
2021
import numpy as np
2122
from common.transformations.model import medmodel_frame_from_road_frame
2223
medmodel_frame_from_ground = medmodel_frame_from_road_frame[:, (0, 1, 3)]
2324
ground_from_medmodel_frame = np.linalg.inv(medmodel_frame_from_ground)
2425
*/
25-
static const auto ground_from_medmodel_frame = (Eigen::Matrix<float, 3, 3>() <<
26-
0.00000000e+00, 0.00000000e+00, 1.00000000e+00,
26+
static const auto ground_from_medmodel_frame = (Eigen::Matrix<float, 3, 3>() <<
27+
0.00000000e+00, 0.00000000e+00, 1.00000000e+00,
2728
-1.09890110e-03, 0.00000000e+00, 2.81318681e-01,
2829
-1.84808520e-20, 9.00738606e-04, -4.28751576e-02).finished();
2930

31+
static const auto ground_from_sbigmodel_frame = (Eigen::Matrix<float, 3, 3>() <<
32+
0.00000000e+00, 7.31372216e-19, 1.00000000e+00,
33+
-2.19780220e-03, 4.11497335e-19, 5.62637363e-01,
34+
-5.46146580e-20, 1.80147721e-03, -2.73464241e-01).finished();
35+
3036
static const auto cam_intrinsics = Eigen::Matrix<float, 3, 3, Eigen::RowMajor>(wide_camera ? ecam_intrinsic_matrix.v : fcam_intrinsic_matrix.v);
3137
static const mat3 yuv_transform = get_model_yuv_transform();
3238

33-
auto extrinsic_matrix = live_calib.getExtrinsicMatrix();
34-
Eigen::Matrix<float, 3, 4> extrinsic_matrix_eigen;
35-
for (int i = 0; i < 4*3; i++) {
36-
extrinsic_matrix_eigen(i / 4, i % 4) = extrinsic_matrix[i];
37-
}
38-
39-
auto camera_frame_from_road_frame = cam_intrinsics * extrinsic_matrix_eigen;
39+
auto ground_from_model_frame = bigmodel_frame ? ground_from_sbigmodel_frame : ground_from_medmodel_frame;
40+
auto camera_frame_from_road_frame = cam_intrinsics * extrinsics;
4041
Eigen::Matrix<float, 3, 3> camera_frame_from_ground;
4142
camera_frame_from_ground.col(0) = camera_frame_from_road_frame.col(0);
4243
camera_frame_from_ground.col(1) = camera_frame_from_road_frame.col(1);
4344
camera_frame_from_ground.col(2) = camera_frame_from_road_frame.col(3);
4445

45-
auto warp_matrix = camera_frame_from_ground * ground_from_medmodel_frame;
46+
auto warp_matrix = camera_frame_from_ground * ground_from_model_frame;
4647
mat3 transform = {};
4748
for (int i=0; i<3*3; i++) {
4849
transform.v[i] = warp_matrix(i / 3, i % 3);
4950
}
5051
return matmul3(yuv_transform, transform);
5152
}
5253

53-
void run_model(ModelState &model, VisionIpcClient &vipc_client, bool wide_camera) {
54+
void run_model(ModelState &model, VisionIpcClient &vipc_client_main, VisionIpcClient &vipc_client_extra, bool main_wide_camera, bool use_extra, bool use_extra_client) {
5455
// messaging
5556
PubMaster pm({"modelV2", "cameraOdometry"});
5657
SubMaster sm({"lateralPlan", "roadCameraState", "liveCalibration"});
@@ -62,20 +63,80 @@ void run_model(ModelState &model, VisionIpcClient &vipc_client, bool wide_camera
6263
double last = 0;
6364
uint32_t run_count = 0;
6465

65-
mat3 model_transform = {};
66+
mat3 model_transform_main = {};
67+
mat3 model_transform_extra = {};
6668
bool live_calib_seen = false;
6769

70+
VisionBuf *buf_main = nullptr;
71+
VisionBuf *buf_extra = nullptr;
72+
73+
VisionIpcBufExtra meta_main = {0};
74+
VisionIpcBufExtra meta_extra = {0};
75+
6876
while (!do_exit) {
69-
VisionIpcBufExtra extra = {};
70-
VisionBuf *buf = vipc_client.recv(&extra);
71-
if (buf == nullptr) continue;
77+
// TODO: change sync logic to use timestamp start of frame in case camerad skips a frame
78+
// log frame id in model packet
79+
80+
// Keep receiving frames until we are at least 1 frame ahead of previous extra frame
81+
while (meta_main.frame_id <= meta_extra.frame_id) {
82+
buf_main = vipc_client_main.recv(&meta_main);
83+
if (meta_main.frame_id <= meta_extra.frame_id) {
84+
LOGE("main camera behind! main: %d (%.5f), extra: %d (%.5f)",
85+
meta_main.frame_id, double(meta_main.timestamp_sof) / 1e9,
86+
meta_extra.frame_id, double(meta_extra.timestamp_sof) / 1e9);
87+
}
88+
89+
if (buf_main == nullptr) break;
90+
}
91+
92+
if (buf_main == nullptr) {
93+
LOGE("vipc_client_main no frame");
94+
continue;
95+
}
96+
97+
if (use_extra_client) {
98+
// Keep receiving extra frames until frame id matches main camera
99+
do {
100+
buf_extra = vipc_client_extra.recv(&meta_extra);
101+
102+
if (meta_main.frame_id > meta_extra.frame_id) {
103+
LOGE("extra camera behind! main: %d (%.5f), extra: %d (%.5f)",
104+
meta_main.frame_id, double(meta_main.timestamp_sof) / 1e9,
105+
meta_extra.frame_id, double(meta_extra.timestamp_sof) / 1e9);
106+
}
107+
} while (buf_extra != nullptr && meta_main.frame_id > meta_extra.frame_id);
108+
109+
if (buf_extra == nullptr) {
110+
LOGE("vipc_client_extra no frame");
111+
continue;
112+
}
113+
114+
if (meta_main.frame_id != meta_extra.frame_id || std::abs((int64_t)meta_main.timestamp_sof - (int64_t)meta_extra.timestamp_sof) > 10000000ULL) {
115+
LOGE("frames out of sync! main: %d (%.5f), extra: %d (%.5f)",
116+
meta_main.frame_id, double(meta_main.timestamp_sof) / 1e9,
117+
meta_extra.frame_id, double(meta_extra.timestamp_sof) / 1e9);
118+
}
119+
} else {
120+
// Use single camera
121+
buf_extra = buf_main;
122+
meta_extra = meta_main;
123+
}
72124

73125
// TODO: path planner timeout?
74126
sm.update(0);
75127
int desire = ((int)sm["lateralPlan"].getLateralPlan().getDesire());
76128
frame_id = sm["roadCameraState"].getRoadCameraState().getFrameId();
77129
if (sm.updated("liveCalibration")) {
78-
model_transform = update_calibration(sm["liveCalibration"].getLiveCalibration(), wide_camera);
130+
auto extrinsic_matrix = sm["liveCalibration"].getLiveCalibration().getExtrinsicMatrix();
131+
Eigen::Matrix<float, 3, 4> extrinsic_matrix_eigen;
132+
for (int i = 0; i < 4*3; i++) {
133+
extrinsic_matrix_eigen(i / 4, i % 4) = extrinsic_matrix[i];
134+
}
135+
136+
model_transform_main = update_calibration(extrinsic_matrix_eigen, main_wide_camera, false);
137+
if (use_extra) {
138+
model_transform_extra = update_calibration(extrinsic_matrix_eigen, Hardware::TICI(), true);
139+
}
79140
live_calib_seen = true;
80141
}
81142

@@ -85,13 +146,12 @@ void run_model(ModelState &model, VisionIpcClient &vipc_client, bool wide_camera
85146
}
86147

87148
double mt1 = millis_since_boot();
88-
ModelOutput *model_output = model_eval_frame(&model, buf->buf_cl, buf->width, buf->height,
89-
model_transform, vec_desire);
149+
ModelOutput *model_output = model_eval_frame(&model, buf_main, buf_extra, model_transform_main, model_transform_extra, vec_desire);
90150
double mt2 = millis_since_boot();
91151
float model_execution_time = (mt2 - mt1) / 1000.0;
92152

93153
// tracked dropped frames
94-
uint32_t vipc_dropped_frames = extra.frame_id - last_vipc_frame_id - 1;
154+
uint32_t vipc_dropped_frames = meta_main.frame_id - last_vipc_frame_id - 1;
95155
float frames_dropped = frame_dropped_filter.update((float)std::min(vipc_dropped_frames, 10U));
96156
if (run_count < 10) { // let frame drops warm up
97157
frame_dropped_filter.reset(0);
@@ -101,13 +161,13 @@ void run_model(ModelState &model, VisionIpcClient &vipc_client, bool wide_camera
101161

102162
float frame_drop_ratio = frames_dropped / (1 + frames_dropped);
103163

104-
model_publish(pm, extra.frame_id, frame_id, frame_drop_ratio, *model_output, extra.timestamp_eof, model_execution_time,
164+
model_publish(pm, meta_main.frame_id, frame_id, frame_drop_ratio, *model_output, meta_main.timestamp_eof, model_execution_time,
105165
kj::ArrayPtr<const float>(model.output.data(), model.output.size()), live_calib_seen);
106-
posenet_publish(pm, extra.frame_id, vipc_dropped_frames, *model_output, extra.timestamp_eof, live_calib_seen);
166+
posenet_publish(pm, meta_main.frame_id, vipc_dropped_frames, *model_output, meta_main.timestamp_eof, live_calib_seen);
107167

108168
//printf("model process: %.2fms, from last %.2fms, vipc_frame_id %u, frame_id, %u, frame_drop %.3f\n", mt2 - mt1, mt1 - last, extra.frame_id, frame_id, frame_drop_ratio);
109169
last = mt1;
110-
last_vipc_frame_id = extra.frame_id;
170+
last_vipc_frame_id = meta_main.frame_id;
111171
}
112172
}
113173

@@ -120,28 +180,42 @@ int main(int argc, char **argv) {
120180
assert(ret == 0);
121181
}
122182

123-
bool wide_camera = Hardware::TICI() ? Params().getBool("EnableWideCamera") : false;
183+
bool main_wide_camera = Hardware::TICI() ? Params().getBool("EnableWideCamera") : false;
184+
bool use_extra = USE_EXTRA;
185+
bool use_extra_client = Hardware::TICI() && use_extra && !main_wide_camera;
124186

125187
// cl init
126188
cl_device_id device_id = cl_get_device_id(CL_DEVICE_TYPE_DEFAULT);
127189
cl_context context = CL_CHECK_ERR(clCreateContext(NULL, 1, &device_id, NULL, NULL, &err));
128190

129191
// init the models
130192
ModelState model;
131-
model_init(&model, device_id, context);
193+
model_init(&model, device_id, context, use_extra);
132194
LOGW("models loaded, modeld starting");
133195

134-
VisionIpcClient vipc_client = VisionIpcClient("camerad", wide_camera ? VISION_STREAM_WIDE_ROAD : VISION_STREAM_ROAD, true, device_id, context);
135-
while (!do_exit && !vipc_client.connect(false)) {
196+
VisionIpcClient vipc_client_main = VisionIpcClient("camerad", main_wide_camera ? VISION_STREAM_WIDE_ROAD : VISION_STREAM_ROAD, true, device_id, context);
197+
VisionIpcClient vipc_client_extra = VisionIpcClient("camerad", VISION_STREAM_WIDE_ROAD, false, device_id, context);
198+
199+
while (!do_exit && !vipc_client_main.connect(false)) {
200+
util::sleep_for(100);
201+
}
202+
203+
while (!do_exit && use_extra_client && !vipc_client_extra.connect(false)) {
136204
util::sleep_for(100);
137205
}
138206

139207
// run the models
140208
// vipc_client.connected is false only when do_exit is true
141-
if (vipc_client.connected) {
142-
const VisionBuf *b = &vipc_client.buffers[0];
143-
LOGW("connected with buffer size: %d (%d x %d)", b->len, b->width, b->height);
144-
run_model(model, vipc_client, wide_camera);
209+
if (!do_exit) {
210+
const VisionBuf *b = &vipc_client_main.buffers[0];
211+
LOGW("connected main cam with buffer size: %d (%d x %d)", b->len, b->width, b->height);
212+
213+
if (use_extra_client) {
214+
const VisionBuf *wb = &vipc_client_extra.buffers[0];
215+
LOGW("connected extra cam with buffer size: %d (%d x %d)", wb->len, wb->width, wb->height);
216+
}
217+
218+
run_model(model, vipc_client_main, vipc_client_extra, main_wide_camera, use_extra, use_extra_client);
145219
}
146220

147221
model_free(&model);

selfdrive/modeld/models/dmonitoring.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,8 @@ DMonitoringResult dmonitoring_eval_frame(DMonitoringModelState* s, void* stream_
166166
//fclose(dump_yuv_file2);
167167

168168
double t1 = millis_since_boot();
169-
s->m->execute(net_input_buf, yuv_buf_len);
169+
s->m->addImage(net_input_buf, yuv_buf_len);
170+
s->m->execute();
170171
double t2 = millis_since_boot();
171172

172173
DMonitoringResult ret = {0};

selfdrive/modeld/models/driving.cc

+18-8
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,19 @@ constexpr const kj::ArrayPtr<const T> to_kj_array_ptr(const std::array<T, size>
2626
return kj::ArrayPtr(arr.data(), arr.size());
2727
}
2828

29-
void model_init(ModelState* s, cl_device_id device_id, cl_context context) {
29+
void model_init(ModelState* s, cl_device_id device_id, cl_context context, bool use_extra) {
3030
s->frame = new ModelFrame(device_id, context);
31+
s->wide_frame = new ModelFrame(device_id, context);
3132

3233
#ifdef USE_THNEED
33-
s->m = std::make_unique<ThneedModel>("../../models/supercombo.thneed", &s->output[0], NET_OUTPUT_SIZE, USE_GPU_RUNTIME);
34+
s->m = std::make_unique<ThneedModel>(use_extra ? "../../models/big_supercombo.thneed" : "../../models/supercombo.thneed",
35+
&s->output[0], NET_OUTPUT_SIZE, USE_GPU_RUNTIME, use_extra);
3436
#elif USE_ONNX_MODEL
35-
s->m = std::make_unique<ONNXModel>("../../models/supercombo.onnx", &s->output[0], NET_OUTPUT_SIZE, USE_GPU_RUNTIME);
37+
s->m = std::make_unique<ONNXModel>(use_extra ? "../../models/big_supercombo.onnx" : "../../models/supercombo.onnx",
38+
&s->output[0], NET_OUTPUT_SIZE, USE_GPU_RUNTIME, use_extra);
3639
#else
37-
s->m = std::make_unique<SNPEModel>("../../models/supercombo.dlc", &s->output[0], NET_OUTPUT_SIZE, USE_GPU_RUNTIME);
40+
s->m = std::make_unique<SNPEModel>(use_extra ? "../../models/big_supercombo.dlc" : "../../models/supercombo.dlc",
41+
&s->output[0], NET_OUTPUT_SIZE, USE_GPU_RUNTIME, use_extra);
3842
#endif
3943

4044
#ifdef TEMPORAL
@@ -52,8 +56,8 @@ void model_init(ModelState* s, cl_device_id device_id, cl_context context) {
5256
#endif
5357
}
5458

55-
ModelOutput* model_eval_frame(ModelState* s, cl_mem yuv_cl, int width, int height,
56-
const mat3 &transform, float *desire_in) {
59+
ModelOutput* model_eval_frame(ModelState* s, VisionBuf* buf, VisionBuf* wbuf,
60+
const mat3 &transform, const mat3 &transform_wide, float *desire_in) {
5761
#ifdef DESIRE
5862
if (desire_in != NULL) {
5963
for (int i = 1; i < DESIRE_LEN; i++) {
@@ -70,8 +74,14 @@ ModelOutput* model_eval_frame(ModelState* s, cl_mem yuv_cl, int width, int heigh
7074
#endif
7175

7276
// if getInputBuf is not NULL, net_input_buf will be
73-
auto net_input_buf = s->frame->prepare(yuv_cl, width, height, transform, static_cast<cl_mem*>(s->m->getInputBuf()));
74-
s->m->execute(net_input_buf, s->frame->buf_size);
77+
auto net_input_buf = s->frame->prepare(buf->buf_cl, buf->width, buf->height, transform, static_cast<cl_mem*>(s->m->getInputBuf()));
78+
s->m->addImage(net_input_buf, s->frame->buf_size);
79+
80+
if (wbuf != nullptr) {
81+
auto net_extra_buf = s->wide_frame->prepare(wbuf->buf_cl, wbuf->width, wbuf->height, transform_wide, static_cast<cl_mem*>(s->m->getExtraBuf()));
82+
s->m->addExtra(net_extra_buf, s->wide_frame->buf_size);
83+
}
84+
s->m->execute();
7585

7686
return (ModelOutput*)&s->output;
7787
}

0 commit comments

Comments
 (0)